TypeDAL 2.3.0__py3-none-any.whl → 2.3.2__py3-none-any.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.
Potentially problematic release.
This version of TypeDAL might be problematic. Click here for more details.
- typedal/__about__.py +1 -1
- typedal/core.py +41 -25
- typedal/serializers/as_json.py +42 -0
- {typedal-2.3.0.dist-info → typedal-2.3.2.dist-info}/METADATA +1 -1
- {typedal-2.3.0.dist-info → typedal-2.3.2.dist-info}/RECORD +7 -6
- {typedal-2.3.0.dist-info → typedal-2.3.2.dist-info}/WHEEL +0 -0
- {typedal-2.3.0.dist-info → typedal-2.3.2.dist-info}/entry_points.txt +0 -0
typedal/__about__.py
CHANGED
typedal/core.py
CHANGED
|
@@ -39,6 +39,7 @@ from .helpers import (
|
|
|
39
39
|
to_snake,
|
|
40
40
|
unwrap_type,
|
|
41
41
|
)
|
|
42
|
+
from .serializers import as_json
|
|
42
43
|
from .types import (
|
|
43
44
|
AfterDeleteCallable,
|
|
44
45
|
AfterInsertCallable,
|
|
@@ -485,7 +486,9 @@ class TypeDAL(pydal.DAL): # type: ignore
|
|
|
485
486
|
# ! dont' use full_dict here:
|
|
486
487
|
other_kwargs = kwargs | {
|
|
487
488
|
k: v for k, v in cls.__dict__.items() if k not in annotations and not k.startswith("_")
|
|
488
|
-
}
|
|
489
|
+
} # other_kwargs was previously used to pass kwargs to typedal, but use @define(**kwargs) for that.
|
|
490
|
+
# now it's only used to extract relationships from the object.
|
|
491
|
+
# other properties of the class (incl methods) should not be touched
|
|
489
492
|
|
|
490
493
|
for key in typedfields.keys() - full_dict.keys():
|
|
491
494
|
# typed fields that don't haven't been added to the object yet
|
|
@@ -512,9 +515,9 @@ class TypeDAL(pydal.DAL): # type: ignore
|
|
|
512
515
|
if k not in relationships and (new_relationship := to_relationship(cls, k, annotations[k]))
|
|
513
516
|
}
|
|
514
517
|
|
|
515
|
-
cache_dependency =
|
|
518
|
+
cache_dependency = kwargs.pop("cache_dependency", True)
|
|
516
519
|
|
|
517
|
-
table: Table = self.define_table(tablename, *fields.values(), **
|
|
520
|
+
table: Table = self.define_table(tablename, *fields.values(), **kwargs)
|
|
518
521
|
|
|
519
522
|
for name, typed_field in typedfields.items():
|
|
520
523
|
field = fields[name]
|
|
@@ -1495,7 +1498,7 @@ class TypedTable(metaclass=TableMeta):
|
|
|
1495
1498
|
return typing.cast(dict[str, Any], result)
|
|
1496
1499
|
|
|
1497
1500
|
@classmethod
|
|
1498
|
-
def as_json(cls, sanitize: bool = True) -> str:
|
|
1501
|
+
def as_json(cls, sanitize: bool = True, indent: Optional[int] = None, **kwargs: Any) -> str:
|
|
1499
1502
|
"""
|
|
1500
1503
|
Dump the object to json.
|
|
1501
1504
|
|
|
@@ -1503,8 +1506,8 @@ class TypedTable(metaclass=TableMeta):
|
|
|
1503
1506
|
- dumps the table info if it's a class
|
|
1504
1507
|
- dumps the row info if it's an instance (see _as_json)
|
|
1505
1508
|
"""
|
|
1506
|
-
|
|
1507
|
-
return
|
|
1509
|
+
data = cls.as_dict(sanitize=sanitize)
|
|
1510
|
+
return as_json.encode(data, indent=indent, **kwargs)
|
|
1508
1511
|
|
|
1509
1512
|
@classmethod
|
|
1510
1513
|
def as_xml(cls, sanitize: bool = True) -> str: # pragma: no cover
|
|
@@ -1534,15 +1537,25 @@ class TypedTable(metaclass=TableMeta):
|
|
|
1534
1537
|
self, datetime_to_str: bool = False, custom_types: typing.Iterable[type] | type | None = None
|
|
1535
1538
|
) -> dict[str, Any]:
|
|
1536
1539
|
row = self._ensure_matching_row()
|
|
1540
|
+
|
|
1537
1541
|
result = row.as_dict(datetime_to_str=datetime_to_str, custom_types=custom_types)
|
|
1538
1542
|
|
|
1543
|
+
def asdict_method(obj: Any) -> Any: # pragma: no cover
|
|
1544
|
+
if hasattr(obj, "_as_dict"): # typedal
|
|
1545
|
+
return obj._as_dict()
|
|
1546
|
+
elif hasattr(obj, "as_dict"): # pydal
|
|
1547
|
+
return obj.as_dict()
|
|
1548
|
+
else: # something else??
|
|
1549
|
+
return obj.__dict__
|
|
1550
|
+
|
|
1539
1551
|
if _with := getattr(self, "_with", None):
|
|
1540
1552
|
for relationship in _with:
|
|
1541
1553
|
data = self.get(relationship)
|
|
1554
|
+
|
|
1542
1555
|
if isinstance(data, list):
|
|
1543
|
-
data = [
|
|
1556
|
+
data = [asdict_method(_) for _ in data]
|
|
1544
1557
|
elif data:
|
|
1545
|
-
data = data
|
|
1558
|
+
data = asdict_method(data)
|
|
1546
1559
|
|
|
1547
1560
|
result[relationship] = data
|
|
1548
1561
|
|
|
@@ -1550,14 +1563,12 @@ class TypedTable(metaclass=TableMeta):
|
|
|
1550
1563
|
|
|
1551
1564
|
def _as_json(
|
|
1552
1565
|
self,
|
|
1553
|
-
mode: str = "object",
|
|
1554
1566
|
default: typing.Callable[[Any], Any] = None,
|
|
1555
|
-
|
|
1556
|
-
serialize: bool = True,
|
|
1567
|
+
indent: Optional[int] = None,
|
|
1557
1568
|
**kwargs: Any,
|
|
1558
1569
|
) -> str:
|
|
1559
|
-
|
|
1560
|
-
return
|
|
1570
|
+
data = self._as_dict()
|
|
1571
|
+
return as_json.encode(data, default=default, indent=indent, **kwargs)
|
|
1561
1572
|
|
|
1562
1573
|
def _as_xml(self, sanitize: bool = True) -> str: # pragma: no cover
|
|
1563
1574
|
row = self._ensure_matching_row()
|
|
@@ -1635,14 +1646,6 @@ class TypedTable(metaclass=TableMeta):
|
|
|
1635
1646
|
# __del__ is also called on the end of a scope so don't remove records on every del!!
|
|
1636
1647
|
|
|
1637
1648
|
# pickling:
|
|
1638
|
-
def __setstate__(self, state: dict[str, Any]) -> None:
|
|
1639
|
-
"""
|
|
1640
|
-
Used by dill when loading from a bytestring.
|
|
1641
|
-
"""
|
|
1642
|
-
# as_dict also includes table info, so dump as json to only get the actual row data
|
|
1643
|
-
# then create a new (more empty) row object:
|
|
1644
|
-
state["_row"] = Row(json.loads(state["_row"]))
|
|
1645
|
-
self.__dict__ |= state
|
|
1646
1649
|
|
|
1647
1650
|
def __getstate__(self) -> dict[str, Any]:
|
|
1648
1651
|
"""
|
|
@@ -1655,6 +1658,7 @@ class TypedTable(metaclass=TableMeta):
|
|
|
1655
1658
|
result: dict[str, Any] = row.as_dict()
|
|
1656
1659
|
|
|
1657
1660
|
if _with := getattr(self, "_with", None):
|
|
1661
|
+
result["_with"] = _with
|
|
1658
1662
|
for relationship in _with:
|
|
1659
1663
|
data = self.get(relationship)
|
|
1660
1664
|
|
|
@@ -1663,6 +1667,15 @@ class TypedTable(metaclass=TableMeta):
|
|
|
1663
1667
|
result["_row"] = self._row.as_json() if self._row else ""
|
|
1664
1668
|
return result
|
|
1665
1669
|
|
|
1670
|
+
def __setstate__(self, state: dict[str, Any]) -> None:
|
|
1671
|
+
"""
|
|
1672
|
+
Used by dill when loading from a bytestring.
|
|
1673
|
+
"""
|
|
1674
|
+
# as_dict also includes table info, so dump as json to only get the actual row data
|
|
1675
|
+
# then create a new (more empty) row object:
|
|
1676
|
+
state["_row"] = Row(json.loads(state["_row"]))
|
|
1677
|
+
self.__dict__ |= state
|
|
1678
|
+
|
|
1666
1679
|
|
|
1667
1680
|
# backwards compat:
|
|
1668
1681
|
TypedRow = TypedTable
|
|
@@ -1862,17 +1875,19 @@ class TypedRows(typing.Collection[T_MetaInstance], Rows):
|
|
|
1862
1875
|
|
|
1863
1876
|
return {k: v.as_dict() for k, v in self.records.items()}
|
|
1864
1877
|
|
|
1865
|
-
def as_json(self,
|
|
1878
|
+
def as_json(self, default: typing.Callable[[Any], Any] = None, indent: Optional[int] = None, **kwargs: Any) -> str:
|
|
1866
1879
|
"""
|
|
1867
1880
|
Turn the data into a dict and then dump to JSON.
|
|
1868
1881
|
"""
|
|
1869
|
-
|
|
1882
|
+
data = self.as_list()
|
|
1883
|
+
|
|
1884
|
+
return as_json.encode(data, default=default, indent=indent, **kwargs)
|
|
1870
1885
|
|
|
1871
|
-
def json(self,
|
|
1886
|
+
def json(self, default: typing.Callable[[Any], Any] = None, indent: Optional[int] = None, **kwargs: Any) -> str:
|
|
1872
1887
|
"""
|
|
1873
1888
|
Turn the data into a dict and then dump to JSON.
|
|
1874
1889
|
"""
|
|
1875
|
-
return
|
|
1890
|
+
return self.as_json(default=default, indent=indent, **kwargs)
|
|
1876
1891
|
|
|
1877
1892
|
def as_list(
|
|
1878
1893
|
self,
|
|
@@ -1888,6 +1903,7 @@ class TypedRows(typing.Collection[T_MetaInstance], Rows):
|
|
|
1888
1903
|
return typing.cast(
|
|
1889
1904
|
list[dict[str, Any]], super().as_list(compact, storage_to_dict, datetime_to_str, custom_types)
|
|
1890
1905
|
)
|
|
1906
|
+
|
|
1891
1907
|
return [_.as_dict() for _ in self.records.values()]
|
|
1892
1908
|
|
|
1893
1909
|
def __getitem__(self, item: int) -> T_MetaInstance:
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Replacement for pydal's json serializer.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import datetime as dt
|
|
6
|
+
import json
|
|
7
|
+
from json import JSONEncoder
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SerializedJson(JSONEncoder):
|
|
12
|
+
"""
|
|
13
|
+
Custom encoder class with slightly improved defaults.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def default(self, o: Any) -> Any:
|
|
17
|
+
"""
|
|
18
|
+
If no logic exists for a type yet, it is processed by this method.
|
|
19
|
+
|
|
20
|
+
It supports sets (turned into list), __json__ methods and will just str() otherwise.
|
|
21
|
+
"""
|
|
22
|
+
if isinstance(o, set):
|
|
23
|
+
return list(o)
|
|
24
|
+
elif isinstance(o, dt.date):
|
|
25
|
+
return str(o)
|
|
26
|
+
elif hasattr(o, "__json__"):
|
|
27
|
+
if callable(o.__json__):
|
|
28
|
+
return o.__json__()
|
|
29
|
+
else:
|
|
30
|
+
return o.__json__
|
|
31
|
+
elif hasattr(o, "__dict__"):
|
|
32
|
+
return o.__dict__
|
|
33
|
+
else:
|
|
34
|
+
# warnings.warn(f"Unkown type {type(o)}")
|
|
35
|
+
return str(o)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def encode(something: Any, indent: int = None, **kw: Any) -> str:
|
|
39
|
+
"""
|
|
40
|
+
Encode anything to JSON with some improved defaults.
|
|
41
|
+
"""
|
|
42
|
+
return json.dumps(something, indent=indent, cls=SerializedJson, **kw)
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
typedal/__about__.py,sha256=
|
|
1
|
+
typedal/__about__.py,sha256=6-cBVRoxdWtgxVEjZ7nYfLXipTL1o9Jjywbqts994pk,206
|
|
2
2
|
typedal/__init__.py,sha256=QQpLiVl9w9hm2LBxey49Y_tCF_VB2bScVaS_mCjYy54,366
|
|
3
3
|
typedal/caching.py,sha256=cglkCphbg93Iy9-KHefQN9-JJxuA5-HjpzZAdw2BGvY,7709
|
|
4
4
|
typedal/cli.py,sha256=F7M9D2pu2D-FoKZJrT3K9Wmbv5_ScUR8j5jNGoTgOfk,11800
|
|
5
5
|
typedal/config.py,sha256=oDYSuPMm261hBoDBAXoq37Umf1Vw8rNx4BlP35WwCSY,11882
|
|
6
|
-
typedal/core.py,sha256=
|
|
6
|
+
typedal/core.py,sha256=wARmyKpwm-3ZGrt2ZdOUfBqfqbrWf_DgqWmaqAdmIow,95392
|
|
7
7
|
typedal/fields.py,sha256=z2PD9vLWqBR_zXtiY0DthqTG4AeF3yxKoeuVfGXnSdg,5197
|
|
8
8
|
typedal/for_py4web.py,sha256=kw44_55-dBWlYmepB7YEev5sj7tbYcgzvp-Ecc7K9_I,2230
|
|
9
9
|
typedal/helpers.py,sha256=ZpHdwBMSANw-P9I5gs56Vf6GUbxGzFsIwbBvASKXX8s,6487
|
|
10
10
|
typedal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
typedal/types.py,sha256=5qm3PgS8DXGCu9ZTUWQiIi2XXD8gz4_4Csg_vZlu_yo,3379
|
|
12
|
-
typedal
|
|
13
|
-
typedal-2.3.
|
|
14
|
-
typedal-2.3.
|
|
15
|
-
typedal-2.3.
|
|
12
|
+
typedal/serializers/as_json.py,sha256=2sWSiU3yecPMhE-1jman227oLSfvSY-Iw-gbg3PnCKk,1138
|
|
13
|
+
typedal-2.3.2.dist-info/METADATA,sha256=uMe7GkSU2AyP23eFObW278v5dUdN4yit7fsi-nvhu9w,7623
|
|
14
|
+
typedal-2.3.2.dist-info/WHEEL,sha256=KGYbc1zXlYddvwxnNty23BeaKzh7YuoSIvIMO4jEhvw,87
|
|
15
|
+
typedal-2.3.2.dist-info/entry_points.txt,sha256=m1wqcc_10rHWPdlQ71zEkmJDADUAnZtn7Jac_6mbyUc,44
|
|
16
|
+
typedal-2.3.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|