pydal-stubs
PEP 561 type stubs for pyDAL.
pyDAL ships no py.typed marker, so type checkers treat everything it exports
as Any (mypy) or Unknown (Pyright). This package fills that gap without
touching pyDAL itself. One name stays deliberately untyped: DAL (see below).
Written against the pyDAL API as of 20251012.3, verified against 20260520.0.
Installation
pip install pydal-stubs
Nothing needs to be imported or configured; mypy and Pyright discover the
pydal-stubs directory automatically, per PEP 561. The stubs contain no
runtime code.
What you get
The full object model is typed: Table, Field, Query, Set, Rows, the
validators, and the helper classes. Table and Field attribute access keeps
its real types:
from pydal.objects import Field, Query, Table
def example(table: Table) -> None:
field: Field = table.some_field # Table.__getattr__ -> Field
same: Field = table["some_field"] # Table.__getitem__ -> Field
q: Query = table.name == "Ada" # comparisons build queries, not bools
Why DAL is Any
pydal.DAL is deliberately exported as a gradual Any alias rather than a
nominal class. Typing it as a class makes every third-party
Callable[[DAL], ...] annotation reject functions annotated with a DAL
subclass, because parameter positions are contravariant. Those annotations
were vacuous while pyDAL was untyped, so a nominal DAL would turn them into
hard errors across whole codebases with no fix available at either call site.
The real surface is pydal.base.DALBase; the public DAL keeps the gradual
behaviour callers already depend on. A consequence is that db.some_table on a
DAL-typed value is Any, not Table.
Frameworks that subclass pyDAL should use DALBase, so their subclass keeps the
whole typed API instead of inheriting from Any:
import typing as t
import pydal
if t.TYPE_CHECKING:
from pydal.base import DALBase as _PyDAL
else:
_PyDAL = pydal.DAL
class MyDAL(_PyDAL): ...
MyDAL().some_table is then a Table, .some_field a Field and
db(query).select() a Rows, while
Callable[[pydal.DAL], ...] elsewhere still accepts (db: MyDAL) -> ....
DALBase exists only for type checkers, which is why the import sits behind
TYPE_CHECKING.
Stubbed modules
| Module | Contents |
|---|---|
pydal |
DAL (gradual alias), Field, SQLCustomType, QueryBuilder, geo helpers, __version__ |
pydal.base |
DALBase (nominal surface), DAL (gradual alias), MetaDAL, ... |
pydal.objects |
Row, Table, Query, Set, Rows, Expression, Field, ... |
pydal.helpers.classes |
Reference, SQLALL, RecordOperator, DatabaseStoredFile, ... |
pydal.validators |
Validator, ValidationError, all IS_* validators, CRYPT, ... |
pydal._globals |
DEFAULT, IDENTITY, OR, AND, ... |
Intentional gaps
This is a partial stub package (py.typed contains partial), so the
runtime pydal package must be installed alongside it (hence the hard
dependency on pydal>=20251012.3).
- Unstubbed modules (
pydal.migrator,pydal.drivers,pydal.adapters.*,pydal.dialects.*, ...) fall back to pyDAL's own source. Subpackages without a stub directory still trigger mypy'simport-untypedor Pyright'sreportMissingTypeStubs; silence those per-module if you import them. - Typos are not caught:
Table.__getattr__returnsFieldfor any name, matching runtime behavior. OnDAL-typed values nothing is checked at all, sinceDALisAny(see above). Expression.__eq__returnsQuery, notbool, a deliberate violation of theobjectcontract that mirrors pyDAL.- Rows are not generic:
RowsyieldsRowandRowattribute access isAny. Per-table row types belong to an ORM layer such as TypeDAL. - Adapter internals (
_adapter, dialect/driver machinery) are typed asAny, and**kwargs-driven APIs acceptAny(pyDAL validates them at runtime). - Installing these stubs can surface new errors in code that relied on pyDAL
being untyped, e.g.
TYPE_CHECKING-only shims of pyDAL classes or container subclasses with Liskov-violating element types.
License
BSD 3-Clause, matching pyDAL. See LICENSE.
Release files for pydal-stubs 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pydal_stubs-0.2.0.tar.gz | 15.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pydal_stubs-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 34.2 kB
Release files / pydal_stubs-0.2.0.tar.gz
| Download URL | pydal_stubs-0.2.0.tar.gz |
|---|---|
| Size | 15.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
219742106a9847f1e604d096179722eec9dd73e6d613978b8eb195f5ed9d35aa
|
|
BLAKE2b-256 checksum How to use checksums |
d486d21d0be5bafbdacbe3302d48309c8ca3da18bf991c5b79b9463bca1f707a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.9 {"installer":{"name":"uv","version":"0.9.9"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"22.3","id":"zena","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / pydal_stubs-0.2.0-py3-none-any.whl
| Download URL | pydal_stubs-0.2.0-py3-none-any.whl |
|---|---|
| Size | 18.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5b1ba29598a0b92c6038e254932480193793eb0fd30678e43969c960c16eb3f0
|
|
BLAKE2b-256 checksum How to use checksums |
5b9ab4032e4fb1a715016d4ac9899eb74bc46234bd9f8d9b6cbd2733dbb204f0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.9 {"installer":{"name":"uv","version":"0.9.9"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"22.3","id":"zena","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|