parallax-postgres 0.1.0__cp315-cp315-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- parallax/postgres/__init__.py +16 -0
- parallax/postgres/_authorization.py +56 -0
- parallax/postgres/_cloaders_binary.cp315-win_amd64.pyd +0 -0
- parallax/postgres/_cloaders_binary.pyi +4 -0
- parallax/postgres/_cloaders_c.cp315-win_amd64.pyd +0 -0
- parallax/postgres/_cloaders_c.pyi +4 -0
- parallax/postgres/_compiled_loaders.py +67 -0
- parallax/postgres/_connection.py +1495 -0
- parallax/postgres/_context.py +749 -0
- parallax/postgres/_endpoint.py +150 -0
- parallax/postgres/_isolation.py +24 -0
- parallax/postgres/_options.py +150 -0
- parallax/postgres/_pool_metrics.py +173 -0
- parallax/postgres/_route.py +346 -0
- parallax/postgres/_route_plan.py +68 -0
- parallax/postgres/_runtime.py +241 -0
- parallax/postgres/_startup.py +294 -0
- parallax/postgres/adapter.py +157 -0
- parallax/postgres/py.typed +0 -0
- parallax_postgres-0.1.0.dist-info/METADATA +147 -0
- parallax_postgres-0.1.0.dist-info/RECORD +25 -0
- parallax_postgres-0.1.0.dist-info/WHEEL +5 -0
- parallax_postgres-0.1.0.dist-info/licenses/LICENSE +201 -0
- parallax_postgres-0.1.0.dist-info/licenses/NOTICE +5 -0
- parallax_postgres-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from parallax.postgres._authorization import PostgresRole
|
|
4
|
+
from parallax.postgres._endpoint import PostgresEndpoint
|
|
5
|
+
from parallax.postgres._isolation import isolation_spelling
|
|
6
|
+
from parallax.postgres._options import OnDemandOptions, PoolOptions
|
|
7
|
+
from parallax.postgres.adapter import PostgresAdapter
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"OnDemandOptions",
|
|
11
|
+
"PoolOptions",
|
|
12
|
+
"PostgresAdapter",
|
|
13
|
+
"PostgresEndpoint",
|
|
14
|
+
"PostgresRole",
|
|
15
|
+
"isolation_spelling",
|
|
16
|
+
]
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
|
+
|
|
6
|
+
from psycopg.sql import SQL, Composed, Identifier
|
|
7
|
+
|
|
8
|
+
from parallax.core.db_port import InvalidAuthorizationError
|
|
9
|
+
from parallax.postgres._connection import (
|
|
10
|
+
_complete_first_send, # pyright: ignore[reportPrivateUsage] - the lease's shared first-send markers
|
|
11
|
+
_start_first_send, # pyright: ignore[reportPrivateUsage] - the lease's shared first-send markers
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
import psycopg
|
|
16
|
+
from psycopg.rows import TupleRow
|
|
17
|
+
|
|
18
|
+
from parallax.postgres._context import PostgresConnectionContext
|
|
19
|
+
|
|
20
|
+
__all__ = ["PostgresRole", "install_role", "restore_role"]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(frozen=True, slots=True)
|
|
24
|
+
class PostgresRole:
|
|
25
|
+
"""A non-empty PostgreSQL role name bound to principal execution."""
|
|
26
|
+
|
|
27
|
+
name: str
|
|
28
|
+
|
|
29
|
+
def __post_init__(self) -> None:
|
|
30
|
+
if not isinstance(self.name, str): # pyright: ignore[reportUnnecessaryIsInstance] - validates untyped callers at the public boundary
|
|
31
|
+
raise InvalidAuthorizationError("a PostgreSQL role name must be a string")
|
|
32
|
+
if not self.name:
|
|
33
|
+
raise InvalidAuthorizationError("a PostgreSQL role name must not be empty")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _role_statement(role: PostgresRole) -> Composed:
|
|
37
|
+
return SQL("SET ROLE {}").format(Identifier(role.name))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _install_role(
|
|
41
|
+
connection: psycopg.Connection[TupleRow],
|
|
42
|
+
context: PostgresConnectionContext | None,
|
|
43
|
+
statement: Composed,
|
|
44
|
+
) -> None:
|
|
45
|
+
with connection.cursor() as cursor:
|
|
46
|
+
_start_first_send(context)
|
|
47
|
+
cursor.execute(statement)
|
|
48
|
+
_complete_first_send(context)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def install_role(connection: Any, role: PostgresRole) -> None:
|
|
52
|
+
_install_role(connection, None, _role_statement(role))
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def restore_role(connection: Any) -> None:
|
|
56
|
+
connection.execute("RESET ROLE")
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import NamedTuple
|
|
4
|
+
|
|
5
|
+
import psycopg
|
|
6
|
+
from psycopg import _cmodule
|
|
7
|
+
from psycopg.abc import Loader
|
|
8
|
+
|
|
9
|
+
__all__ = ["CompiledLoaders", "compiled_loaders"]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class CompiledLoaders(NamedTuple):
|
|
13
|
+
"""The text loaders the adapter registers on every connection."""
|
|
14
|
+
|
|
15
|
+
float4: type[Loader]
|
|
16
|
+
timestamptz: type[Loader]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def compiled_loaders(implementation: str) -> CompiledLoaders:
|
|
20
|
+
"""The compiled loaders built for psycopg's ``implementation``, or an ``ImportError``.
|
|
21
|
+
|
|
22
|
+
psycopg's C Transformer calls a loader's decoding directly only when the
|
|
23
|
+
loader extends the C loader base of the build it runs, and calls anything
|
|
24
|
+
else through Python per cell. The loaders are compiled once against each
|
|
25
|
+
build, so the variant is chosen by the implementation psycopg selected, and
|
|
26
|
+
only that variant is imported: the other build need not be installed.
|
|
27
|
+
|
|
28
|
+
Nothing slower stands in for a refusal. The pure-Python implementation, a
|
|
29
|
+
variant that cannot be loaded, and a variant that does not extend the base
|
|
30
|
+
it was compiled against as that base is actually laid out are all refused,
|
|
31
|
+
since each would decode correctly at a cost nobody asked for, or not at all.
|
|
32
|
+
"""
|
|
33
|
+
if implementation not in ("binary", "c"):
|
|
34
|
+
raise ImportError(
|
|
35
|
+
f"psycopg is running its {implementation!r} implementation, which decodes every "
|
|
36
|
+
f"cell through Python; parallax-postgres decodes with compiled loaders that only "
|
|
37
|
+
f"psycopg's 'binary' or 'c' implementation can run, so install psycopg[binary] or "
|
|
38
|
+
f"psycopg[c] and leave PSYCOPG_IMPL unset or naming one of them"
|
|
39
|
+
)
|
|
40
|
+
try:
|
|
41
|
+
loaders = _variant(implementation)
|
|
42
|
+
except Exception as exc:
|
|
43
|
+
raise ImportError(
|
|
44
|
+
f"parallax-postgres could not load its compiled loaders for psycopg's "
|
|
45
|
+
f"{implementation!r} implementation; reinstall parallax-postgres for this "
|
|
46
|
+
f"interpreter and platform"
|
|
47
|
+
) from exc
|
|
48
|
+
base: type = _cmodule._psycopg.CLoader # pyright: ignore[reportPrivateUsage] - the base the Transformer checks loaders against
|
|
49
|
+
# The Float32 loader adds no field of its own, so its size is the base's
|
|
50
|
+
# size as it was declared when the variant was compiled.
|
|
51
|
+
if not all(issubclass(loader, base) for loader in loaders) or (
|
|
52
|
+
loaders.float4.__basicsize__ != base.__basicsize__
|
|
53
|
+
):
|
|
54
|
+
raise ImportError(
|
|
55
|
+
f"parallax-postgres's compiled loaders for psycopg's {implementation!r} "
|
|
56
|
+
f"implementation do not match the C loader layout of the installed psycopg "
|
|
57
|
+
f"{psycopg.__version__}; install the psycopg release parallax-postgres declares"
|
|
58
|
+
)
|
|
59
|
+
return loaders
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _variant(implementation: str) -> CompiledLoaders:
|
|
63
|
+
if implementation == "binary":
|
|
64
|
+
from parallax.postgres import _cloaders_binary as variant
|
|
65
|
+
else:
|
|
66
|
+
from parallax.postgres import _cloaders_c as variant
|
|
67
|
+
return CompiledLoaders(variant.ExactFloat4Loader, variant.InfinityTimestamptzLoader)
|