brdocs-validation 0.3.0__py3-none-any.whl → 0.5.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.
br_docs/__init__.py CHANGED
@@ -1,5 +1,6 @@
1
+ from typing import Annotated
2
+
1
3
  from pydantic.functional_validators import AfterValidator
2
- from typing_extensions import Annotated
3
4
 
4
5
  from br_docs.validators.cert import CERTv
5
6
  from br_docs.validators.cnh import CNHv
@@ -8,9 +9,9 @@ from br_docs.validators.cns import CNSv
8
9
  from br_docs.validators.cpf import CPFv
9
10
  from br_docs.validators.nis import NISv
10
11
  from br_docs.validators.renavam import RENAVAMv
12
+ from br_docs.validators.sei import SEIv
11
13
  from br_docs.validators.te import TEv
12
14
 
13
-
14
15
  CPF = Annotated[str, AfterValidator(CPFv())]
15
16
  CNPJ = Annotated[str, AfterValidator(CNPJv())]
16
17
  CNH = Annotated[str, AfterValidator(CNHv())]
@@ -19,3 +20,4 @@ CNS = Annotated[str, AfterValidator(CNSv())]
19
20
  RENAVAM = Annotated[str, AfterValidator(RENAVAMv())]
20
21
  TE = Annotated[str, AfterValidator(TEv())]
21
22
  CERT = Annotated[str, AfterValidator(CERTv())]
23
+ SEI = Annotated[str, AfterValidator(SEIv())]
@@ -16,7 +16,7 @@ class CheckDigits(ABC, ValuesRegex):
16
16
  return value
17
17
 
18
18
  def validate(self, value: str):
19
- numbers = list(map(int, re.findall(r"\d", value)))
19
+ numbers = list(map(int, re.findall(r'\d', value)))
20
20
  check_digits = [numbers.pop(x) for x in range(-self.CHECK_DIGITS, 0)]
21
21
  digits_calculated = self.calculate_digits(numbers)
22
22
  for check_digit, digit_calculated in zip(check_digits, digits_calculated):
@@ -5,7 +5,7 @@ from br_docs.validators import CheckDigits
5
5
 
6
6
  class CERTv(CheckDigits):
7
7
  """ Certidões de casamento, nascimento e óbito """
8
- Patterns = re.compile(r"^\d{32}$"),
8
+ Patterns = re.compile(r'^\d{32}$'),
9
9
  CHECK_DIGITS = 2
10
10
  CertAlgarismsMultipliers = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
11
11
 
br_docs/validators/cnh.py CHANGED
@@ -4,7 +4,7 @@ from br_docs.validators import CheckDigits
4
4
 
5
5
 
6
6
  class CNHv(CheckDigits):
7
- Patterns = re.compile(r"^\d{11}$"),
7
+ Patterns = re.compile(r'^\d{11}$'),
8
8
  CHECK_DIGITS = 2
9
9
 
10
10
  @classmethod
@@ -1,25 +1,77 @@
1
1
  import re
2
+ from math import ceil
3
+
4
+ from pydantic_core import PydanticCustomError
2
5
 
3
6
  from br_docs.validators import CheckDigits
4
7
 
5
8
 
6
9
  class CNPJv(CheckDigits):
7
- Patterns = re.compile(r"^\d{14}$"), re.compile(r"^[0-9]{2}\.[0-9]{3}\.[0-9]{3}/[0-9]{4}-[0-9]{2}$"),
8
- CnpjAlgarismsMultipliers = 6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2,
10
+ """
11
+ CNPJ validator supporting both numeric (legacy) and alphanumeric (2026+) formats.
12
+ Algorithm: https://www.serpro.gov.br/ (calculodvcnpjalfanaumerico.pdf)
13
+ """
14
+
15
+ Patterns = (
16
+ re.compile(r'^\d{14}$'), # Numeric unformatted
17
+ re.compile(
18
+ r'^[0-9]{2}\.[0-9]{3}\.[0-9]{3}/[0-9]{4}-[0-9]{2}$'
19
+ ), # Numeric formatted
20
+ re.compile(r'^[0-9A-Z]{12}\d{2}$', re.IGNORECASE), # Alphanumeric unformatted
21
+ re.compile(
22
+ r'^[0-9A-Z]{2}\.[0-9A-Z]{3}\.[0-9A-Z]{3}/[0-9A-Z]{4}-\d{2}$', re.IGNORECASE
23
+ ), # Alphanumeric formatted
24
+ )
9
25
  CHECK_DIGITS = 2
