Skip to content

Commit

Permalink
fix(query): A class with postponed db.define could not be used to mak…
Browse files Browse the repository at this point in the history
…e queries
  • Loading branch information
robinvandernoord committed Jun 27, 2023
1 parent 03f5f85 commit 2e55363
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 5 deletions.
37 changes: 32 additions & 5 deletions src/typedal/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,22 +125,28 @@ class Article(TypedTable):
# remove internal stuff:
annotations = {k: v for k, v in annotations.items() if not k.startswith("_")}

fields = [self._to_field(fname, ftype) for fname, ftype in annotations.items()]
typedfields = {k: v for k, v in annotations.items() if isinstance(v, TypedFieldType)}

fields = {fname: self._to_field(fname, ftype) for fname, ftype in annotations.items()}
other_kwargs = {k: v for k, v in cls.__dict__.items() if k not in annotations and not k.startswith("_")}

table: Table = self.define_table(tablename, *fields, **other_kwargs)
table: Table = self.define_table(tablename, *fields.values(), **other_kwargs)

for name, typed_field in typedfields.items():
field = fields[name]
typed_field.bind(field, table)

cls.__set_internals__(db=self, table=table)

# the ACTUAL output is not TypedTable but rather pydal.Table
# but telling the editor it is T helps with hinting.
return table

def __call__(self, *_args: Query, **kwargs: typing.Any) -> pydal.objects.Set:
def __call__(self, *_args: Query | bool, **kwargs: typing.Any) -> pydal.objects.Set:
"""
A db instance can be called directly to perform a query.
Usually, only a query is passed
Usually, only a query is passed.
Example:
db(query).select()
Expand All @@ -149,6 +155,9 @@ def __call__(self, *_args: Query, **kwargs: typing.Any) -> pydal.objects.Set:
args = list(_args)
if args:
cls = args[0]
if isinstance(cls, bool):
raise ValueError("Don't actually pass a bool to db()! Use a query instead.")

if issubclass(type(cls), type) and issubclass(cls, TypedTable):
# table defined without @db.define decorator!
args[0] = cls.id != None
Expand Down Expand Up @@ -330,7 +339,14 @@ class TypedFieldType(Field): # type: ignore
Typed version of pydal.Field, which will be converted to a normal Field in the background.
"""

_table = "<any table>"
# todo: .bind

# will be set by .bind on db.define
name = ""
_db = None
_rname = None
_table = None

_type: T_annotation
kwargs: typing.Any

Expand Down Expand Up @@ -381,6 +397,17 @@ def _to_field(self, extra_kwargs: typing.MutableMapping[str, typing.Any]) -> typ
extra_kwargs.update(other_kwargs)
return extra_kwargs.pop("type", False) or TypeDAL._annotation_to_pydal_fieldtype(self._type, extra_kwargs)

def bind(self, field: Field, table: Table) -> None:
"""
Bind the right db/table/field info to this class, so queries can be made using `Class.field == ...`.
"""
self.name = field.name
self.type = field.type
super().bind(table)

# def __eq__(self, value):
# return Query(self.db, self._dialect.eq, self, value)


S = typing.TypeVar("S")

Expand Down
15 changes: 15 additions & 0 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@ class SecondNewSyntax(TypedTable):
### Select
from pprint import pprint

assert db(FirstNewSyntax.name == "First").count()
assert db(FirstNewSyntax.location == "Norway").count()
assert not db(FirstNewSyntax.location == "Nope").count()
assert not db(FirstNewSyntax.location == "Nope").count()

assert db(SecondNewSyntax.name == "Second").count()
assert db(SecondNewSyntax.location == "Rotterdam").count()
assert not db(SecondNewSyntax.location == "Nope").count()
assert not db(SecondNewSyntax.location == "Nope").count()

def _print_and_assert_len(lst, exp):
pprint(lst)
real = len(lst)
Expand All @@ -151,6 +161,11 @@ def _print_and_assert_len(lst, exp):
assert SecondNewSyntax(1).location == "Rotterdam"


def test_dont_allow_bool_in_query():
with pytest.raises(ValueError):
db(True)


def test_invalid_union():
with pytest.raises(NotImplementedError):
@db.define
Expand Down

0 comments on commit 2e55363

Please sign in to comment.