@@ -11,9 +11,33 @@ import asyncpg
1111from asyncpg import exceptions
1212
1313
14- cdef void * binary_codec_map[(MAXSUPPORTEDOID + 1 ) * 2 ]
15- cdef void * text_codec_map[(MAXSUPPORTEDOID + 1 ) * 2 ]
16- cdef dict EXTRA_CODECS = {}
14+ # The class indirection is needed because Cython
15+ # does not (as of 3.1.0) store global cdef variables
16+ # in module state.
17+ @cython.final
18+ cdef class CodecMap:
19+
20+ def __cinit__ (self ):
21+ self .extra_codecs = {}
22+ self .binary_codec_map = < void ** > cpython.PyMem_Calloc(
23+ (MAXSUPPORTEDOID + 1 ) * 2 , sizeof(void * ))
24+ self .text_codec_map = < void ** > cpython.PyMem_Calloc(
25+ (MAXSUPPORTEDOID + 1 ) * 2 , sizeof(void * ))
26+
27+ cdef inline void * get_binary_codec_ptr(self , uint32_t idx):
28+ return < void * > self .binary_codec_map[idx]
29+
30+ cdef inline void set_binary_codec_ptr(self , uint32_t idx, void * ptr):
31+ self .binary_codec_map[idx] = ptr
32+
33+ cdef inline void * get_text_codec_ptr(self , uint32_t idx):
34+ return < void * > self .text_codec_map[idx]
35+
36+ cdef inline void set_text_codec_ptr(self , uint32_t idx, void * ptr):
37+ self .text_codec_map[idx] = ptr
38+
39+
40+ codec_map = CodecMap()
1741
1842
1943@cython.final
@@ -67,7 +91,7 @@ cdef class Codec:
6791 )
6892
6993 if element_names is not None :
70- self .record_desc = record.ApgRecordDesc_New (
94+ self .record_desc = RecordDescriptor (
7195 element_names, tuple (element_names))
7296 else :
7397 self .record_desc = None
@@ -271,7 +295,7 @@ cdef class Codec:
271295 schema = self .schema,
272296 data_type = self .name,
273297 )
274- result = record.ApgRecord_New (asyncpg.Record, self .record_desc , elem_count)
298+ result = self .record_desc.make_record (asyncpg.Record, elem_count)
275299 for i in range (elem_count):
276300 elem_typ = self .element_type_oids[i]
277301 received_elem_typ = < uint32_t> hton.unpack_int32(frb_read(buf, 4 ))
@@ -301,7 +325,7 @@ cdef class Codec:
301325 settings, frb_slice_from(& elem_buf, buf, elem_len))
302326
303327 cpython.Py_INCREF(elem)
304- record .ApgRecord_SET_ITEM(result, i, elem)
328+ recordcapi .ApgRecord_SET_ITEM(result, i, elem)
305329
306330 return result
307331
@@ -811,9 +835,9 @@ cdef inline Codec get_core_codec(
811835 if oid > MAXSUPPORTEDOID:
812836 return None
813837 if format == PG_FORMAT_BINARY:
814- ptr = binary_codec_map[ oid * xformat]
838+ ptr = ( < CodecMap > codec_map).get_binary_codec_ptr( oid * xformat)
815839 elif format == PG_FORMAT_TEXT:
816- ptr = text_codec_map[ oid * xformat]
840+ ptr = ( < CodecMap > codec_map).get_text_codec_ptr( oid * xformat)
817841
818842 if ptr is NULL :
819843 return None
@@ -839,7 +863,10 @@ cdef inline Codec get_any_core_codec(
839863
840864
841865cdef inline int has_core_codec(uint32_t oid):
842- return binary_codec_map[oid] != NULL or text_codec_map[oid] != NULL
866+ return (
867+ (< CodecMap> codec_map).get_binary_codec_ptr(oid) != NULL
868+ or (< CodecMap> codec_map).get_text_codec_ptr(oid) != NULL
869+ )
843870
844871
845872cdef register_core_codec(uint32_t oid,
@@ -867,9 +894,9 @@ cdef register_core_codec(uint32_t oid,
867894 cpython.Py_INCREF(codec) # immortalize
868895
869896 if format == PG_FORMAT_BINARY:
870- binary_codec_map[ oid * xformat] = < void * > codec
897+ ( < CodecMap > codec_map).set_binary_codec_ptr( oid * xformat, < void * > codec)
871898 elif format == PG_FORMAT_TEXT:
872- text_codec_map[ oid * xformat] = < void * > codec
899+ ( < CodecMap > codec_map).set_text_codec_ptr( oid * xformat, < void * > codec)
873900 else :
874901 raise exceptions.InternalClientError(
875902 ' invalid data format: {}' .format(format))
@@ -888,8 +915,8 @@ cdef register_extra_codec(str name,
888915 codec = Codec(INVALIDOID)
889916 codec.init(name, None , kind, CODEC_C, format, PG_XFORMAT_OBJECT,
890917 encode, decode, None , None , None , None , None , None , None , 0 )
891- EXTRA_CODECS [name, format] = codec
918+ ( < CodecMap > codec_map).extra_codecs [name, format] = codec
892919
893920
894921cdef inline Codec get_extra_codec(str name, ServerDataFormat format):
895- return EXTRA_CODECS .get((name, format))
922+ return ( < CodecMap > codec_map).extra_codecs .get((name, format))
0 commit comments