26
+ CnpjAlgarismsMultipliers = 6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2
27
+
28
+ def validate(self, value: str):
29
+ """Validate CNPJ with alphanumeric support."""
30
+ clean = value.upper().replace('.', '').replace('/', '').replace('-', '')
31
+ base_chars = clean[:-2]
32
+ check_str = clean[-2:]
33
+ try:
34
+ check_1, check_2 = int(check_str[0]), int(check_str[1])
35
+ except ValueError:
36
+ raise PydanticCustomError('invalid', 'Invalid value')
37
+ calc_1, calc_2 = self.calculate_digits_alphanumeric(base_chars)
38
+ if check_1 != calc_1 or check_2 != calc_2:
39
+ raise PydanticCustomError('invalid', 'Invalid value')
40
+
41
+ @staticmethod
42
+ def char_to_value(char: str) -> int:
43
+ return ord(char) - 48
44
+
45
+ @classmethod
46
+ def calculate_digits_alphanumeric(cls, base_chars: str) -> tuple[int, int]:
47
+ values = [cls.char_to_value(c) for c in base_chars]
48
+ d1 = cls._calc_digit(values)
49
+ d2 = cls._calc_digit(values + [d1])
50
+ return d1, d2
51
+
52
+ @staticmethod
53
+ def _calc_digit(values: list[int]) -> int:
54
+ n = len(values)
55
+ weights = []
56
+ for _ in range(ceil(n / 8)):
57
+ weights.extend(range(2, 10))
58
+ weights = weights[:n]
59
+ weights.reverse()
60
+ total = sum(v * w for v, w in zip(values, weights))
61
+ rem = total % 11
62
+ return 0 if rem < 2 else 11 - rem
10
63
 
11
64
  @classmethod
12
65
  def calculate_digits(cls, non_digits: list[int]) -> tuple[int, int]:
13
- """ https://web.archive.org/web/20240222180515/https://www.macoratti.net/alg_cnpj.htm """
14
- calc = sum(x*y for x, y in zip(non_digits, cls.CnpjAlgarismsMultipliers[1:])) % 11
15
- if calc < 2:
16
- digit_one = 0
17
- else:
18
- digit_one = 11 - calc
19
- non_digits.append(digit_one)
20
- calc_2 = sum(x*y for x, y in zip(non_digits, cls.CnpjAlgarismsMultipliers)) % 11
21
- if calc_2 < 2:
22
- digit_two = 0
23
- else:
24
- digit_two = 11 - calc_2
25
- return digit_one, digit_two
66
+ """Legacy method for backward compatibility."""
67
+ calc = (
68
+ sum(x * y for x, y in zip(non_digits, cls.CnpjAlgarismsMultipliers[1:]))
69
+ % 11
70
+ )
71
+ d1 = 0 if calc < 2 else 11 - calc
72
+ non_digits.append(d1)
73
+ calc2 = (
74
+ sum(x * y for x, y in zip(non_digits, cls.CnpjAlgarismsMultipliers)) % 11
75
+ )
76
+ d2 = 0 if calc2 < 2 else 11 - calc2
77
+ return d1, d2
br_docs/validators/cns.py CHANGED
@@ -6,7 +6,7 @@ from br_docs.validators import CheckDigits
6
6
 
7
7
 
8
8
  class CNSv(CheckDigits):
9
- Patterns = re.compile(r"^\d{15}$"),
9
+ Patterns = re.compile(r'^\d{15}$'),
10
10
 
11
11
  def validate(self, value: str):
12
12
  valid_value = self.calculate_digits(list(map(int, value)))[0]
