cnpj-dv 1.0.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.
cnpj_dv-1.0.0/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Julio L. Muller
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cnpj_dv-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,313 @@
1
+ Metadata-Version: 2.4
2
+ Name: cnpj-dv
3
+ Version: 1.0.0
4
+ Summary: Utility resources to calculate check digits on CNPJ (Brazilian employer ID)
5
+ Author: Julio L. Muller
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://cnpj-utils.vercel.app/
8
+ Project-URL: Source, https://github.com/LacusSolutions/br-utils-py
9
+ Project-URL: Tracker, https://github.com/LacusSolutions/br-utils-py/issues
10
+ Keywords: cnpj,verificar,verificador,verify,verification,check,check-digit,check-digits,pt-br,br
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Natural Language :: English
14
+ Classifier: Natural Language :: Portuguese (Brazilian)
15
+ Classifier: Operating System :: MacOS :: MacOS X
16
+ Classifier: Operating System :: Microsoft :: Windows
17
+ Classifier: Operating System :: POSIX
18
+ Classifier: Operating System :: Unix
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Programming Language :: Python :: 3.14
25
+ Classifier: Topic :: Software Development :: Libraries
26
+ Classifier: Topic :: Utilities
27
+ Requires-Python: >=3.10
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Dynamic: license-file
31
+
32
+ ![cnpj-dv for Python](https://br-utils.vercel.app/img/cover_cnpj-dv.jpg)
33
+
34
+ [![PyPI Version](https://img.shields.io/pypi/v/cnpj-dv)](https://pypi.org/project/cnpj-dv)
35
+ [![PyPI Downloads](https://img.shields.io/pypi/dm/cnpj-dv)](https://pypi.org/project/cnpj-dv)
36
+ [![Python Version](https://img.shields.io/pypi/pyversions/cnpj-dv)](https://www.python.org/)
37
+ [![Test Status](https://img.shields.io/github/actions/workflow/status/LacusSolutions/br-utils-py/ci.yml?label=ci/cd)](https://github.com/LacusSolutions/br-utils-py/actions)
38
+ [![Last Update Date](https://img.shields.io/github/last-commit/LacusSolutions/br-utils-py)](https://github.com/LacusSolutions/br-utils-py)
39
+ [![Project License](https://img.shields.io/github/license/LacusSolutions/br-utils-py)](https://github.com/LacusSolutions/br-utils-py/blob/main/LICENSE)
40
+
41
+ Utility class to calculate check digits on CNPJ (Brazilian employer ID).
42
+
43
+ ## Python Support
44
+
45
+ | ![Python 3.10](https://img.shields.io/badge/Python-3.10-3776AB?logo=python&logoColor=white) | ![Python 3.11](https://img.shields.io/badge/Python-3.11-3776AB?logo=python&logoColor=white) | ![Python 3.12](https://img.shields.io/badge/Python-3.12-3776AB?logo=python&logoColor=white) | ![Python 3.13](https://img.shields.io/badge/Python-3.13-3776AB?logo=python&logoColor=white) | ![Python 3.14](https://img.shields.io/badge/Python-3.14-3776AB?logo=python&logoColor=white) |
46
+ |--- | --- | --- | --- | --- |
47
+ | Passing ✔ | Passing ✔ | Passing ✔ | Passing ✔ | Passing ✔ |
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ $ pip install cnpj-dv
53
+ ```
54
+
55
+ ## Import
56
+
57
+ ```python
58
+ from cnpj_dv import CnpjCheckDigits
59
+ ```
60
+
61
+ ## Usage
62
+
63
+ ### Basic Usage
64
+
65
+ ```python
66
+ # Calculate check digits from a 12-digit CNPJ base
67
+ check_digits = CnpjCheckDigits("914157320007")
68
+
69
+ print(check_digits.first_digit) # returns 9
70
+ print(check_digits.second_digit) # returns 3
71
+ print(check_digits.to_string()) # returns '91415732000793'
72
+ print(check_digits.to_list()) # returns [9, 1, 4, 1, 5, 7, 3, 2, 0, 0, 0, 7, 9, 3]
73
+ ```
74
+
75
+ ### Input Formats
76
+
77
+ The `CnpjCheckDigits` class accepts multiple input formats:
78
+
79
+ #### String Input
80
+
81
+ ```python
82
+ # Plain string (non-numeric characters are automatically stripped)
83
+ check_digits = CnpjCheckDigits("914157320007")
84
+ check_digits = CnpjCheckDigits("91.415.732/0007") # formatting is ignored
85
+ check_digits = CnpjCheckDigits("914157320007") # 12 digits
86
+ check_digits = CnpjCheckDigits("91415732000793") # 14 digits (only first 12 are used)
87
+ ```
88
+
89
+ #### List of Strings
90
+
91
+ ```python
92
+ # List of single-character strings
93
+ check_digits = CnpjCheckDigits(["9", "1", "4", "1", "5", "7", "3", "2", "0", "0", "0", "7"])
94
+
95
+ # List with multi-digit strings (automatically flattened)
96
+ check_digits = CnpjCheckDigits(["914157320007"]) # flattens to individual digits
97
+ check_digits = CnpjCheckDigits(["91", "415", "732", "0007"]) # also flattens
98
+ ```
99
+
100
+ #### List of Integers
101
+
102
+ ```python
103
+ # List of single-digit integers
104
+ check_digits = CnpjCheckDigits([9, 1, 4, 1, 5, 7, 3, 2, 0, 0, 0, 7])
105
+
106
+ # List with multi-digit integers (automatically flattened)
107
+ check_digits = CnpjCheckDigits([914157320007]) # flattens to individual digits
108
+ check_digits = CnpjCheckDigits([914, 157, 320, 7]) # also flattens
109
+ ```
110
+
111
+ ### Properties
112
+
113
+ #### `first_digit: int`
114
+
115
+ Returns the first check digit (13th digit of the CNPJ).
116
+
117
+ ```python
118
+ check_digits = CnpjCheckDigits("914157320007")
119
+ print(check_digits.first_digit) # returns 9
120
+ ```
121
+
122
+ #### `second_digit: int`
123
+
124
+ Returns the second check digit (14th digit of the CNPJ).
125
+
126
+ ```python
127
+ check_digits = CnpjCheckDigits("914157320007")
128
+ print(check_digits.second_digit) # returns 3
129
+ ```
130
+
131
+ ### Methods
132
+
133
+ #### `to_list() -> list[int]`
134
+
135
+ Returns the complete CNPJ as a list of integers (12 base digits + 2 check digits).
136
+
137
+ ```python
138
+ check_digits = CnpjCheckDigits("914157320007")
139
+ print(check_digits.to_list()) # returns [9, 1, 4, 1, 5, 7, 3, 2, 0, 0, 0, 7, 9, 3]
140
+ ```
141
+
142
+ #### `to_string() -> str`
143
+
144
+ Returns the complete CNPJ as a string (12 base digits + 2 check digits).
145
+
146
+ ```python
147
+ check_digits = CnpjCheckDigits("914157320007")
148
+ print(check_digits.to_string()) # returns '91415732000793'
149
+ ```
150
+
151
+ ### Examples
152
+
153
+ ```python
154
+ from cnpj_dv import CnpjCheckDigits
155
+
156
+ # Calculate check digits for a CNPJ base
157
+ base = "914157320007"
158
+ check_digits = CnpjCheckDigits(base)
159
+
160
+ # Get individual check digits
161
+ first = check_digits.first_digit # 9
162
+ second = check_digits.second_digit # 3
163
+
164
+ # Get complete CNPJ
165
+ complete = check_digits.to_string() # '91415732000793'
166
+
167
+ # Work with formatted input
168
+ formatted = CnpjCheckDigits("91.415.732/0007")
169
+ print(formatted.to_string()) # '91415732000793'
170
+
171
+ # Work with list input
172
+ list_input = CnpjCheckDigits([9, 1, 4, 1, 5, 7, 3, 2, 0, 0, 0, 7])
173
+ print(list_input.to_string()) # '91415732000793'
174
+ ```
175
+
176
+ ## Error Handling
177
+
178
+ The package raises specific exceptions for different error scenarios:
179
+
180
+ ### `CnpjTypeError`
181
+
182
+ Raised when the input type is not supported (must be `str`, `list[str]`, or `list[int]`).
183
+
184
+ ```python
185
+ from cnpj_dv import CnpjCheckDigits, CnpjTypeError
186
+
187
+ try:
188
+ CnpjCheckDigits(12345678901234) # int not allowed
189
+ except CnpjTypeError as e:
190
+ print(e) # CNPJ input must be of type str, list[str] or list[int]. Got "int".
191
+ ```
192
+
193
+ ### `CnpjInvalidLengthError`
194
+
195
+ Raised when the input does not contain 12 to 14 digits.
196
+
197
+ ```python
198
+ from cnpj_dv import CnpjCheckDigits, CnpjInvalidLengthError
199
+
200
+ try:
201
+ CnpjCheckDigits("12345678901") # only 11 digits
202
+ except CnpjInvalidLengthError as e:
203
+ print(e) # Parameter "12345678901" does not contain 12 to 14 digits. Got 11.
204
+ ```
205
+
206
+ ### `CnpjCheckDigitsCalculationError`
207
+
208
+ Raised when the check digit calculation fails due to invalid sequence length.
209
+
210
+ ```python
211
+ from cnpj_dv import CnpjCheckDigits, CnpjCheckDigitsCalculationError
212
+
213
+ # This is an internal error that should not occur in normal usage
214
+ # It happens when the sequence passed to _calculate() has invalid length
215
+ ```
216
+
217
+ ## Features
218
+
219
+ - ✅ **Multiple Input Formats**: Accepts strings, lists of strings, or lists of integers
220
+ - ✅ **Format Agnostic**: Automatically strips non-numeric characters from string input
221
+ - ✅ **Auto-Expansion**: Automatically expands multi-digit numbers in lists to individual digits
222
+ - ✅ **Lazy Evaluation**: Check digits are calculated only when accessed (via properties)
223
+ - ✅ **Type Safety**: Built with Python 3.10+ type hints
224
+ - ✅ **Zero Dependencies**: No external dependencies required
225
+ - ✅ **Comprehensive Error Handling**: Specific exceptions for different error scenarios
226
+
227
+ ## API Reference
228
+
229
+ ### CnpjCheckDigits Class
230
+
231
+ #### Constructor
232
+
233
+ ```python
234
+ CnpjCheckDigits(cnpj_digits: str | list[str] | list[int]) -> CnpjCheckDigits
235
+ ```
236
+
237
+ Creates a new `CnpjCheckDigits` instance from the provided CNPJ base digits.
238
+
239
+ **Parameters:**
240
+ - `cnpj_digits` (str | list[str] | list[int]): The CNPJ base digits (12-14 digits). Can be:
241
+ - A string with 12-14 digits (formatting characters are ignored)
242
+ - A list of strings (each string can be a single digit or multi-digit number)
243
+ - A list of integers (each integer can be a single digit or multi-digit number)
244
+
245
+ **Raises:**
246
+ - `CnpjTypeError`: If the input type is not supported
247
+ - `CnpjInvalidLengthError`: If the input does not contain 12-14 digits
248
+
249
+ **Returns:**
250
+ - `CnpjCheckDigits`: A new instance ready to calculate check digits
251
+
252
+ #### Properties
253
+
254
+ ##### `first_digit: int`
255
+
256
+ The first check digit (13th digit of the CNPJ). Calculated lazily on first access.
257
+
258
+ ##### `second_digit: int`
259
+
260
+ The second check digit (14th digit of the CNPJ). Calculated lazily on first access.
261
+
262
+ #### Methods
263
+
264
+ ##### `to_list() -> list[int]`
265
+
266
+ Returns the complete CNPJ as a list of 14 integers (12 base digits + 2 check digits).
267
+
268
+ ##### `to_string() -> str`
269
+
270
+ Returns the complete CNPJ as a string of 14 digits (12 base digits + 2 check digits).
271
+
272
+ ## Calculation Algorithm
273
+
274
+ The package calculates CNPJ check digits using the official Brazilian algorithm:
275
+
276
+ 1. **First Check Digit (13th position)**:
277
+ - Uses digits 1-12 of the CNPJ base
278
+ - Applies weights: 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2 (from right to left)
279
+ - Calculates: `sum(digit × weight) % 11`
280
+ - Result: `0` if remainder < 2, otherwise `11 - remainder`
281
+
282
+ 2. **Second Check Digit (14th position)**:
283
+ - Uses digits 1-12 + first check digit
284
+ - Applies weights: 6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2 (from right to left)
285
+ - Calculates: `sum(digit × weight) % 11`
286
+ - Result: `0` if remainder < 2, otherwise `11 - remainder`
287
+
288
+ ## Dependencies
289
+
290
+ - **Python**: >= 3.10
291
+
292
+ No external dependencies required.
293
+
294
+ ## Contribution & Support
295
+
296
+ We welcome contributions! Please see our [Contributing Guidelines](https://github.com/LacusSolutions/br-utils-py/blob/main/CONTRIBUTING.md) for details. But if you find this project helpful, please consider:
297
+
298
+ - ⭐ Starring the repository
299
+ - 🤝 Contributing to the codebase
300
+ - 💡 [Suggesting new features](https://github.com/LacusSolutions/br-utils-py/issues)
301
+ - 🐛 [Reporting bugs](https://github.com/LacusSolutions/br-utils-py/issues)
302
+
303
+ ## License
304
+
305
+ This project is licensed under the MIT License - see the [LICENSE](https://github.com/LacusSolutions/br-utils-py/blob/main/LICENSE) file for details.
306
+
307
+ ## Changelog
308
+
309
+ See [CHANGELOG](https://github.com/LacusSolutions/br-utils-py/blob/main/packages/cnpj-dv/CHANGELOG.md) for a list of changes and version history.
310
+
311
+ ---
312
+
313
+ Made with ❤️ by [Lacus Solutions](https://github.com/LacusSolutions)
@@ -0,0 +1,282 @@
1
+ ![cnpj-dv for Python](https://br-utils.vercel.app/img/cover_cnpj-dv.jpg)
2
+
3
+ [![PyPI Version](https://img.shields.io/pypi/v/cnpj-dv)](https://pypi.org/project/cnpj-dv)
4
+ [![PyPI Downloads](https://img.shields.io/pypi/dm/cnpj-dv)](https://pypi.org/project/cnpj-dv)
5
+ [![Python Version](https://img.shields.io/pypi/pyversions/cnpj-dv)](https://www.python.org/)
6
+ [![Test Status](https://img.shields.io/github/actions/workflow/status/LacusSolutions/br-utils-py/ci.yml?label=ci/cd)](https://github.com/LacusSolutions/br-utils-py/actions)
7
+ [![Last Update Date](https://img.shields.io/github/last-commit/LacusSolutions/br-utils-py)](https://github.com/LacusSolutions/br-utils-py)
8
+ [![Project License](https://img.shields.io/github/license/LacusSolutions/br-utils-py)](https://github.com/LacusSolutions/br-utils-py/blob/main/LICENSE)
9
+
10
+ Utility class to calculate check digits on CNPJ (Brazilian employer ID).
11
+
12
+ ## Python Support
13
+
14
+ | ![Python 3.10](https://img.shields.io/badge/Python-3.10-3776AB?logo=python&logoColor=white) | ![Python 3.11](https://img.shields.io/badge/Python-3.11-3776AB?logo=python&logoColor=white) | ![Python 3.12](https://img.shields.io/badge/Python-3.12-3776AB?logo=python&logoColor=white) | ![Python 3.13](https://img.shields.io/badge/Python-3.13-3776AB?logo=python&logoColor=white) | ![Python 3.14](https://img.shields.io/badge/Python-3.14-3776AB?logo=python&logoColor=white) |
15
+ |--- | --- | --- | --- | --- |
16
+ | Passing ✔ | Passing ✔ | Passing ✔ | Passing ✔ | Passing ✔ |
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ $ pip install cnpj-dv
22
+ ```
23
+
24
+ ## Import
25
+
26
+ ```python
27
+ from cnpj_dv import CnpjCheckDigits
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ### Basic Usage
33
+
34
+ ```python
35
+ # Calculate check digits from a 12-digit CNPJ base
36
+ check_digits = CnpjCheckDigits("914157320007")
37
+
38
+ print(check_digits.first_digit) # returns 9
39
+ print(check_digits.second_digit) # returns 3
40
+ print(check_digits.to_string()) # returns '91415732000793'
41
+ print(check_digits.to_list()) # returns [9, 1, 4, 1, 5, 7, 3, 2, 0, 0, 0, 7, 9, 3]
42
+ ```
43
+
44
+ ### Input Formats
45
+
46
+ The `CnpjCheckDigits` class accepts multiple input formats:
47
+
48
+ #### String Input
49
+
50
+ ```python
51
+ # Plain string (non-numeric characters are automatically stripped)
52
+ check_digits = CnpjCheckDigits("914157320007")
53
+ check_digits = CnpjCheckDigits("91.415.732/0007") # formatting is ignored
54
+ check_digits = CnpjCheckDigits("914157320007") # 12 digits
55
+ check_digits = CnpjCheckDigits("91415732000793") # 14 digits (only first 12 are used)
56
+ ```
57
+
58
+ #### List of Strings
59
+
60
+ ```python
61
+ # List of single-character strings
62
+ check_digits = CnpjCheckDigits(["9", "1", "4", "1", "5", "7", "3", "2", "0", "0", "0", "7"])
63
+
64
+ # List with multi-digit strings (automatically flattened)
65
+ check_digits = CnpjCheckDigits(["914157320007"]) # flattens to individual digits
66
+ check_digits = CnpjCheckDigits(["91", "415", "732", "0007"]) # also flattens
67
+ ```
68
+
69
+ #### List of Integers
70
+
71
+ ```python
72
+ # List of single-digit integers
73
+ check_digits = CnpjCheckDigits([9, 1, 4, 1, 5, 7, 3, 2, 0, 0, 0, 7])
74
+
75
+ # List with multi-digit integers (automatically flattened)
76
+ check_digits = CnpjCheckDigits([914157320007]) # flattens to individual digits
77
+ check_digits = CnpjCheckDigits([914, 157, 320, 7]) # also flattens
78
+ ```
79
+
80
+ ### Properties
81
+
82
+ #### `first_digit: int`
83
+
84
+ Returns the first check digit (13th digit of the CNPJ).
85
+
86
+ ```python
87
+ check_digits = CnpjCheckDigits("914157320007")
88
+ print(check_digits.first_digit) # returns 9
89
+ ```
90
+
91
+ #### `second_digit: int`
92
+
93
+ Returns the second check digit (14th digit of the CNPJ).
94
+
95
+ ```python
96
+ check_digits = CnpjCheckDigits("914157320007")
97
+ print(check_digits.second_digit) # returns 3
98
+ ```
99
+
100
+ ### Methods
101
+
102
+ #### `to_list() -> list[int]`
103
+
104
+ Returns the complete CNPJ as a list of integers (12 base digits + 2 check digits).
105
+
106
+ ```python
107
+ check_digits = CnpjCheckDigits("914157320007")
108
+ print(check_digits.to_list()) # returns [9, 1, 4, 1, 5, 7, 3, 2, 0, 0, 0, 7, 9, 3]
109
+ ```
110
+
111
+ #### `to_string() -> str`
112
+
113
+ Returns the complete CNPJ as a string (12 base digits + 2 check digits).
114
+
115
+ ```python
116
+ check_digits = CnpjCheckDigits("914157320007")
117
+ print(check_digits.to_string()) # returns '91415732000793'
118
+ ```
119
+
120
+ ### Examples
121
+
122
+ ```python
123
+ from cnpj_dv import CnpjCheckDigits
124
+
125
+ # Calculate check digits for a CNPJ base
126
+ base = "914157320007"
127
+ check_digits = CnpjCheckDigits(base)
128
+
129
+ # Get individual check digits
130
+ first = check_digits.first_digit # 9
131
+ second = check_digits.second_digit # 3
132
+
133
+ # Get complete CNPJ
134
+ complete = check_digits.to_string() # '91415732000793'
135
+
136
+ # Work with formatted input
137
+ formatted = CnpjCheckDigits("91.415.732/0007")
138
+ print(formatted.to_string()) # '91415732000793'
139
+
140
+ # Work with list input
141
+ list_input = CnpjCheckDigits([9, 1, 4, 1, 5, 7, 3, 2, 0, 0, 0, 7])
142
+ print(list_input.to_string()) # '91415732000793'
143
+ ```
144
+
145
+ ## Error Handling
146
+
147
+ The package raises specific exceptions for different error scenarios:
148
+
149
+ ### `CnpjTypeError`
150
+
151
+ Raised when the input type is not supported (must be `str`, `list[str]`, or `list[int]`).
152
+
153
+ ```python
154
+ from cnpj_dv import CnpjCheckDigits, CnpjTypeError
155
+
156
+ try:
157
+ CnpjCheckDigits(12345678901234) # int not allowed
158
+ except CnpjTypeError as e:
159
+ print(e) # CNPJ input must be of type str, list[str] or list[int]. Got "int".
160
+ ```
161
+
162
+ ### `CnpjInvalidLengthError`
163
+
164
+ Raised when the input does not contain 12 to 14 digits.
165
+
166
+ ```python
167
+ from cnpj_dv import CnpjCheckDigits, CnpjInvalidLengthError
168
+
169
+ try:
170
+ CnpjCheckDigits("12345678901") # only 11 digits
171
+ except CnpjInvalidLengthError as e:
172
+ print(e) # Parameter "12345678901" does not contain 12 to 14 digits. Got 11.
173
+ ```
174
+
175
+ ### `CnpjCheckDigitsCalculationError`
176
+
177
+ Raised when the check digit calculation fails due to invalid sequence length.
178
+
179
+ ```python
180
+ from cnpj_dv import CnpjCheckDigits, CnpjCheckDigitsCalculationError
181
+
182
+ # This is an internal error that should not occur in normal usage
183
+ # It happens when the sequence passed to _calculate() has invalid length
184
+ ```
185
+
186
+ ## Features
187
+
188
+ - ✅ **Multiple Input Formats**: Accepts strings, lists of strings, or lists of integers
189
+ - ✅ **Format Agnostic**: Automatically strips non-numeric characters from string input
190
+ - ✅ **Auto-Expansion**: Automatically expands multi-digit numbers in lists to individual digits
191
+ - ✅ **Lazy Evaluation**: Check digits are calculated only when accessed (via properties)
192
+ - ✅ **Type Safety**: Built with Python 3.10+ type hints
193
+ - ✅ **Zero Dependencies**: No external dependencies required
194
+ - ✅ **Comprehensive Error Handling**: Specific exceptions for different error scenarios
195
+
196
+ ## API Reference
197
+
198
+ ### CnpjCheckDigits Class
199
+
200
+ #### Constructor
201
+
202
+ ```python
203
+ CnpjCheckDigits(cnpj_digits: str | list[str] | list[int]) -> CnpjCheckDigits
204
+ ```
205
+
206
+ Creates a new `CnpjCheckDigits` instance from the provided CNPJ base digits.
207
+
208
+ **Parameters:**
209
+ - `cnpj_digits` (str | list[str] | list[int]): The CNPJ base digits (12-14 digits). Can be:
210
+ - A string with 12-14 digits (formatting characters are ignored)
211
+ - A list of strings (each string can be a single digit or multi-digit number)
212
+ - A list of integers (each integer can be a single digit or multi-digit number)
213
+
214
+ **Raises:**
215
+ - `CnpjTypeError`: If the input type is not supported
216
+ - `CnpjInvalidLengthError`: If the input does not contain 12-14 digits
217
+
218
+ **Returns:**
219
+ - `CnpjCheckDigits`: A new instance ready to calculate check digits
220
+
221
+ #### Properties
222
+
223
+ ##### `first_digit: int`
224
+
225
+ The first check digit (13th digit of the CNPJ). Calculated lazily on first access.
226
+
227
+ ##### `second_digit: int`
228
+
229
+ The second check digit (14th digit of the CNPJ). Calculated lazily on first access.
230
+
231
+ #### Methods
232
+
233
+ ##### `to_list() -> list[int]`
234
+
235
+ Returns the complete CNPJ as a list of 14 integers (12 base digits + 2 check digits).
236
+
237
+ ##### `to_string() -> str`
238
+
239
+ Returns the complete CNPJ as a string of 14 digits (12 base digits + 2 check digits).
240
+
241
+ ## Calculation Algorithm
242
+
243
+ The package calculates CNPJ check digits using the official Brazilian algorithm:
244
+
245
+ 1. **First Check Digit (13th position)**:
246
+ - Uses digits 1-12 of the CNPJ base
247
+ - Applies weights: 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2 (from right to left)
248
+ - Calculates: `sum(digit × weight) % 11`
249
+ - Result: `0` if remainder < 2, otherwise `11 - remainder`
250
+
251
+ 2. **Second Check Digit (14th position)**:
252
+ - Uses digits 1-12 + first check digit
253
+ - Applies weights: 6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2 (from right to left)
254
+ - Calculates: `sum(digit × weight) % 11`
255
+ - Result: `0` if remainder < 2, otherwise `11 - remainder`
256
+
257
+ ## Dependencies
258
+
259
+ - **Python**: >= 3.10
260
+
261
+ No external dependencies required.
262
+
263
+ ## Contribution & Support
264
+
265
+ We welcome contributions! Please see our [Contributing Guidelines](https://github.com/LacusSolutions/br-utils-py/blob/main/CONTRIBUTING.md) for details. But if you find this project helpful, please consider:
266
+
267
+ - ⭐ Starring the repository
268
+ - 🤝 Contributing to the codebase
269
+ - 💡 [Suggesting new features](https://github.com/LacusSolutions/br-utils-py/issues)
270
+ - 🐛 [Reporting bugs](https://github.com/LacusSolutions/br-utils-py/issues)
271
+
272
+ ## License
273
+
274
+ This project is licensed under the MIT License - see the [LICENSE](https://github.com/LacusSolutions/br-utils-py/blob/main/LICENSE) file for details.
275
+
276
+ ## Changelog
277
+
278
+ See [CHANGELOG](https://github.com/LacusSolutions/br-utils-py/blob/main/packages/cnpj-dv/CHANGELOG.md) for a list of changes and version history.
279
+
280
+ ---
281
+
282
+ Made with ❤️ by [Lacus Solutions](https://github.com/LacusSolutions)
@@ -0,0 +1,70 @@
1
+ [project]
2
+ name = "cnpj-dv"
3
+ dynamic = [ "version" ]
4
+ description = "Utility resources to calculate check digits on CNPJ (Brazilian employer ID)"
5
+ license = "MIT"
6
+ license-files = [ "LICENSE" ]
7
+ keywords = [
8
+ "cnpj",
9
+ "verificar",
10
+ "verificador",
11
+ "verify",
12
+ "verification",
13
+ "check",
14
+ "check-digit",
15
+ "check-digits",
16
+ "pt-br",
17
+ "br",
18
+ ]
19
+ classifiers = [
20
+ "Development Status :: 5 - Production/Stable",
21
+ "Intended Audience :: Developers",
22
+ "Natural Language :: English",
23
+ "Natural Language :: Portuguese (Brazilian)",
24
+ "Operating System :: MacOS :: MacOS X",
25
+ "Operating System :: Microsoft :: Windows",
26
+ "Operating System :: POSIX",
27
+ "Operating System :: Unix",
28
+ "Programming Language :: Python :: 3 :: Only",
29
+ "Programming Language :: Python :: 3.10",
30
+ "Programming Language :: Python :: 3.11",
31
+ "Programming Language :: Python :: 3.12",
32
+ "Programming Language :: Python :: 3.13",
33
+ "Programming Language :: Python :: 3.14",
34
+ "Topic :: Software Development :: Libraries",
35
+ "Topic :: Utilities",
36
+ ]
37
+ requires-python = ">=3.10"
38
+
39
+ [[project.authors]]
40
+ name = "Julio L. Muller"
41
+
42
+ [project.readme]
43
+ file = "README.md"
44
+ content-type = "text/markdown"
45
+
46
+ [project.urls]
47
+ Homepage = "https://cnpj-utils.vercel.app/"
48
+ Source = "https://github.com/LacusSolutions/br-utils-py"
49
+ Tracker = "https://github.com/LacusSolutions/br-utils-py/issues"
50
+
51
+ [build-system]
52
+ requires = [ "setuptools>=80.9.0", "wheel" ]
53
+ build-backend = "setuptools.build_meta"
54
+
55
+ [tool.setuptools.dynamic.version]
56
+ attr = "cnpj_dv.__version__"
57
+
58
+ [tool.setuptools.packages.find]
59
+ where = [ "src/" ]
60
+
61
+ [tool.pytest.ini_options]
62
+ minversion = "9.0"
63
+ testpaths = [ "tests/" ]
64
+ python_files = [ "*_test.py" ]
65
+ python_functions = [ "test_*" ]
66
+ python_classes = [ "*Test" ]
67
+
68
+ [tool.coverage.run]
69
+ source = [ "src/" ]
70
+ omit = [ "tests/*" ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,17 @@
1
+ from .cnpj_check_digits import CnpjCheckDigits
2
+ from .exceptions import (
3
+ CnpjCheckDigitsCalculationError,
4
+ CnpjCheckDigitsError,
5
+ CnpjInvalidLengthError,
6
+ CnpjTypeError,
7
+ )
8
+
9
+ __all__ = [
10
+ "CnpjCheckDigits",
11
+ "CnpjCheckDigitsCalculationError",
12
+ "CnpjCheckDigitsError",
13
+ "CnpjInvalidLengthError",
14
+ "CnpjTypeError",
15
+ ]
16
+
17
+ __version__ = "1.0.0"
@@ -0,0 +1,147 @@
1
+ import re
2
+
3
+ from .exceptions import (
4
+ CnpjCheckDigitsCalculationError,
5
+ CnpjInvalidLengthError,
6
+ CnpjTypeError,
7
+ )
8
+
9
+ CNPJ_MIN_LENGTH = 12
10
+ CNPJ_MAX_LENGTH = 14
11
+
12
+
13
+ class CnpjCheckDigits:
14
+ """Class to calculate CNPJ check digits."""
15
+
16
+ __slots__ = ("_cnpj_digits", "_first_digit", "_second_digit")
17
+
18
+ def __init__(self, cnpj_digits: str | list[str] | list[int]) -> None:
19
+ original_input = cnpj_digits
20
+
21
+ if not isinstance(cnpj_digits, (str, list)):
22
+ raise CnpjTypeError(original_input)
23
+
24
+ if isinstance(cnpj_digits, str):
25
+ cnpj_digits = self._handle_string_input(cnpj_digits, original_input)
26
+ elif isinstance(cnpj_digits, list):
27
+ cnpj_digits = self._handle_list_input(cnpj_digits, original_input)
28
+
29
+ self._validate_length(cnpj_digits, original_input)
30
+ self._cnpj_digits = cnpj_digits[:CNPJ_MIN_LENGTH]
31
+ self._first_digit: int | None = None
32
+ self._second_digit: int | None = None
33
+
34
+ @property
35
+ def first_digit(self) -> int:
36
+ """Calculates and returns the first check digit.As it's immutable, it caches the calculation result."""
37
+ if self._first_digit is None:
38
+ base_digits_sequence = self._cnpj_digits.copy()
39
+ self._first_digit = self._calculate(base_digits_sequence)
40
+
41
+ return self._first_digit
42
+
43
+ @property
44
+ def second_digit(self) -> int:
45
+ """Calculates and returns the second check digit.As it's immutable, it caches the calculation result. And, as it depends on the first check digit, it's also calculated."""
46
+ if self._second_digit is None:
47
+ base_digits_sequence = [*self._cnpj_digits, self.first_digit]
48
+ self._second_digit = self._calculate(base_digits_sequence)
49
+
50
+ return self._second_digit
51
+
52
+ def to_list(self) -> list[int]:
53
+ """Returns the complete CNPJ as a list of 14 integers (12 base digits + 2 check digits)."""
54
+ return [*self._cnpj_digits, self.first_digit, self.second_digit]
55
+
56
+ def to_string(self) -> str:
57
+ """Returns the complete CNPJ as a string of 14 digits (12 base digits + 2 check digits)."""
58
+ return "".join(str(digit) for digit in self.to_list())
59
+
60
+ def _handle_string_input(self, cnpj_digits: str, original_input: str) -> list[int]:
61
+ """When CNPJ is provided as a string, it's validated and converted to a list of integers."""
62
+ numeric_str = re.sub(r"[^0-9]", "", cnpj_digits)
63
+
64
+ if not numeric_str:
65
+ raise CnpjInvalidLengthError(
66
+ original_input, CNPJ_MIN_LENGTH, CNPJ_MAX_LENGTH, 0
67
+ )
68
+
69
+ return [int(d) for d in numeric_str]
70
+
71
+ def _handle_list_input(
72
+ self, cnpj_digits: list[str] | list[int], original_input: list
73
+ ) -> list[int]:
74
+ """When CNPJ is provided as a list of strings or integers, it's validated and converted to a list of integers for further processing."""
75
+ if all(isinstance(digit, str) for digit in cnpj_digits):
76
+ return self._handle_string_list(cnpj_digits, original_input)
77
+
78
+ if all(isinstance(digit, int) for digit in cnpj_digits):
79
+ return self._flatten_digits(cnpj_digits)
80
+
81
+ raise CnpjTypeError(original_input)
82
+
83
+ def _handle_string_list(
84
+ self, cnpj_digits: list[str], original_input: list
85
+ ) -> list[int]:
86
+ """When CNPJ is provided as a list of strings, it's validated and converted to a list of integers for further processing."""
87
+ total_length = sum(len(digit_str) for digit_str in cnpj_digits if digit_str)
88
+
89
+ if total_length < CNPJ_MIN_LENGTH or total_length > CNPJ_MAX_LENGTH:
90
+ raise CnpjInvalidLengthError(
91
+ original_input, CNPJ_MIN_LENGTH, CNPJ_MAX_LENGTH, total_length
92
+ )
93
+
94
+ flat_digits = []
95
+
96
+ for digit_str in cnpj_digits:
97
+ if not digit_str:
98
+ continue
99
+
100
+ try:
101
+ digit_int = int(digit_str)
102
+ flat_digits.extend(self._flatten_digits([digit_int]))
103
+ except ValueError as e:
104
+ raise CnpjTypeError(original_input) from e
105
+
106
+ return flat_digits
107
+
108
+ def _flatten_digits(self, digits: list[int]) -> list[int]:
109
+ """Breaks down multiple digits within the array into individual digits. Negative numbers are converted to their absolute value."""
110
+ flat_digits = []
111
+
112
+ for digit in digits:
113
+ abs_digit = abs(digit)
114
+ flat_digits.extend([int(d) for d in str(abs_digit)])
115
+
116
+ return flat_digits
117
+
118
+ def _validate_length(
119
+ self, cnpj_digits: list[int], original_input: str | list
120
+ ) -> None:
121
+ """Validates the length of the CNPJ digits."""
122
+ length = len(cnpj_digits)
123
+
124
+ if length < CNPJ_MIN_LENGTH or length > CNPJ_MAX_LENGTH:
125
+ raise CnpjInvalidLengthError(
126
+ original_input, CNPJ_MIN_LENGTH, CNPJ_MAX_LENGTH, length
127
+ )
128
+
129
+ def _calculate(self, cnpj_sequence: list[int]) -> int:
130
+ """Calculates the CNPJ check digits using the official Brazilian algorithm. For the first check digit, it uses the digits 1 through 12 of the CNPJ base. For the second one, it uses the digits 1 through 13 (with the first check digit)."""
131
+ min_length = CNPJ_MIN_LENGTH
132
+ max_length = CNPJ_MAX_LENGTH - 1
133
+ sequence_length = len(cnpj_sequence)
134
+
135
+ if sequence_length < min_length or sequence_length > max_length:
136
+ raise CnpjCheckDigitsCalculationError(cnpj_sequence)
137
+
138
+ factor = 2
139
+ sum_result = 0
140
+
141
+ for num in reversed(cnpj_sequence):
142
+ sum_result += num * factor
143
+ factor = 2 if factor == 9 else factor + 1
144
+
145
+ remainder = sum_result % 11
146
+
147
+ return 0 if remainder < 2 else 11 - remainder
@@ -0,0 +1,45 @@
1
+ class CnpjCheckDigitsError(Exception):
2
+ """Base exception for all cnpj-dv related errors."""
3
+
4
+
5
+ class CnpjTypeError(CnpjCheckDigitsError):
6
+ """Raised when a CNPJ digits is not a string or a list of strings or integers."""
7
+
8
+ def __init__(self, cnpj) -> None:
9
+ self.cnpj = cnpj
10
+
11
+ super().__init__(
12
+ f"CNPJ input must be of type str, list[str] or list[int]. Got {type(cnpj).__name__}."
13
+ )
14
+
15
+
16
+ class CnpjInvalidLengthError(CnpjCheckDigitsError):
17
+ """Raised when a CNPJ string does not contain the expected number of digits."""
18
+
19
+ def __init__(
20
+ self,
21
+ cnpj: str | list[str] | list[int],
22
+ min_expected_length: int,
23
+ max_expected_length: int,
24
+ actual_length: int,
25
+ ) -> None:
26
+ self.cnpj = cnpj
27
+ self.min_expected_length = min_expected_length
28
+ self.max_expected_length = max_expected_length
29
+ self.actual_length = actual_length
30
+
31
+ super().__init__(
32
+ f'Parameter "{cnpj}" does not contain {min_expected_length} to {max_expected_length} digits. '
33
+ f"Got {actual_length}."
34
+ )
35
+
36
+
37
+ class CnpjCheckDigitsCalculationError(CnpjCheckDigitsError):
38
+ """Raised when the calculation of the CNPJ check digits fails."""
39
+
40
+ def __init__(self, cnpj_digits: list[int]) -> None:
41
+ self.cnpj_digits = cnpj_digits
42
+
43
+ super().__init__(
44
+ f"Failed to calculate the CNPJ check digits for the sequence: {cnpj_digits}."
45
+ )
@@ -0,0 +1,313 @@
1
+ Metadata-Version: 2.4
2
+ Name: cnpj-dv
3
+ Version: 1.0.0
4
+ Summary: Utility resources to calculate check digits on CNPJ (Brazilian employer ID)
5
+ Author: Julio L. Muller
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://cnpj-utils.vercel.app/
8
+ Project-URL: Source, https://github.com/LacusSolutions/br-utils-py
9
+ Project-URL: Tracker, https://github.com/LacusSolutions/br-utils-py/issues
10
+ Keywords: cnpj,verificar,verificador,verify,verification,check,check-digit,check-digits,pt-br,br
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Natural Language :: English
14
+ Classifier: Natural Language :: Portuguese (Brazilian)
15
+ Classifier: Operating System :: MacOS :: MacOS X
16
+ Classifier: Operating System :: Microsoft :: Windows
17
+ Classifier: Operating System :: POSIX
18
+ Classifier: Operating System :: Unix
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Programming Language :: Python :: 3.14
25
+ Classifier: Topic :: Software Development :: Libraries
26
+ Classifier: Topic :: Utilities
27
+ Requires-Python: >=3.10
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Dynamic: license-file
31
+
32
+ ![cnpj-dv for Python](https://br-utils.vercel.app/img/cover_cnpj-dv.jpg)
33
+
34
+ [![PyPI Version](https://img.shields.io/pypi/v/cnpj-dv)](https://pypi.org/project/cnpj-dv)
35
+ [![PyPI Downloads](https://img.shields.io/pypi/dm/cnpj-dv)](https://pypi.org/project/cnpj-dv)
36
+ [![Python Version](https://img.shields.io/pypi/pyversions/cnpj-dv)](https://www.python.org/)
37
+ [![Test Status](https://img.shields.io/github/actions/workflow/status/LacusSolutions/br-utils-py/ci.yml?label=ci/cd)](https://github.com/LacusSolutions/br-utils-py/actions)
38
+ [![Last Update Date](https://img.shields.io/github/last-commit/LacusSolutions/br-utils-py)](https://github.com/LacusSolutions/br-utils-py)
39
+ [![Project License](https://img.shields.io/github/license/LacusSolutions/br-utils-py)](https://github.com/LacusSolutions/br-utils-py/blob/main/LICENSE)
40
+
41
+ Utility class to calculate check digits on CNPJ (Brazilian employer ID).
42
+
43
+ ## Python Support
44
+
45
+ | ![Python 3.10](https://img.shields.io/badge/Python-3.10-3776AB?logo=python&logoColor=white) | ![Python 3.11](https://img.shields.io/badge/Python-3.11-3776AB?logo=python&logoColor=white) | ![Python 3.12](https://img.shields.io/badge/Python-3.12-3776AB?logo=python&logoColor=white) | ![Python 3.13](https://img.shields.io/badge/Python-3.13-3776AB?logo=python&logoColor=white) | ![Python 3.14](https://img.shields.io/badge/Python-3.14-3776AB?logo=python&logoColor=white) |
46
+ |--- | --- | --- | --- | --- |
47
+ | Passing ✔ | Passing ✔ | Passing ✔ | Passing ✔ | Passing ✔ |
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ $ pip install cnpj-dv
53
+ ```
54
+
55
+ ## Import
56
+
57
+ ```python
58
+ from cnpj_dv import CnpjCheckDigits
59
+ ```
60
+
61
+ ## Usage
62
+
63
+ ### Basic Usage
64
+
65
+ ```python
66
+ # Calculate check digits from a 12-digit CNPJ base
67
+ check_digits = CnpjCheckDigits("914157320007")
68
+
69
+ print(check_digits.first_digit) # returns 9
70
+ print(check_digits.second_digit) # returns 3
71
+ print(check_digits.to_string()) # returns '91415732000793'
72
+ print(check_digits.to_list()) # returns [9, 1, 4, 1, 5, 7, 3, 2, 0, 0, 0, 7, 9, 3]
73
+ ```
74
+
75
+ ### Input Formats
76
+
77
+ The `CnpjCheckDigits` class accepts multiple input formats:
78
+
79
+ #### String Input
80
+
81
+ ```python
82
+ # Plain string (non-numeric characters are automatically stripped)
83
+ check_digits = CnpjCheckDigits("914157320007")
84
+ check_digits = CnpjCheckDigits("91.415.732/0007") # formatting is ignored
85
+ check_digits = CnpjCheckDigits("914157320007") # 12 digits
86
+ check_digits = CnpjCheckDigits("91415732000793") # 14 digits (only first 12 are used)
87
+ ```
88
+
89
+ #### List of Strings
90
+
91
+ ```python
92
+ # List of single-character strings
93
+ check_digits = CnpjCheckDigits(["9", "1", "4", "1", "5", "7", "3", "2", "0", "0", "0", "7"])
94
+
95
+ # List with multi-digit strings (automatically flattened)
96
+ check_digits = CnpjCheckDigits(["914157320007"]) # flattens to individual digits
97
+ check_digits = CnpjCheckDigits(["91", "415", "732", "0007"]) # also flattens
98
+ ```
99
+
100
+ #### List of Integers
101
+
102
+ ```python
103
+ # List of single-digit integers
104
+ check_digits = CnpjCheckDigits([9, 1, 4, 1, 5, 7, 3, 2, 0, 0, 0, 7])
105
+
106
+ # List with multi-digit integers (automatically flattened)
107
+ check_digits = CnpjCheckDigits([914157320007]) # flattens to individual digits
108
+ check_digits = CnpjCheckDigits([914, 157, 320, 7]) # also flattens
109
+ ```
110
+
111
+ ### Properties
112
+
113
+ #### `first_digit: int`
114
+
115
+ Returns the first check digit (13th digit of the CNPJ).
116
+
117
+ ```python
118
+ check_digits = CnpjCheckDigits("914157320007")
119
+ print(check_digits.first_digit) # returns 9
120
+ ```
121
+
122
+ #### `second_digit: int`
123
+
124
+ Returns the second check digit (14th digit of the CNPJ).
125
+
126
+ ```python
127
+ check_digits = CnpjCheckDigits("914157320007")
128
+ print(check_digits.second_digit) # returns 3
129
+ ```
130
+
131
+ ### Methods
132
+
133
+ #### `to_list() -> list[int]`
134
+
135
+ Returns the complete CNPJ as a list of integers (12 base digits + 2 check digits).
136
+
137
+ ```python
138
+ check_digits = CnpjCheckDigits("914157320007")
139
+ print(check_digits.to_list()) # returns [9, 1, 4, 1, 5, 7, 3, 2, 0, 0, 0, 7, 9, 3]
140
+ ```
141
+
142
+ #### `to_string() -> str`
143
+
144
+ Returns the complete CNPJ as a string (12 base digits + 2 check digits).
145
+
146
+ ```python
147
+ check_digits = CnpjCheckDigits("914157320007")
148
+ print(check_digits.to_string()) # returns '91415732000793'
149
+ ```
150
+
151
+ ### Examples
152
+
153
+ ```python
154
+ from cnpj_dv import CnpjCheckDigits
155
+
156
+ # Calculate check digits for a CNPJ base
157
+ base = "914157320007"
158
+ check_digits = CnpjCheckDigits(base)
159
+
160
+ # Get individual check digits
161
+ first = check_digits.first_digit # 9
162
+ second = check_digits.second_digit # 3
163
+
164
+ # Get complete CNPJ
165
+ complete = check_digits.to_string() # '91415732000793'
166
+
167
+ # Work with formatted input
168
+ formatted = CnpjCheckDigits("91.415.732/0007")
169
+ print(formatted.to_string()) # '91415732000793'
170
+
171
+ # Work with list input
172
+ list_input = CnpjCheckDigits([9, 1, 4, 1, 5, 7, 3, 2, 0, 0, 0, 7])
173
+ print(list_input.to_string()) # '91415732000793'
174
+ ```
175
+
176
+ ## Error Handling
177
+
178
+ The package raises specific exceptions for different error scenarios:
179
+
180
+ ### `CnpjTypeError`
181
+
182
+ Raised when the input type is not supported (must be `str`, `list[str]`, or `list[int]`).
183
+
184
+ ```python
185
+ from cnpj_dv import CnpjCheckDigits, CnpjTypeError
186
+
187
+ try:
188
+ CnpjCheckDigits(12345678901234) # int not allowed
189
+ except CnpjTypeError as e:
190
+ print(e) # CNPJ input must be of type str, list[str] or list[int]. Got "int".
191
+ ```
192
+
193
+ ### `CnpjInvalidLengthError`
194
+
195
+ Raised when the input does not contain 12 to 14 digits.
196
+
197
+ ```python
198
+ from cnpj_dv import CnpjCheckDigits, CnpjInvalidLengthError
199
+
200
+ try:
201
+ CnpjCheckDigits("12345678901") # only 11 digits
202
+ except CnpjInvalidLengthError as e:
203
+ print(e) # Parameter "12345678901" does not contain 12 to 14 digits. Got 11.
204
+ ```
205
+
206
+ ### `CnpjCheckDigitsCalculationError`
207
+
208
+ Raised when the check digit calculation fails due to invalid sequence length.
209
+
210
+ ```python
211
+ from cnpj_dv import CnpjCheckDigits, CnpjCheckDigitsCalculationError
212
+
213
+ # This is an internal error that should not occur in normal usage
214
+ # It happens when the sequence passed to _calculate() has invalid length
215
+ ```
216
+
217
+ ## Features
218
+
219
+ - ✅ **Multiple Input Formats**: Accepts strings, lists of strings, or lists of integers
220
+ - ✅ **Format Agnostic**: Automatically strips non-numeric characters from string input
221
+ - ✅ **Auto-Expansion**: Automatically expands multi-digit numbers in lists to individual digits
222
+ - ✅ **Lazy Evaluation**: Check digits are calculated only when accessed (via properties)
223
+ - ✅ **Type Safety**: Built with Python 3.10+ type hints
224
+ - ✅ **Zero Dependencies**: No external dependencies required
225
+ - ✅ **Comprehensive Error Handling**: Specific exceptions for different error scenarios
226
+
227
+ ## API Reference
228
+
229
+ ### CnpjCheckDigits Class
230
+
231
+ #### Constructor
232
+
233
+ ```python
234
+ CnpjCheckDigits(cnpj_digits: str | list[str] | list[int]) -> CnpjCheckDigits
235
+ ```
236
+
237
+ Creates a new `CnpjCheckDigits` instance from the provided CNPJ base digits.
238
+
239
+ **Parameters:**
240
+ - `cnpj_digits` (str | list[str] | list[int]): The CNPJ base digits (12-14 digits). Can be:
241
+ - A string with 12-14 digits (formatting characters are ignored)
242
+ - A list of strings (each string can be a single digit or multi-digit number)
243
+ - A list of integers (each integer can be a single digit or multi-digit number)
244
+
245
+ **Raises:**
246
+ - `CnpjTypeError`: If the input type is not supported
247
+ - `CnpjInvalidLengthError`: If the input does not contain 12-14 digits
248
+
249
+ **Returns:**
250
+ - `CnpjCheckDigits`: A new instance ready to calculate check digits
251
+
252
+ #### Properties
253
+
254
+ ##### `first_digit: int`
255
+
256
+ The first check digit (13th digit of the CNPJ). Calculated lazily on first access.
257
+
258
+ ##### `second_digit: int`
259
+
260
+ The second check digit (14th digit of the CNPJ). Calculated lazily on first access.
261
+
262
+ #### Methods
263
+
264
+ ##### `to_list() -> list[int]`
265
+
266
+ Returns the complete CNPJ as a list of 14 integers (12 base digits + 2 check digits).
267
+
268
+ ##### `to_string() -> str`
269
+
270
+ Returns the complete CNPJ as a string of 14 digits (12 base digits + 2 check digits).
271
+
272
+ ## Calculation Algorithm
273
+
274
+ The package calculates CNPJ check digits using the official Brazilian algorithm:
275
+
276
+ 1. **First Check Digit (13th position)**:
277
+ - Uses digits 1-12 of the CNPJ base
278
+ - Applies weights: 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2 (from right to left)
279
+ - Calculates: `sum(digit × weight) % 11`
280
+ - Result: `0` if remainder < 2, otherwise `11 - remainder`
281
+
282
+ 2. **Second Check Digit (14th position)**:
283
+ - Uses digits 1-12 + first check digit
284
+ - Applies weights: 6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2 (from right to left)
285
+ - Calculates: `sum(digit × weight) % 11`
286
+ - Result: `0` if remainder < 2, otherwise `11 - remainder`
287
+
288
+ ## Dependencies
289
+
290
+ - **Python**: >= 3.10
291
+
292
+ No external dependencies required.
293
+
294
+ ## Contribution & Support
295
+
296
+ We welcome contributions! Please see our [Contributing Guidelines](https://github.com/LacusSolutions/br-utils-py/blob/main/CONTRIBUTING.md) for details. But if you find this project helpful, please consider:
297
+
298
+ - ⭐ Starring the repository
299
+ - 🤝 Contributing to the codebase
300
+ - 💡 [Suggesting new features](https://github.com/LacusSolutions/br-utils-py/issues)
301
+ - 🐛 [Reporting bugs](https://github.com/LacusSolutions/br-utils-py/issues)
302
+
303
+ ## License
304
+
305
+ This project is licensed under the MIT License - see the [LICENSE](https://github.com/LacusSolutions/br-utils-py/blob/main/LICENSE) file for details.
306
+
307
+ ## Changelog
308
+
309
+ See [CHANGELOG](https://github.com/LacusSolutions/br-utils-py/blob/main/packages/cnpj-dv/CHANGELOG.md) for a list of changes and version history.
310
+
311
+ ---
312
+
313
+ Made with ❤️ by [Lacus Solutions](https://github.com/LacusSolutions)
@@ -0,0 +1,10 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/cnpj_dv/__init__.py
5
+ src/cnpj_dv/cnpj_check_digits.py
6
+ src/cnpj_dv/exceptions.py
7
+ src/cnpj_dv.egg-info/PKG-INFO
8
+ src/cnpj_dv.egg-info/SOURCES.txt
9
+ src/cnpj_dv.egg-info/dependency_links.txt
10
+ src/cnpj_dv.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ cnpj_dv