Uploaded image for project: 'Python Driver'
  1. Python Driver
  2. PYTHON-378

Inconsistency between pure Python BSON._dict_to_bson and _cbson._dict_to_bson

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Minor - P4
    • Resolution: Fixed
    • Affects Version/s: 2.2.1
    • Fix Version/s: 3.0
    • Component/s: None
    • Labels:
    • Environment:
      python 2.7/3.2 ubuntu
    • Backwards Compatibility:
      Minor Change
    • Sprint:
      Python Sprint 6

      Description

      The pure Python implementation of _dict_to_bson in fact accepts
      arbitrary mapping types, while the C implementation only accepts
      mapping types based on `dict`.

      The attached BUG-arbitrary-mapping.patch (see
      https://github.com/wolfmanx/mongo-python-driver/commit/6eb4cc47e35c3fc8bb17a81bf9189c3d4fa7b4a4)
      provides a possible solution that allows to enable/disable this feature.

      IMHO, the default should be either to break existing code or at list
      issue a warning, since there is no easy way to fix code, that depends
      on the behavior of the pure Python implementation and suddenly won't
      run with the C extension enabled.

      With the following test case in test_zz_bson.py (see attachment, only
      excerpt shown here)::

      class TestBSON(unittest.TestCase):
       
          def setUp(self):
      	pass
       
          def test_arbitrary_mapping_type(self):
              class ArbitrayMapping(object):
                  def __init__(self):
                      self._arbitrary_mapping_dict_ = dict()
                  def __getattr__(self, attr):
                      try:
                          return getattr(self._arbitrary_mapping_dict_, attr)
                      except AttributeError:
                          return super(ArbitrayMapping, self).__getattribute__(attr)
                  def __iter__(self):
                      return self._arbitrary_mapping_dict_.__iter__()
                  def __getitem__(self, key):
                      return self._arbitrary_mapping_dict_.__getitem__(key)
                  def __setitem__(self, key, val):
                      return self._arbitrary_mapping_dict_.__setitem__(key, val)
       
              am = ArbitrayMapping()
              self.assertRaises(TypeError, BSON.encode, am)
              am['_id'] = 'FFFFFFFFFFFFFFFFFFFFFFFF'
              self.assertRaises(TypeError, BSON.encode, am)

      Running the test with the C extension, a `TypeError` is raised, since
      _cbson._dict_to_bson only accepts real `dict` objects. Therefore,
      the test passes::

      $ python setup.py test -s test.test_zz_bson
       
      test_arbitrary_mapping_type (test.test_zz_bson.TestBSON) ... ok

      But without the C Extension, the test fails, since the Python version
      of _dict_to_bson indeed accepts arbitrary mapping types::

      $ find -name '*.so' | xargs -r rm; python setup.py --without-c-ext test -s test.test_zz_bson
       
      test_arbitrary_mapping_type (test.test_zz_bson.TestBSON) ... FAIL
       
      ======================================================================
      FAIL: test_arbitrary_mapping_type (test.test_zz_bson.TestBSON)
      ----------------------------------------------------------------------
      Traceback (most recent call last):
        File "/home/ws/project/ws-util/mongodb/pymongo/mongo-python-driver-git/test/test_zz_bson.py", line 85, in test_arbitrary_mapping_type
          self.assertRaises(TypeError, BSON.encode, am)
      AssertionError: TypeError not raised
       
      ----------------------------------------------------------------------

        Attachments

        1. BUG-arbitrary-mapping.patch
          3 kB
        2. test_zz_bson.py
          2 kB

          Issue Links

            Activity

              People

              • Votes:
                1 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: