Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9e42642

Browse files
authored
Add Python 3.14 support, experimental subinterpreter/freethreading support (#1279)
The bulk of the changes here is a rewrite of `recordobj.c` to use modernCPython API to properly isolate the module (PEP 489, PEP 573, PEP 630).This, along with Cython flags, enables support for safely importing`asyncpg` in subinterpreters. The `Record` freelist is nowthread-specific, so asyncpg should be thread-safe *at the C level*.Support for subinterpreters and freethreading is EXPERIMENTAL.
1 parent6fe1c49 commit9e42642

24 files changed

+3538
-519
lines changed

‎.clang-format‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# A clang-format style that approximates Python's PEP 7
2+
BasedOnStyle:Google
3+
AlwaysBreakAfterReturnType:All
4+
AllowShortIfStatementsOnASingleLine:false
5+
AlignAfterOpenBracket:Align
6+
BreakBeforeBraces:Stroustrup
7+
ColumnLimit:95
8+
DerivePointerAlignment:false
9+
IndentWidth:4
10+
Language:Cpp
11+
PointerAlignment:Right
12+
ReflowComments:true
13+
SpaceBeforeParens:ControlStatements
14+
SpacesInParentheses:false
15+
TabWidth:4
16+
UseTab:Never
17+
SortIncludes:false

‎.clangd‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Diagnostics:
2+
Includes:
3+
IgnoreHeader:
4+
-"pythoncapi_compat.*\\.h"

‎.github/workflows/tests.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
# job.
1818
strategy:
1919
matrix:
20-
python-version:["3.9", "3.10", "3.11", "3.12", "3.13"]
20+
python-version:["3.9", "3.10", "3.11", "3.12", "3.13", "3.14", "3.14t"]
2121
os:[ubuntu-latest, macos-latest, windows-latest]
2222
loop:[asyncio, uvloop]
2323
exclude:

‎.gitignore‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ docs/_build
3333
/.pytest_cache/
3434
/.eggs
3535
/.vscode
36+
/.zed
3637
/.mypy_cache
3738
/.venv*
3839
/.tox
40+
/compile_commands.json

‎asyncpg/connection.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2751,8 +2751,8 @@ def _check_record_class(record_class):
27512751
andissubclass(record_class,protocol.Record)
27522752
):
27532753
if (
2754-
record_class.__new__isnotobject.__new__
2755-
orrecord_class.__init__isnotobject.__init__
2754+
record_class.__new__isnotprotocol.Record.__new__
2755+
orrecord_class.__init__isnotprotocol.Record.__init__
27562756
):
27572757
raiseexceptions.InterfaceError(
27582758
'record_class must not redefine __new__ or __init__'

‎asyncpg/protocol/__init__.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@
88

99
from __future__importannotations
1010

11-
from .protocolimportProtocol,Record,NO_TIMEOUT,BUILTIN_TYPE_NAME_MAP
11+
from .protocolimportProtocol,NO_TIMEOUT,BUILTIN_TYPE_NAME_MAP
12+
from .recordimportRecord

‎asyncpg/protocol/codecs/base.pxd‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@ ctypedef object (*codec_decode_func)(Codec codec,
2222
FRBuffer*buf)
2323

2424

25+
cdefclass CodecMap:
26+
cdef:
27+
void** binary_codec_map
28+
void** text_codec_map
29+
dict extra_codecs
30+
31+
cdef inlinevoid*get_binary_codec_ptr(self, uint32_t idx)
32+
cdef inlinevoid set_binary_codec_ptr(self, uint32_t idx,void*ptr)
33+
cdef inlinevoid*get_text_codec_ptr(self, uint32_t idx)
34+
cdef inlinevoid set_text_codec_ptr(self, uint32_t idx,void*ptr)
35+
36+
2537
cdefenum CodecType:
2638
CODEC_UNDEFINED=0
2739
CODEC_C=1

‎asyncpg/protocol/codecs/base.pyx‎

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,33 @@ import asyncpg
1111
from 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

6993
if element_namesisnotNone:
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 iinrange(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
returnNone
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 ptrisNULL:
819843
returnNone
@@ -839,7 +863,10 @@ cdef inline Codec get_any_core_codec(
839863

840864

841865
cdef inlineint has_core_codec(uint32_t oid):
842-
return binary_codec_map[oid] !=NULLor 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

845872
cdef 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

894921
cdef inline Codec get_extra_codec(str name, ServerDataFormat format):
895-
returnEXTRA_CODECS.get((name, format))
922+
return(<CodecMap>codec_map).extra_codecs.get((name, format))

‎asyncpg/protocol/coreproto.pyx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import hashlib
1111
include"scram.pyx"
1212

1313

14-
cdefdictAUTH_METHOD_NAME= {
14+
AUTH_METHOD_NAME= {
1515
AUTH_REQUIRED_KERBEROS:'kerberosv5',
1616
AUTH_REQUIRED_PASSWORD:'password',
1717
AUTH_REQUIRED_PASSWORDMD5:'md5',
@@ -1229,5 +1229,5 @@ cdef class CoreProtocol:
12291229
pass
12301230

12311231

1232-
cdef bytesSYNC_MESSAGE= bytes(WriteBuffer.new_message(b'S').end_message())
1233-
cdef bytesFLUSH_MESSAGE= bytes(WriteBuffer.new_message(b'H').end_message())
1232+
SYNC_MESSAGE= bytes(WriteBuffer.new_message(b'S').end_message())
1233+
FLUSH_MESSAGE= bytes(WriteBuffer.new_message(b'H').end_message())

‎asyncpg/protocol/encodings.pyx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
https://www.postgresql.org/docs/current/static/multibyte.html#CHARSET-TABLE
1111
'''
1212

13-
cdefdictENCODINGS_MAP= {
13+
ENCODINGS_MAP= {
1414
'abc':'cp1258',
1515
'alt':'cp866',
1616
'euc_cn':'euccn',

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp