Skip to content

test_pyexpat.MemoryProtectionTest fails when Python was built with expat 2.7.1 but runs with 2.7.2 #144739

Description

@hroncok

Bug report

Bug description:

  1. Build Python with system expat 2.7.1
  2. Update expat to e.g. 2.7.2
  3. test_pyexpat.MemoryProtectionTest fail with AttributeError: 'pyexpat.xmlparser' object has no attribute 'SetAllocTrackerMaximumAmplification'

======================================================================
ERROR: test_set_activation_threshold__fail_for_subparser (test.test_pyexpat.MemoryProtectionTest.test_set_activation_threshold__fail_for_subparser)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 966, in test_set_activation_threshold__fail_for_subparser
    self.assert_root_parser_failure(setter, 12345)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 920, in assert_root_parser_failure
    self.assertRaisesRegex(expat.ExpatError, msg, func, *args, **kwargs)
    ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/unittest/case.py", line 1338, in assertRaisesRegex
    return context.handle('assertRaisesRegex', args, kwargs)
           ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/unittest/case.py", line 238, in handle
    callable_obj(*args, **kwargs)
    ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 1018, in set_activation_threshold
    return parser.SetAllocTrackerActivationThreshold(threshold)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'pyexpat.xmlparser' object has no attribute 'SetAllocTrackerActivationThreshold'

======================================================================
ERROR: test_set_activation_threshold__invalid_threshold_range (test.test_pyexpat.MemoryProtectionTest.test_set_activation_threshold__invalid_threshold_range)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 960, in test_set_activation_threshold__invalid_threshold_range
    self.assertRaises(OverflowError, setter, _testcapi.ULLONG_MAX + 1)
    ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/unittest/case.py", line 795, in assertRaises
    return context.handle('assertRaises', args, kwargs)
           ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/unittest/case.py", line 238, in handle
    callable_obj(*args, **kwargs)
    ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 1018, in set_activation_threshold
    return parser.SetAllocTrackerActivationThreshold(threshold)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'pyexpat.xmlparser' object has no attribute 'SetAllocTrackerActivationThreshold'

======================================================================
ERROR: test_set_activation_threshold__invalid_threshold_type (test.test_pyexpat.MemoryProtectionTest.test_set_activation_threshold__invalid_threshold_type)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 951, in test_set_activation_threshold__invalid_threshold_type
    self.assertRaises(TypeError, setter, 1.0)
    ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/unittest/case.py", line 795, in assertRaises
    return context.handle('assertRaises', args, kwargs)
           ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/unittest/case.py", line 238, in handle
    callable_obj(*args, **kwargs)
    ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 1018, in set_activation_threshold
    return parser.SetAllocTrackerActivationThreshold(threshold)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'pyexpat.xmlparser' object has no attribute 'SetAllocTrackerActivationThreshold'

======================================================================
ERROR: test_set_activation_threshold__threshold_not_reached (test.test_pyexpat.MemoryProtectionTest.test_set_activation_threshold__threshold_not_reached)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 1036, in test_set_activation_threshold__threshold_not_reached
    self.set_activation_threshold(parser, pow(10, 5))
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 1018, in set_activation_threshold
    return parser.SetAllocTrackerActivationThreshold(threshold)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'pyexpat.xmlparser' object has no attribute 'SetAllocTrackerActivationThreshold'

======================================================================
ERROR: test_set_activation_threshold__threshold_reached (test.test_pyexpat.MemoryProtectionTest.test_set_activation_threshold__threshold_reached)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 1026, in test_set_activation_threshold__threshold_reached
    self.set_activation_threshold(parser, 3)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 1018, in set_activation_threshold
    return parser.SetAllocTrackerActivationThreshold(threshold)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'pyexpat.xmlparser' object has no attribute 'SetAllocTrackerActivationThreshold'

======================================================================
ERROR: test_set_maximum_amplification__amplification_exceeded (test.test_pyexpat.MemoryProtectionTest.test_set_maximum_amplification__amplification_exceeded)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 1046, in test_set_maximum_amplification__amplification_exceeded
    self.set_activation_threshold(parser, 0)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 1018, in set_activation_threshold
    return parser.SetAllocTrackerActivationThreshold(threshold)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'pyexpat.xmlparser' object has no attribute 'SetAllocTrackerActivationThreshold'

