pabigot / pyxb

Python XML Schema Bindings
Apache License 2.0
130 stars 75 forks source link

validateBinding, toDOM and toxml raise AbstractElementError on unpickled pyxb object with abstract element/substitutionGroup #129

Open indrat opened 3 years ago

indrat commented 3 years ago

Reporting this issue for posterity, I realise this is unlikely to be fixed due to #100.

After pickling and unpickling a pyxb object that has an abstract element/substitutionGroup in a list element the object is no longer passes validateBinding and is unable to be converted to a DOM object or XML.

Adding the following to tests/trac/trac-0026/check-validation.py demonstrates the issue.

    def testPickle (self):
        # After pickling should be able to invoke `validateBinding`, `toxml` or `toDOM` on `other`
        instance = trac26.CreateFromDocument(self.Good_xmlt)
        self.assertEqual(2, len(instance.eAbstractCard))
        self.assertTrue(isinstance(instance.eAbstractCard[0], trac26.tCardCymru))
        self.assertTrue(isinstance(instance.eAbstractCard[1], trac26.tCardEnglish))
        self.assertTrue(instance.validateBinding())
        instance.toxml()
        pickled = pickle.dumps(instance)
        other = pickle.loads(pickled)
        self.assertEqual(2, len(other.eAbstractCard))
        self.assertTrue(isinstance(other.eAbstractCard[0], trac26.tCardCymru))
        self.assertTrue(isinstance(other.eAbstractCard[1], trac26.tCardEnglish))
        # the following all raise `AbstractElementError`
        self.assertTrue(other.validateBinding())
        other.toxml()
        other.toDOM()
› python --version
Python 3.8.2
======================================================================
ERROR: testPickle (__main__.TestAbstractElementError)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "check-validation.py", line 139, in testPickle
    self.assertTrue(other.validateBinding())
  File "/pyxb/pyxb/binding/basis.py", line 560, in toxml
    dom = self.toDOM(bds, element_name=element_name)
  File "/pyxb/pyxb/binding/basis.py", line 532, in toDOM
    self._toDOM_csc(bds, element)
  File "/pyxb/pyxb/binding/basis.py", line 2680, in _toDOM_csc
    order = self._validatedChildren()
  File "/pyxb/pyxb/binding/basis.py", line 2207, in _validatedChildren
    return self.__automatonConfiguration.sequencedChildren()
  File "/pyxb/pyxb/binding/content.py", line 580, in sequencedChildren
    symbol_set = instance._symbolSet()
  File "/pyxb/pyxb/binding/basis.py", line 2236, in _symbolSet
    rv[eu] = [ converter(_v) for _v in value ]
  File "/pyxb/pyxb/binding/basis.py", line 2236, in <listcomp>
    rv[eu] = [ converter(_v) for _v in value ]
  File "/pyxb/pyxb/binding/basis.py", line 1661, in compatibleValue
    raise pyxb.AbstractElementError(self, location, value)
pyxb.exceptions_.AbstractElementError: Cannot instantiate abstract element eAbstractCard directly