br_docs/validators/cpf.py CHANGED
@@ -4,7 +4,7 @@ from br_docs.validators import CheckDigits
4
4
 
5
5
 
6
6
  class CPFv(CheckDigits):
7
- Patterns = re.compile(r"^(?!(\d)\1{10}$)\d{11}$"), re.compile(r"^[0-9]{3}\.[0-9]{3}\.[0-9]{3}-[0-9]{2}$")
7
+ Patterns = re.compile(r'^(?!(\d)\1{10}$)\d{11}$'), re.compile(r'^[0-9]{3}\.[0-9]{3}\.[0-9]{3}-[0-9]{2}$')
8
8
  CHECK_DIGITS = 2
9
9
 
10
10
  @staticmethod
br_docs/validators/nis.py CHANGED
@@ -6,7 +6,7 @@ from br_docs.validators import CheckDigits
6
6
  class NISv(CheckDigits):
7
7
  """ NIS is the number of NIT, PIS, PASEP and NIS itself. """
8
8
 
9
- Patterns = re.compile(r"^\d{11}$"), re.compile(r"^[0-9]{3}\.[0-9]{5}\.[0-9]{2}-[0-9]$")
9
+ Patterns = re.compile(r'^\d{11}$'), re.compile(r'^[0-9]{3}\.[0-9]{5}\.[0-9]{2}-[0-9]$')
10
10
  NisAlgarismsMultipliers = 3, 2, 9, 8, 7, 6, 5, 4, 3, 2
11
11
  CHECK_DIGITS = 1
12
12
 
@@ -4,7 +4,7 @@ from br_docs.validators import CheckDigits
4
4
 
5
5
 
6
6
  class RENAVAMv(CheckDigits):
7
- Patterns = re.compile(r"^\d{9,11}$"),
7
+ Patterns = re.compile(r'^\d{9,11}$'),
8
8
  CHECK_DIGITS = 1
9
9
 
10
10
  @staticmethod
@@ -0,0 +1,17 @@
1
+ import re
2
+
3
+ from pydantic_core import PydanticCustomError
4
+
5
+
6
+ class SEIv:
7
+ Patterns = re.compile(r'^\d{5}-?\d{8}/?\d{4}-?\d{2}$')
8
+
9
+ def __call__(self, value: str) -> str:
10
+ self.validate(value)
11
+ return value
12
+
13
+ def validate(self, value: str) -> str:
14
+ check_format = bool(self.Patterns.match(value))
15
+ if check_format is not True:
16
+ raise PydanticCustomError('invalid', 'Invalid Value')
17
+ return value
br_docs/validators/te.py CHANGED
@@ -7,7 +7,7 @@ from br_docs.validators import CheckDigits
7
7
 
8
8
  class TEv(CheckDigits):
9
9
  """ Titulo de eleitor """
10
- Patterns = re.compile(r"^\d{12}$"),
10
+ Patterns = re.compile(r'^\d{12}$'),
11
11
 
12
12
  def validate(self, value: str):
13
13
  valid_value = self.calculate_digits(list(map(int, value)))[0]
@@ -13,6 +13,6 @@ class ValuesRegex:
13
13
  next(filter(lambda x: x.match(value), self.Patterns))
14
14
  except StopIteration:
15
15
  raise PydanticCustomError(
16
- "format",
16
+ 'format',
17
17
  "Invalid value's format"
18
18
  )
@@ -1,9 +1,9 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: brdocs-validation
3
- Version: 0.3.0
3
+ Version: 0.5.0
4
4
  Summary: Validate brazilian documents using Type Hints in classes inheriting Pydantic's (V2) BaseModel
5
- Author-email: Vinícius Aguiar <vaguiararqdevsoftware@proton.me>
6
- Maintainer-email: Vinícius Aguiar <vaguiararqdevsoftware@proton.me>
5
+ Author-email: Vinícius Aguiar <vaguiararqdevsoftware@proton.me>, Rafael Kamimura <rafael.kamimura@proton.me>
6
+ Maintainer-email: Vinícius Aguiar <vaguiararqdevsoftware@proton.me>, Rafael Kamimura <rafael.kamimura@proton.me>
7
7
  Project-URL: Repository, https://github.com/vinicius-oa/BRdocs-validation
8
8
  Keywords: pydantic-v2,cpf-validador,cnpj-validador,validador-pispasep,validador-titulo-eleitor
9
9
  Classifier: Development Status :: 5 - Production/Stable
@@ -20,15 +20,16 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
20
  Requires-Python: >=3.10
21
21
  Description-Content-Type: text/markdown
22
22
  License-File: LICENSE.txt
23
- Requires-Dist: pydantic >=2.0
23
+ Requires-Dist: pydantic>=2.0
24
24
  Provides-Extra: dev
25
- Requires-Dist: build ; extra == 'dev'
26
- Requires-Dist: mypy ; extra == 'dev'
27
- Requires-Dist: pytest ; extra == 'dev'
28
- Requires-Dist: wheel ; extra == 'dev'
29
- Requires-Dist: twine ; extra == 'dev'
30
- Requires-Dist: tox ; extra == 'dev'
31
- Requires-Dist: ruff ; extra == 'dev'
25
+ Requires-Dist: build; extra == "dev"
26
+ Requires-Dist: mypy; extra == "dev"
27
+ Requires-Dist: pytest; extra == "dev"
28
+ Requires-Dist: wheel; extra == "dev"
29
+ Requires-Dist: twine; extra == "dev"
30
+ Requires-Dist: tox; extra == "dev"
31
+ Requires-Dist: ruff; extra == "dev"
32
+ Dynamic: license-file
32
33
 
