data-sitter 0.1.3__py3-none-any.whl → 0.1.6__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 +51 -28
- data_sitter/FieldResolver.py +31 -20
- data_sitter/Validation.py +21 -12
- data_sitter/cli.py +1 -1
- data_sitter/field_types/BaseField.py +29 -19
- data_sitter/field_types/FieldTypes.py +9 -0
- data_sitter/field_types/FloatField.py +20 -1
- data_sitter/field_types/IntegerField.py +2 -0
- data_sitter/field_types/NumericField.py +33 -27
- data_sitter/field_types/StringField.py +75 -40
- data_sitter/rules/Enums.py +7 -0
- data_sitter/rules/LogicalRule.py +68 -0
- data_sitter/rules/MatchedRule.py +17 -14
- data_sitter/rules/Parser/alias_parameters_parser.py +0 -20
- data_sitter/rules/ProcessedRule.py +24 -0
- data_sitter/rules/Rule.py +19 -2
- data_sitter/rules/RuleRegistry.py +50 -29
- data_sitter/rules/__init__.py +7 -1
- data_sitter/utils/logger_config.py +1 -1
- data_sitter-0.1.6.dist-info/METADATA +220 -0
- data_sitter-0.1.6.dist-info/RECORD +30 -0
- {data_sitter-0.1.3.dist-info → data_sitter-0.1.6.dist-info}/WHEEL +1 -1
- data_sitter-0.1.3.dist-info/METADATA +0 -8
- data_sitter-0.1.3.dist-info/RECORD +0 -26
- {data_sitter-0.1.3.dist-info → data_sitter-0.1.6.dist-info}/entry_points.txt +0 -0
- {data_sitter-0.1.3.dist-info → data_sitter-0.1.6.dist-info}/top_level.txt +0 -0
@@ -1,89 +1,124 @@
|
|
1
|
+
import re
|
1
2
|
from typing import List
|
2
3
|
|
3
4
|
from .BaseField import BaseField
|
5
|
+
from .FieldTypes import FieldTypes
|
4
6
|
from ..rules import register_rule, register_field
|
5
7
|
|
6
8
|
|
7
9
|
@register_field
|
8
10
|
class StringField(BaseField):
|
9
11
|
field_type = str
|
12
|
+
type_name = FieldTypes.STRING
|
10
13
|
|
11
14
|
@register_rule("Is not empty")
|
12
15
|
def validate_not_empty(self):
|
13
16
|
def validator(value: str):
|
14
17
|
if value == "":
|
15
|
-
raise ValueError("
|
18
|
+
raise ValueError("String cannot be empty.")
|
16
19
|
return value
|
17
|
-
|
20
|
+
return validator
|
18
21
|
|
19
22
|
@register_rule("Starts with {prefix:String}")
|
20
23
|
def validate_starts_with(self, prefix: List[str]):
|
21
24
|
def validator(value: str):
|
22
25
|
if not value.startswith(prefix):
|
23
|
-
raise ValueError(f"
|
26
|
+
raise ValueError(f"Value must start with '{prefix}'.")
|
24
27
|
return value
|
25
|
-
|
28
|
+
return validator
|
26
29
|
|
27
|
-
@register_rule("Ends with {
|
28
|
-
def validate_ends_with(self,
|
30
|
+
@register_rule("Ends with {suffix:String}")
|
31
|
+
def validate_ends_with(self, suffix: List[str]):
|
29
32
|
def validator(value: str):
|
30
|
-
if not value.endswith(
|
31
|
-
raise ValueError(f"
|
33
|
+
if not value.endswith(suffix):
|
34
|
+
raise ValueError(f"Value must end with '{suffix}'.")
|
32
35
|
return value
|
33
|
-
|
36
|
+
return validator
|
34
37
|
|
35
|
-
@register_rule("
|
36
|
-
|
38
|
+
@register_rule("Is one of {possible_values:Strings}", fixed_params={"negative": False})
|
39
|
+
@register_rule("Is not one of {possible_values:Strings}", fixed_params={"negative": True})
|
40
|
+
def validate_in(self, possible_values: List[str], negative: bool):
|
37
41
|
def validator(value: str):
|
38
|
-
|
39
|
-
|
42
|
+
condition = value in possible_values
|
43
|
+
if condition and negative:
|
44
|
+
raise ValueError(f"Value '{value}' is not allowed.")
|
45
|
+
if not condition and not negative:
|
46
|
+
raise ValueError(f"Value '{value}' must be one of the possible values.")
|
40
47
|
return value
|
41
|
-
|
48
|
+
return validator
|
42
49
|
|
43
|
-
@register_rule("
|
50
|
+
@register_rule("Has length between {min_val:Integer} and {max_val:Integer}")
|
44
51
|
def validate_length_between(self, min_val: int, max_val: int):
|
45
52
|
def validator(value: str):
|
46
53
|
if not (min_val < len(value) < max_val):
|
47
|
-
raise ValueError(f"Length
|
54
|
+
raise ValueError(f"Length must be between {min_val} and {max_val} characters.")
|
48
55
|
return value
|
49
|
-
|
56
|
+
return validator
|
50
57
|
|
51
|
-
@register_rule("
|
58
|
+
@register_rule("Has maximum length {max_len:Integer}")
|
52
59
|
def validate_max_length(self, max_len: int):
|
53
60
|
def validator(value: str):
|
54
61
|
if len(value) > max_len:
|
55
|
-
raise ValueError(f"Length
|
62
|
+
raise ValueError(f"Length must not exceed {max_len} characters.")
|
56
63
|
return value
|
57
|
-
|
64
|
+
return validator
|
58
65
|
|
59
|
-
@register_rule("
|
60
|
-
def
|
66
|
+
@register_rule("Has minimum length {min_len:Integer}")
|
67
|
+
def validate_min_length(self, min_len: int):
|
61
68
|
def validator(value: str):
|
62
|
-
if len(value)
|
63
|
-
raise ValueError(f"Length
|
69
|
+
if len(value) < min_len:
|
70
|
+
raise ValueError(f"Length must be at least {min_len} characters.")
|
64
71
|
return value
|
65
|
-
|
72
|
+
return validator
|
66
73
|
|
67
|
-
@register_rule("
|
68
|
-
def
|
74
|
+
@register_rule("Is uppercase")
|
75
|
+
def validate_uppercase(self):
|
69
76
|
def validator(value: str):
|
70
|
-
if
|
71
|
-
raise ValueError(
|
77
|
+
if not value.isupper():
|
78
|
+
raise ValueError("Value must be in uppercase.")
|
72
79
|
return value
|
73
|
-
|
80
|
+
return validator
|
74
81
|
|
75
|
-
@register_rule("
|
76
|
-
def
|
82
|
+
@register_rule("Is lowercase")
|
83
|
+
def validate_lowercase(self):
|
77
84
|
def validator(value: str):
|
78
|
-
if
|
79
|
-
raise ValueError(
|
85
|
+
if not value.islower():
|
86
|
+
raise ValueError("Value must be in lowercase.")
|
80
87
|
return value
|
81
|
-
|
88
|
+
return validator
|
82
89
|
|
83
|
-
@register_rule("
|
84
|
-
def
|
90
|
+
@register_rule("Matches regex {pattern:String}")
|
91
|
+
def validate_matches_regex(self, pattern: str):
|
85
92
|
def validator(value: str):
|
86
|
-
if not
|
87
|
-
raise ValueError("
|
93
|
+
if not re.match(pattern, value):
|
94
|
+
raise ValueError(f"Value does not match the required pattern {pattern}.")
|
95
|
+
return value
|
96
|
+
return validator
|
97
|
+
|
98
|
+
@register_rule("Is valid email")
|
99
|
+
def validate_email(self):
|
100
|
+
EMAIL_REGEX = r"^[\w\.-]+@[\w\.-]+\.\w+$"
|
101
|
+
|
102
|
+
def validator(value: str):
|
103
|
+
if not re.match(EMAIL_REGEX, value):
|
104
|
+
raise ValueError("Invalid email format.")
|
105
|
+
return value
|
106
|
+
return validator
|
107
|
+
|
108
|
+
@register_rule("Is valid URL")
|
109
|
+
def validate_url(self):
|
110
|
+
URL_REGEX = r"^(https?|ftp):\/\/[^\s/$.?#].[^\s]*$"
|
111
|
+
|
112
|
+
def validator(value: str):
|
113
|
+
if not re.match(URL_REGEX, value):
|
114
|
+
raise ValueError("Invalid URL format.")
|
115
|
+
return value
|
116
|
+
return validator
|
117
|
+
|
118
|
+
@register_rule("Has no digits")
|
119
|
+
def validate_no_digits(self):
|
120
|
+
def validator(value: str):
|
121
|
+
if any(char.isdigit() for char in value):
|
122
|
+
raise ValueError("Value must not contain any digits.")
|
88
123
|
return value
|
89
|
-
|
124
|
+
return validator
|
@@ -0,0 +1,68 @@
|
|
1
|
+
from typing import TYPE_CHECKING, Callable, List
|
2
|
+
|
3
|
+
from .Enums import LogicalOperator
|
4
|
+
from .ProcessedRule import ProcessedRule, LogicalParsedRule
|
5
|
+
|
6
|
+
if TYPE_CHECKING: # pragma: no cover
|
7
|
+
from ..field_types import BaseField
|
8
|
+
|
9
|
+
|
10
|
+
def and_or_validator(validators: List[Callable], operator: LogicalOperator) -> Callable:
|
11
|
+
def validator(value):
|
12
|
+
exceptions = []
|
13
|
+
for validator_ in validators:
|
14
|
+
try:
|
15
|
+
validator_(value)
|
16
|
+
exceptions.append(None) # No error, validation passed
|
17
|
+
except Exception as e:
|
18
|
+
exceptions.append(str(e)) # Store error message
|
19
|
+
|
20
|
+
if operator == LogicalOperator.OR and all(exceptions):
|
21
|
+
raise ValueError(f"None of the conditions were met. Errors: {exceptions}")
|
22
|
+
if operator == LogicalOperator.AND and any(exceptions):
|
23
|
+
exceptions = list(filter(None, exceptions))
|
24
|
+
raise ValueError(f"Not all conditions were met. Errors: {exceptions}")
|
25
|
+
return value
|
26
|
+
return validator
|
27
|
+
|
28
|
+
|
29
|
+
def not_validator(validator_: Callable):
|
30
|
+
def validator(value):
|
31
|
+
try:
|
32
|
+
validator_(value)
|
33
|
+
except Exception:
|
34
|
+
return value # Validation passes if the condition fails
|
35
|
+
else:
|
36
|
+
raise ValueError("Condition was met, but expected NOT to be met.")
|
37
|
+
return validator
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
class LogicalRule(ProcessedRule):
|
42
|
+
operator: LogicalOperator
|
43
|
+
processed_rules: List[ProcessedRule]
|
44
|
+
|
45
|
+
def __init__(self, operator: LogicalOperator, processed_rules: List[ProcessedRule]):
|
46
|
+
if operator not in LogicalOperator:
|
47
|
+
raise TypeError(f'Logical Operator not recognised: {operator}')
|
48
|
+
if not processed_rules:
|
49
|
+
raise ValueError("Logical rules must have at least one rule.")
|
50
|
+
if operator == LogicalOperator.NOT and len(processed_rules) != 1:
|
51
|
+
raise TypeError(f'Not Operator can only contain one rule. Cotains: {len(processed_rules)}')
|
52
|
+
self.operator = operator
|
53
|
+
self.processed_rules = processed_rules
|
54
|
+
|
55
|
+
@property
|
56
|
+
def parsed_rule(self) -> LogicalParsedRule:
|
57
|
+
return {self.operator: [pr.parsed_rule for pr in self.processed_rules]}
|
58
|
+
|
59
|
+
def get_validator(self, field_instance: "BaseField") -> Callable:
|
60
|
+
if self.operator in (LogicalOperator.OR, LogicalOperator.AND):
|
61
|
+
return and_or_validator([pr.get_validator(field_instance) for pr in self.processed_rules], self.operator)
|
62
|
+
elif self.operator == LogicalOperator.NOT:
|
63
|
+
return not_validator(self.processed_rules[0].get_validator(field_instance))
|
64
|
+
else:
|
65
|
+
raise TypeError(f'Logical Operator not recognised: {self.operator}')
|
66
|
+
|
67
|
+
def get_front_end_repr(self) -> dict:
|
68
|
+
return {self.operator: [pr.get_front_end_repr() for pr in self.processed_rules]}
|
data_sitter/rules/MatchedRule.py
CHANGED
@@ -1,23 +1,20 @@
|
|
1
|
-
from typing import TYPE_CHECKING, Any, Dict
|
1
|
+
from typing import TYPE_CHECKING, Any, Callable, Dict
|
2
2
|
|
3
3
|
from .Rule import Rule
|
4
4
|
from .RuleRegistry import RuleRegistry
|
5
|
+
from .ProcessedRule import ProcessedRule, MatchedParsedRule
|
5
6
|
from .Parser.parser_utils import get_value_from_reference
|
6
7
|
|
7
|
-
if TYPE_CHECKING:
|
8
|
-
from field_types import BaseField
|
8
|
+
if TYPE_CHECKING: # pragma: no cover
|
9
|
+
from ..field_types import BaseField
|
9
10
|
|
10
11
|
|
11
12
|
class RuleParsedValuesMismatch(Exception):
|
12
13
|
pass
|
13
14
|
|
14
15
|
|
15
|
-
class
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
class MatchedRule(Rule):
|
20
|
-
parsed_rule: str
|
16
|
+
class MatchedRule(ProcessedRule):
|
17
|
+
parsed_rule: MatchedParsedRule
|
21
18
|
parsed_values: Dict[str, Any]
|
22
19
|
values: Dict[str, Any]
|
23
20
|
|
@@ -48,10 +45,16 @@ class MatchedRule(Rule):
|
|
48
45
|
if set(self.rule_params) != parsed_values_values:
|
49
46
|
raise RuleParsedValuesMismatch(f"Rule Params: {self.rule_params}, Parsed Values: {parsed_values_values}")
|
50
47
|
|
51
|
-
def
|
48
|
+
def get_validator(self, field_instance: "BaseField") -> Callable:
|
52
49
|
field_class = RuleRegistry.get_type(self.field_type)
|
53
50
|
if not isinstance(field_instance, field_class):
|
54
|
-
raise
|
55
|
-
|
56
|
-
|
57
|
-
|
51
|
+
raise TypeError(f"Cannot add rule to {type(field_instance).__name__}, expected {self.field_type}.")
|
52
|
+
return self.rule_setter(self=field_instance, **self.resolved_values)
|
53
|
+
|
54
|
+
def get_front_end_repr(self) -> dict:
|
55
|
+
return {
|
56
|
+
"rule": self.field_rule,
|
57
|
+
"parsed_rule": self.parsed_rule,
|
58
|
+
"rule_params": self.rule_params,
|
59
|
+
"parsed_values": self.parsed_values,
|
60
|
+
}
|
@@ -56,23 +56,3 @@ alias_parameters_types = {
|
|
56
56
|
"String": parse_string,
|
57
57
|
"Strings": parse_array_of("String", parse_string),
|
58
58
|
}
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
# class Store()
|
67
|
-
# pass
|
68
|
-
|
69
|
-
|
70
|
-
# values = {"classes": ["UNCLASSIFIED"], "min_length": 5, "max_length": 50}
|
71
|
-
|
72
|
-
|
73
|
-
# alias_parser = Parser("Value in {possible_values:Strings}", extra_types=alias_parameters_types)
|
74
|
-
# # print(alias_parser.parse("Value In ['UNCLASSIFIED', 'CLASSIFIED']"))
|
75
|
-
|
76
|
-
# with Store(values=values) as store:
|
77
|
-
# print(alias_parser.parse("Value In $values.classes"))
|
78
|
-
# print(store.)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
from typing import TYPE_CHECKING, Dict, List, Union
|
3
|
+
|
4
|
+
from .Rule import Rule
|
5
|
+
from .Enums import LogicalOperator
|
6
|
+
|
7
|
+
if TYPE_CHECKING: # pragma: no cover
|
8
|
+
from ..field_types import BaseField
|
9
|
+
|
10
|
+
MatchedParsedRule = str
|
11
|
+
LogicalParsedRule = Dict[LogicalOperator, List["ParsedRule"]]
|
12
|
+
ParsedRule = Union[MatchedParsedRule, LogicalParsedRule]
|
13
|
+
|
14
|
+
|
15
|
+
class ProcessedRule(Rule, ABC):
|
16
|
+
parsed_rule: ParsedRule
|
17
|
+
|
18
|
+
@abstractmethod
|
19
|
+
def get_validator(self, field_instance: "BaseField"):
|
20
|
+
pass # pragma: no cover
|
21
|
+
|
22
|
+
@abstractmethod
|
23
|
+
def get_front_end_repr(self) -> dict:
|
24
|
+
pass # pragma: no cover
|
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)
|
@@ -1,64 +1,85 @@
|
|
1
1
|
from itertools import chain
|
2
|
-
from
|
3
|
-
|
2
|
+
from typing import TYPE_CHECKING, Callable, Dict, List, NamedTuple, Type
|
3
|
+
|
4
4
|
|
5
5
|
from .Rule import Rule
|
6
6
|
from ..utils.logger_config import get_logger
|
7
|
+
from ..field_types.FieldTypes import FieldTypes
|
7
8
|
|
8
9
|
|
9
|
-
if TYPE_CHECKING:
|
10
|
+
if TYPE_CHECKING: # pragma: no cover
|
10
11
|
from field_types.BaseField import BaseField
|
11
12
|
|
12
13
|
logger = get_logger(__name__)
|
13
14
|
|
14
15
|
|
15
|
-
class
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
@classmethod
|
20
|
-
def register_rule(cls, field_rule: str):
|
21
|
-
def _register(func: callable):
|
22
|
-
field_type, func_name = func.__qualname__.split(".")
|
23
|
-
logger.debug("Registering function '%s' for %s. Rule: %s", func_name, field_type, field_rule)
|
16
|
+
class RuleMetadata(NamedTuple):
|
17
|
+
rule: str
|
18
|
+
fixed_params: dict
|
24
19
|
|
25
|
-
rule = Rule(field_type, field_rule, func)
|
26
|
-
cls.rules[field_type].append(rule)
|
27
|
-
logger.debug("Function '%s' Registered", func_name)
|
28
|
-
return func
|
29
20
|
|
30
|
-
|
21
|
+
class RuleRegistry:
|
22
|
+
rules: Dict[str, List[Rule]] = {}
|
23
|
+
type_map: Dict[str, Type["BaseField"]] = {}
|
31
24
|
|
32
25
|
@classmethod
|
33
26
|
def register_field(cls, field_class: Type["BaseField"]) -> Type["BaseField"]:
|
34
|
-
|
27
|
+
field_type_name = field_class.type_name
|
28
|
+
cls.type_map[field_class.type_name] = field_class
|
29
|
+
cls.rules[field_class.type_name] = []
|
30
|
+
|
31
|
+
for method in field_class.__dict__.values():
|
32
|
+
metadata: RuleMetadata = getattr(method, "_rule_metadata", None)
|
33
|
+
if metadata is None:
|
34
|
+
continue
|
35
|
+
rule = Rule(
|
36
|
+
field_type=field_type_name,
|
37
|
+
field_rule=metadata.rule,
|
38
|
+
rule_setter=method,
|
39
|
+
fixed_params=metadata.fixed_params
|
40
|
+
)
|
41
|
+
cls.add_rule(field_class, rule)
|
35
42
|
return field_class
|
36
43
|
|
37
44
|
@classmethod
|
38
|
-
def
|
39
|
-
|
45
|
+
def add_rule(cls, field_class: Type["BaseField"], rule: Rule):
|
46
|
+
if field_class.type_name not in cls.rules:
|
47
|
+
raise ValueError(f"Field not registered: {field_class.type_name}")
|
48
|
+
cls.rules[field_class.type_name].append(rule)
|
49
|
+
|
50
|
+
@classmethod
|
51
|
+
def get_type(cls, type_name: str) -> Type["BaseField"]:
|
52
|
+
return cls.type_map.get(type_name)
|
40
53
|
|
41
54
|
@classmethod
|
42
55
|
def get_rules_for(cls, field_class: Type["BaseField"]):
|
43
|
-
if field_class.
|
44
|
-
return cls.rules[
|
56
|
+
if field_class.type_name == FieldTypes.BASE:
|
57
|
+
return cls.rules[FieldTypes.BASE]
|
45
58
|
parent_rules = list(chain.from_iterable(cls.get_rules_for(p) for p in field_class.get_parents()))
|
46
|
-
return cls.rules[field_class.
|
59
|
+
return cls.rules[field_class.type_name] + parent_rules
|
47
60
|
|
48
61
|
@classmethod
|
49
62
|
def get_rules_definition(cls):
|
50
63
|
return [
|
51
64
|
{
|
52
|
-
"field":
|
53
|
-
"parent_field": [p.
|
54
|
-
"rules": cls.rules.get(
|
65
|
+
"field": name,
|
66
|
+
"parent_field": [p.type_name for p in field_class.get_parents()],
|
67
|
+
"rules": cls.rules.get(name, [])
|
55
68
|
}
|
56
|
-
for
|
69
|
+
for name, field_class in cls.type_map.items()
|
57
70
|
]
|
58
71
|
|
59
72
|
|
60
|
-
def register_rule(rule: str):
|
61
|
-
|
73
|
+
def register_rule(rule: str, fixed_params: dict = None):
|
74
|
+
def _register(func: Callable):
|
75
|
+
setattr(func, "_rule_metadata",
|
76
|
+
RuleMetadata(
|
77
|
+
rule=rule,
|
78
|
+
fixed_params=fixed_params or {}
|
79
|
+
)
|
80
|
+
)
|
81
|
+
return func
|
82
|
+
return _register
|
62
83
|
|
63
84
|
|
64
85
|
def register_field(field_class: type):
|
data_sitter/rules/__init__.py
CHANGED
@@ -1,14 +1,20 @@
|
|
1
1
|
from .Rule import Rule
|
2
2
|
from .Parser import RuleParser
|
3
|
+
from .Enums import LogicalOperator
|
3
4
|
from .MatchedRule import MatchedRule
|
5
|
+
from .LogicalRule import LogicalRule
|
6
|
+
from .ProcessedRule import ProcessedRule
|
4
7
|
from .RuleRegistry import RuleRegistry, register_rule, register_field
|
5
8
|
|
6
9
|
|
7
10
|
__all__ = [
|
8
11
|
"Rule",
|
9
|
-
"MatchedRule",
|
10
12
|
"RuleParser",
|
13
|
+
"MatchedRule",
|
14
|
+
"LogicalRule",
|
15
|
+
"ProcessedRule",
|
11
16
|
"RuleRegistry",
|
12
17
|
"register_rule",
|
13
18
|
"register_field",
|
19
|
+
"LogicalOperator",
|
14
20
|
]
|
@@ -11,7 +11,7 @@ DEFAULT_LEVEL = "INFO"
|
|
11
11
|
VALID_LOG_LEVEL = ["CRITICAL", "FATAL", "ERROR", "WARN", "WARNING", "INFO", "DEBUG", "NOTSET"]
|
12
12
|
LOG_LEVEL = environ.get("LOG_LEVEL", DEFAULT_LEVEL)
|
13
13
|
|
14
|
-
if LOG_LEVEL not in VALID_LOG_LEVEL:
|
14
|
+
if LOG_LEVEL not in VALID_LOG_LEVEL: # pragma: no cover
|
15
15
|
LOG_LEVEL = DEFAULT_LEVEL
|
16
16
|
|
17
17
|
|