@@ -558,18 +558,11 @@ cdef class TextReader:
558
558
pass
559
559
560
560
def __dealloc__ (self ):
561
- self .close( )
561
+ _close( self )
562
562
parser_del(self .parser)
563
563
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 )
573
566
574
567
def _set_quoting (self , quote_char: str | bytes | None , quoting: int ):
575
568
if not isinstance (quoting, int ):
@@ -1292,6 +1285,21 @@ cdef class TextReader:
1292
1285
return None
1293
1286
1294
1287
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
+
1295
1303
cdef:
1296
1304
object _true_values = [b' True' , b' TRUE' , b' true' ]
1297
1305
object _false_values = [b' False' , b' FALSE' , b' false' ]
0 commit comments