data-sitter 0.1.2__py3-none-any.whl → 0.1.4__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.
- data_sitter/Contract.py +39 -4
- data_sitter/FieldResolver.py +1 -3
- data_sitter/Validation.py +39 -0
- data_sitter/cli.py +1 -1
- data_sitter/field_types/BaseField.py +5 -4
- data_sitter/field_types/FloatField.py +11 -1
- data_sitter/field_types/NumericField.py +22 -18
- data_sitter/field_types/StringField.py +63 -30
- data_sitter/rules/Rule.py +19 -2
- data_sitter/rules/RuleRegistry.py +4 -4
- {data_sitter-0.1.2.dist-info → data_sitter-0.1.4.dist-info}/METADATA +2 -1
- data_sitter-0.1.4.dist-info/RECORD +26 -0
- data_sitter-0.1.2.dist-info/RECORD +0 -25
- {data_sitter-0.1.2.dist-info → data_sitter-0.1.4.dist-info}/WHEEL +0 -0
- {data_sitter-0.1.2.dist-info → data_sitter-0.1.4.dist-info}/entry_points.txt +0 -0
- {data_sitter-0.1.2.dist-info → data_sitter-0.1.4.dist-info}/top_level.txt +0 -0
data_sitter/Contract.py
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
+
import json
|
2
|
+
import yaml
|
1
3
|
from typing import Any, Dict, List, NamedTuple
|
2
4
|
from functools import cached_property
|
3
5
|
|
4
6
|
from pydantic import BaseModel
|
5
7
|
|
8
|
+
from .Validation import Validation
|
6
9
|
from .field_types import BaseField
|
7
10
|
from .FieldResolver import FieldResolver
|
8
11
|
from .rules import MatchedRule, RuleRegistry, RuleParser
|
@@ -51,6 +54,14 @@ class Contract:
|
|
51
54
|
values=contract_dict.get("values", {}),
|
52
55
|
)
|
53
56
|
|
57
|
+
@classmethod
|
58
|
+
def from_json(cls, contract_json: str):
|
59
|
+
return cls.from_dict(json.loads(contract_json))
|
60
|
+
|
61
|
+
@classmethod
|
62
|
+
def from_yaml(cls, contract_yaml: str):
|
63
|
+
return cls.from_dict(yaml.load(contract_yaml, yaml.Loader))
|
64
|
+
|
54
65
|
@cached_property
|
55
66
|
def field_validators(self) -> Dict[str, BaseField]:
|
56
67
|
field_validators = {}
|
@@ -68,10 +79,13 @@ class Contract:
|
|
68
79
|
return rules
|
69
80
|
|
70
81
|
def model_validate(self, item: dict):
|
71
|
-
|
72
|
-
|
82
|
+
return self.pydantic_model.model_validate(item).model_dump()
|
83
|
+
|
84
|
+
def validate(self, item: dict) -> Validation:
|
85
|
+
return Validation.validate(self.pydantic_model, item)
|
73
86
|
|
74
|
-
|
87
|
+
@cached_property
|
88
|
+
def pydantic_model(self) -> BaseModel:
|
75
89
|
return type(self.name, (BaseModel,), {
|
76
90
|
"__annotations__": {
|
77
91
|
field_name: field_validator.get_annotation()
|
@@ -79,7 +93,28 @@ class Contract:
|
|
79
93
|
}
|
80
94
|
})
|
81
95
|
|
82
|
-
|
96
|
+
@cached_property
|
97
|
+
def contract(self) -> dict:
|
98
|
+
return {
|
99
|
+
"name": self.name,
|
100
|
+
"fields": [
|
101
|
+
{
|
102
|
+
"field_name": field_name,
|
103
|
+
"field_type": field_validator.__class__.__name__,
|
104
|
+
"field_rules": [rule.parsed_rule for rule in self.rules.get(field_name, [])]
|
105
|
+
}
|
106
|
+
for field_name, field_validator in self.field_validators.items()
|
107
|
+
],
|
108
|
+
"values": self.rule_parser.values
|
109
|
+
}
|
110
|
+
|
111
|
+
def get_json_contract(self, indent: int=2) -> str:
|
112
|
+
return json.dumps(self.contract, indent=indent)
|
113
|
+
|
114
|
+
def get_yaml_contract(self, indent: int=2) -> str:
|
115
|
+
return yaml.dump(self.contract, Dumper=yaml.Dumper, indent=indent, sort_keys=False)
|
116
|
+
|
117
|
+
def get_front_end_contract(self) -> dict:
|
83
118
|
return {
|
84
119
|
"name": self.name,
|
85
120
|
"fields": [
|
data_sitter/FieldResolver.py
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
from typing import Dict, List, Type
|
3
2
|
|
4
3
|
from .field_types import BaseField
|
@@ -32,8 +31,7 @@ class FieldResolver:
|
|
32
31
|
return matched_rules
|
33
32
|
|
34
33
|
def get_field_validator(self, field_name: str, parsed_rules: List[str]) -> BaseField:
|
35
|
-
|
36
|
-
validator = self.field_class(field_name, is_optional)
|
34
|
+
validator = self.field_class(field_name)
|
37
35
|
matched_rules = self.get_matched_rules(parsed_rules)
|
38
36
|
for matched_rule in matched_rules:
|
39
37
|
matched_rule.add_to_instance(validator)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
from collections import defaultdict
|
2
|
+
from typing import Any, Dict, List, Type
|
3
|
+
|
4
|
+
from pydantic import BaseModel, ValidationError
|
5
|
+
|
6
|
+
|
7
|
+
class Validation():
|
8
|
+
item: Dict[str, Any]
|
9
|
+
errors: Dict[str, List[str]]
|
10
|
+
unknowns: Dict[str, Any]
|
11
|
+
|
12
|
+
def __init__(self, item: dict, errors: dict = None, unknowns: dict = None):
|
13
|
+
self.item = item
|
14
|
+
self.errors = errors if errors else None
|
15
|
+
self.unknowns = unknowns if unknowns else None
|
16
|
+
|
17
|
+
def to_dict(self) -> dict:
|
18
|
+
return {key: value for key in ["item", "errors", "unknowns"] if (value := getattr(self, key))}
|
19
|
+
|
20
|
+
@classmethod
|
21
|
+
def validate(cls, PydanticModel: Type[BaseModel], input_item: dict) -> "Validation":
|
22
|
+
model_keys = PydanticModel.model_json_schema()['properties'].keys()
|
23
|
+
item = {key: None for key in model_keys} # Filling not present values with Nones
|
24
|
+
errors = defaultdict(list)
|
25
|
+
unknowns = {}
|
26
|
+
for key, value in input_item.items():
|
27
|
+
if key in item:
|
28
|
+
item[key] = value
|
29
|
+
else:
|
30
|
+
unknowns[key] = value
|
31
|
+
try:
|
32
|
+
validated = PydanticModel(**item).model_dump()
|
33
|
+
except ValidationError as e:
|
34
|
+
validated = item
|
35
|
+
for error in e.errors():
|
36
|
+
field = error['loc'][0] # Extract the field name
|
37
|
+
msg = error['msg']
|
38
|
+
errors[field].append(msg)
|
39
|
+
return Validation(item=validated, errors=dict(errors), unknowns=unknowns)
|
data_sitter/cli.py
CHANGED
@@ -23,7 +23,7 @@ def main():
|
|
23
23
|
contract_path = Path(args.contract)
|
24
24
|
contract_dict = json.loads(contract_path.read_text(encoding))
|
25
25
|
contract = Contract.from_dict(contract_dict)
|
26
|
-
pydantic_contract = contract.
|
26
|
+
pydantic_contract = contract.pydantic_model
|
27
27
|
|
28
28
|
if file_path.suffix == '.csv':
|
29
29
|
with open(file_path, encoding=encoding) as f:
|
@@ -21,20 +21,21 @@ class BaseField(ABC):
|
|
21
21
|
validators = None
|
22
22
|
field_type = None
|
23
23
|
|
24
|
-
def __init__(self, name: str
|
24
|
+
def __init__(self, name: str) -> None:
|
25
25
|
self.name = name
|
26
|
-
self.is_optional =
|
26
|
+
self.is_optional = True
|
27
27
|
self.validators = []
|
28
28
|
|
29
|
-
@register_rule("
|
29
|
+
@register_rule("Is not null")
|
30
30
|
def validator_not_null(self):
|
31
31
|
def _validator(value):
|
32
32
|
if self.is_optional:
|
33
33
|
return value
|
34
34
|
if value is None:
|
35
|
-
raise ValueError("Value cannot be null")
|
35
|
+
raise ValueError("Value cannot be null.")
|
36
36
|
return value
|
37
37
|
|
38
|
+
self.is_optional = False
|
38
39
|
self.validators.append(_validator)
|
39
40
|
|
40
41
|
def validate(self, value):
|
@@ -1,7 +1,17 @@
|
|
1
1
|
from .NumericField import NumericField
|
2
|
-
from ..rules import register_field
|
2
|
+
from ..rules import register_field, register_rule
|
3
3
|
|
4
4
|
|
5
5
|
@register_field
|
6
6
|
class FloatField(NumericField):
|
7
7
|
field_type = float
|
8
|
+
|
9
|
+
@register_rule("Has at most {decimal_places:Integer} decimal places")
|
10
|
+
def validate_max_decimal_places(self, decimal_places: int):
|
11
|
+
def validator(value):
|
12
|
+
if not isinstance(value, float):
|
13
|
+
raise ValueError("Value must be a floating-point number.")
|
14
|
+
if len(str(value).split(".")[1]) > decimal_places:
|
15
|
+
raise ValueError(f"Value must have at most {decimal_places} decimal places.")
|
16
|
+
return value
|
17
|
+
self.validators.append(validator)
|
@@ -10,66 +10,70 @@ Numeric = Union[int, float]
|
|
10
10
|
class NumericField(BaseField):
|
11
11
|
field_type = Numeric
|
12
12
|
|
13
|
-
@register_rule("
|
13
|
+
@register_rule("Is not zero")
|
14
14
|
def validate_non_zero(self):
|
15
15
|
def validator(value: Numeric):
|
16
16
|
if value == 0:
|
17
|
-
raise ValueError("Value
|
17
|
+
raise ValueError("Value cannot be zero.")
|
18
18
|
return value
|
19
19
|
self.validators.append(validator)
|
20
20
|
|
21
|
-
@register_rule("
|
21
|
+
@register_rule("Is positive")
|
22
22
|
def validate_positive(self):
|
23
23
|
def validator(value: Numeric):
|
24
24
|
if value < 0:
|
25
|
-
raise ValueError(
|
25
|
+
raise ValueError("Value must be positive.")
|
26
26
|
return value
|
27
27
|
self.validators.append(validator)
|
28
28
|
|
29
|
-
@register_rule("
|
29
|
+
@register_rule("Is negative")
|
30
30
|
def validate_negative(self):
|
31
31
|
def validator(value: Numeric):
|
32
32
|
if value >= 0:
|
33
|
-
raise ValueError(
|
33
|
+
raise ValueError("Value must be less than zero.")
|
34
34
|
return value
|
35
35
|
self.validators.append(validator)
|
36
36
|
|
37
|
-
@register_rule("
|
37
|
+
@register_rule("Is at least {min_val:Number}")
|
38
38
|
def validate_min(self, min_val: Numeric):
|
39
39
|
def validator(value: Numeric):
|
40
40
|
if value < min_val:
|
41
|
-
raise ValueError(f"Value
|
41
|
+
raise ValueError(f"Value must be at least {min_val}.")
|
42
42
|
return value
|
43
43
|
self.validators.append(validator)
|
44
44
|
|
45
|
-
@register_rule("
|
45
|
+
@register_rule("Is at most {max_val:Number}")
|
46
46
|
def validate_max(self, max_val: Numeric):
|
47
47
|
def validator(value: Numeric):
|
48
48
|
if value > max_val:
|
49
|
-
raise ValueError(f"Value
|
49
|
+
raise ValueError(f"Value must not exceed {max_val}.")
|
50
50
|
return value
|
51
51
|
self.validators.append(validator)
|
52
52
|
|
53
|
-
@register_rule("
|
53
|
+
@register_rule("Is greater than {threshold:Number}")
|
54
54
|
def validate_greater_than(self, threshold: Numeric):
|
55
55
|
def validator(value: Numeric):
|
56
56
|
if value <= threshold:
|
57
|
-
raise ValueError(f"Value
|
57
|
+
raise ValueError(f"Value must be greater than {threshold}.")
|
58
58
|
return value
|
59
59
|
self.validators.append(validator)
|
60
60
|
|
61
|
-
@register_rule("
|
61
|
+
@register_rule("Is less than {threshold:Number}")
|
62
62
|
def validate_less_than(self, threshold: Numeric):
|
63
63
|
def validator(value: Numeric):
|
64
64
|
if value >= threshold:
|
65
|
-
raise ValueError(f"Value
|
65
|
+
raise ValueError(f"Value must be less than {threshold}.")
|
66
66
|
return value
|
67
67
|
self.validators.append(validator)
|
68
68
|
|
69
|
-
@register_rule("
|
70
|
-
|
69
|
+
@register_rule("Is between {min_val:Number} and {max_val:Number}", fixed_params={"negative": False})
|
70
|
+
@register_rule("Is not between {min_val:Number} and {max_val:Number}", fixed_params={"negative": True})
|
71
|
+
def validate_between(self, min_val: Numeric, max_val: Numeric, negative: bool):
|
71
72
|
def validator(value: Numeric):
|
72
|
-
|
73
|
-
|
73
|
+
condition = (min_val < value < max_val)
|
74
|
+
if condition and negative:
|
75
|
+
raise ValueError(f"Value must not be between {min_val} and {max_val}.")
|
76
|
+
if not condition and not negative:
|
77
|
+
raise ValueError(f"Value must be between {min_val} and {max_val}.")
|
74
78
|
return value
|
75
79
|
self.validators.append(validator)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import re
|
1
2
|
from typing import List
|
2
3
|
|
3
4
|
from .BaseField import BaseField
|
@@ -12,7 +13,7 @@ class StringField(BaseField):
|
|
12
13
|
def validate_not_empty(self):
|
13
14
|
def validator(value: str):
|
14
15
|
if value == "":
|
15
|
-
raise ValueError("
|
16
|
+
raise ValueError("String cannot be empty.")
|
16
17
|
return value
|
17
18
|
self.validators.append(validator)
|
18
19
|
|
@@ -20,70 +21,102 @@ class StringField(BaseField):
|
|
20
21
|
def validate_starts_with(self, prefix: List[str]):
|
21
22
|
def validator(value: str):
|
22
23
|
if not value.startswith(prefix):
|
23
|
-
raise ValueError(f"
|
24
|
+
raise ValueError(f"Value must start with '{prefix}'.")
|
24
25
|
return value
|
25
26
|
self.validators.append(validator)
|
26
27
|
|
27
|
-
@register_rule("Ends with {
|
28
|
-
def validate_ends_with(self,
|
28
|
+
@register_rule("Ends with {suffix:String}")
|
29
|
+
def validate_ends_with(self, suffix: List[str]):
|
29
30
|
def validator(value: str):
|
30
|
-
if not value.endswith(
|
31
|
-
raise ValueError(f"
|
31
|
+
if not value.endswith(suffix):
|
32
|
+
raise ValueError(f"Value must end with '{suffix}'.")
|
32
33
|
return value
|
33
34
|
self.validators.append(validator)
|
34
35
|
|
35
|
-
@register_rule("
|
36
|
-
|
36
|
+
@register_rule("Is one of {possible_values:Strings}", fixed_params={"negative": False})
|
37
|
+
@register_rule("Is not one of {possible_values:Strings}", fixed_params={"negative": True})
|
38
|
+
def validate_in(self, possible_values: List[str], negative: bool):
|
37
39
|
def validator(value: str):
|
38
|
-
|
39
|
-
|
40
|
+
condition = value in possible_values
|
41
|
+
if condition and negative:
|
42
|
+
raise ValueError(f"Value '{value}' is not allowed.")
|
43
|
+
if not condition and not negative:
|
44
|
+
raise ValueError(f"Value '{value}' must be one of the possible values.")
|
40
45
|
return value
|
41
46
|
self.validators.append(validator)
|
42
47
|
|
43
|
-
@register_rule("
|
48
|
+
@register_rule("Has length between {min_val:Integer} and {max_val:Integer}")
|
44
49
|
def validate_length_between(self, min_val: int, max_val: int):
|
45
50
|
def validator(value: str):
|
46
51
|
if not (min_val < len(value) < max_val):
|
47
|
-
raise ValueError(f"Length
|
52
|
+
raise ValueError(f"Length must be between {min_val} and {max_val} characters.")
|
48
53
|
return value
|
49
54
|
self.validators.append(validator)
|
50
55
|
|
51
|
-
@register_rule("
|
56
|
+
@register_rule("Has maximum length {max_len:Integer}")
|
52
57
|
def validate_max_length(self, max_len: int):
|
53
58
|
def validator(value: str):
|
54
59
|
if len(value) > max_len:
|
55
|
-
raise ValueError(f"Length
|
60
|
+
raise ValueError(f"Length must not exceed {max_len} characters.")
|
56
61
|
return value
|
57
62
|
self.validators.append(validator)
|
58
63
|
|
59
|
-
@register_rule("
|
60
|
-
def
|
64
|
+
@register_rule("Has minimum length {min_len:Integer}")
|
65
|
+
def validate_min_length(self, min_len: int):
|
61
66
|
def validator(value: str):
|
62
|
-
if len(value)
|
63
|
-
raise ValueError(f"Length
|
67
|
+
if len(value) < min_len:
|
68
|
+
raise ValueError(f"Length must be at least {min_len} characters.")
|
64
69
|
return value
|
65
70
|
self.validators.append(validator)
|
66
71
|
|
67
|
-
@register_rule("
|
68
|
-
def
|
72
|
+
@register_rule("Is uppercase")
|
73
|
+
def validate_uppercase(self):
|
69
74
|
def validator(value: str):
|
70
|
-
if
|
71
|
-
raise ValueError(
|
75
|
+
if not value.isupper():
|
76
|
+
raise ValueError("Value must be in uppercase.")
|
72
77
|
return value
|
73
78
|
self.validators.append(validator)
|
74
79
|
|
75
|
-
@register_rule("
|
76
|
-
def
|
80
|
+
@register_rule("Is lowercase")
|
81
|
+
def validate_lowercase(self):
|
77
82
|
def validator(value: str):
|
78
|
-
if
|
79
|
-
raise ValueError(
|
83
|
+
if not value.islower():
|
84
|
+
raise ValueError("Value must be in lowercase.")
|
80
85
|
return value
|
81
86
|
self.validators.append(validator)
|
82
87
|
|
83
|
-
@register_rule("
|
84
|
-
def
|
88
|
+
@register_rule("Matches regex {pattern:String}")
|
89
|
+
def validate_matches_regex(self, pattern: str):
|
85
90
|
def validator(value: str):
|
86
|
-
if not
|
87
|
-
raise ValueError("
|
91
|
+
if not re.match(pattern, value):
|
92
|
+
raise ValueError(f"Value does not match the required pattern {pattern}.")
|
93
|
+
return value
|
94
|
+
self.validators.append(validator)
|
95
|
+
|
96
|
+
@register_rule("Is valid email")
|
97
|
+
def validate_email(self):
|
98
|
+
EMAIL_REGEX = r"^[\w\.-]+@[\w\.-]+\.\w+$"
|
99
|
+
|
100
|
+
def validator(value: str):
|
101
|
+
if not re.match(EMAIL_REGEX, value):
|
102
|
+
raise ValueError("Invalid email format.")
|
103
|
+
return value
|
104
|
+
self.validators.append(validator)
|
105
|
+
|
106
|
+
@register_rule("Is valid URL")
|
107
|
+
def validate_url(self):
|
108
|
+
URL_REGEX = r"^(https?|ftp):\/\/[^\s/$.?#].[^\s]*$"
|
109
|
+
|
110
|
+
def validator(value: str):
|
111
|
+
if not re.match(URL_REGEX, value):
|
112
|
+
raise ValueError("Invalid URL format.")
|
113
|
+
return value
|
114
|
+
self.validators.append(validator)
|
115
|
+
|
116
|
+
@register_rule("Has no digits")
|
117
|
+
def validate_no_digits(self):
|
118
|
+
def validator(value: str):
|
119
|
+
if any(char.isdigit() for char in value):
|
120
|
+
raise ValueError("Value must not contain any digits.")
|
88
121
|
return value
|
89
122
|
self.validators.append(validator)
|
data_sitter/rules/Rule.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import functools
|
1
2
|
import string
|
2
3
|
from inspect import signature
|
3
4
|
from typing import Callable
|
@@ -15,12 +16,15 @@ class Rule:
|
|
15
16
|
field_type: str
|
16
17
|
field_rule: str
|
17
18
|
rule_setter: Callable
|
19
|
+
fixed_params: dict
|
18
20
|
|
19
|
-
def __init__(self, field_type: str, field_rule: str, rule_setter: Callable) -> None:
|
21
|
+
def __init__(self, field_type: str, field_rule: str, rule_setter: Callable, fixed_params: dict = None) -> None:
|
20
22
|
self.field_type = field_type
|
21
23
|
self.field_rule = field_rule
|
22
24
|
self.rule_setter = rule_setter
|
25
|
+
self.fixed_params = fixed_params or {}
|
23
26
|
self.__validate_rule_function_params()
|
27
|
+
self.__apply_fixed_params()
|
24
28
|
|
25
29
|
def __repr__(self):
|
26
30
|
return self.field_rule
|
@@ -39,6 +43,19 @@ class Rule:
|
|
39
43
|
if "self" not in rule_setter_params:
|
40
44
|
raise NotAClassMethod()
|
41
45
|
|
46
|
+
rule_setter_params = rule_setter_params - set(self.fixed_params)
|
42
47
|
rule_setter_params.remove("self")
|
43
48
|
if set(self.rule_params) != rule_setter_params:
|
44
|
-
|
49
|
+
rule_total_params = set(self.rule_params).union(set(self.fixed_params))
|
50
|
+
raise RuleFunctionParamsMismatch(f"Rule Params: {rule_total_params}, Setter Params: {rule_setter_params}")
|
51
|
+
|
52
|
+
def __apply_fixed_params(self):
|
53
|
+
if not self.fixed_params:
|
54
|
+
return
|
55
|
+
rule_setter_sign = signature(self.rule_setter)
|
56
|
+
all_params = rule_setter_sign.parameters
|
57
|
+
|
58
|
+
for param in self.fixed_params:
|
59
|
+
if param not in all_params:
|
60
|
+
raise ValueError(f"The fixed parameter '{param}' is not in the function '{self.rule_setter.__name__}'.")
|
61
|
+
self.rule_setter = functools.partial(self.rule_setter, **self.fixed_params)
|
@@ -17,12 +17,12 @@ class RuleRegistry:
|
|
17
17
|
type_map: Dict[str, Type["BaseField"]] = {}
|
18
18
|
|
19
19
|
@classmethod
|
20
|
-
def register_rule(cls, field_rule: str):
|
20
|
+
def register_rule(cls, field_rule: str, fixed_params: dict = None):
|
21
21
|
def _register(func: callable):
|
22
22
|
field_type, func_name = func.__qualname__.split(".")
|
23
23
|
logger.debug("Registering function '%s' for %s. Rule: %s", func_name, field_type, field_rule)
|
24
24
|
|
25
|
-
rule = Rule(field_type, field_rule, func)
|
25
|
+
rule = Rule(field_type, field_rule, func, fixed_params)
|
26
26
|
cls.rules[field_type].append(rule)
|
27
27
|
logger.debug("Function '%s' Registered", func_name)
|
28
28
|
return func
|
@@ -57,8 +57,8 @@ class RuleRegistry:
|
|
57
57
|
]
|
58
58
|
|
59
59
|
|
60
|
-
def register_rule(rule: str):
|
61
|
-
return RuleRegistry.register_rule(rule)
|
60
|
+
def register_rule(rule: str, fixed_params: dict = None):
|
61
|
+
return RuleRegistry.register_rule(rule, fixed_params)
|
62
62
|
|
63
63
|
|
64
64
|
def register_field(field_class: type):
|
@@ -1,8 +1,9 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: data-sitter
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.4
|
4
4
|
Summary: A Python library that reads data contracts and generates Pydantic models for seamless data validation.
|
5
5
|
Author-email: Lázaro Pereira Candea <lazaro@candea.es>
|
6
6
|
Requires-Dist: python-dotenv==1.0.1
|
7
|
+
Requires-Dist: PyYAML==6.0.2
|
7
8
|
Requires-Dist: parse_type==0.6.4
|
8
9
|
Requires-Dist: pydantic==2.10.5
|
@@ -0,0 +1,26 @@
|
|
1
|
+
data_sitter/Contract.py,sha256=ow6CdT7XRbxBy4tY5av3_L9d8qv59nw70ih-jVMKlBU,4561
|
2
|
+
data_sitter/FieldResolver.py,sha256=0XSA-doOY4cM_Ikd09hUxykYZOLR5pHwkbNiTmdtweQ,1819
|
3
|
+
data_sitter/Validation.py,sha256=5jdIQZyTrEmXZ_SJP0lq-EEFKrGbYH6z4EQ56oFR7Ck,1474
|
4
|
+
data_sitter/__init__.py,sha256=qbE-wU8ELMFwOMG4UTK0lmzn5XF2MK3rc22E8ROgypo,113
|
5
|
+
data_sitter/cli.py,sha256=1ICrtokqV5RvvWhzWKAeS5ZUSUpiviQyy2JSK71ER10,1666
|
6
|
+
data_sitter/field_types/BaseField.py,sha256=mCEy9hFhwus1gW1P6ctbUCUrZ9rJMtreOvfiy9MkO5Q,1799
|
7
|
+
data_sitter/field_types/FloatField.py,sha256=75zYGwI65GYIiZWgb5cwb3QoWukp3X-YcrmqhIxOe1w,675
|
8
|
+
data_sitter/field_types/IntegerField.py,sha256=o__5z3bg6wsx7FIfJbBYZW5b760-WSZw_05J-OSKXR0,147
|
9
|
+
data_sitter/field_types/NumericField.py,sha256=s8aEkk42HYY30citCaBjIynLGfKE7gPayvVq3fdVd2Y,2981
|
10
|
+
data_sitter/field_types/StringField.py,sha256=wXlfCTPGPDr2j_lHW6LqtAFKNBoff6nk0tE5Xt02xsQ,4645
|
11
|
+
data_sitter/field_types/__init__.py,sha256=GdssttQCJksGcZn7oPM53vOsqOL6R5xRiRJDEtr38Ww,293
|
12
|
+
data_sitter/rules/MatchedRule.py,sha256=uHXuo7Np-Bq7IOHaHMYFmYFPRT8aYDEKCdFKcvWf4DM,1946
|
13
|
+
data_sitter/rules/Rule.py,sha256=xE31dUwLHD3IzcmPfdqLuXS_rmw-kFdIaCKHvpIArig,2115
|
14
|
+
data_sitter/rules/RuleRegistry.py,sha256=iqxcbzypk-_S4ukASNjEe9TD7J-f2psXWR0GVOPlK0E,2134
|
15
|
+
data_sitter/rules/__init__.py,sha256=_cTO0SUkW_WW2VBx2NGd8n5TUio7gptkBr9MorW2ZZk,289
|
16
|
+
data_sitter/rules/Parser/RuleParser.py,sha256=7biF5N3Cf3Rf5bgB4pXUpBaZ4r5EL1I9YHvSTjdydBA,2127
|
17
|
+
data_sitter/rules/Parser/__init__.py,sha256=F8qJ7luwq0C65e7pNOzBHB2sF1lMcvIFYfDNJj6XQTc,205
|
18
|
+
data_sitter/rules/Parser/alias_parameters_parser.py,sha256=jsx_JWzkA4lY2nq4hzc4fG7_nnh7yLxmVj6WIP1Mm68,1933
|
19
|
+
data_sitter/rules/Parser/parser_utils.py,sha256=ypI021uYJTsHAoKGShAfnhd5xQGtqqTGTHozleefsLQ,642
|
20
|
+
data_sitter/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
|
+
data_sitter/utils/logger_config.py,sha256=w9E4jWfGJnkC9tZz4qrolSqglKm4jEB8l6vjC-qfj8A,1215
|
22
|
+
data_sitter-0.1.4.dist-info/METADATA,sha256=dKf83KLklS2JXoiWJCcEBGi6EqKYUcVn5XPXoL-bQBc,353
|
23
|
+
data_sitter-0.1.4.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
24
|
+
data_sitter-0.1.4.dist-info/entry_points.txt,sha256=1I7xxqFZvA78wmDx7NGavttAb8JFWM3Wxgehftx_5C4,53
|
25
|
+
data_sitter-0.1.4.dist-info/top_level.txt,sha256=Q7N21PYeqIdRbDvZQCJXhbbv0PFIf876gu1_DpInH_E,12
|
26
|
+
data_sitter-0.1.4.dist-info/RECORD,,
|
@@ -1,25 +0,0 @@
|
|
1
|
-
data_sitter/Contract.py,sha256=87GcIltT0ofhZNZg_de8DP4rTj9Ab2pvGr-HSVACrfs,3375
|
2
|
-
data_sitter/FieldResolver.py,sha256=aSavmk3V8QCphLRL6i3T_V2DIsWfEKBdcCnZC71hrx0,1895
|
3
|
-
data_sitter/__init__.py,sha256=qbE-wU8ELMFwOMG4UTK0lmzn5XF2MK3rc22E8ROgypo,113
|
4
|
-
data_sitter/cli.py,sha256=J_FzO8qnF5AVS4PH2AY5ljs4IpCrIg2l2z6PpFsjjWk,1672
|
5
|
-
data_sitter/field_types/BaseField.py,sha256=_Pg6a7gdmQFwb4f7LDyOxElX8j0NnTYZGOJJr_jddt8,1797
|
6
|
-
data_sitter/field_types/FloatField.py,sha256=pWU449uUFzlpnIpZI-2WxN1YKv7PxIiYe_c7W91VqCc,147
|
7
|
-
data_sitter/field_types/IntegerField.py,sha256=o__5z3bg6wsx7FIfJbBYZW5b760-WSZw_05J-OSKXR0,147
|
8
|
-
data_sitter/field_types/NumericField.py,sha256=ncPSrUOOgU5MPcA7in_lR6Luqb1xOo8m7UL6TW1qqGw,2665
|
9
|
-
data_sitter/field_types/StringField.py,sha256=XVN_0SE7bVlJijEiVIe_Ce22olY-DI0lmmZq3LU7TVE,3444
|
10
|
-
data_sitter/field_types/__init__.py,sha256=GdssttQCJksGcZn7oPM53vOsqOL6R5xRiRJDEtr38Ww,293
|
11
|
-
data_sitter/rules/MatchedRule.py,sha256=uHXuo7Np-Bq7IOHaHMYFmYFPRT8aYDEKCdFKcvWf4DM,1946
|
12
|
-
data_sitter/rules/Rule.py,sha256=UzZku6qo6GEUmDT86KS1Ee-2S9f_TTYlHC_O87V-984,1327
|
13
|
-
data_sitter/rules/RuleRegistry.py,sha256=YwBTsGY8S0ZDuwHuyQwcFgUWYORXK0Q44mV8v2oFVKc,2052
|
14
|
-
data_sitter/rules/__init__.py,sha256=_cTO0SUkW_WW2VBx2NGd8n5TUio7gptkBr9MorW2ZZk,289
|
15
|
-
data_sitter/rules/Parser/RuleParser.py,sha256=7biF5N3Cf3Rf5bgB4pXUpBaZ4r5EL1I9YHvSTjdydBA,2127
|
16
|
-
data_sitter/rules/Parser/__init__.py,sha256=F8qJ7luwq0C65e7pNOzBHB2sF1lMcvIFYfDNJj6XQTc,205
|
17
|
-
data_sitter/rules/Parser/alias_parameters_parser.py,sha256=jsx_JWzkA4lY2nq4hzc4fG7_nnh7yLxmVj6WIP1Mm68,1933
|
18
|
-
data_sitter/rules/Parser/parser_utils.py,sha256=ypI021uYJTsHAoKGShAfnhd5xQGtqqTGTHozleefsLQ,642
|
19
|
-
data_sitter/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
20
|
-
data_sitter/utils/logger_config.py,sha256=w9E4jWfGJnkC9tZz4qrolSqglKm4jEB8l6vjC-qfj8A,1215
|
21
|
-
data_sitter-0.1.2.dist-info/METADATA,sha256=bh7X-lbFECJk7uV1oT5miVBOVfypkYAERAS6wbAZ7r8,324
|
22
|
-
data_sitter-0.1.2.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
23
|
-
data_sitter-0.1.2.dist-info/entry_points.txt,sha256=1I7xxqFZvA78wmDx7NGavttAb8JFWM3Wxgehftx_5C4,53
|
24
|
-
data_sitter-0.1.2.dist-info/top_level.txt,sha256=Q7N21PYeqIdRbDvZQCJXhbbv0PFIf876gu1_DpInH_E,12
|
25
|
-
data_sitter-0.1.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|