@@ -11,9 +11,33 @@ import asyncpg
1111from asyncpgimport exceptions
1212
1313
14- cdefvoid * binary_codec_map[(MAXSUPPORTEDOID+ 1 )* 2 ]
15- cdefvoid * text_codec_map[(MAXSUPPORTEDOID+ 1 )* 2 ]
16- cdefdict 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+ cdefclass 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 inlinevoid * get_binary_codec_ptr(self , uint32_t idx):
28+ return < void * > self .binary_codec_map[idx]
29+
30+ cdef inlinevoid set_binary_codec_ptr(self , uint32_t idx,void * ptr):
31+ self .binary_codec_map[idx]= ptr
32+
33+ cdef inlinevoid * get_text_codec_ptr(self , uint32_t idx):
34+ return < void * > self .text_codec_map[idx]
35+
36+ cdef inlinevoid 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
6993if element_namesis not None :
70- self .record_desc= record.ApgRecordDesc_New (
94+ self .record_desc= RecordDescriptor (
7195 element_names,tuple (element_names))
7296else :
7397self .record_desc= None
@@ -271,7 +295,7 @@ cdef class Codec:
271295schema = self .schema,
272296data_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)
275299for iin 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
306330return result
307331
@@ -811,9 +835,9 @@ cdef inline Codec get_core_codec(
811835if oid> MAXSUPPORTEDOID:
812836return None
813837if format== PG_FORMAT_BINARY:
814- ptr= binary_codec_map[ oid* xformat]
838+ ptr= ( < CodecMap > codec_map).get_binary_codec_ptr( oid* xformat)
815839elif format== PG_FORMAT_TEXT:
816- ptr= text_codec_map[ oid* xformat]
840+ ptr= ( < CodecMap > codec_map).get_text_codec_ptr( oid* xformat)
817841
818842if ptris NULL :
819843return None
@@ -839,7 +863,10 @@ cdef inline Codec get_any_core_codec(
839863
840864
841865cdef inlineint 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
869896if format== PG_FORMAT_BINARY:
870- binary_codec_map[ oid* xformat] = < void * > codec
897+ ( < CodecMap > codec_map).set_binary_codec_ptr( oid* xformat, < void * > codec)
871898elif format== PG_FORMAT_TEXT:
872- text_codec_map[ oid* xformat] = < void * > codec
899+ ( < CodecMap > codec_map).set_text_codec_ptr( oid* xformat, < void * > codec)
873900else :
874901raise 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))