exdrf 0.0.1.dev0__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.
Files changed (57) hide show
  1. exdrf/__init__.py +0 -0
  2. exdrf/__version__.py +24 -0
  3. exdrf/api.py +51 -0
  4. exdrf/constants.py +30 -0
  5. exdrf/dataset.py +197 -0
  6. exdrf/field.py +554 -0
  7. exdrf/field_types/__init__.py +0 -0
  8. exdrf/field_types/api.py +78 -0
  9. exdrf/field_types/blob_field.py +44 -0
  10. exdrf/field_types/bool_field.py +47 -0
  11. exdrf/field_types/date_field.py +49 -0
  12. exdrf/field_types/date_time.py +52 -0
  13. exdrf/field_types/dur_field.py +44 -0
  14. exdrf/field_types/enum_field.py +41 -0
  15. exdrf/field_types/filter_field.py +11 -0
  16. exdrf/field_types/float_field.py +85 -0
  17. exdrf/field_types/float_list.py +18 -0
  18. exdrf/field_types/formatted.py +39 -0
  19. exdrf/field_types/int_field.py +70 -0
  20. exdrf/field_types/int_list.py +18 -0
  21. exdrf/field_types/ref_base.py +105 -0
  22. exdrf/field_types/ref_m2m.py +39 -0
  23. exdrf/field_types/ref_m2o.py +23 -0
  24. exdrf/field_types/ref_o2m.py +36 -0
  25. exdrf/field_types/ref_o2o.py +32 -0
  26. exdrf/field_types/sort_field.py +18 -0
  27. exdrf/field_types/str_field.py +77 -0
  28. exdrf/field_types/str_list.py +18 -0
  29. exdrf/field_types/time_field.py +49 -0
  30. exdrf/filter.py +653 -0
  31. exdrf/filter_dsl.py +950 -0
  32. exdrf/filter_op_catalog.py +222 -0
  33. exdrf/label_dsl.py +691 -0
  34. exdrf/moment.py +496 -0
  35. exdrf/py.typed +0 -0
  36. exdrf/py_support.py +21 -0
  37. exdrf/resource.py +901 -0
  38. exdrf/sa_fi_item.py +69 -0
  39. exdrf/sa_filter_op.py +324 -0
  40. exdrf/utils.py +17 -0
  41. exdrf/validator.py +45 -0
  42. exdrf/var_bag.py +328 -0
  43. exdrf/visitor.py +58 -0
  44. exdrf-0.0.1.dev0.dist-info/METADATA +42 -0
  45. exdrf-0.0.1.dev0.dist-info/RECORD +57 -0
  46. exdrf-0.0.1.dev0.dist-info/WHEEL +5 -0
  47. exdrf-0.0.1.dev0.dist-info/top_level.txt +3 -0
  48. exdrf_tests/__init__.py +0 -0
  49. exdrf_tests/test_dataset.py +422 -0
  50. exdrf_tests/test_field.py +109 -0
  51. exdrf_tests/test_filter.py +425 -0
  52. exdrf_tests/test_filter_dsl.py +556 -0
  53. exdrf_tests/test_label_dsl.py +234 -0
  54. exdrf_tests/test_resource.py +107 -0
  55. exdrf_tests/test_utils.py +43 -0
  56. exdrf_tests/test_visitor.py +31 -0
  57. exdrf_tests/var_bag_test.py +502 -0
