@@ -11,9 +11,31 @@ 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((MAXSUPPORTEDOID + 1 ) * 2 , sizeof(void * ));
23+ self .text_codec_map = < void ** > cpython.PyMem_Calloc((MAXSUPPORTEDOID + 1 ) * 2 , sizeof(void * ));
24+
25+ cdef inline void * get_binary_codec_ptr(self , uint32_t idx):
26+ return < void * > self .binary_codec_map[idx]
27+
28+ cdef inline void set_binary_codec_ptr(self , uint32_t idx, void * ptr):
29+ self .binary_codec_map[idx] = ptr
30+
31+ cdef inline void * get_text_codec_ptr(self , uint32_t idx):
32+ return < void * > self .text_codec_map[idx]
33+
34+ cdef inline void set_text_codec_ptr(self , uint32_t idx, void * ptr):
35+ self .text_codec_map[idx] = ptr
36+
37+
38+ codec_map = CodecMap()
1739
1840
1941@cython.final
@@ -67,7 +89,7 @@ cdef class Codec:
6789 )
6890
6991 if element_names is not None :
70- self .record_desc = record.ApgRecordDesc_New (
92+ self .record_desc = RecordDescriptor (
7193 element_names, tuple (element_names))
7294 else :
7395 self .record_desc = None
@@ -271,7 +293,7 @@ cdef class Codec:
271293 schema = self .schema,
272294 data_type = self .name,
273295 )
274- result = record.ApgRecord_New (asyncpg.Record, self .record_desc , elem_count)
296+ result = self .record_desc.make_record (asyncpg.Record, elem_count)
275297 for i in range (elem_count):
276298 elem_typ = self .element_type_oids[i]
277299 received_elem_typ = < uint32_t> hton.unpack_int32(frb_read(buf, 4 ))
@@ -301,7 +323,7 @@ cdef class Codec:
301323 settings, frb_slice_from(& elem_buf, buf, elem_len))
302324
303325 cpython.Py_INCREF(elem)
304- record .ApgRecord_SET_ITEM(result, i, elem)
326+ recordcapi .ApgRecord_SET_ITEM(result, i, elem)
305327
306328 return result
307329
@@ -811,9 +833,9 @@ cdef inline Codec get_core_codec(
811833 if oid > MAXSUPPORTEDOID:
812834 return None
813835 if format == PG_FORMAT_BINARY:
814- ptr = binary_codec_map[ oid * xformat]
836+ ptr = ( < CodecMap > codec_map).get_binary_codec_ptr( oid * xformat)
815837 elif format == PG_FORMAT_TEXT:
816- ptr = text_codec_map[ oid * xformat]
838+ ptr = ( < CodecMap > codec_map).get_text_codec_ptr( oid * xformat)
817839
818840 if ptr is NULL :
819841 return None
@@ -839,7 +861,10 @@ cdef inline Codec get_any_core_codec(
839861
840862
841863cdef inline int has_core_codec(uint32_t oid):
842- return binary_codec_map[oid] != NULL or text_codec_map[oid] != NULL
864+ return (
865+ (< CodecMap> codec_map).get_binary_codec_ptr(oid) != NULL
866+ or (< CodecMap> codec_map).get_text_codec_ptr(oid) != NULL
867+ )
843868
844869
845870cdef register_core_codec(uint32_t oid,
@@ -867,9 +892,9 @@ cdef register_core_codec(uint32_t oid,
867892 cpython.Py_INCREF(codec) # immortalize
868893
869894 if format == PG_FORMAT_BINARY:
870- binary_codec_map[ oid * xformat] = < void * > codec
895+ ( < CodecMap > codec_map).set_binary_codec_ptr( oid * xformat, < void * > codec)
871896 elif format == PG_FORMAT_TEXT:
872- text_codec_map[ oid * xformat] = < void * > codec
897+ ( < CodecMap > codec_map).set_text_codec_ptr( oid * xformat, < void * > codec)
873898 else :
874899 raise exceptions.InternalClientError(
875900 ' invalid data format: {}' .format(format))
@@ -888,8 +913,8 @@ cdef register_extra_codec(str name,
888913 codec = Codec(INVALIDOID)
889914 codec.init(name, None , kind, CODEC_C, format, PG_XFORMAT_OBJECT,
890915 encode, decode, None , None , None , None , None , None , None , 0 )
891- EXTRA_CODECS [name, format] = codec
916+ ( < CodecMap > codec_map).extra_codecs [name, format] = codec
892917
893918
894919cdef inline Codec get_extra_codec(str name, ServerDataFormat format):
895- return EXTRA_CODECS .get((name, format))
920+ return ( < CodecMap > codec_map).extra_codecs .get((name, format))
0 commit comments