cup-check 0.2.0__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.
cup_check/__init__.py ADDED
@@ -0,0 +1,14 @@
1
+ """Validazione formale locale dei Codici Unici di Progetto."""
2
+
3
+ from cup_check.models import Outcome, Rule, ValidationResult, Warning
4
+ from cup_check.validator import normalize_cup, validate_format, validate_many
5
+
6
+ __all__ = [
7
+ "Outcome",
8
+ "Rule",
9
+ "ValidationResult",
10
+ "Warning",
11
+ "normalize_cup",
12
+ "validate_format",
13
+ "validate_many",
14
+ ]
cup_check/models.py ADDED
@@ -0,0 +1,33 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from enum import StrEnum
5
+
6
+
7
+ class Outcome(StrEnum):
8
+ INVALIDO_FORMATO = "INVALIDO_FORMATO"
9
+ FORMATO_VALIDO_DA_VERIFICARE = "FORMATO_VALIDO_DA_VERIFICARE"
10
+
11
+
12
+ class Rule(StrEnum):
13
+ R0 = "R0"
14
+ R1 = "R1"
15
+ R2 = "R2"
16
+ R3 = "R3"
17
+ R4 = "R4"
18
+ R5 = "R5"
19
+
20
+
21
+ class Warning(StrEnum):
22
+ N1 = "N1"
23
+ N2 = "N2"
24
+
25
+
26
+ @dataclass(frozen=True)
27
+ class ValidationResult:
28
+ input_row: int | None
29
+ raw_value: str
30
+ normalized_value: str
31
+ outcome: Outcome
32
+ failed_rules: tuple[Rule, ...]
33
+ warnings: tuple[Warning, ...]
cup_check/validator.py ADDED
@@ -0,0 +1,90 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from collections.abc import Iterable
5
+ from datetime import UTC, datetime
6
+
7
+ from cup_check.models import Outcome, Rule, ValidationResult, Warning
8
+
9
+ _ALLOWED_CHARS = re.compile(r"^[A-Z0-9]*$")
10
+ _FIRST_POSITION = re.compile(r"^[A-Z]")
11
+ _TWO_DIGIT_YEAR = re.compile(r"^\d{2}$")
12
+
13
+
14
+ def normalize_cup(value: object) -> str:
15
+ return str("" if value is None else value).strip().upper()
16
+
17
+
18
+ def validate_format(
19
+ value: object,
20
+ input_row: int | None = None,
21
+ *,
22
+ current_year: int | None = None,
23
+ ) -> ValidationResult:
24
+ raw_value = str("" if value is None else value)
25
+ trimmed_value = raw_value.strip()
26
+ normalized_value = normalize_cup(raw_value)
27
+ failed_rules: list[Rule] = []
28
+ warnings = _normalization_warnings(raw_value, trimmed_value, normalized_value)
29
+
30
+ if len(trimmed_value) == 0:
31
+ return ValidationResult(
32
+ input_row=input_row,
33
+ raw_value=raw_value,
34
+ normalized_value=normalized_value,
35
+ outcome=Outcome.INVALIDO_FORMATO,
36
+ failed_rules=(Rule.R0,),
37
+ warnings=warnings,
38
+ )
39
+
40
+ if len(normalized_value) != 15:
41
+ failed_rules.append(Rule.R1)
42
+
43
+ if _ALLOWED_CHARS.fullmatch(normalized_value) is None:
44
+ failed_rules.append(Rule.R2)
45
+
46
+ if _FIRST_POSITION.match(normalized_value) is None:
47
+ failed_rules.append(Rule.R3)
48
+
49
+ year_token = normalized_value[4:6]
50
+ two_digit_year = (current_year if current_year is not None else datetime.now(UTC).year) % 100
51
+ if _TWO_DIGIT_YEAR.fullmatch(year_token) is None or int(year_token) > two_digit_year:
52
+ failed_rules.append(Rule.R4)
53
+
54
+ if not (len(normalized_value) > 3 and "A" <= normalized_value[3] <= "Z"):
55
+ failed_rules.append(Rule.R5)
56
+
57
+ return ValidationResult(
58
+ input_row=input_row,
59
+ raw_value=raw_value,
60
+ normalized_value=normalized_value,
61
+ outcome=(
62
+ Outcome.FORMATO_VALIDO_DA_VERIFICARE
63
+ if len(failed_rules) == 0
64
+ else Outcome.INVALIDO_FORMATO
65
+ ),
66
+ failed_rules=tuple(failed_rules),
67
+ warnings=warnings,
68
+ )
69
+
70
+
71
+ def validate_many(
72
+ values: Iterable[object],
73
+ *,
74
+ current_year: int | None = None,
75
+ ) -> tuple[ValidationResult, ...]:
76
+ return tuple(
77
+ validate_format(value, input_row=index, current_year=current_year)
78
+ for index, value in enumerate(values, start=1)
79
+ )
80
+
81
+
82
+ def _normalization_warnings(
83
+ raw_value: str, trimmed_value: str, normalized_value: str
84
+ ) -> tuple[Warning, ...]:
85
+ warnings = []
86
+ if raw_value != trimmed_value:
87
+ warnings.append(Warning.N1)
88
+ if trimmed_value != normalized_value:
89
+ warnings.append(Warning.N2)
90
+ return tuple(warnings)
@@ -0,0 +1,42 @@
1
+ Metadata-Version: 2.4
2
+ Name: cup-check
3
+ Version: 0.2.0
4
+ Summary: Validazione formale locale dei Codici Unici di Progetto (CUP).
5
+ Project-URL: Homepage, https://github.com/ale-saglia/cup-check
6
+ Project-URL: Repository, https://github.com/ale-saglia/cup-check
7
+ Project-URL: Issues, https://github.com/ale-saglia/cup-check/issues
8
+ Author: Alessandro Saglia
9
+ License-Expression: EUPL-1.2
10
+ Keywords: codice unico progetto,cup,opencup,validazione
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: European Union Public Licence 1.2 (EUPL 1.2)
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
+ Requires-Python: >=3.12
18
+ Description-Content-Type: text/markdown
19
+
20
+ # cup-check
21
+
22
+ Libreria Python per validare localmente il formato dei Codici Unici di Progetto (CUP).
23
+
24
+ La verifica e solo formale: un CUP con formato valido viene restituito come
25
+ `FORMATO_VALIDO_DA_VERIFICARE`, non come CUP esistente.
26
+
27
+ ```python
28
+ from cup_check import validate_format
29
+
30
+ result = validate_format("G17H03000130001")
31
+
32
+ print(result.outcome)
33
+ print(result.failed_rules)
34
+ ```
35
+
36
+ Per validare piu valori:
37
+
38
+ ```python
39
+ from cup_check import validate_many
40
+
41
+ results = validate_many(["G17H03000130001", "117H03000130001"])
42
+ ```
@@ -0,0 +1,6 @@
1
+ cup_check/__init__.py,sha256=ZkUNNXOVt7d6edAt1zKUrpxQNAbnmirRsPpaIM7Rtio,358
2
+ cup_check/models.py,sha256=T-uZUTMh95gyqYmTWNjr7Ah0dhq1fPElIuVazziBkOE,601
3
+ cup_check/validator.py,sha256=IPmmEaynv2oBGki6jTHiI3BVMUdd-xrNkkPujZmT5b4,2729
4
+ cup_check-0.2.0.dist-info/METADATA,sha256=l5szInRdZTlvHcfQ7BkwgciR-Sb3Zjj3c0UFx9sxCl4,1364
5
+ cup_check-0.2.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
6
+ cup_check-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any