-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpyproject.toml
More file actions
141 lines (127 loc) · 5.7 KB
/
Copy pathpyproject.toml
File metadata and controls
141 lines (127 loc) · 5.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
[build-system]
requires = ["hatchling>=1.26"]
build-backend = "hatchling.build"
[project]
name = "sqlalchemy-dqlite"
version = "0.4.0"
description = "SQLAlchemy 2.0 dialect for dqlite distributed SQLite"
readme = "README.md"
requires-python = ">=3.13"
license = "MIT"
authors = [{ name = "Antoine Leclair", email = "antoineleclair@gmail.com" }]
keywords = ["dqlite", "sqlite", "distributed", "database", "sqlalchemy", "orm"]
classifiers = [
"Development Status :: 3 - Alpha",
"Framework :: AsyncIO",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Topic :: Database",
"Topic :: Database :: Database Engines/Servers",
"Topic :: Database :: Front-Ends",
"Typing :: Typed",
]
dependencies = [
"dqlite-dbapi>=0.4.0,<0.5.0",
# The SA dialect imports dqliteclient and dqlitewire directly
# (base.py / aio.py reach into client exception classes for
# is_disconnect, and into dqlitewire for shared helpers). Pin
# both transitively so a future major-version bump in either
# package surfaces at install time, not at module-import time
# in user code.
"dqlite-client>=0.4.0,<0.5.0",
"dqlite-wire>=0.4.0,<0.5.0",
"sqlalchemy>=2.0,<3.0",
]
[tool.uv.sources]
dqlite-dbapi = { path = "../python-dqlite-dbapi", editable = true }
dqlite-client = { path = "../python-dqlite-client", editable = true }
dqlite-wire = { path = "../python-dqlite-wire", editable = true }
[project.urls]
Homepage = "https://github.com/letsdiscodev/sqlalchemy-dqlite"
Repository = "https://github.com/letsdiscodev/sqlalchemy-dqlite"
Issues = "https://github.com/letsdiscodev/sqlalchemy-dqlite/issues"
[project.optional-dependencies]
dev = ["pytest>=8.0", "pytest-cov>=4.0", "pytest-asyncio>=0.23", "mypy>=1.0", "ruff>=0.4"]
[project.entry-points."sqlalchemy.dialects"]
# Bare ``dqlite`` is the URL-default; ``dqlite.dqlitedbapi`` is the
# explicit driver-suffix form (URL ``dqlite+dqlitedbapi://``). Both
# resolve to the same class, mirroring how ``sqlite+pysqlite://`` and
# bare ``sqlite://`` both reach ``SQLiteDialect_pysqlite`` in SA's
# built-in dispatch (see ``sqlalchemy/dialects/__init__.py:_auto_fn``).
# We have to register the explicit form because we are external to SA;
# its built-ins are auto-routed by name-splitting, ours are not.
dqlite = "sqlalchemydqlite:DqliteDialect"
"dqlite.dqlitedbapi" = "sqlalchemydqlite:DqliteDialect"
"dqlite.aio" = "sqlalchemydqlite.aio:DqliteDialect_aio"
[tool.hatch.build.targets.wheel]
packages = ["src/sqlalchemydqlite"]
# Hatchling's default file-selection would already ship ``py.typed`` via
# ``packages``, but declaring it explicitly is the documented PEP 561
# pattern and makes the intent obvious to anyone auditing the wheel.
[tool.hatch.build.targets.wheel.force-include]
"src/sqlalchemydqlite/py.typed" = "sqlalchemydqlite/py.typed"
[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["src"]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
# Exclude the SA compliance suite from the default pytest run.
# tests/compliance/ loads SA's pytest plugin via its conftest, which
# replaces pytest's normal collection model and requires CLI options
# (--dburi etc.) the project-wide test runner does not pass. Run the
# suite explicitly with ``pytest tests/compliance/``.
addopts = ["--ignore=tests/compliance"]
filterwarnings = [
# Promote deprecations to errors so the suite catches stdlib
# deprecation surface under the CPython version the workspace
# already runs CI on (3.13/3.14). Whitelist genuine third-party
# noise with explicit ``ignore:<pattern>:DeprecationWarning:<module>``
# entries below, with a comment explaining the upstream tracker.
"error::DeprecationWarning",
"error::PendingDeprecationWarning",
]
[tool.mypy]
strict = true
python_version = "3.13"
# Tests live under ``tests/`` with no ``__init__.py``; mypy needs
# ``explicit_package_bases`` (or namespace packages) to avoid the
# duplicate-conftest module-name collision when scanning sibling
# integration/ subdirectories. ``mypy_path`` mirrors the
# ``pythonpath = ["src"]`` declared for pytest so the source files
# resolve under the package name (``sqlalchemydqlite``), not the
# layout path (``src.sqlalchemydqlite``).
explicit_package_bases = true
mypy_path = "src"
# Tests use a few patterns that mypy's strict mode flags but are
# correct at runtime. Disabling these codes only inside ``tests.*``
# keeps strict typing on production code while letting the test suite
# use idiomatic patterns without per-line ``# type: ignore`` noise:
#
# * ``method-assign`` — monkey-patching bound methods
# (``conn.execute = fake_execute``) is the standard way to inject a
# fake without subclassing.
# * ``no-untyped-def`` / ``no-untyped-call`` — pytest fixtures and
# small helpers are conventionally written without type annotations.
# * ``comparison-overlap`` — ``assert SomeIntEnum.FOO == 0`` is the
# canonical "this enum matches its int value" pin against a
# reference table; mypy's literal-type narrowing incorrectly flags
# it as non-overlapping even though IntEnum's ``__eq__`` works.
[[tool.mypy.overrides]]
module = "tests.*"
disable_error_code = ["method-assign", "no-untyped-def", "no-untyped-call", "comparison-overlap"]
[tool.ruff]
target-version = "py313"
line-length = 100
src = ["src", "tests"]
[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B", "SIM"]
[tool.ruff.lint.isort]
known-first-party = ["sqlalchemydqlite", "dqlitedbapi", "dqliteclient", "dqlitewire"]
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
docstring-code-format = true