TypeDAL 2.3.1__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 CHANGED
@@ -5,4 +5,4 @@ This file contains the Version info for this package.
5
5
  # SPDX-FileCopyrightText: 2023-present Robin van der Noord <robinvandernoord@gmail.com>
6
6
  #
7
7
  # SPDX-License-Identifier: MIT
8
- __version__ = "2.3.1"
8
+ __version__ = "2.3.2"
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,
@@ -1497,7 +1498,7 @@ class TypedTable(metaclass=TableMeta):
1497
1498
  return typing.cast(dict[str, Any], result)
1498
1499
 
1499
1500
  @classmethod
1500
- def as_json(cls, sanitize: bool = True) -> str:
1501
+ def as_json(cls, sanitize: bool = True, indent: Optional[int] = None, **kwargs: Any) -> str:
1501
1502
  """
1502
1503
  Dump the object to json.
1503
1504
 
@@ -1505,8 +1506,8 @@ class TypedTable(metaclass=TableMeta):
1505
1506
  - dumps the table info if it's a class
1506
1507
  - dumps the row info if it's an instance (see _as_json)
1507
1508
  """
1508
- table = cls._ensure_table_defined()
1509
- return typing.cast(str, table.as_json(sanitize))
1509
+ data = cls.as_dict(sanitize=sanitize)
1510
+ return as_json.encode(data, indent=indent, **kwargs)
1510
1511
 
1511
1512
  @classmethod
1512
1513
  def as_xml(cls, sanitize: bool = True) -> str: # pragma: no cover
@@ -1536,15 +1537,25 @@ class TypedTable(metaclass=TableMeta):
1536
1537
  self, datetime_to_str: bool = False, custom_types: typing.Iterable[type] | type | None = None
1537
1538
  ) -> dict[str, Any]:
1538
1539
  row = self._ensure_matching_row()
1540
+
1539
1541
  result = row.as_dict(datetime_to_str=datetime_to_str, custom_types=custom_types)
1540
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
+
1541
1551
  if _with := getattr(self, "_with", None):
1542
1552
  for relationship in _with:
1543
1553
  data = self.get(relationship)
1554
+
1544
1555
  if isinstance(data, list):
1545
- data = [_.as_dict() if getattr(_, "as_dict", None) else _ for _ in data]
1556
+ data = [asdict_method(_) for _ in data]
1546
1557
  elif data:
1547
- data = data.as_dict()
1558
+ data = asdict_method(data)
1548
1559
 
1549
1560
  result[relationship] = data
1550
1561
 
@@ -1552,14 +1563,12 @@ class TypedTable(metaclass=TableMeta):
1552
1563
 
1553
1564
  def _as_json(
1554
1565
  self,
1555
- mode: str = "object",
1556
1566
  default: typing.Callable[[Any], Any] = None,
1557
- colnames: list[str] = None,
1558
- serialize: bool = True,
1567
+ indent: Optional[int] = None,
1559
1568
  **kwargs: Any,
1560
1569
  ) -> str:
1561
- row = self._ensure_matching_row()
1562
- return typing.cast(str, row.as_json(mode, default, colnames, serialize, *kwargs))
1570
+ data = self._as_dict()
1571
+ return as_json.encode(data, default=default, indent=indent, **kwargs)
1563
1572
 
1564
1573
  def _as_xml(self, sanitize: bool = True) -> str: # pragma: no cover
1565
1574
  row = self._ensure_matching_row()
@@ -1637,14 +1646,6 @@ class TypedTable(metaclass=TableMeta):
1637
1646
  # __del__ is also called on the end of a scope so don't remove records on every del!!
1638
1647
 
1639
1648
  # pickling:
1640
- def __setstate__(self, state: dict[str, Any]) -> None:
1641
- """
1642
- Used by dill when loading from a bytestring.
1643
- """
1644
- # as_dict also includes table info, so dump as json to only get the actual row data
1645
- # then create a new (more empty) row object:
1646
- state["_row"] = Row(json.loads(state["_row"]))
1647
- self.__dict__ |= state
1648
1649
 
