Skip to content

Commit e55aab9

Browse files
authored
gh-109230: test_pyexpat no longer depends on the current directory (#109233)
Fix test_pyexpat.test_exception(): it can now be run from a directory different than Python source code directory. Before, the test failed in this case. Skip the test if Modules/pyexpat.c source is not available. Skip also the test on Python implementations other than CPython.
1 parent cbb3a6f commit e55aab9

File tree

2 files changed

+53
-24
lines changed

2 files changed

+53
-24
lines changed

Lib/test/test_pyexpat.py

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
# XXX TypeErrors on calling handlers, or on bad return values from a
22
# handler, are obscure and unhelpful.
33

4-
from io import BytesIO
54
import os
65
import platform
76
import sys
87
import sysconfig
98
import unittest
109
import traceback
10+
from io import BytesIO
11+
from test import support
12+
from test.support import os_helper
1113

1214
from xml.parsers import expat
1315
from xml.parsers.expat import errors
@@ -439,37 +441,59 @@ def test7(self):
439441
# Test handling of exception from callback:
440442
class HandlerExceptionTest(unittest.TestCase):
441443
def StartElementHandler(self, name, attrs):
442-
raise RuntimeError(name)
444+
raise RuntimeError(f'StartElementHandler: <{name}>')
443445

444446
def check_traceback_entry(self, entry, filename, funcname):
445-
self.assertEqual(os.path.basename(entry[0]), filename)
446-
self.assertEqual(entry[2], funcname)
447+
self.assertEqual(os.path.basename(entry.filename), filename)
448+
self.assertEqual(entry.name, funcname)
447449

450+
@support.cpython_only
448451
def test_exception(self):
452+
# gh-66652: test _PyTraceback_Add() used by pyexpat.c to inject frames
453+
454+
# Change the current directory to the Python source code directory
455+
# if it is available.
456+
src_dir = sysconfig.get_config_var('abs_builddir')
457+
if src_dir:
458+
have_source = os.path.isdir(src_dir)
459+
else:
460+
have_source = False
461+
if have_source:
462+
with os_helper.change_cwd(src_dir):
463+
self._test_exception(have_source)
464+
else:
465+
self._test_exception(have_source)
466+
467+
def _test_exception(self, have_source):
468+
# Use path relative to the current directory which should be the Python
469+
# source code directory (if it is available).
470+
PYEXPAT_C = os.path.join('Modules', 'pyexpat.c')
471+
449472
parser = expat.ParserCreate()
450473
parser.StartElementHandler = self.StartElementHandler
451474
try:
452475
parser.Parse(b"<a><b><c/></b></a>", True)
453-
self.fail()
454-
except RuntimeError as e:
455-
self.assertEqual(e.args[0], 'a',
456-
"Expected RuntimeError for element 'a', but" + \
457-
" found %r" % e.args[0])
458-
# Check that the traceback contains the relevant line in pyexpat.c
459-
entries = traceback.extract_tb(e.__traceback__)
460-
self.assertEqual(len(entries), 3)
461-
self.check_traceback_entry(entries[0],
462-
"test_pyexpat.py", "test_exception")
463-
self.check_traceback_entry(entries[1],
464-
"pyexpat.c", "StartElement")
465-
self.check_traceback_entry(entries[2],
466-
"test_pyexpat.py", "StartElementHandler")
467-
if (sysconfig.is_python_build()
468-
and not (sys.platform == 'win32' and platform.machine() == 'ARM')
469-
and not is_emscripten
470-
and not is_wasi
471-
):
472-
self.assertIn('call_with_frame("StartElement"', entries[1][3])
476+
477+
self.fail("the parser did not raise RuntimeError")
478+
except RuntimeError as exc:
479+
self.assertEqual(exc.args[0], 'StartElementHandler: <a>', exc)
480+
entries = traceback.extract_tb(exc.__traceback__)
481+
482+
self.assertEqual(len(entries), 3, entries)
483+
self.check_traceback_entry(entries[0],
484+
"test_pyexpat.py", "_test_exception")
485+
self.check_traceback_entry(entries[1],
486+
os.path.basename(PYEXPAT_C),
487+
"StartElement")
488+
self.check_traceback_entry(entries[2],
489+
"test_pyexpat.py", "StartElementHandler")
490+
491+
# Check that the traceback contains the relevant line in
492+
# Modules/pyexpat.c. Skip the test if Modules/pyexpat.c is not
493+
# available.
494+
if have_source and os.path.exists(PYEXPAT_C):
495+
self.assertIn('call_with_frame("StartElement"',
496+
entries[1].line)
473497

474498

475499
# Test Current* members:
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Fix ``test_pyexpat.test_exception()``: it can now be run from a directory
2+
different than Python source code directory. Before, the test failed in this
3+
case. Skip the test if Modules/pyexpat.c source is not available. Skip also
4+
the test on Python implementations other than CPython. Patch by Victor
5+
Stinner.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy