universal-validator 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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Parthiv Rawat
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,2 @@
1
+ include README.md
2
+ include LICENSE
@@ -0,0 +1,432 @@
1
+ Metadata-Version: 2.4
2
+ Name: universal-validator
3
+ Version: 1.0.0
4
+ Summary: Comprehensive data validation library for API, database, and form contexts
5
+ Home-page: https://github.com/parthivrawat/universal-validator
6
+ Author: Parthiv Rawat
7
+ License: MIT
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.7
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Requires-Python: >=3.7
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
24
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
25
+ Dynamic: author
26
+ Dynamic: classifier
27
+ Dynamic: description
28
+ Dynamic: description-content-type
29
+ Dynamic: home-page
30
+ Dynamic: license
31
+ Dynamic: license-file
32
+ Dynamic: provides-extra
33
+ Dynamic: requires-python
34
+ Dynamic: summary
35
+
36
+ # Universal Data Validator
37
+
38
+ A comprehensive data validation library for Python that works across API, database, and form contexts.
39
+
40
+ ## Features
41
+
42
+ - ✅ **Rich Validator Types**: String, int, float, bool, email, URL, list, dict
43
+ - ✅ **Schema-Based Validation**: Define complex data structures
44
+ - ✅ **Custom Validators**: Add your own validation logic
45
+ - ✅ **Nested Validation**: Validate nested objects and lists
46
+ - ✅ **Clear Error Messages**: Detailed error reporting with field paths
47
+ - ✅ **Zero Dependencies**: No external dependencies required
48
+ - ✅ **Production Ready**: Comprehensive test coverage
49
+
50
+ ## Installation
51
+
52
+ ```bash
53
+ pip install universal-validator
54
+ ```
55
+
56
+ ## Quick Start
57
+
58
+ ```python
59
+ from universal_validator import Schema, validators
60
+
61
+ schema = Schema({
62
+ 'email': validators.email(),
63
+ 'age': validators.int(min_value=0, max_value=120),
64
+ 'username': validators.string(min_length=3, max_length=20),
65
+ 'tags': validators.list(validators.string())
66
+ })
67
+
68
+ result = schema.validate(data)
69
+ if not result.valid:
70
+ for error in result.errors:
71
+ print(f"{error.field}: {error.message}")
72
+ ```
73
+
74
+ ## Usage Examples
75
+
76
+ ### String Validation
77
+
78
+ ```python
79
+ from universal_validator import validators
80
+
81
+ # Basic string
82
+ validator = validators.string()
83
+
84
+ # String with length constraints
85
+ validator = validators.string(min_length=3, max_length=20)
86
+
87
+ # String with pattern
88
+ validator = validators.string(pattern=r'^\d{3}-\d{4}$')
89
+
90
+ # String with choices
91
+ validator = validators.string(choices=['red', 'green', 'blue'])
92
+
93
+ # Optional string
94
+ validator = validators.string(required=False)
95
+
96
+ # Nullable string
97
+ validator = validators.string(nullable=True)
98
+ ```
99
+
100
+ ### Integer and Float Validation
101
+
102
+ ```python
103
+ # Integer with range
104
+ age_validator = validators.int(min_value=0, max_value=120)
105
+
106
+ # Float with range
107
+ price_validator = validators.float(min_value=0.0, max_value=9999.99)
108
+
109
+ # Optional integer
110
+ count_validator = validators.int(required=False)
111
+ ```
112
+
113
+ ### Boolean Validation
114
+
115
+ ```python
116
+ # Boolean
117
+ terms_validator = validators.bool()
118
+
119
+ # Optional boolean
120
+ newsletter_validator = validators.bool(required=False)
121
+ ```
122
+
123
+ ### Email and URL Validation
124
+
125
+ ```python
126
+ # Email validation
127
+ email_validator = validators.email()
128
+
129
+ # URL validation
130
+ url_validator = validators.url()
131
+ ```
132
+
133
+ ### List Validation
134
+
135
+ ```python
136
+ # Simple list
137
+ tags_validator = validators.list()
138
+
139
+ # List with item validation
140
+ numbers_validator = validators.list(validators.int())
141
+
142
+ # List with length constraints
143
+ items_validator = validators.list(
144
+ validators.string(),
145
+ min_length=1,
146
+ max_length=10
147
+ )
148
+ ```
149
+
150
+ ### Dictionary Validation
151
+
152
+ ```python
153
+ # Dictionary with schema
154
+ address_validator = validators.dict({
155
+ 'street': validators.string(),
156
+ 'city': validators.string(),
157
+ 'zip': validators.string(pattern=r'^\d{5}$')
158
+ })
159
+
160
+ # Nested dictionary
161
+ user_validator = validators.dict({
162
+ 'name': validators.string(),
163
+ 'email': validators.email(),
164
+ 'address': validators.dict({
165
+ 'street': validators.string(),
166
+ 'city': validators.string()
167
+ })
168
+ })
169
+ ```
170
+
171
+ ### Schema Validation
172
+
173
+ ```python
174
+ from universal_validator import Schema, validators
175
+
176
+ # Define schema
177
+ user_schema = Schema({
178
+ 'username': validators.string(min_length=3, max_length=20),
179
+ 'email': validators.email(),
180
+ 'age': validators.int(min_value=13, required=False),
181
+ 'bio': validators.string(max_length=500, required=False),
182
+ 'tags': validators.list(validators.string()),
183
+ 'settings': validators.dict({
184
+ 'theme': validators.string(choices=['light', 'dark']),
185
+ 'notifications': validators.bool()
186
+ })
187
+ })
188
+
189
+ # Validate data
190
+ data = {
191
+ 'username': 'john_doe',
192
+ 'email': 'john@example.com',
193
+ 'age': 25,
194
+ 'tags': ['python', 'javascript'],
195
+ 'settings': {
196
+ 'theme': 'dark',
197
+ 'notifications': True
198
+ }
199
+ }
200
+
201
+ result = user_schema.validate(data)
202
+
203
+ if result.valid:
204
+ print("✅ Data is valid!")
205
+ else:
206
+ print("❌ Validation errors:")
207
+ for error in result.errors:
208
+ print(f" {error.field}: {error.message}")
209
+ ```
210
+
211
+ ### Custom Validators
212
+
213
+ ```python
214
+ from universal_validator import validators
215
+
216
+ def is_even(value):
217
+ """Custom validator to check if number is even."""
218
+ if value % 2 != 0:
219
+ return "Value must be even"
220
+ return None
221
+
222
+ # Add custom validator
223
+ validator = validators.int().custom(is_even)
224
+
225
+ result = validator.validate(4, 'number')
226
+ print(result.valid) # True
227
+
228
+ result = validator.validate(3, 'number')
229
+ print(result.valid) # False
230
+ print(result.errors[0].message) # "Value must be even"
231
+ ```
232
+
233
+ ### Multiple Custom Validators
234
+
235
+ ```python
236
+ def is_positive(value):
237
+ return "Must be positive" if value <= 0 else None
238
+
239
+ def is_even(value):
240
+ return "Must be even" if value % 2 != 0 else None
241
+
242
+ validator = validators.int().custom(is_positive).custom(is_even)
243
+
244
+ result = validator.validate(4, 'field')
245
+ print(result.valid) # True
246
+
247
+ result = validator.validate(-2, 'field')
248
+ print(result.valid) # False
249
+ ```
250
+
251
+ ## Real-World Examples
252
+
253
+ ### User Registration
254
+
255
+ ```python
256
+ from universal_validator import Schema, validators
257
+
258
+ registration_schema = Schema({
259
+ 'username': validators.string(min_length=3, max_length=20),
260
+ 'email': validators.email(),
261
+ 'password': validators.string(min_length=8),
262
+ 'confirm_password': validators.string(min_length=8),
263
+ 'age': validators.int(min_value=13, required=False),
264
+ 'terms_accepted': validators.bool()
265
+ })
266
+
267
+ data = {
268
+ 'username': 'john_doe',
269
+ 'email': 'john@example.com',
270
+ 'password': 'secure_password_123',
271
+ 'confirm_password': 'secure_password_123',
272
+ 'age': 25,
273
+ 'terms_accepted': True
274
+ }
275
+
276
+ result = registration_schema.validate(data)
277
+ ```
278
+
279
+ ### API Request Validation
280
+
281
+ ```python
282
+ api_request_schema = Schema({
283
+ 'method': validators.string(choices=['GET', 'POST', 'PUT', 'DELETE']),
284
+ 'url': validators.url(),
285
+ 'headers': validators.dict(required=False),
286
+ 'body': validators.dict(required=False),
287
+ 'timeout': validators.float(min_value=0, required=False)
288
+ })
289
+
290
+ request_data = {
291
+ 'method': 'POST',
292
+ 'url': 'https://api.example.com/users',
293
+ 'headers': {'Content-Type': 'application/json'},
294
+ 'body': {'name': 'John'},
295
+ 'timeout': 30.0
296
+ }
297
+
298
+ result = api_request_schema.validate(request_data)
299
+ ```
300
+
301
+ ### Configuration Validation
302
+
303
+ ```python
304
+ config_schema = Schema({
305
+ 'database': validators.dict({
306
+ 'host': validators.string(),
307
+ 'port': validators.int(min_value=1, max_value=65535),
308
+ 'username': validators.string(),
309
+ 'password': validators.string(),
310
+ 'ssl': validators.bool()
311
+ }),
312
+ 'cache': validators.dict({
313
+ 'enabled': validators.bool(),
314
+ 'ttl': validators.int(min_value=0),
315
+ 'max_size': validators.int(min_value=1)
316
+ }),
317
+ 'features': validators.list(validators.string())
318
+ })
319
+
320
+ config = {
321
+ 'database': {
322
+ 'host': 'localhost',
323
+ 'port': 5432,
324
+ 'username': 'admin',
325
+ 'password': 'secret',
326
+ 'ssl': True
327
+ },
328
+ 'cache': {
329
+ 'enabled': True,
330
+ 'ttl': 3600,
331
+ 'max_size': 1000
332
+ },
333
+ 'features': ['feature1', 'feature2']
334
+ }
335
+
336
+ result = config_schema.validate(config)
337
+ ```
338
+
339
+ ## Error Handling
340
+
341
+ ```python
342
+ from universal_validator import Schema, validators, ValidationError
343
+
344
+ schema = Schema({
345
+ 'email': validators.email()
346
+ })
347
+
348
+ # Option 1: Check result
349
+ result = schema.validate({'email': 'invalid'})
350
+ if not result.valid:
351
+ for error in result.errors:
352
+ print(f"{error.field}: {error.message}")
353
+
354
+ # Option 2: Raise exception
355
+ try:
356
+ schema.validate_or_raise({'email': 'invalid'})
357
+ except ValidationError as e:
358
+ print(f"Validation failed: {e}")
359
+ ```
360
+
361
+ ## API Reference
362
+
363
+ ### Validators
364
+
365
+ - `validators.string(min_length, max_length, pattern, choices, required, nullable)` - String validator
366
+ - `validators.int(min_value, max_value, required, nullable)` - Integer validator
367
+ - `validators.float(min_value, max_value, required, nullable)` - Float validator
368
+ - `validators.bool(required, nullable)` - Boolean validator
369
+ - `validators.email(required, nullable)` - Email validator
370
+ - `validators.url(required, nullable)` - URL validator
371
+ - `validators.list(item_validator, min_length, max_length, required, nullable)` - List validator
372
+ - `validators.dict(schema, required, nullable)` - Dictionary validator
373
+
374
+ ### Schema
375
+
376
+ - `Schema(schema_dict)` - Create a schema
377
+ - `schema.validate(data)` - Validate data and return ValidationResult
378
+ - `schema.validate_or_raise(data)` - Validate data and raise ValidationError if invalid
379
+
380
+ ### ValidationResult
381
+
382
+ - `result.valid` - Boolean indicating if validation passed
383
+ - `result.errors` - List of ValidationError objects
384
+
385
+ ### ValidationError
386
+
387
+ - `error.field` - Field name that failed validation
388
+ - `error.message` - Error message
389
+ - `error.value` - Value that failed validation
390
+
391
+ ## Testing
392
+
393
+ ```bash
394
+ # Install dev dependencies
395
+ pip install -e ".[dev]"
396
+
397
+ # Run tests
398
+ pytest test_universal_validator.py -v
399
+
400
+ # Run with coverage
401
+ pytest test_universal_validator.py --cov=universal_validator --cov-report=html
402
+ ```
403
+
404
+ ## Comparison with Other Libraries
405
+
406
+ | Feature | universal-validator | pydantic | marshmallow | cerberus |
407
+ |---------|-------------------|----------|-------------|----------|
408
+ | Schema-based | ✅ | ✅ | ✅ | ✅ |
409
+ | Custom validators | ✅ | ✅ | ✅ | ✅ |
410
+ | Zero dependencies | ✅ | ❌ | ❌ | ✅ |
411
+ | Nested validation | ✅ | ✅ | ✅ | ✅ |
412
+ | Clear errors | ✅ | ✅ | ✅ | ✅ |
413
+ | Simple API | ✅ | ❌ | ❌ | ✅ |
414
+ | Type hints | ✅ | ✅ | ❌ | ❌ |
415
+
416
+ ## License
417
+
418
+ MIT License
419
+
420
+ ## Contributing
421
+
422
+ Contributions are welcome! Please feel free to submit a Pull Request.
423
+
424
+ ## Changelog
425
+
426
+ ### 1.0.0 (2024-01-15)
427
+ - Initial release
428
+ - Support for string, int, float, bool, email, URL, list, dict validators
429
+ - Schema-based validation
430
+ - Custom validators
431
+ - Nested validation
432
+ - Comprehensive test coverage