1649
1650
  def __getstate__(self) -> dict[str, Any]:
1650
1651
  """
@@ -1657,6 +1658,7 @@ class TypedTable(metaclass=TableMeta):
1657
1658
  result: dict[str, Any] = row.as_dict()
1658
1659
 
1659
1660
  if _with := getattr(self, "_with", None):
1661
+ result["_with"] = _with
1660
1662
  for relationship in _with:
1661
1663
  data = self.get(relationship)
1662
1664
 
@@ -1665,6 +1667,15 @@ class TypedTable(metaclass=TableMeta):
1665
1667
  result["_row"] = self._row.as_json() if self._row else ""
1666
1668
  return result
1667
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
+
1668
1679
 
1669
1680
  # backwards compat:
1670
1681
  TypedRow = TypedTable
@@ -1864,17 +1875,19 @@ class TypedRows(typing.Collection[T_MetaInstance], Rows):
1864
1875
 
1865
1876
  return {k: v.as_dict() for k, v in self.records.items()}
1866
1877
 
1867
- def as_json(self, mode: str = "object", default: typing.Callable[[Any], Any] = None) -> str:
1878
+ def as_json(self, default: typing.Callable[[Any], Any] = None, indent: Optional[int] = None, **kwargs: Any) -> str:
1868
1879
  """
1869
1880
  Turn the data into a dict and then dump to JSON.
1870
1881
  """
1871
- return typing.cast(str, super().as_json(mode=mode, default=default))
1882
+ data = self.as_list()
1883
+
1884
+ return as_json.encode(data, default=default, indent=indent, **kwargs)
1872
1885
 
1873
- def json(self, mode: str = "object", default: typing.Callable[[Any], Any] = None) -> str:
1886
+ def json(self, default: typing.Callable[[Any], Any] = None, indent: Optional[int] = None, **kwargs: Any) -> str:
1874
1887
  """
1875
1888
  Turn the data into a dict and then dump to JSON.
1876
1889
  """
1877
- return typing.cast(str, super().as_json(mode=mode, default=default))
1890
+ return self.as_json(default=default, indent=indent, **kwargs)
1878
1891
 
1879
1892
  def as_list(
1880
1893
  self,
@@ -1890,6 +1903,7 @@ class TypedRows(typing.Collection[T_MetaInstance], Rows):
1890
1903
  return typing.cast(
1891
1904
  list[dict[str, Any]], super().as_list(compact, storage_to_dict, datetime_to_str, custom_types)
1892
1905
  )
1906
+
1893
1907
  return [_.as_dict() for _ in self.records.values()]
1894
1908
 
1895
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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: TypeDAL
3
- Version: 2.3.1
3
+ Version: 2.3.2
4
4
  Summary: Typing support for PyDAL
5
5
  Project-URL: Documentation, https://typedal.readthedocs.io/
6
6
  Project-URL: Issues, https://github.com/trialandsuccess/TypeDAL/issues
@@ -1,15 +1,16 @@
1
- typedal/__about__.py,sha256=zwx64BodMOAs5q_ozAOIpvLt0qmwbc3erHMOeipjJPY,206
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=DZaGzzwY4_2SbLuAmpF5rnyP-3QRFSul7x69WHIIKCQ,94991
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-2.3.1.dist-info/METADATA,sha256=9fKhoB54Od1csvrgYp_HzucWAC5Z_pB0QdR0Wbq6Yhk,7623
13
- typedal-2.3.1.dist-info/WHEEL,sha256=KGYbc1zXlYddvwxnNty23BeaKzh7YuoSIvIMO4jEhvw,87
14
- typedal-2.3.1.dist-info/entry_points.txt,sha256=m1wqcc_10rHWPdlQ71zEkmJDADUAnZtn7Jac_6mbyUc,44
15
- typedal-2.3.1.dist-info/RECORD,,
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,,