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

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Minor - P4 Minor - P4
    • 3.0
    • Affects Version/s: 2.2.1
    • Component/s: None
    • Environment:
      python 2.7/3.2 ubuntu
    • Minor Change

      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
      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):
          def test_arbitrary_mapping_type(self):
              class ArbitrayMapping(object):
                  def __init__(self):
                      self._arbitrary_mapping_dict_ = dict()
                  def __getattr__(self, attr):
                          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

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

            luke.lovett Luke Lovett
            wolfmanx Wolfgang Scherer
            1 Vote for this issue
            3 Start watching this issue