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
    • Labels:
    • 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
      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
      
      ----------------------------------------------------------------------
      

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

            Assignee:
            luke.lovett Luke Lovett
            Reporter:
            wolfmanx Wolfgang Scherer
            Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: