pydantic-brasil 0.1.0__tar.gz

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 (34) hide show
  1. pydantic_brasil-0.1.0/LICENSE +21 -0
  2. pydantic_brasil-0.1.0/PKG-INFO +361 -0
  3. pydantic_brasil-0.1.0/README.md +323 -0
  4. pydantic_brasil-0.1.0/pydantic_brasil/__init__.py +64 -0
  5. pydantic_brasil-0.1.0/pydantic_brasil/base.py +138 -0
  6. pydantic_brasil-0.1.0/pydantic_brasil/cep.py +125 -0
  7. pydantic_brasil-0.1.0/pydantic_brasil/cnpj.py +161 -0
  8. pydantic_brasil-0.1.0/pydantic_brasil/cpf.py +148 -0
  9. pydantic_brasil-0.1.0/pydantic_brasil/document.py +107 -0
  10. pydantic_brasil-0.1.0/pydantic_brasil/exceptions.py +55 -0
  11. pydantic_brasil-0.1.0/pydantic_brasil/inscricao_estadual.py +224 -0
  12. pydantic_brasil-0.1.0/pydantic_brasil/money.py +198 -0
  13. pydantic_brasil-0.1.0/pydantic_brasil/phone.py +232 -0
  14. pydantic_brasil-0.1.0/pydantic_brasil/pix.py +177 -0
  15. pydantic_brasil-0.1.0/pydantic_brasil/py.typed +1 -0
  16. pydantic_brasil-0.1.0/pydantic_brasil/vehicles.py +261 -0
  17. pydantic_brasil-0.1.0/pydantic_brasil.egg-info/PKG-INFO +361 -0
  18. pydantic_brasil-0.1.0/pydantic_brasil.egg-info/SOURCES.txt +32 -0
  19. pydantic_brasil-0.1.0/pydantic_brasil.egg-info/dependency_links.txt +1 -0
  20. pydantic_brasil-0.1.0/pydantic_brasil.egg-info/requires.txt +14 -0
  21. pydantic_brasil-0.1.0/pydantic_brasil.egg-info/top_level.txt +1 -0
  22. pydantic_brasil-0.1.0/pyproject.toml +99 -0
  23. pydantic_brasil-0.1.0/setup.cfg +4 -0
  24. pydantic_brasil-0.1.0/tests/test_cep.py +66 -0
  25. pydantic_brasil-0.1.0/tests/test_cnpj.py +82 -0
  26. pydantic_brasil-0.1.0/tests/test_coverage_boost.py +119 -0
  27. pydantic_brasil-0.1.0/tests/test_cpf.py +95 -0
  28. pydantic_brasil-0.1.0/tests/test_document.py +58 -0
  29. pydantic_brasil-0.1.0/tests/test_inscricao_estadual.py +64 -0
  30. pydantic_brasil-0.1.0/tests/test_money.py +84 -0
  31. pydantic_brasil-0.1.0/tests/test_phone.py +75 -0
  32. pydantic_brasil-0.1.0/tests/test_pix.py +69 -0
  33. pydantic_brasil-0.1.0/tests/test_pydantic_integration.py +70 -0
  34. pydantic_brasil-0.1.0/tests/test_vehicles.py +93 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Luan Schons
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,361 @@
1
+ Metadata-Version: 2.4
2
+ Name: pydantic-brasil
3
+ Version: 0.1.0
4
+ Summary: Modern, high-performance Brazilian data types and validators for Pydantic v2 (CPF, CNPJ, CEP, Chave PIX, Telefone, Placa Mercosul, CNH, IE, Dinheiro BRL)
5
+ Author-email: Luan Schons <luanschons2000@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Luan1Schons/pydantic-brasil
8
+ Project-URL: Repository, https://github.com/Luan1Schons/pydantic-brasil
9
+ Project-URL: Issues, https://github.com/Luan1Schons/pydantic-brasil/issues
10
+ Keywords: pydantic,pydantic-v2,brasil,brazil,cpf,cnpj,cep,pix,chave-pix,telefone,placa,mercosul,fastapi,validation
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: pydantic>=2.0.0
25
+ Requires-Dist: typing-extensions>=4.6.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
28
+ Requires-Dist: pytest-cov>=5.0.0; extra == "dev"
29
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
30
+ Requires-Dist: mypy>=1.9.0; extra == "dev"
31
+ Requires-Dist: flake8>=7.0.0; extra == "dev"
32
+ Requires-Dist: black>=24.0.0; extra == "dev"
33
+ Requires-Dist: build>=1.1.0; extra == "dev"
34
+ Requires-Dist: twine>=5.0.0; extra == "dev"
35
+ Requires-Dist: fastapi>=0.110.0; extra == "dev"
36
+ Requires-Dist: httpx>=0.27.0; extra == "dev"
37
+ Dynamic: license-file
38
+
39
+ # pydantic-brasil 🇧🇷
40
+
41
+ [![PyPI version](https://img.shields.io/pypi/v/pydantic-brasil?color=blue&style=flat-square)](https://pypi.org/project/pydantic-brasil/)
42
+ [![Python versions](https://img.shields.io/pypi/pyversions/pydantic-brasil?style=flat-square)](https://pypi.org/project/pydantic-brasil/)
43
+ [![CI Tests](https://github.com/Luan1Schons/pydantic-brasil/actions/workflows/test.yml/badge.svg)](https://github.com/Luan1Schons/pydantic-brasil/actions/workflows/test.yml)
44
+ [![Coverage](https://img.shields.io/badge/coverage-94%25-brightgreen?style=flat-square)](https://github.com/Luan1Schons/pydantic-brasil)
45
+ [![Pydantic v2](https://img.shields.io/badge/pydantic-v2-E92063?logo=pydantic&logoColor=white&style=flat-square)](https://docs.pydantic.dev/)
46
+ [![Types](https://img.shields.io/badge/typing-Mypy%20Strict-blue?style=flat-square)](https://mypy.readthedocs.io/)
47
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg?style=flat-square)](https://opensource.org/licenses/MIT)
48
+
49
+ **Modern, high-performance Brazilian data types and validators for Pydantic v2 and FastAPI.**
50
+
51
+ *Read this in [Português (Brasil)](README.pt-BR.md).*
52
+
53
+ ---
54
+
55
+ ## ⚡ Highlights
56
+
57
+ - **⚡ Built natively for Pydantic v2**: Integrates directly with `pydantic-core` via `__get_pydantic_core_schema__` for lightning-fast C-speed validation.
58
+ - **🛡️ 2026 Alphanumeric CNPJ Ready**: Full support for both traditional numeric CNPJ and the new Receita Federal 2026 alphanumeric CNPJ format.
59
+ - **🔒 LGPD-Compliant Masking**: Native `.masked` property on sensitive fields (`123.***.***-00`) for logs, analytics, and telemetry.
60
+ - **🗄️ Database-Optimized**: `model_dump()` automatically serializes documents, phones, and postal codes into clean unpunctuated digits for optimal indexing and querying in Postgres, MySQL, MongoDB, etc.
61
+ - **🚀 Zero External Dependencies**: Powered only by `pydantic>=2.0.0` and `typing-extensions`.
62
+ - **🎯 100% Type-Safe**: Full PEP 561 compliance (`py.typed`) and passes `mypy --strict`.
63
+ - **🧪 Built-in Test Data Generators**: Generate realistic, valid documents on demand (`CPF.generate()`, `CNPJ.generate()`, `ChavePIX.generate_evp()`, etc.).
64
+
65
+ ---
66
+
67
+ ## 📦 Supported Brazilian Types
68
+
69
+ | Type | Name / Alias | Features & Properties |
70
+ | :--- | :--- | :--- |
71
+ | **CPF** | `CPF` | Mod 11 checksum, repeated digit detection, `.fiscal_region`, `.formatted`, `.digits`, `.masked`, `.generate()` |
72
+ | **CNPJ** | `CNPJ` | Traditional + 2026 Alphanumeric format, `.is_matriz`, `.is_filial`, `.branch_number`, `.formatted`, `.digits`, `.masked`, `.generate()` |
73
+ | **Documento Geral** | `CPFouCNPJ`, `DocumentoBR` | Polymorphic auto-detection, `.is_cpf`, `.is_cnpj`, `.as_cpf()`, `.as_cnpj()` |
74
+ | **CEP** | `CEP` | 8-digit postal validation, Correios UF range detection (`.state`), `.formatted`, `.digits`, `.generate()` |
75
+ | **Telefone** | `TelefoneBR` | Mobile (9 digits) and landline (8 digits), ANATEL DDD check, `.ddd`, `.e164`, `.whatsapp_link`, `.is_mobile`, `.generate()` |
76
+ | **Chave PIX** | `ChavePIX`, `PixKey` | Bacen types (CPF, CNPJ, Email, Phone, EVP), `.key_type`, `.normalized`, `.formatted`, `.masked`, `.generate_evp()` |
77
+ | **Dinheiro BRL** | `DinheiroBRL`, `BRL` | `Decimal`-backed financial precision, parses `"R$ 1.250,50"`, `.centavos` (int), `.formatted`, arithmetic ops |
78
+ | **Placa Veicular** | `PlacaVeiculo` | Mercosul (`ABC1D23`) and Legacy (`ABC-1234`), `.is_mercosul`, `.to_mercosul()`, `.to_antiga()` |
79
+ | **RENAVAM** | `RENAVAM` | 11-digit national vehicle registry validation with Mod 11 |
80
+ | **CNH** | `CNH` | 11-digit national driver's license with dual Mod 11 verification |
81
+ | **Inscrição Estadual**| `InscricaoEstadual` | SP (including rural 'P' prefix), RJ, MG, RS, PR, SC, and generic length fallback; accepts `"ISENTO"` |
82
+
83
+ ---
84
+
85
+ ## 🚀 Installation
86
+
87
+ ```bash
88
+ pip install pydantic-brasil
89
+ ```
90
+
91
+ or with Poetry:
92
+
93
+ ```bash
94
+ poetry add pydantic-brasil
95
+ ```
96
+
97
+ or with uv:
98
+
99
+ ```bash
100
+ uv add pydantic-brasil
101
+ ```
102
+
103
+ ---
104
+
105
+ ## 🛠️ Quickstart
106
+
107
+ ### 1. Pydantic Model Validation
108
+
109
+ ```python
110
+ from pydantic import BaseModel
111
+ from pydantic_brasil import CPF, CNPJ, CEP, TelefoneBR, ChavePIX, DinheiroBRL
112
+
113
+ class CustomerSchema(BaseModel):
114
+ name: str
115
+ cpf: CPF
116
+ cnpj: CNPJ
117
+ cep: CEP
118
+ phone: TelefoneBR
119
+ pix: ChavePIX
120
+ credit_limit: DinheiroBRL
121
+
122
+ # Accepts formatted strings, raw digits, integers, etc.
123
+ customer = CustomerSchema(
124
+ name="Maria Silva",
125
+ cpf="123.456.789-09",
126
+ cnpj="12.ABC.345/0001-67", # Supports 2026 alphanumeric format!
127
+ cep="01310-100",
128
+ phone="(11) 98765-4321",
129
+ pix="maria.silva@example.com",
130
+ credit_limit="R$ 12.500,75",
131
+ )
132
+
133
+ # Rich property access
134
+ print(customer.cpf.formatted) # "123.456.789-09"
135
+ print(customer.cpf.digits) # "12345678909"
136
+ print(customer.cpf.masked) # "123.***.***-09" (LGPD safe)
137
+ print(customer.cpf.fiscal_region) # ["SP"]
138
+
139
+ print(customer.phone.e164) # "+5511987654321"
140
+ print(customer.phone.whatsapp_link) # "https://wa.me/5511987654321"
141
+
142
+ print(customer.pix.key_type) # PixKeyType.EMAIL
143
+ print(customer.credit_limit.centavos) # 1250075 (int, perfect for payment gateways)
144
+
145
+ # Database-friendly dumping
146
+ print(customer.model_dump())
147
+ # {
148
+ # "name": "Maria Silva",
149
+ # "cpf": "12345678909",
150
+ # "cnpj": "12ABC345000167",
151
+ # "cep": "01310100",
152
+ # "phone": "11987654321",
153
+ # "pix": "maria.silva@example.com",
154
+ # "credit_limit": 12500.75
155
+ # }
156
+ ```
157
+
158
+ ### 2. FastAPI Integration
159
+
160
+ All types generate clean OpenAPI schemas with proper descriptions and examples in Swagger UI (`/docs`):
161
+
162
+ ```python
163
+ from fastapi import FastAPI, HTTPException
164
+ from pydantic import BaseModel
165
+ from pydantic_brasil import CPF, ChavePIX, DinheiroBRL
166
+
167
+ app = FastAPI(title="Minha API Brasileira")
168
+
169
+ class PixPaymentRequest(BaseModel):
170
+ pix_key: ChavePIX
171
+ amount: DinheiroBRL
172
+ payer_cpf: CPF
173
+
174
+ @app.post("/pix/pay")
175
+ def process_pix(payment: PixPaymentRequest):
176
+ return {
177
+ "status": "success",
178
+ "key_type": payment.pix_key.key_type,
179
+ "amount_cents": payment.amount.centavos,
180
+ "payer": payment.payer_cpf.masked,
181
+ }
182
+ ```
183
+
184
+ ---
185
+
186
+ ## 🔍 Detailed Usage
187
+
188
+ ### CPF & Fiscal Regions
189
+
190
+ ```python
191
+ from pydantic_brasil import CPF
192
+
193
+ cpf = CPF("123.456.789-09")
194
+
195
+ # Format representations
196
+ cpf.formatted # "123.456.789-09"
197
+ cpf.digits # "12345678909"
198
+ cpf.masked # "123.***.***-09"
199
+
200
+ # Identify tax issuance region by 9th digit
201
+ cpf.fiscal_region # ["SP"]
202
+
203
+ # Smart comparison (formats don't matter)
204
+ CPF("123.456.789-09") == "12345678909" # True
205
+ CPF("123.456.789-09") == 12345678909 # True
206
+
207
+ # Generate mock data for unit tests
208
+ test_cpf = CPF.generate(state="RS", formatted=True)
209
+ ```
210
+
211
+ ### CNPJ (Including 2026 Alphanumeric Format)
212
+
213
+ The Federal Revenue of Brazil (Receita Federal) introduced the alphanumeric format for CNPJs starting in 2026. `pydantic-brasil` handles both legacy numeric and new alphanumeric formats seamlessly:
214
+
215
+ ```python
216
+ from pydantic_brasil import CNPJ
217
+
218
+ # Traditional numeric CNPJ
219
+ cnpj_old = CNPJ("12.345.678/0001-95")
220
+
221
+ # 2026 Alphanumeric CNPJ
222
+ cnpj_new = CNPJ("12.ABC.345/0001-67")
223
+ cnpj_new.is_matriz # True
224
+ cnpj_new.branch_number # "0001"
225
+ cnpj_new.masked # "12.***.***/0001-67"
226
+
227
+ # Generate test CNPJs
228
+ test_cnpj = CNPJ.generate(branch=1, formatted=True)
229
+ ```
230
+
231
+ ### Polymorphic Document (`CPFouCNPJ` / `DocumentoBR`)
232
+
233
+ When a field can be either a person's CPF or a company's CNPJ:
234
+
235
+ ```python
236
+ from pydantic_brasil import CPFouCNPJ
237
+
238
+ doc = CPFouCNPJ("12.345.678/0001-95")
239
+ if doc.is_cnpj:
240
+ company = doc.as_cnpj()
241
+ print(company.is_matriz)
242
+ ```
243
+
244
+ ### CEP & State Inference
245
+
246
+ ```python
247
+ from pydantic_brasil import CEP
248
+
249
+ cep = CEP("01310-100")
250
+ cep.formatted # "01310-100"
251
+ cep.digits # "01310100"
252
+ cep.state # "SP" (Inferred from Correios postal range)
253
+
254
+ test_cep = CEP.generate(state="RJ")
255
+ ```
256
+
257
+ ### TelefoneBR (Landline & Mobile)
258
+
259
+ ```python
260
+ from pydantic_brasil import TelefoneBR
261
+
262
+ phone = TelefoneBR("+55 (11) 98765-4321")
263
+ phone.digits # "11987654321"
264
+ phone.formatted # "(11) 98765-4321"
265
+ phone.e164 # "+5511987654321"
266
+ phone.whatsapp_link # "https://wa.me/5511987654321"
267
+ phone.ddd # "11"
268
+ phone.is_mobile # True
269
+ phone.is_landline # False
270
+
271
+ # Generate mock phones
272
+ test_phone = TelefoneBR.generate(ddd=21, mobile=True)
273
+ ```
274
+
275
+ ### Chave PIX
276
+
277
+ Auto-detects and validates the 5 official types according to Central Bank rules:
278
+
279
+ ```python
280
+ from pydantic_brasil import ChavePIX, PixKeyType
281
+
282
+ key1 = ChavePIX("123.456.789-09") # PixKeyType.CPF
283
+ key2 = ChavePIX("user@company.com.br") # PixKeyType.EMAIL
284
+ key3 = ChavePIX("+5511987654321") # PixKeyType.PHONE
285
+ key4 = ChavePIX("550e8400-e29b-41d4-a716-446655440000") # PixKeyType.EVP
286
+
287
+ print(key1.normalized) # "12345678909"
288
+ print(key3.normalized) # "+5511987654321"
289
+ print(key2.masked) # "u***r@company.com.br"
290
+
291
+ # Generate random EVP
292
+ random_pix = ChavePIX.generate_evp()
293
+ ```
294
+
295
+ ### DinheiroBRL (Monetary Precision)
296
+
297
+ Avoid floating-point representation bugs (`0.1 + 0.2 != 0.3`). `DinheiroBRL` uses `Decimal` internally and offers convenient constructors and conversions:
298
+
299
+ ```python
300
+ from pydantic_brasil import DinheiroBRL
301
+
302
+ price = DinheiroBRL("R$ 1.500,50")
303
+ print(price.centavos) # 150050 (int, ideal for payment APIs)
304
+ print(price.formatted) # "R$ 1.500,50"
305
+
306
+ # From integer cents
307
+ fee = DinheiroBRL.from_centavos(250) # R$ 2,50
308
+
309
+ # Native math operations
310
+ total = price + fee
311
+ print(total.formatted) # "R$ 1.503,00"
312
+ ```
313
+
314
+ ### Placa Veicular (Mercosul & Legacy)
315
+
316
+ ```python
317
+ from pydantic_brasil import PlacaVeiculo
318
+
319
+ placa = PlacaVeiculo("ABC-1234")
320
+ print(placa.is_antiga) # True
321
+ print(placa.to_mercosul()) # "ABC1C34"
322
+
323
+ mercosul = PlacaVeiculo("ABC1C34")
324
+ print(mercosul.is_mercosul) # True
325
+ print(mercosul.to_antiga()) # "ABC-1234"
326
+ ```
327
+
328
+ ---
329
+
330
+ ## 🧪 Testing & Code Quality
331
+
332
+ ```bash
333
+ # Run pytest with coverage report
334
+ pytest --cov=pydantic_brasil --cov-report=term-missing
335
+
336
+ # Run strict type checking
337
+ mypy pydantic_brasil tests
338
+
339
+ # Check formatting and style
340
+ flake8
341
+ black --check .
342
+ ```
343
+
344
+ ---
345
+
346
+ ## 🤝 Contributing
347
+
348
+ Contributions are very welcome! Feel free to open an issue or pull request.
349
+ For major changes, please open an issue first to discuss what you would like to change.
350
+
351
+ 1. Fork the Project
352
+ 2. Create your Feature Branch (`git checkout -b feature/MinhaFeature`)
353
+ 3. Commit your Changes (`git commit -m 'feat: Adiciona nova funcionalidade'`)
354
+ 4. Push to the Branch (`git push origin feature/MinhaFeature`)
355
+ 5. Open a Pull Request
356
+
357
+ ---
358
+
359
+ ## 📄 License
360
+
361
+ Distributed under the MIT License. See `LICENSE` for more information.
@@ -0,0 +1,323 @@
1
+ # pydantic-brasil 🇧🇷
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/pydantic-brasil?color=blue&style=flat-square)](https://pypi.org/project/pydantic-brasil/)
4
+ [![Python versions](https://img.shields.io/pypi/pyversions/pydantic-brasil?style=flat-square)](https://pypi.org/project/pydantic-brasil/)
5
+ [![CI Tests](https://github.com/Luan1Schons/pydantic-brasil/actions/workflows/test.yml/badge.svg)](https://github.com/Luan1Schons/pydantic-brasil/actions/workflows/test.yml)
6
+ [![Coverage](https://img.shields.io/badge/coverage-94%25-brightgreen?style=flat-square)](https://github.com/Luan1Schons/pydantic-brasil)
7
+ [![Pydantic v2](https://img.shields.io/badge/pydantic-v2-E92063?logo=pydantic&logoColor=white&style=flat-square)](https://docs.pydantic.dev/)
8
+ [![Types](https://img.shields.io/badge/typing-Mypy%20Strict-blue?style=flat-square)](https://mypy.readthedocs.io/)
9
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg?style=flat-square)](https://opensource.org/licenses/MIT)
10
+
11
+ **Modern, high-performance Brazilian data types and validators for Pydantic v2 and FastAPI.**
12
+
13
+ *Read this in [Português (Brasil)](README.pt-BR.md).*
14
+
15
+ ---
16
+
17
+ ## ⚡ Highlights
18
+
19
+ - **⚡ Built natively for Pydantic v2**: Integrates directly with `pydantic-core` via `__get_pydantic_core_schema__` for lightning-fast C-speed validation.
20
+ - **🛡️ 2026 Alphanumeric CNPJ Ready**: Full support for both traditional numeric CNPJ and the new Receita Federal 2026 alphanumeric CNPJ format.
21
+ - **🔒 LGPD-Compliant Masking**: Native `.masked` property on sensitive fields (`123.***.***-00`) for logs, analytics, and telemetry.
22
+ - **🗄️ Database-Optimized**: `model_dump()` automatically serializes documents, phones, and postal codes into clean unpunctuated digits for optimal indexing and querying in Postgres, MySQL, MongoDB, etc.
23
+ - **🚀 Zero External Dependencies**: Powered only by `pydantic>=2.0.0` and `typing-extensions`.
24
+ - **🎯 100% Type-Safe**: Full PEP 561 compliance (`py.typed`) and passes `mypy --strict`.
25
+ - **🧪 Built-in Test Data Generators**: Generate realistic, valid documents on demand (`CPF.generate()`, `CNPJ.generate()`, `ChavePIX.generate_evp()`, etc.).
26
+
27
+ ---
28
+
29
+ ## 📦 Supported Brazilian Types
30
+
31
+ | Type | Name / Alias | Features & Properties |
32
+ | :--- | :--- | :--- |
33
+ | **CPF** | `CPF` | Mod 11 checksum, repeated digit detection, `.fiscal_region`, `.formatted`, `.digits`, `.masked`, `.generate()` |
34
+ | **CNPJ** | `CNPJ` | Traditional + 2026 Alphanumeric format, `.is_matriz`, `.is_filial`, `.branch_number`, `.formatted`, `.digits`, `.masked`, `.generate()` |
35
+ | **Documento Geral** | `CPFouCNPJ`, `DocumentoBR` | Polymorphic auto-detection, `.is_cpf`, `.is_cnpj`, `.as_cpf()`, `.as_cnpj()` |
36
+ | **CEP** | `CEP` | 8-digit postal validation, Correios UF range detection (`.state`), `.formatted`, `.digits`, `.generate()` |
37
+ | **Telefone** | `TelefoneBR` | Mobile (9 digits) and landline (8 digits), ANATEL DDD check, `.ddd`, `.e164`, `.whatsapp_link`, `.is_mobile`, `.generate()` |
38
+ | **Chave PIX** | `ChavePIX`, `PixKey` | Bacen types (CPF, CNPJ, Email, Phone, EVP), `.key_type`, `.normalized`, `.formatted`, `.masked`, `.generate_evp()` |
39
+ | **Dinheiro BRL** | `DinheiroBRL`, `BRL` | `Decimal`-backed financial precision, parses `"R$ 1.250,50"`, `.centavos` (int), `.formatted`, arithmetic ops |
40
+ | **Placa Veicular** | `PlacaVeiculo` | Mercosul (`ABC1D23`) and Legacy (`ABC-1234`), `.is_mercosul`, `.to_mercosul()`, `.to_antiga()` |
41
+ | **RENAVAM** | `RENAVAM` | 11-digit national vehicle registry validation with Mod 11 |
42
+ | **CNH** | `CNH` | 11-digit national driver's license with dual Mod 11 verification |
43
+ | **Inscrição Estadual**| `InscricaoEstadual` | SP (including rural 'P' prefix), RJ, MG, RS, PR, SC, and generic length fallback; accepts `"ISENTO"` |
44
+
45
+ ---
46
+
47
+ ## 🚀 Installation
48
+
49
+ ```bash
50
+ pip install pydantic-brasil
51
+ ```
52
+
53
+ or with Poetry:
54
+
55
+ ```bash
56
+ poetry add pydantic-brasil
57
+ ```
58
+
59
+ or with uv:
60
+
61
+ ```bash
62
+ uv add pydantic-brasil
63
+ ```
64
+
65
+ ---
66
+
67
+ ## 🛠️ Quickstart
68
+
69
+ ### 1. Pydantic Model Validation
70
+
71
+ ```python
72
+ from pydantic import BaseModel
73
+ from pydantic_brasil import CPF, CNPJ, CEP, TelefoneBR, ChavePIX, DinheiroBRL
74
+
75
+ class CustomerSchema(BaseModel):
76
+ name: str
77
+ cpf: CPF
78
+ cnpj: CNPJ
79
+ cep: CEP
80
+ phone: TelefoneBR
81
+ pix: ChavePIX
82
+ credit_limit: DinheiroBRL
83
+
84
+ # Accepts formatted strings, raw digits, integers, etc.
85
+ customer = CustomerSchema(
86
+ name="Maria Silva",
87
+ cpf="123.456.789-09",
88
+ cnpj="12.ABC.345/0001-67", # Supports 2026 alphanumeric format!
89
+ cep="01310-100",
90
+ phone="(11) 98765-4321",
91
+ pix="maria.silva@example.com",
92
+ credit_limit="R$ 12.500,75",
93
+ )
94
+
95
+ # Rich property access
96
+ print(customer.cpf.formatted) # "123.456.789-09"
97
+ print(customer.cpf.digits) # "12345678909"
98
+ print(customer.cpf.masked) # "123.***.***-09" (LGPD safe)
99
+ print(customer.cpf.fiscal_region) # ["SP"]
100
+
101
+ print(customer.phone.e164) # "+5511987654321"
102
+ print(customer.phone.whatsapp_link) # "https://wa.me/5511987654321"
103
+
104
+ print(customer.pix.key_type) # PixKeyType.EMAIL
105
+ print(customer.credit_limit.centavos) # 1250075 (int, perfect for payment gateways)
106
+
107
+ # Database-friendly dumping
108
+ print(customer.model_dump())
109
+ # {
110
+ # "name": "Maria Silva",
111
+ # "cpf": "12345678909",
112
+ # "cnpj": "12ABC345000167",
113
+ # "cep": "01310100",
114
+ # "phone": "11987654321",
115
+ # "pix": "maria.silva@example.com",
116
+ # "credit_limit": 12500.75
117
+ # }
118
+ ```
119
+
120
+ ### 2. FastAPI Integration
121
+
122
+ All types generate clean OpenAPI schemas with proper descriptions and examples in Swagger UI (`/docs`):
123
+
124
+ ```python
125
+ from fastapi import FastAPI, HTTPException
126
+ from pydantic import BaseModel
127
+ from pydantic_brasil import CPF, ChavePIX, DinheiroBRL
128
+
129
+ app = FastAPI(title="Minha API Brasileira")
130
+
131
+ class PixPaymentRequest(BaseModel):
132
+ pix_key: ChavePIX
133
+ amount: DinheiroBRL
134
+ payer_cpf: CPF
135
+
136
+ @app.post("/pix/pay")
137
+ def process_pix(payment: PixPaymentRequest):
138
+ return {
139
+ "status": "success",
140
+ "key_type": payment.pix_key.key_type,
141
+ "amount_cents": payment.amount.centavos,
142
+ "payer": payment.payer_cpf.masked,
143
+ }
144
+ ```
145
+
146
+ ---
147
+
148
+ ## 🔍 Detailed Usage
149
+
150
+ ### CPF & Fiscal Regions
151
+
152
+ ```python
153
+ from pydantic_brasil import CPF
154
+
155
+ cpf = CPF("123.456.789-09")
156
+
157
+ # Format representations
158
+ cpf.formatted # "123.456.789-09"
159
+ cpf.digits # "12345678909"
160
+ cpf.masked # "123.***.***-09"
161
+
162
+ # Identify tax issuance region by 9th digit
163
+ cpf.fiscal_region # ["SP"]
164
+
165
+ # Smart comparison (formats don't matter)
166
+ CPF("123.456.789-09") == "12345678909" # True
167
+ CPF("123.456.789-09") == 12345678909 # True
168
+
169
+ # Generate mock data for unit tests
170
+ test_cpf = CPF.generate(state="RS", formatted=True)
171
+ ```
172
+
173
+ ### CNPJ (Including 2026 Alphanumeric Format)
174
+
175
+ The Federal Revenue of Brazil (Receita Federal) introduced the alphanumeric format for CNPJs starting in 2026. `pydantic-brasil` handles both legacy numeric and new alphanumeric formats seamlessly:
176
+
177
+ ```python
178
+ from pydantic_brasil import CNPJ
179
+
180
+ # Traditional numeric CNPJ
181
+ cnpj_old = CNPJ("12.345.678/0001-95")
182
+
183
+ # 2026 Alphanumeric CNPJ
184
+ cnpj_new = CNPJ("12.ABC.345/0001-67")
185
+ cnpj_new.is_matriz # True
186
+ cnpj_new.branch_number # "0001"
187
+ cnpj_new.masked # "12.***.***/0001-67"
188
+
189
+ # Generate test CNPJs
190
+ test_cnpj = CNPJ.generate(branch=1, formatted=True)
191
+ ```
192
+
193
+ ### Polymorphic Document (`CPFouCNPJ` / `DocumentoBR`)
194
+
195
+ When a field can be either a person's CPF or a company's CNPJ:
196
+
197
+ ```python
198
+ from pydantic_brasil import CPFouCNPJ
199
+
200
+ doc = CPFouCNPJ("12.345.678/0001-95")
201
+ if doc.is_cnpj:
202
+ company = doc.as_cnpj()
203
+ print(company.is_matriz)
204
+ ```
205
+
206
+ ### CEP & State Inference
207
+
208
+ ```python
209
+ from pydantic_brasil import CEP
210
+
211
+ cep = CEP("01310-100")
212
+ cep.formatted # "01310-100"
213
+ cep.digits # "01310100"
214
+ cep.state # "SP" (Inferred from Correios postal range)
215
+
216
+ test_cep = CEP.generate(state="RJ")
217
+ ```
218
+
219
+ ### TelefoneBR (Landline & Mobile)
220
+
221
+ ```python
222
+ from pydantic_brasil import TelefoneBR
223
+
224
+ phone = TelefoneBR("+55 (11) 98765-4321")
225
+ phone.digits # "11987654321"
226
+ phone.formatted # "(11) 98765-4321"
227
+ phone.e164 # "+5511987654321"
228
+ phone.whatsapp_link # "https://wa.me/5511987654321"
229
+ phone.ddd # "11"
230
+ phone.is_mobile # True
231
+ phone.is_landline # False
232
+
233
+ # Generate mock phones
234
+ test_phone = TelefoneBR.generate(ddd=21, mobile=True)
235
+ ```
236
+
237
+ ### Chave PIX
238
+
239
+ Auto-detects and validates the 5 official types according to Central Bank rules:
240
+
241
+ ```python
242
+ from pydantic_brasil import ChavePIX, PixKeyType
243
+
244
+ key1 = ChavePIX("123.456.789-09") # PixKeyType.CPF
245
+ key2 = ChavePIX("user@company.com.br") # PixKeyType.EMAIL
246
+ key3 = ChavePIX("+5511987654321") # PixKeyType.PHONE
247
+ key4 = ChavePIX("550e8400-e29b-41d4-a716-446655440000") # PixKeyType.EVP
248
+
249
+ print(key1.normalized) # "12345678909"
250
+ print(key3.normalized) # "+5511987654321"
251
+ print(key2.masked) # "u***r@company.com.br"
252
+
253
+ # Generate random EVP
254
+ random_pix = ChavePIX.generate_evp()
255
+ ```
256
+
257
+ ### DinheiroBRL (Monetary Precision)
258
+
259
+ Avoid floating-point representation bugs (`0.1 + 0.2 != 0.3`). `DinheiroBRL` uses `Decimal` internally and offers convenient constructors and conversions:
260
+
261
+ ```python
262
+ from pydantic_brasil import DinheiroBRL
263
+
264
+ price = DinheiroBRL("R$ 1.500,50")
265
+ print(price.centavos) # 150050 (int, ideal for payment APIs)
266
+ print(price.formatted) # "R$ 1.500,50"
267
+
268
+ # From integer cents
269
+ fee = DinheiroBRL.from_centavos(250) # R$ 2,50
270
+
271
+ # Native math operations
272
+ total = price + fee
273
+ print(total.formatted) # "R$ 1.503,00"
274
+ ```
275
+
276
+ ### Placa Veicular (Mercosul & Legacy)
277
+
278
+ ```python
279
+ from pydantic_brasil import PlacaVeiculo
280
+
281
+ placa = PlacaVeiculo("ABC-1234")
282
+ print(placa.is_antiga) # True
283
+ print(placa.to_mercosul()) # "ABC1C34"
284
+
285
+ mercosul = PlacaVeiculo("ABC1C34")
286
+ print(mercosul.is_mercosul) # True
287
+ print(mercosul.to_antiga()) # "ABC-1234"
288
+ ```
289
+
290
+ ---
291
+
292
+ ## 🧪 Testing & Code Quality
293
+
294
+ ```bash
295
+ # Run pytest with coverage report
296
+ pytest --cov=pydantic_brasil --cov-report=term-missing
297
+
298
+ # Run strict type checking
299
+ mypy pydantic_brasil tests
300
+
301
+ # Check formatting and style
302
+ flake8
303
+ black --check .
304
+ ```
305
+
306
+ ---
307
+
308
+ ## 🤝 Contributing
309
+
310
+ Contributions are very welcome! Feel free to open an issue or pull request.
311
+ For major changes, please open an issue first to discuss what you would like to change.
312
+
313
+ 1. Fork the Project
314
+ 2. Create your Feature Branch (`git checkout -b feature/MinhaFeature`)
315
+ 3. Commit your Changes (`git commit -m 'feat: Adiciona nova funcionalidade'`)
316
+ 4. Push to the Branch (`git push origin feature/MinhaFeature`)
317
+ 5. Open a Pull Request
318
+
319
+ ---
320
+
321
+ ## 📄 License
322
+
323
+ Distributed under the MIT License. See `LICENSE` for more information.