======================================================================
ERROR: test_set_maximum_amplification__amplification_not_exceeded (test.test_pyexpat.MemoryProtectionTest.test_set_maximum_amplification__amplification_not_exceeded)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 1056, in test_set_maximum_amplification__amplification_not_exceeded
    self.set_activation_threshold(parser, 0)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 1018, in set_activation_threshold
    return parser.SetAllocTrackerActivationThreshold(threshold)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'pyexpat.xmlparser' object has no attribute 'SetAllocTrackerActivationThreshold'

======================================================================
ERROR: test_set_maximum_amplification__fail_for_subparser (test.test_pyexpat.MemoryProtectionTest.test_set_maximum_amplification__fail_for_subparser)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 1000, in test_set_maximum_amplification__fail_for_subparser
    self.assert_root_parser_failure(setter, 123.45)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 920, in assert_root_parser_failure
    self.assertRaisesRegex(expat.ExpatError, msg, func, *args, **kwargs)
    ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/unittest/case.py", line 1338, in assertRaisesRegex
    return context.handle('assertRaisesRegex', args, kwargs)
           ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/unittest/case.py", line 238, in handle
    callable_obj(*args, **kwargs)
    ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 1021, in set_maximum_amplification
    return parser.SetAllocTrackerMaximumAmplification(max_factor)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'pyexpat.xmlparser' object has no attribute 'SetAllocTrackerMaximumAmplification'

======================================================================
ERROR: test_set_maximum_amplification__infinity (test.test_pyexpat.MemoryProtectionTest.test_set_maximum_amplification__infinity)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 979, in test_set_maximum_amplification__infinity
    self.assertIsNone(self.set_maximum_amplification(parser, inf))
                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 1021, in set_maximum_amplification
    return parser.SetAllocTrackerMaximumAmplification(max_factor)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'pyexpat.xmlparser' object has no attribute 'SetAllocTrackerMaximumAmplification'

======================================================================
ERROR: test_set_maximum_amplification__invalid_max_factor_range (test.test_pyexpat.MemoryProtectionTest.test_set_maximum_amplification__invalid_max_factor_range)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 993, in test_set_maximum_amplification__invalid_max_factor_range
    self.assertRaisesRegex(expat.ExpatError, msg, setter, float('nan'))
    ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/unittest/case.py", line 1338, in assertRaisesRegex
    return context.handle('assertRaisesRegex', args, kwargs)
           ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/unittest/case.py", line 238, in handle
    callable_obj(*args, **kwargs)
    ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 1021, in set_maximum_amplification
    return parser.SetAllocTrackerMaximumAmplification(max_factor)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'pyexpat.xmlparser' object has no attribute 'SetAllocTrackerMaximumAmplification'

======================================================================
ERROR: test_set_maximum_amplification__invalid_max_factor_type (test.test_pyexpat.MemoryProtectionTest.test_set_maximum_amplification__invalid_max_factor_type)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 985, in test_set_maximum_amplification__invalid_max_factor_type
    self.assertRaises(TypeError, setter, None)
    ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/unittest/case.py", line 795, in assertRaises
    return context.handle('assertRaises', args, kwargs)
           ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/unittest/case.py", line 238, in handle
    callable_obj(*args, **kwargs)
    ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.13/test/test_pyexpat.py", line 1021, in set_maximum_amplification
    return parser.SetAllocTrackerMaximumAmplification(max_factor)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'pyexpat.xmlparser' object has no attribute 'SetAllocTrackerMaximumAmplification'

----------------------------------------------------------------------
Ran 11 tests in 0.013s

Updating expat to a newer version, unlike downgrading, should generally be a safe operation. The test has a @unittest.skipIf(expat.version_info < (2, 7, 2), "requires Expat >= 2.7.2") decorator. But in fact it should rather check for "was compiled with pyexpat < 2.7.2".

I belive this could be fixed by changing the skip to a hasattr based check and will submit a PR.

CPython versions tested on:

3.13, 3.14, 3.15

Operating systems tested on:

Linux

Linked PRs

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions