mirror of
https://github.com/python/cpython.git
synced 2026-04-14 07:41:00 +00:00
gh-145966: Fix _csv DIALECT_GETATTR macro silently masking non-AttributeError exceptions (GH-145974)
The DIALECT_GETATTR macro in dialect_new() unconditionally called PyErr_Clear() when PyObject_GetAttrString() failed, which suppressed all exceptions including MemoryError, KeyboardInterrupt, and RuntimeError. Now only AttributeError is cleared; other exceptions propagate via the existing error handling path. Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
This commit is contained in:
parent
1efd9939c8
commit
dc24b8a6d4
3 changed files with 22 additions and 7 deletions
|
|
@ -1280,6 +1280,19 @@ class mydialect(csv.Dialect):
|
|||
self.assertRaises(ValueError, create_invalid, field_name, " ",
|
||||
skipinitialspace=True)
|
||||
|
||||
def test_dialect_getattr_non_attribute_error_propagates(self):
|
||||
# gh-145966: non-AttributeError exceptions raised by __getattr__
|
||||
# during dialect attribute lookup must propagate, not be silenced.
|
||||
class BadDialect:
|
||||
def __getattr__(self, name):
|
||||
raise RuntimeError("boom")
|
||||
|
||||
with self.assertRaises(RuntimeError):
|
||||
csv.reader([], dialect=BadDialect())
|
||||
|
||||
with self.assertRaises(RuntimeError):
|
||||
csv.writer(StringIO(), dialect=BadDialect())
|
||||
|
||||
|
||||
class TestSniffer(unittest.TestCase):
|
||||
sample1 = """\
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
Non-:exc:`AttributeError` exceptions raised during dialect attribute lookup
|
||||
in :mod:`csv` are no longer silently suppressed.
|
||||
|
|
@ -497,13 +497,13 @@ dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
|||
Py_XINCREF(skipinitialspace);
|
||||
Py_XINCREF(strict);
|
||||
if (dialect != NULL) {
|
||||
#define DIALECT_GETATTR(v, n) \
|
||||
do { \
|
||||
if (v == NULL) { \
|
||||
v = PyObject_GetAttrString(dialect, n); \
|
||||
if (v == NULL) \
|
||||
PyErr_Clear(); \
|
||||
} \
|
||||
#define DIALECT_GETATTR(v, n) \
|
||||
do { \
|
||||
if (v == NULL) { \
|
||||
if (PyObject_GetOptionalAttrString(dialect, n, &v) < 0) { \
|
||||
goto err; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
DIALECT_GETATTR(delimiter, "delimiter");
|
||||
DIALECT_GETATTR(doublequote, "doublequote");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue