Skip to content

Commit 98d26b8

Browse files
committed
BUG: doing a class method lookup in __dealloc__ is dangerous
1 parent 776857a commit 98d26b8

File tree

1 file changed

+18
-10
lines changed

1 file changed

+18
-10
lines changed

pandas/_libs/parsers.pyx

+18-10
Original file line numberDiff line numberDiff line change
@@ -558,18 +558,11 @@ cdef class TextReader:
558558
pass
559559

560560
def __dealloc__(self):
561-
self.close()
561+
_close(self)
562562
parser_del(self.parser)
563563

564-
def close(self) -> None:
565-
# also preemptively free all allocated memory
566-
parser_free(self.parser)
567-
if self.true_set:
568-
kh_destroy_str_starts(self.true_set)
569-
self.true_set = NULL
570-
if self.false_set:
571-
kh_destroy_str_starts(self.false_set)
572-
self.false_set = NULL
564+
def close(self):
565+
_close(self)
573566

574567
def _set_quoting(self, quote_char: str | bytes | None, quoting: int):
575568
if not isinstance(quoting, int):
@@ -1292,6 +1285,21 @@ cdef class TextReader:
12921285
return None
12931286

12941287

1288+
# Factor out code common to TextReader.__dealloc__ and TextReader.close
1289+
# It cannot be a class method, since calling self.close() in __dealloc__
1290+
# which causes a class attribute lookup and violates best parctices
1291+
# https://cython.readthedocs.io/en/latest/src/userguide/special_methods.html#finalization-method-dealloc
1292+
cdef _close(TextReader reader):
1293+
# also preemptively free all allocated memory
1294+
parser_free(reader.parser)
1295+
if reader.true_set:
1296+
kh_destroy_str_starts(reader.true_set)
1297+
reader.true_set = NULL
1298+
if reader.false_set:
1299+
kh_destroy_str_starts(reader.false_set)
1300+
reader.false_set = NULL
1301+
1302+
12951303
cdef:
12961304
object _true_values = [b'True', b'TRUE', b'true']
12971305
object _false_values = [b'False', b'FALSE', b'false']

0 commit comments

Comments
 (0)