33
34
  ![Test](https://github.com/vinicius-oa/BRdocs-validation/actions/workflows/test.yml/badge.svg)
34
35
  ![codecov](https://codecov.io/gh/vinicius-oa/BRdocs-validation/graph/badge.svg?token=Z211YIKO8L)
@@ -54,10 +55,12 @@ pip install brdocs-validation
54
55
  | RENAVAM | | Only numbers | Length: _9, 10 & 11_ |
55
56
  | TE | Título de eleitor | Only numbers | |
56
57
  | CERT | Certidão de casamento, nascimento e óbito | Only numbers | |
58
+ | SEI | Número do Processo SEI | 12345-67890123/4567-89 OR without special chars | |
59
+
57
60
  ## Usage
58
61
 
59
62
  ```python
60
- from br_docs import CNPJ, CPF, CNH, NIS, CNS, RENAVAM, TE, CERT
63
+ from br_docs import CNPJ, CPF, CNH, NIS, CNS, RENAVAM, TE, CERT, SEI
61
64
  from pydantic import BaseModel
62
65
 
63
66
 
@@ -70,4 +73,5 @@ class User(BaseModel):
70
73
  renavam: RENAVAM
71
74
  te: TE
72
75
  cert: CERT
76
+ sei: SEI
73
77
  ```
@@ -0,0 +1,18 @@
1
+ br_docs/__init__.py,sha256=waSCaSq_1h2UQ58DgWr4lFUhvxBII7N6W7qzYOWZO4Q,875
2
+ br_docs/validators/__init__.py,sha256=5YQuwUepQoAwNpGhme8gvc7FXZLw7jtfAOxOim6QBRE,1021
3
+ br_docs/validators/cert.py,sha256=D0UYje40qgzQ68ktXCj_WAJVAf95nf67nBXdxv82Y1Q,962
4
+ br_docs/validators/cnh.py,sha256=K1phbs5DARaLr10M27l9UMxwhF2liodd4pCvb83cQ8Q,1119
5
+ br_docs/validators/cnpj.py,sha256=wcXPxzoCPgivlNwiokJbjsnlE2CfaGl1HKyAEzin9rY,2696
6
+ br_docs/validators/cns.py,sha256=x9X6_FGIHn-rCoqPynEbunbv7V_4KKp49jkdEz1IKts,1140
7
+ br_docs/validators/cpf.py,sha256=XoZuVdKAvXgVFP6sire4ngyqzumBrjB5FH3Lm9k_Bcc,611
8
+ br_docs/validators/nis.py,sha256=yzk_ozDuWXn4GgsjpWMQaQsVkTZktiP5qBXhSM483SE,661
9
+ br_docs/validators/renavam.py,sha256=xPn8yuVDZBPpx1o-jzD3MBPUj_q4fpMQf_UQUIP3f4k,738
10
+ br_docs/validators/sei.py,sha256=WHy3exmb-5tlZuNmMxkTzyMHBOhUrm6uyj6nyozhXv4,448
11
+ br_docs/validators/te.py,sha256=G4Gw_MX9YFDx6jLV9QULnqM-wBQq60O4JC8QQnADYYI,1153
12
+ br_docs/validators/types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ br_docs/validators/types/format.py,sha256=ZVqlJ5sGWIpxTyJYIB8JCu2EaL_yDEehUfqTFnkh6Qc,421
14
+ brdocs_validation-0.5.0.dist-info/licenses/LICENSE.txt,sha256=FdwJdtrJG9B1E0C3y6BG6QhRznIfFLzPXdUzclDkZYs,1073
15
+ brdocs_validation-0.5.0.dist-info/METADATA,sha256=OqfVfd9wRasP4q0cDD64OgC28QpOo7LklEQy8xernGs,3932
16
+ brdocs_validation-0.5.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
17
+ brdocs_validation-0.5.0.dist-info/top_level.txt,sha256=COjwP4hy4qNtPXnPVmsgWBi_-2Byyw_0gmjorp3UnRA,8
18
+ brdocs_validation-0.5.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,17 +0,0 @@
1
- br_docs/__init__.py,sha256=fOgdmOpBtrRKMwoxQdlKz-zB6XyorhB5s9mZi3lJyg0,801
2
- br_docs/validators/__init__.py,sha256=7DeKn9Uq2znYN-P2yAVRkqwGY-Bvh8GIEjbpCMe9sRQ,1021
3
- br_docs/validators/cert.py,sha256=KpRxqavETcpSPVJbIWz7gfs-KjjnsuvmtZcV6mmAcI4,962
4
- br_docs/validators/cnh.py,sha256=3rjcusDdCdUD_id_oIWcMtM0biATDu_yYkuaq_NVSEg,1119
5
- br_docs/validators/cnpj.py,sha256=0avmB7_apQChP2WUHTfLxWEe6k9-4qA0jRbdu7mLqM4,914
6
- br_docs/validators/cns.py,sha256=sDiZEeoUZ2yo9J-3opE2ZjOTVO9eTCBlPBhRBlfuGcE,1140
7
- br_docs/validators/cpf.py,sha256=a9oxE3Su-RYpGKMAzO4SUD4kddm8qkbbhSVKFEhkOog,611
8
- br_docs/validators/nis.py,sha256=47wi0sLjsr9aDdxVuVfSMRtQfV9AnW32tm2j5hRjiO0,661
9
- br_docs/validators/renavam.py,sha256=IeJimMmERHGZ1b3Tjo731ThZzNR7dA1NeZA97r3CqOo,738
10
- br_docs/validators/te.py,sha256=KuGwM9pVydP1QKeKd6t57Ay4IG6augY11qIRwjLgDVo,1153
11
- br_docs/validators/types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- br_docs/validators/types/format.py,sha256=hj4f3KjW7mAz7l1F6pXby4_BahGNGdaIbNbmsQxrXTI,421
13
- brdocs_validation-0.3.0.dist-info/LICENSE.txt,sha256=FdwJdtrJG9B1E0C3y6BG6QhRznIfFLzPXdUzclDkZYs,1073
14
- brdocs_validation-0.3.0.dist-info/METADATA,sha256=nzjAVsrS3BSB7r2eSlA18_yT9mb7zxKWhp7WCrZ--Co,3669
15
- brdocs_validation-0.3.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
16
- brdocs_validation-0.3.0.dist-info/top_level.txt,sha256=COjwP4hy4qNtPXnPVmsgWBi_-2Byyw_0gmjorp3UnRA,8
17
- brdocs_validation-0.3.0.dist-info/RECORD,,