@@ -0,0 +1,36 @@
1
+ from typing import TYPE_CHECKING, Any, Optional
2
+
3
+ from attrs import define, field
4
+
5
+ from exdrf.constants import FIELD_TYPE_REF_ONE_TO_MANY
6
+ from exdrf.field_types.ref_base import RefBaseField
7
+
8
+ if TYPE_CHECKING:
9
+ from exdrf.resource import ExResource
10
+
11
+
12
+ @define
13
+ class RefOneToManyField(RefBaseField):
14
+ """This type of field is created by OneToMany relations.
15
+
16
+ In this type of relation there is one item of the present resource
17
+ that is related to many items of the related resource. Expect the foreign
18
+ key to be in the *related* resource.
19
+
20
+ It is asserted that in this case the `is_list` attribute is set to
21
+ `True`.
22
+ """
23
+
24
+ type_name: str = field(default=FIELD_TYPE_REF_ONE_TO_MANY)
25
+ is_list: bool = field(default=True)
26
+ subordinate: bool = field(default=False)
27
+ bridge: Optional["ExResource"] = field(default=None)
28
+
29
+ def field_properties(self, explicit: bool = False) -> dict[str, Any]:
30
+ result = super().field_properties(explicit)
31
+ if self.subordinate or explicit:
32
+ result["subordinate"] = self.subordinate
33
+ return result
34
+
35
+ def __repr__(self) -> str:
36
+ return f"O2M({self.ref.name})"
@@ -0,0 +1,32 @@
1
+ from typing import Any
2
+
3
+ from attrs import define, field
4
+
5
+ from exdrf.constants import FIELD_TYPE_REF_ONE_TO_ONE
6
+ from exdrf.field_types.ref_base import RefBaseField
7
+
8
+
9
+ @define
10
+ class RefOneToOneField(RefBaseField):
11
+ """This type of field is created by OneToOne relations.
12
+
13
+ In this type of relation there is one item of the present resource
14
+ that is related to one item of the related resource. The foreign key mey
15
+ be in either the present, in the related resource but *not in both*.
16
+
17
+ It is asserted that in this case the `is_list` attribute is set to
18
+ `False`.
19
+ """
20
+
21
+ type_name: str = field(default=FIELD_TYPE_REF_ONE_TO_ONE)
22
+ is_list: bool = field(default=False)
23
+ subordinate: bool = field(default=False)
24
+
25
+ def field_properties(self, explicit: bool = False) -> dict[str, Any]:
26
+ result = super().field_properties(explicit)
27
+ if self.subordinate or explicit:
28
+ result["subordinate"] = self.subordinate
29
+ return result
30
+
31
+ def __repr__(self) -> str:
32
+ return f"O2O({self.ref.name})"
@@ -0,0 +1,18 @@
1
+ from typing import TYPE_CHECKING, List
2
+
3
+ from attrs import define, field
4
+
5
+ from exdrf.constants import FIELD_TYPE_SORT
6
+ from exdrf.field import ExField
7
+
8
+ if TYPE_CHECKING:
9
+ from exdrf.dataset import ExDataset
10
+ from exdrf.resource import ExResource
11
+
12
+
13
+ @define
14
+ class SortField(ExField):
15
+ type_name: str = field(default=FIELD_TYPE_SORT)
16
+
17
+ def extra_ref(self, d_set: "ExDataset") -> List["ExResource"]:
18
+ return [d_set["SortItem"]]
@@ -0,0 +1,77 @@
1
+ from typing import Any, List, Optional, Tuple
2
+
3
+ from attrs import define, field
4
+ from pydantic import Field, field_validator
5
+
6
+ from exdrf.constants import FIELD_TYPE_STRING
7
+ from exdrf.field import ExField, FieldInfo
8
+
9
+
10
+ @define
11
+ class StrField(ExField):
12
+ """A field that stores strings.
13
+
14
+ Attributes:
15
+ multiline: Whether the string can span multiple lines.
16
+ min_length: The minimum length of the string.
17
+ max_length: The maximum length of the string.
18
+ enum_values: The list of predefined (named) values for the field. The
19
+ first element of the tuple is the value, the second element is the
20
+ display name.
21
+ no_dia_field: The name of the field that is used to store the value
22
+ of this field without diacritics.
23
+ """
24
+
25
+ type_name: str = field(default=FIELD_TYPE_STRING)
26
+
27
+ multiline: bool = field(default=False)
28
+ min_length: int = field(default=None)
29
+ max_length: int = field(default=None)
30
+ enum_values: List[Tuple[str, str]] = field(factory=list)
31
+
32
+ no_dia_field: Optional["ExField"] = field(default=None)
33
+
34
+ def __repr__(self) -> str:
35
+ return f"StrF({self.resource.name}.{self.name})"
36
+
37
+ def field_properties(self, explicit: bool = False) -> dict[str, Any]:
38
+ result = super().field_properties(explicit)
39
+ if self.multiline or explicit:
40
+ result["multiline"] = self.multiline
41
+ if self.min_length is not None or explicit:
42
+ result["min_length"] = self.min_length
43
+ if self.max_length is not None or explicit:
44
+ result["max_length"] = self.max_length
45
+ if self.enum_values or explicit:
46
+ result["enum_values"] = self.enum_values
47
+ return result
48
+
49
+
50
+ class StrInfo(FieldInfo):
51
+ """Parser for information about a string field.
52
+
53
+ Attributes:
54
+ multiline: Whether the string can span multiple lines.
55
+ min_length: The minimum length of the string.
56
+ max_length: The maximum length of the string. Note that providing a
57
+ value for this attribute will override the derived value from the
58
+ database column (like `VARCHAR(255)`; see `field_from_sql_col()`
59
+ implementation).
60
+ enum_values: The list of predefined (named) values for the field. The
61
+ first element of the tuple is the value, the second element is the
62
+ display name.
63
+ """
64
+
65
+ multiline: Optional[bool] = None
66
+ min_length: Optional[int] = None
67
+ max_length: Optional[int] = None
68
+ enum_values: List[Tuple[str, str]] = Field(default_factory=list)
69
+
70
+ @field_validator("enum_values", mode="before")
71
+ @classmethod
72
+ def validate_enum_values(cls, v):
73
+ """Validate the enum values.
74
+
75
+ Accepts either a list of (int, str) tuples or an Enum class.
76
+ """
77
+ return cls.validate_enum_with_type(v, str)
@@ -0,0 +1,18 @@
1
+ from attrs import define, field
2
+
3
+ from exdrf.constants import FIELD_TYPE_STRING_LIST
4
+ from exdrf.field_types.str_field import StrField, StrInfo
5
+
6
+
7
+ @define
8
+ class StrListField(StrField):
9
+ """A field that stores list of strings."""
10
+
11
+ type_name: str = field(default=FIELD_TYPE_STRING_LIST)
12
+
13
+ def __repr__(self) -> str:
14
+ return f"SListF({self.resource.name}.{self.name})"
15
+
16
+
17
+ class StrListInfo(StrInfo):
18
+ """Parser for information about a string-list field."""
@@ -0,0 +1,49 @@
1
+ from datetime import time
2
+ from typing import Any, Optional
3
+
4
+ from attrs import define, field
5
+
6
+ from exdrf.constants import FIELD_TYPE_TIME
7
+ from exdrf.field import ExField, FieldInfo
8
+
9
+
10
+ @define
11
+ class TimeField(ExField):
12
+ """A field that stores a time of day (without a date)
13
+
14
+ Attributes:
15
+ min: The minimum time that can be stored in the field.
16
+ max: The maximum time that can be stored in the field.
17
+ format: The format of the time string.
18
+ """
19
+
20
+ type_name: str = field(default=FIELD_TYPE_TIME)
21
+
22
+ min: time = field(default=None)
23
+ max: time = field(default=None)
24
+ format: str = field(default="HH:mm:ss")
25
+
26
+ def __repr__(self) -> str:
27
+ return f"TimeF({self.resource.name}.{self.name})"
28
+
29
+ def field_properties(self, explicit: bool = False) -> dict[str, Any]:
30
+ result = super().field_properties(explicit)
31
+ if self.min is not None or explicit:
32
+ result["min"] = self.min
33
+ if self.max is not None or explicit:
34
+ result["max"] = self.max
35
+ if self.format or explicit:
36
+ result["format"] = self.format
37
+ return result
38
+
39
+
40
+ class TimeInfo(FieldInfo):
41
+ """Parser for information about a date-time field.
42
+
43
+ Attributes:
44
+ min: The minimum time that can be stored in the field.
45
+ max: The maximum time that can be stored in the field.
46
+ """
47
+
48
+ min: Optional[time] = None
49
+ max: Optional[time] = None