Typing support for PyDAL
Project description
TypeDAL
Typing support for PyDAL.
This package aims to improve the typing support for PyDAL. By using classes instead of the define_table method,
type hinting the result of queries can improve the experience while developing. In the background, the queries are still
generated and executed by pydal itself, this package only proves some logic to properly pass calls from class methods to
the underlying db.define_table
pydal Tables.
TypeDAL
is the replacement class for DAL that manages the code on top of DAL.TypedTable
must be the parent class of any custom Tables you define (e.g.class SomeTable(TypedTable)
)TypedField
can be used instead of Python native types when extra settings (such as default) are required ( e.g.name: TypedField(str, default="John Doe")
)TypedRows
: can be used as the return type of .select() and subscribed with the actual table class, so e.g.rows: TypedRows[SomeTable]
. If you're lazy,list[SomeTable]
works fine too but that misses hinting possibilities such as.first()
.
Translations from pydal to typedal
Description | pydal | pydal alternative | typedal | typedal alternative(s) | ... |
Setup |
from pydal import DAL, Field
db = DAL(...)
|
from typedal import TypeDAL, TypedTable, TypedField, TypedRows
from typedal.fields import TextField
from typing import Optional
db = TypeDAL(...)
|
|||
Table Definitions |
db.define_table("table_name",
Field("fieldname", "string", required=True),
Field("otherfield", "float"),
Field("yet_another", "text", default="Something")
)
|
@db.define
class TableName(TypedTable):
fieldname: str
otherfield: float | None
yet_another: TypedField(str, type="text", default="something", required=False)
|
import typing
class TableName(TypedTable):
fieldname: str
otherfield: typing.Optional[float]
yet_another: TextField(default="something", required=False)
db.define(TableName)
|
||
Insert |
db.table_name.insert(fieldname="value")
|
db.table_name.insert(fieldname="value")
|
TableName.insert(fieldname="value")
|
||
(quick) Select |
rows = db(db.table_name).select() # -> Any (Rows)
row = db.table_name(id=1) # -> Any (Row)
|
rows: TypedRows[TableName] = db(db.table_name).select() # -> TypedRows[TableName]
row: TableName = db.table_name(id=1) # -> TableName
|
rows: TypedRows[TableName] = db(TableName).select() # -> TypedRows[TableName]
row = TableName(id=1) # -> TableName
|
All Types
pydal | typedal (native python type) | typedal (using TypedField) | typedal (using specific Field) |
---|---|---|---|
Field('name', 'string') |
name: str |
name: TypedField(str) |
name: StringField() |
Field('name', 'text') |
× | name: TypedField(str, type="text") |
name: TextField() |
Field('name', 'blob') |
name: bytes |
name: TypedField(bytes) |
name: BlobField() |
Field('name', 'boolean') |
name: bool |
name: TypedField(bool) |
name: BooleanField() |
Field('name', 'integer') |
name: int |
name: TypedField(int) |
name: IntegerField() |
Field('name', 'double') |
name: float |
name: TypedField(float) |
name: DoubleField() |
Field('name', 'decimal(n,m)') |
name: decimal.Decimal |
name: TypedField(decimal.Decimal) |
name: DecimalField(n=n, m=m) |
Field('name', 'date') |
name: datetime.date |
name: TypedField(datetime.date) |
name: DateField() |
Field('name', 'time') |
name: datetime.time |
name: TypedField(datetime.time) |
name: TimeField() |
Field('name', 'datetime') |
name: datetime.datetime |
name: TypedField(datetime.datetime) |
name: DatetimeField() |
Field('name', 'password') |
× | name: TypedField(str, type="password") |
name: PasswordField() |
Field('name', 'upload') |
× | name: TypedField(str, type="upload) |
name: UploadField() |
Field('name', 'reference <table>') |
name: Table |
name: TypedField(Table) |
name: ReferenceField('table') |
Field('name', 'list:string') |
name: list[str] |
name: TypedField(list[str]) |
name: ListStringField() |
Field('name', 'list:integer') |
name: list[int] |
name: TypedField() |
name: ListIntegerField() |
Field('name', 'list:reference <table>') |
name: list[Table] |
name: TypedField() |
name: ListReferenceField('table') |
Field('name', 'json') |
× | name: TypedField() |
name: JSONField() |
Field('name', 'bigint') |
× | name: TypedField() |
name: BigintField() |
Field('name', 'big-id') |
× | × | × |
Field('name', 'big-reference') |
× | × | × |
Making a field required/optional
pydal | typedal (native python type) | typedal (using TypedField) | typedal (using specific Field) |
---|---|---|---|
Field('name', 'string', required=True) |
name: str |
name: TypedField(str, required=True) |
name: StringField(required=True) |
Field('name', 'text', required=False) |
name: typing.Optional[str] or name: str | None |
name: TypedField(str, type="text", required=False) |
name: StringField(required=False) |
Caveats
- This package depends heavily on the current implementation of annotations (which are computed when the class is
defined). PEP 563 (Postponed Evaluation of Annotations, accepted) aims to change this behavior (
and
from __future__ import annotations
already does) in a way that this module currently can not handle: all annotations are converted to string representations. This makes it very hard to re-evaluate the annotation into the original type, since the variable scope is lost (and thus references to variables or other classes are ambiguous or simply impossible to find). TypedField
limitations; Since pydal implements some magic methods to perform queries, some features of typing will not work on a typed field:typing.Optional
or a union (Field() | None
) will result in errors. The only way to make a typedfield optional right now, would be to setrequired=False
as an argument yourself. This is also a reason whytyping.get_type_hints
is not a solution for the first caveat.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
TypeDal-0.6.1.tar.gz
(7.0 kB
view details)
Built Distribution
File details
Details for the file TypeDal-0.6.1.tar.gz
.
File metadata
- Download URL: TypeDal-0.6.1.tar.gz
- Upload date:
- Size: 7.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.10.9
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 28237143ca299b752aad3ae6e38cabab7441dacde8fd945c0f6a6f027ce2505d |
|
MD5 | 05953727ac59440d75e3173a3bd506c3 |
|
BLAKE2b-256 | 60d8066645b4f10bd28846714733fc3d51b1596d16dd1884c92e23cbb453650f |
Provenance
File details
Details for the file TypeDal-0.6.1-py3-none-any.whl
.
File metadata
- Download URL: TypeDal-0.6.1-py3-none-any.whl
- Upload date:
- Size: 7.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.10.9
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 51366ae1ec96e50cc5d452f476bef73bd92c12ba2c48ddec5f0fc38a0ffe4f1f |
|
MD5 | d4bba812931a587dffda4f1754949db4 |
|
BLAKE2b-256 | fff1b8d742bc268a4189fc6a9a29cb136272e7e37d9c78ca894ba424aa184c4f |