From e7f1a02cd1530312f83b8069037f13e858816e4b Mon Sep 17 00:00:00 2001 From: Bryan Forbes Date: Mon, 25 Jul 2022 17:30:21 -0500 Subject: [PATCH 01/15] Improve type completeness (#15) --- types.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/types.py b/types.py index 195f0f4..9ed0e9b 100644 --- a/types.py +++ b/types.py @@ -208,7 +208,7 @@ def from_int(cls: typing.Type[_BitString], x: int, length: int, def __repr__(self) -> str: return ''.format(self.as_string()) - __str__ = __repr__ + __str__: typing.Callable[['BitString'], str] = __repr__ def __eq__(self, other: object) -> bool: if not isinstance(other, BitString): @@ -353,6 +353,8 @@ class Path: __slots__ = '_is_closed', 'points' + points: typing.Tuple[Point, ...] + def __init__(self, *points: typing.Sequence[float], is_closed: bool = False) -> None: self.points = tuple(Point(*p) for p in points) From a9a747d066cbd47bd0a7b2503ee02e903ec4c4ca Mon Sep 17 00:00:00 2001 From: Fantix King Date: Fri, 18 Aug 2023 06:32:09 +0900 Subject: [PATCH 02/15] Fix wrong codecs API use (#20) Fixes #18 --- codecs/text.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codecs/text.pyx b/codecs/text.pyx index 17b5d25..79f375d 100644 --- a/codecs/text.pyx +++ b/codecs/text.pyx @@ -14,7 +14,7 @@ cdef inline as_pg_string_and_size( if settings.is_encoding_utf8(): cstr[0] = cpythonx.PyUnicode_AsUTF8AndSize(obj, size) else: - encoded = settings.get_text_codec().encode(obj) + encoded = settings.get_text_codec().encode(obj)[0] cpython.PyBytes_AsStringAndSize(encoded, cstr, size) if size[0] > 0x7fffffff: @@ -40,7 +40,7 @@ cdef inline decode_pg_string(CodecContext settings, const char* data, return cpython.PyUnicode_DecodeUTF8(data, len, NULL) else: bytes = cpython.PyBytes_FromStringAndSize(data, len) - return settings.get_text_codec().decode(bytes) + return settings.get_text_codec().decode(bytes)[0] cdef text_decode(CodecContext settings, FRBuffer *buf): From c26f17975ce3b5f6e012356ed21006103a7ad4a3 Mon Sep 17 00:00:00 2001 From: Vadim Markovtsev Date: Thu, 17 Aug 2023 23:36:32 +0200 Subject: [PATCH 03/15] Remove the duplicate buffer bounds check (#16) frb_check does exactly the same: `n > frb.len` --- frb.pxd | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frb.pxd b/frb.pxd index 1ae9561..9ff8d10 100644 --- a/frb.pxd +++ b/frb.pxd @@ -24,8 +24,7 @@ cdef: inline const char* frb_read(FRBuffer *frb, ssize_t n) except NULL: cdef const char *result - if n > frb.len: - frb_check(frb, n) + frb_check(frb, n) result = frb.buf frb.buf += n From debae2bef2c3cce81d73cc143e4ffba9d5c91a10 Mon Sep 17 00:00:00 2001 From: Vitaly Kirsanov Date: Fri, 18 Aug 2023 00:39:49 +0300 Subject: [PATCH 04/15] Issue #1020 Infinity numeric support (#22) --- codecs/numeric.pyx | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/codecs/numeric.pyx b/codecs/numeric.pyx index 16b0083..b75d096 100644 --- a/codecs/numeric.pyx +++ b/codecs/numeric.pyx @@ -16,6 +16,8 @@ DEF MAX_DSCALE = 0x3FFF DEF NUMERIC_POS = 0x0000 DEF NUMERIC_NEG = 0x4000 DEF NUMERIC_NAN = 0xC000 +DEF NUMERIC_PINF = 0xD000 +DEF NUMERIC_NINF = 0xF000 _Dec = decimal.Decimal @@ -51,8 +53,6 @@ cdef numeric_encode_binary(CodecContext settings, WriteBuffer buf, obj): dec = _Dec(obj) dt = dec.as_tuple() - if dt.exponent == 'F': - raise ValueError('numeric type does not support infinite values') if dt.exponent == 'n' or dt.exponent == 'N': # NaN @@ -60,6 +60,15 @@ cdef numeric_encode_binary(CodecContext settings, WriteBuffer buf, obj): num_pgdigits = 0 weight = 0 dscale = 0 + elif dt.exponent == 'F': + # Infinity + if dt.sign: + sign = NUMERIC_NINF + else: + sign = NUMERIC_PINF + num_pgdigits = 0 + weight = 0 + dscale = 0 else: exponent = dt.exponent if exponent < 0 and -exponent > MAX_DSCALE: @@ -160,6 +169,12 @@ cdef numeric_decode_binary_ex( if sign == NUMERIC_NAN: # Not-a-number return _Dec('NaN') + elif sign == NUMERIC_PINF: + # +Infinity + return _Dec('Infinity') + elif sign == NUMERIC_NINF: + # -Infinity + return _Dec('-Infinity') if num_pgdigits == 0: # Zero From 881be4cbd24ebae2fe45c79a434b2168ebb0ae6c Mon Sep 17 00:00:00 2001 From: Thomas Merkel Date: Thu, 17 Aug 2023 23:40:43 +0200 Subject: [PATCH 05/15] Provide illumos support (#23) To support illumos based distributions the endian.h could be included on the specified location. --- hton.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hton.h b/hton.h index 6b00c5e..1dd2994 100644 --- a/hton.h +++ b/hton.h @@ -1,6 +1,6 @@ #include -#if defined(__linux__) || defined(__CYGWIN__) +#if defined(__linux__) || defined(__CYGWIN__) || defined(__sun) #include #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) \ || defined(__DragonFly__) From d1618aa12b5421316ad84e3b3f07ff9275551b2c Mon Sep 17 00:00:00 2001 From: Fantix King Date: Sun, 8 Oct 2023 06:23:21 +0900 Subject: [PATCH 06/15] Optionally allow JSON encode/decode (#18) --- codecs/__init__.pxd | 4 ++++ codecs/context.pyx | 12 ++++++++++++ codecs/json.pyx | 30 +++++++++++++++++++++++++++++- 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/codecs/__init__.pxd b/codecs/__init__.pxd index 924d8f9..2dbcbd3 100644 --- a/codecs/__init__.pxd +++ b/codecs/__init__.pxd @@ -9,6 +9,10 @@ cdef class CodecContext: cpdef get_text_codec(self) cdef is_encoding_utf8(self) + cpdef get_json_decoder(self) + cdef is_decoding_json(self) + cpdef get_json_encoder(self) + cdef is_encoding_json(self) ctypedef object (*encode_func)(CodecContext settings, diff --git a/codecs/context.pyx b/codecs/context.pyx index 7df5b23..216da2d 100644 --- a/codecs/context.pyx +++ b/codecs/context.pyx @@ -12,3 +12,15 @@ cdef class CodecContext: cdef is_encoding_utf8(self): raise NotImplementedError + + cpdef get_json_decoder(self): + raise NotImplementedError + + cdef is_decoding_json(self): + raise NotImplementedError + + cpdef get_json_encoder(self): + raise NotImplementedError + + cdef is_encoding_json(self): + raise NotImplementedError diff --git a/codecs/json.pyx b/codecs/json.pyx index d1b50a0..97e6916 100644 --- a/codecs/json.pyx +++ b/codecs/json.pyx @@ -10,6 +10,9 @@ cdef jsonb_encode(CodecContext settings, WriteBuffer buf, obj): char *str ssize_t size + if settings.is_encoding_json(): + obj = settings.get_json_encoder().encode(obj) + as_pg_string_and_size(settings, obj, &str, &size) if size > 0x7fffffff - 1: @@ -26,4 +29,29 @@ cdef jsonb_decode(CodecContext settings, FRBuffer *buf): if format != 1: raise ValueError('unexpected JSONB format: {}'.format(format)) - return text_decode(settings, buf) + rv = text_decode(settings, buf) + + if settings.is_decoding_json(): + rv = settings.get_json_decoder().decode(rv) + + return rv + + +cdef json_encode(CodecContext settings, WriteBuffer buf, obj): + cdef: + char *str + ssize_t size + + if settings.is_encoding_json(): + obj = settings.get_json_encoder().encode(obj) + + text_encode(settings, buf, obj) + + +cdef json_decode(CodecContext settings, FRBuffer *buf): + rv = text_decode(settings, buf) + + if settings.is_decoding_json(): + rv = settings.get_json_decoder().decode(rv) + + return rv From 1c3cad14d53c8f3088106f4eab8f612b7293569b Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Sat, 7 Oct 2023 14:44:34 -0700 Subject: [PATCH 07/15] Default to not-encoding JSON instead of raising A regression from #18. --- codecs/context.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codecs/context.pyx b/codecs/context.pyx index 216da2d..c4d4416 100644 --- a/codecs/context.pyx +++ b/codecs/context.pyx @@ -17,10 +17,10 @@ cdef class CodecContext: raise NotImplementedError cdef is_decoding_json(self): - raise NotImplementedError + return False cpdef get_json_encoder(self): raise NotImplementedError cdef is_encoding_json(self): - raise NotImplementedError + return False From ea27e3f8b212b9847100d584ab6bfe9d79898b99 Mon Sep 17 00:00:00 2001 From: Eugene Toder Date: Thu, 29 Feb 2024 20:01:54 -0500 Subject: [PATCH 08/15] Export json_encode/decode functions (#26) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise we get compilation warnings: ``` asyncpg/pgproto/pgproto.c:23994:18: warning: ‘__pyx_f_7asyncpg_7pgproto_7pgproto_json_decode’ defined but not used [-Wunused-function] 23994 | static PyObject *__pyx_f_7asyncpg_7pgproto_7pgproto_json_decode(struct __pyx_obj_7asyncpg_7pgproto_7pgproto_CodecContext *__pyx_v_settings, struct __pyx_t_7asyncpg_7pgproto_7pgproto_FRBuffer *__pyx_v_buf) { | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ asyncpg/pgproto/pgproto.c:23886:18: warning: ‘__pyx_f_7asyncpg_7pgproto_7pgproto_json_encode’ defined but not used [-Wunused-function] 23886 | static PyObject *__pyx_f_7asyncpg_7pgproto_7pgproto_json_encode(struct __pyx_obj_7asyncpg_7pgproto_7pgproto_CodecContext *__pyx_v_settings, struct __pyx_obj_7asyncpg_7pgproto_7pgproto_WriteBuffer *__pyx_v_buf, PyObject *__pyx_v_obj) { | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` --- codecs/__init__.pxd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/codecs/__init__.pxd b/codecs/__init__.pxd index 2dbcbd3..67e20b8 100644 --- a/codecs/__init__.pxd +++ b/codecs/__init__.pxd @@ -103,6 +103,8 @@ cdef float8_decode(CodecContext settings, FRBuffer * buf) # JSON cdef jsonb_encode(CodecContext settings, WriteBuffer buf, obj) cdef jsonb_decode(CodecContext settings, FRBuffer * buf) +cdef json_encode(CodecContext settings, WriteBuffer buf, obj) +cdef json_decode(CodecContext settings, FRBuffer *buf) # JSON path From 3cad045ea75d884abb33352ceb827cda566b2a4c Mon Sep 17 00:00:00 2001 From: Bryan Forbes Date: Thu, 29 Feb 2024 19:02:15 -0600 Subject: [PATCH 09/15] Improve typing (#25) --- pgproto.pyi | 7 +++++ types.py | 74 +++++++++++++++++++++++++++++++---------------------- 2 files changed, 50 insertions(+), 31 deletions(-) diff --git a/pgproto.pyi b/pgproto.pyi index 24cc630..cbbcaec 100644 --- a/pgproto.pyi +++ b/pgproto.pyi @@ -4,10 +4,17 @@ import uuid class CodecContext: def get_text_codec(self) -> codecs.CodecInfo: ... + def get_json_decoder(self) -> object: ... + def get_json_encoder(self) -> object: ... +@typing.final class ReadBuffer: ... + +@typing.final class WriteBuffer: ... + class BufferError(Exception): ... +@typing.final class UUID(uuid.UUID): def __init__(self, inp: typing.AnyStr) -> None: ... diff --git a/types.py b/types.py index 9ed0e9b..af3d2ba 100644 --- a/types.py +++ b/types.py @@ -4,15 +4,18 @@ # This module is part of asyncpg and is released under # the Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0 +from __future__ import annotations -import builtins -import sys import typing -if sys.version_info >= (3, 8): - from typing import Literal, SupportsIndex -else: - from typing_extensions import Literal, SupportsIndex +if typing.TYPE_CHECKING: + import builtins + import sys + + if sys.version_info < (3, 11): + from typing_extensions import Self + else: + from typing import Self __all__ = ( @@ -20,8 +23,7 @@ 'Box', 'Line', 'LineSegment', 'Circle', ) -_BitString = typing.TypeVar('_BitString', bound='BitString') -_BitOrderType = Literal['big', 'little'] +_BitOrderType = typing.Literal['big', 'little'] class BitString: @@ -29,8 +31,11 @@ class BitString: __slots__ = '_bytes', '_bitlength' + _bytes: bytes + _bitlength: int + def __init__(self, - bitstring: typing.Optional[builtins.bytes] = None) -> None: + bitstring: builtins.bytes | None = None) -> None: if not bitstring: self._bytes = bytes() self._bitlength = 0 @@ -67,9 +72,9 @@ def __init__(self, self._bitlength = bitlen @classmethod - def frombytes(cls: typing.Type[_BitString], - bytes_: typing.Optional[builtins.bytes] = None, - bitlength: typing.Optional[int] = None) -> _BitString: + def frombytes(cls, + bytes_: builtins.bytes | None = None, + bitlength: int | None = None) -> Self: if bitlength is None: if bytes_ is None: bytes_ = bytes() @@ -151,9 +156,9 @@ def to_int(self, bitorder: _BitOrderType = 'big', return x @classmethod - def from_int(cls: typing.Type[_BitString], x: int, length: int, + def from_int(cls, x: int, length: int, bitorder: _BitOrderType = 'big', *, signed: bool = False) \ - -> _BitString: + -> Self: """Represent the Python int x as a BitString. Acts similarly to int.to_bytes. @@ -243,17 +248,23 @@ class Point(typing.Tuple[float, float]): __slots__ = () - def __new__(cls, - x: typing.Union[typing.SupportsFloat, - SupportsIndex, - typing.Text, - builtins.bytes, - builtins.bytearray], - y: typing.Union[typing.SupportsFloat, - SupportsIndex, - typing.Text, - builtins.bytes, - builtins.bytearray]) -> 'Point': + def __new__( + cls, + x: ( + typing.SupportsFloat | + typing.SupportsIndex | + typing.Text | + builtins.bytes | + builtins.bytearray + ), + y: ( + typing.SupportsFloat | + typing.SupportsIndex | + typing.Text | + builtins.bytes | + builtins.bytearray + ) + ) -> Self: return super().__new__(cls, typing.cast(typing.Any, (float(x), float(y)))) @@ -279,7 +290,7 @@ class Box(typing.Tuple[Point, Point]): __slots__ = () def __new__(cls, high: typing.Sequence[float], - low: typing.Sequence[float]) -> 'Box': + low: typing.Sequence[float]) -> Self: return super().__new__(cls, typing.cast(typing.Any, (Point(*high), Point(*low)))) @@ -305,7 +316,7 @@ class Line(typing.Tuple[float, float, float]): __slots__ = () - def __new__(cls, A: float, B: float, C: float) -> 'Line': + def __new__(cls, A: float, B: float, C: float) -> Self: return super().__new__(cls, typing.cast(typing.Any, (A, B, C))) @property @@ -327,7 +338,7 @@ class LineSegment(typing.Tuple[Point, Point]): __slots__ = () def __new__(cls, p1: typing.Sequence[float], - p2: typing.Sequence[float]) -> 'LineSegment': + p2: typing.Sequence[float]) -> Self: return super().__new__(cls, typing.cast(typing.Any, (Point(*p1), Point(*p2)))) @@ -388,8 +399,9 @@ def __getitem__(self, i: int) -> Point: def __getitem__(self, i: slice) -> typing.Tuple[Point, ...]: ... - def __getitem__(self, i: typing.Union[int, slice]) \ - -> typing.Union[Point, typing.Tuple[Point, ...]]: + def __getitem__( + self, i: int | slice + ) -> Point | typing.Tuple[Point, ...]: return self.points[i] def __contains__(self, point: object) -> bool: @@ -411,7 +423,7 @@ class Circle(typing.Tuple[Point, float]): __slots__ = () - def __new__(cls, center: Point, radius: float) -> 'Circle': + def __new__(cls, center: Point, radius: float) -> Self: return super().__new__(cls, typing.cast(typing.Any, (center, radius))) @property From 4df3c2614c6d1672f2908d91f319d97c8c3864c1 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Thu, 9 May 2024 17:52:05 +0300 Subject: [PATCH 10/15] `typing.Text` is deprecated (#27) Use `str` instead. Source: - https://github.com/python/cpython/blob/35b5eaa176a5bae8a0cacb9c9f40ec948ecc4325/Lib/typing.py#L3419-L3420 - https://github.com/python/cpython/issues/92332 --- types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types.py b/types.py index af3d2ba..0c45467 100644 --- a/types.py +++ b/types.py @@ -253,14 +253,14 @@ def __new__( x: ( typing.SupportsFloat | typing.SupportsIndex | - typing.Text | + str | builtins.bytes | builtins.bytearray ), y: ( typing.SupportsFloat | typing.SupportsIndex | - typing.Text | + str | builtins.bytes | builtins.bytearray ) From 780c5228fc40632bbacceaf7b98264eded5f2fc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alja=C5=BE=20Mur=20Er=C5=BEen?= Date: Tue, 9 Jul 2024 17:19:15 +0200 Subject: [PATCH 11/15] Make redirect_messages return count (#28) ReadBuffer.redirect_messages now returns the number of messages redirected. This is needed for counting RowDescription messages to figure out how many rows were modified by DML statements. --- README.rst | 2 +- buffer.pxd | 2 +- buffer.pyx | 22 ++++++++++++++++------ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/README.rst b/README.rst index f232582..c3f93a7 100644 --- a/README.rst +++ b/README.rst @@ -1 +1 @@ -Low-level IO utilities for PosgtreSQL drivers. +Low-level IO utilities for PostgreSQL drivers. diff --git a/buffer.pxd b/buffer.pxd index c2d4c6e..9e7bbac 100644 --- a/buffer.pxd +++ b/buffer.pxd @@ -127,7 +127,7 @@ cdef class ReadBuffer: cdef inline const char* try_consume_message(self, ssize_t* len) cdef bytes consume_message(self) cdef discard_message(self) - cdef redirect_messages(self, WriteBuffer buf, char mtype, int stop_at=?) + cdef int32_t redirect_messages(self, WriteBuffer buf, char mtype, int stop_at=?) cdef bytearray consume_messages(self, char mtype) cdef finish_message(self) cdef inline _finish_message(self) diff --git a/buffer.pyx b/buffer.pyx index e05d4c7..e34295a 100644 --- a/buffer.pyx +++ b/buffer.pyx @@ -667,8 +667,13 @@ cdef class ReadBuffer: self._finish_message() return mem - cdef redirect_messages(self, WriteBuffer buf, char mtype, + cdef int32_t redirect_messages(self, WriteBuffer buf, char mtype, int stop_at=0): + # Redirects messages from self into buf until either + # a message with a type different than mtype is encountered, or + # buf contains stop_at bytes. + # Returns the number of messages redirected. + if not self._current_message_ready: raise BufferError( 'consume_full_messages called on a buffer without a ' @@ -687,8 +692,11 @@ cdef class ReadBuffer: ssize_t new_pos0 ssize_t pos_delta int32_t done + int32_t count + count = 0 while True: + count += 1 buf.write_byte(mtype) buf.write_int32(self._current_message_len) @@ -701,10 +709,10 @@ cdef class ReadBuffer: if self._length > 0: self._ensure_first_buf() else: - return + return count if stop_at and buf._length >= stop_at: - return + return count # Fast path: exhaust buf0 as efficiently as possible. if self._pos0 + 5 <= self._len0: @@ -727,6 +735,7 @@ cdef class ReadBuffer: if new_pos0 + msg_len > cbuf_len: break new_pos0 += msg_len + count += 1 if new_pos0 != self._pos0: assert self._pos0 < new_pos0 <= self._len0 @@ -734,7 +743,8 @@ cdef class ReadBuffer: pos_delta = new_pos0 - self._pos0 buf.write_cstr( cbuf + self._pos0, - pos_delta) + pos_delta + ) self._pos0 = new_pos0 self._length -= pos_delta @@ -743,11 +753,11 @@ cdef class ReadBuffer: if done: # The next message is of a different type. - return + return count # Back to slow path. if not self.take_message_type(mtype): - return + return count cdef bytearray consume_messages(self, char mtype): """Consume consecutive messages of the same type.""" From b8109fb311a59f30f9947567a13508da9a776564 Mon Sep 17 00:00:00 2001 From: "Michael J. Sullivan" Date: Mon, 4 Nov 2024 21:36:29 -0800 Subject: [PATCH 12/15] Work around a recent Cython bug. (#29) I'll be sending a fix upstream also but I want to move things forward on our side without waiting for a Cython release. --- uuid.pyx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/uuid.pyx b/uuid.pyx index 52900ff..f140e66 100644 --- a/uuid.pyx +++ b/uuid.pyx @@ -172,7 +172,13 @@ cdef class UUID(__UUIDReplaceMe): if self._int is None: # The cache is important because `self.int` can be # used multiple times by __hash__ etc. - self._int = int.from_bytes(self.bytes, 'big') + # + # The or 0 works around a bug interaction between cpython + # 3.10 and earlier and Cython ~3.0.11 in which + # int.from_bytes returns a "non-canonical 0" and then + # Cython's implementation of & mishandles it. + # See cython/cython#6480. + self._int = int.from_bytes(self.bytes, 'big') or 0 return self._int @property From 9f415b2c834df119422c011e5163e21064bff6ad Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Thu, 7 Nov 2024 18:17:08 -0800 Subject: [PATCH 13/15] Make `buffer.pyx` more standalone Move some definitions into `buffer.{pyx,pxd}` to reduce the hassle of cimporting it. --- buffer.pxd | 7 +++++++ buffer.pxi | 3 +++ buffer.pyx | 2 ++ consts.pxi | 3 --- 4 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 buffer.pxi diff --git a/buffer.pxd b/buffer.pxd index 9e7bbac..05d62bf 100644 --- a/buffer.pxd +++ b/buffer.pxd @@ -5,6 +5,13 @@ # the Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0 +from libc.stdint cimport int8_t, uint8_t, int16_t, uint16_t, \ + int32_t, uint32_t, int64_t, uint64_t + + +include "./buffer.pxi" + + cdef class WriteBuffer: cdef: # Preallocated small buffer diff --git a/buffer.pxi b/buffer.pxi new file mode 100644 index 0000000..626880e --- /dev/null +++ b/buffer.pxi @@ -0,0 +1,3 @@ +DEF _BUFFER_INITIAL_SIZE = 1024 +DEF _BUFFER_MAX_GROW = 65536 +DEF _BUFFER_FREELIST_SIZE = 256 diff --git a/buffer.pyx b/buffer.pyx index e34295a..462a51f 100644 --- a/buffer.pyx +++ b/buffer.pyx @@ -12,6 +12,8 @@ import collections class BufferError(Exception): pass +include "./buffer.pxi" + @cython.no_gc_clear @cython.final @cython.freelist(_BUFFER_FREELIST_SIZE) diff --git a/consts.pxi b/consts.pxi index dbce085..68bf31f 100644 --- a/consts.pxi +++ b/consts.pxi @@ -5,8 +5,5 @@ # the Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0 -DEF _BUFFER_INITIAL_SIZE = 1024 -DEF _BUFFER_MAX_GROW = 65536 -DEF _BUFFER_FREELIST_SIZE = 256 DEF _MAXINT32 = 2**31 - 1 DEF _NUMERIC_DECODER_SMALLBUF_SIZE = 256 From a9d29929a5f20ef6260442a6715fc4af28f7c011 Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Mon, 24 Nov 2025 11:10:14 -0800 Subject: [PATCH 14/15] Constify globals in datetime --- codecs/datetime.pyx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/codecs/datetime.pyx b/codecs/datetime.pyx index bed0b9e..4d43b85 100644 --- a/codecs/datetime.pyx +++ b/codecs/datetime.pyx @@ -27,10 +27,10 @@ cdef int32_t pg_date_offset_ord = \ cpython.PyLong_AsLong(pg_epoch_date.toordinal()) # Binary representations of infinity for datetimes. -cdef int64_t pg_time64_infinity = 0x7fffffffffffffff -cdef int64_t pg_time64_negative_infinity = 0x8000000000000000 -cdef int32_t pg_date_infinity = 0x7fffffff -cdef int32_t pg_date_negative_infinity = 0x80000000 +cdef const int64_t pg_time64_infinity = 0x7fffffffffffffff +cdef const int64_t pg_time64_negative_infinity = 0x8000000000000000 +cdef const int32_t pg_date_infinity = 0x7fffffff +cdef const int32_t pg_date_negative_infinity = 0x80000000 infinity_datetime = datetime.datetime( datetime.MAXYEAR, 12, 31, 23, 59, 59, 999999) From a29a6f6aaa09013cb33ffadb8dd57e21d671ab55 Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Mon, 24 Nov 2025 11:10:23 -0800 Subject: [PATCH 15/15] Remove cdef from UUID class variable This makes it so that Cython can store it in the module state --- uuid.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uuid.pyx b/uuid.pyx index f140e66..e1accd2 100644 --- a/uuid.pyx +++ b/uuid.pyx @@ -72,7 +72,7 @@ _hextable[:] = [ ] -cdef std_UUID = uuid.UUID +std_UUID = uuid.UUID cdef pg_uuid_bytes_from_str(str u, char *out): @@ -356,4 +356,4 @@ cpython.PyTuple_SET_ITEM(UUID.__mro__, 1, std_UUID) # -cdef pg_UUID = UUID +pg_UUID = UUID