valid8r 0.2.7__tar.gz → 0.2.8__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.

Potentially problematic release.


This version of valid8r might be problematic. Click here for more details.

valid8r-0.2.8/PKG-INFO ADDED
@@ -0,0 +1,246 @@
1
+ Metadata-Version: 2.4
2
+ Name: valid8r
3
+ Version: 0.2.8
4
+ Summary: Clean, flexible input validation for Python applications
5
+ License: MIT
6
+ Keywords: validation,input,cli,maybe-monad
7
+ Author: Mike Lane
8
+ Author-email: mikelane@gmail.com
9
+ Requires-Python: >=3.11,<4.0
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Requires-Dist: email-validator (>=2.3.0,<3.0.0)
19
+ Requires-Dist: pydantic (>=2.0)
20
+ Requires-Dist: pydantic-core (>=2.27.0,<3.0.0)
21
+ Requires-Dist: uuid-utils (>=0.11.0,<0.12.0)
22
+ Project-URL: Repository, https://github.com/mikelane/valid8r
23
+ Description-Content-Type: text/markdown
24
+
25
+ # Valid8r
26
+
27
+ A clean, flexible input validation library for Python applications.
28
+
29
+ ## Features
30
+
31
+ - **Clean Type Parsing**: Parse strings to various Python types with robust error handling
32
+ - **Flexible Validation**: Chain validators and create custom validation rules
33
+ - **Monadic Error Handling**: Use Maybe monad for clean error propagation
34
+ - **Input Prompting**: Prompt users for input with built-in validation
35
+ - **Structured Results**: Network parsers return rich dataclasses with parsed components
36
+
37
+ ## Available Parsers
38
+
39
+ ### Basic Types
40
+ - **Numbers**: `parse_int`, `parse_float`, `parse_complex`, `parse_decimal`
41
+ - **Text**: `parse_bool` (flexible true/false parsing)
42
+ - **Dates**: `parse_date` (ISO 8601 format)
43
+ - **UUIDs**: `parse_uuid` (with optional version validation)
44
+
45
+ ### Collections
46
+ - **Lists**: `parse_list` (with element parser)
47
+ - **Dictionaries**: `parse_dict` (with key/value parsers)
48
+ - **Sets**: `parse_set` (with element parser)
49
+
50
+ ### Network & Communication
51
+ - **IP Addresses**: `parse_ipv4`, `parse_ipv6`, `parse_ip` (either v4 or v6)
52
+ - **Networks**: `parse_cidr` (IPv4/IPv6 CIDR notation)
53
+ - **Phone Numbers**: `parse_phone` → PhoneNumber (NANP validation)
54
+ - **URLs**: `parse_url` → UrlParts (scheme, host, port, path, query, etc.)
55
+ - **Email**: `parse_email` → EmailAddress (normalized case)
56
+
57
+ ### Advanced
58
+ - **Enums**: `parse_enum` (type-safe enum parsing)
59
+ - **Custom**: `create_parser`, `make_parser`, `validated_parser` (parser factories)
60
+
61
+ ## Installation
62
+
63
+ ```bash
64
+ pip install valid8r
65
+ ```
66
+
67
+ ## Quick Start
68
+
69
+ ```python
70
+ from valid8r import (
71
+ parsers,
72
+ prompt,
73
+ validators,
74
+ )
75
+
76
+ # Simple validation
77
+ age = prompt.ask(
78
+ "Enter your age: ",
79
+ parser=parsers.parse_int,
80
+ validator=validators.minimum(0) & validators.maximum(120)
81
+ )
82
+
83
+ print(f"Your age is {age}")
84
+ ```
85
+
86
+ ### IP parsing helpers
87
+
88
+ ```python
89
+ from valid8r.core.maybe import Success, Failure
90
+ from valid8r.core import parsers
91
+
92
+ # IPv4 / IPv6 / generic IP
93
+ for text in ["192.168.0.1", "::1", " 10.0.0.1 "]:
94
+ match parsers.parse_ip(text):
95
+ case Success(addr):
96
+ print("Parsed:", addr)
97
+ case Failure(err):
98
+ print("Error:", err)
99
+
100
+ # CIDR (strict by default)
101
+ match parsers.parse_cidr("10.0.0.0/8"):
102
+ case Success(net):
103
+ print("Network:", net) # 10.0.0.0/8
104
+ case Failure(err):
105
+ print("Error:", err)
106
+
107
+ # Non-strict masks host bits
108
+ match parsers.parse_cidr("10.0.0.1/24", strict=False):
109
+ case Success(net):
110
+ assert str(net) == "10.0.0.0/24"
111
+ ```
112
+
113
+ ### URL and Email helpers
114
+
115
+ ```python
116
+ from valid8r.core.maybe import Success, Failure
117
+ from valid8r.core import parsers
118
+
119
+ # URL parsing with structured result (UrlParts)
120
+ match parsers.parse_url("https://alice:pw@example.com:8443/x?q=1#top"):
121
+ case Success(u):
122
+ print(f"Scheme: {u.scheme}") # https
123
+ print(f"Host: {u.host}") # example.com
124
+ print(f"Port: {u.port}") # 8443
125
+ print(f"Path: {u.path}") # /x
126
+ print(f"Query: {u.query}") # {'q': '1'}
127
+ print(f"Fragment: {u.fragment}") # top
128
+ case Failure(err):
129
+ print("Error:", err)
130
+
131
+ # Email parsing with normalized case (EmailAddress)
132
+ match parsers.parse_email("First.Last+tag@Example.COM"):
133
+ case Success(e):
134
+ print(f"Local: {e.local}") # First.Last+tag
135
+ print(f"Domain: {e.domain}") # example.com (normalized)
136
+ case Failure(err):
137
+ print("Error:", err)
138
+ ```
139
+
140
+ ### Phone Number Parsing
141
+
142
+ ```python
143
+ from valid8r.core.maybe import Success, Failure
144
+ from valid8r.core import parsers
145
+
146
+ # Phone number parsing with NANP validation (PhoneNumber)
147
+ match parsers.parse_phone("+1 (555) 123-4567"):
148
+ case Success(phone):
149
+ print(f"Country: {phone.country_code}") # 1
150
+ print(f"Area: {phone.area_code}") # 555
151
+ print(f"Exchange: {phone.exchange}") # 123
152
+ print(f"Subscriber: {phone.subscriber}") # 4567
153
+
154
+ # Format for display using properties
155
+ print(f"E.164: {phone.e164}") # +15551234567
156
+ print(f"National: {phone.national}") # (555) 123-4567
157
+ case Failure(err):
158
+ print("Error:", err)
159
+
160
+ # Also accepts various formats
161
+ for number in ["5551234567", "(555) 123-4567", "555-123-4567"]:
162
+ result = parsers.parse_phone(number)
163
+ assert result.is_success()
164
+ ```
165
+
166
+ ## Testing Support
167
+
168
+ Valid8r includes comprehensive testing utilities to help you verify your validation logic:
169
+
170
+ ```python
171
+ from valid8r import Maybe, validators, parsers, prompt
172
+ from valid8r.testing import (
173
+ MockInputContext,
174
+ assert_maybe_success,
175
+ assert_maybe_failure,
176
+ )
177
+
178
+ def validate_age(age: int) -> Maybe[int]:
179
+ """Validate age is between 0 and 120."""
180
+ return (validators.minimum(0) & validators.maximum(120))(age)
181
+
182
+ # Test validation functions with assert helpers
183
+ result = validate_age(42)
184
+ assert assert_maybe_success(result, 42)
185
+
186
+ result = validate_age(-5)
187
+ assert assert_maybe_failure(result, "at least 0")
188
+
189
+ # Test prompts with mock input
190
+ with MockInputContext(["yes", "42", "invalid", "25"]):
191
+ # First prompt
192
+ result = prompt.ask("Continue? ", parser=parsers.parse_bool)
193
+ assert result.value_or(False) == True
194
+
195
+ # Second prompt
196
+ age = prompt.ask(
197
+ "Age? ",
198
+ parser=parsers.parse_int,
199
+ validator=validate_age
200
+ )
201
+ assert age == 42
202
+
203
+ # Third prompt will fail, fourth succeeds
204
+ age = prompt.ask(
205
+ "Age again? ",
206
+ parser=parsers.parse_int,
207
+ retries=1 # Retry once after failure
208
+ )
209
+ assert age == 25
210
+ ```
211
+
212
+ ### Testing Utilities Reference
213
+
214
+ - **`assert_maybe_success(result, expected_value)`**: Assert that a Maybe is Success with the expected value
215
+ - **`assert_maybe_failure(result, error_substring)`**: Assert that a Maybe is Failure containing the error substring
216
+ - **`MockInputContext(inputs)`**: Context manager for mocking user input in tests
217
+
218
+ For more examples, see the [documentation](https://valid8r.readthedocs.io/).
219
+
220
+ ## Development
221
+
222
+ This project uses Poetry for dependency management and Tox for testing.
223
+
224
+ ### Setup
225
+
226
+ ```bash
227
+ # Install Poetry
228
+ curl -sSL https://install.python-poetry.org | python3 -
229
+
230
+ # Install dependencies
231
+ poetry install
232
+ ```
233
+
234
+ ### Running Tests
235
+
236
+ ```bash
237
+ # Run all tests
238
+ poetry run tox
239
+
240
+ # Run BDD tests
241
+ poetry run tox -e bdd
242
+ ```
243
+
244
+ ## License
245
+ MIT
246
+
@@ -0,0 +1,221 @@
1
+ # Valid8r
2
+
3
+ A clean, flexible input validation library for Python applications.
4
+
5
+ ## Features
6
+
7
+ - **Clean Type Parsing**: Parse strings to various Python types with robust error handling
8
+ - **Flexible Validation**: Chain validators and create custom validation rules
9
+ - **Monadic Error Handling**: Use Maybe monad for clean error propagation
10
+ - **Input Prompting**: Prompt users for input with built-in validation
11
+ - **Structured Results**: Network parsers return rich dataclasses with parsed components
12
+
13
+ ## Available Parsers
14
+
15
+ ### Basic Types
16
+ - **Numbers**: `parse_int`, `parse_float`, `parse_complex`, `parse_decimal`
17
+ - **Text**: `parse_bool` (flexible true/false parsing)
18
+ - **Dates**: `parse_date` (ISO 8601 format)
19
+ - **UUIDs**: `parse_uuid` (with optional version validation)
20
+
21
+ ### Collections
22
+ - **Lists**: `parse_list` (with element parser)
23
+ - **Dictionaries**: `parse_dict` (with key/value parsers)
24
+ - **Sets**: `parse_set` (with element parser)
25
+
26
+ ### Network & Communication
27
+ - **IP Addresses**: `parse_ipv4`, `parse_ipv6`, `parse_ip` (either v4 or v6)
28
+ - **Networks**: `parse_cidr` (IPv4/IPv6 CIDR notation)
29
+ - **Phone Numbers**: `parse_phone` → PhoneNumber (NANP validation)
30
+ - **URLs**: `parse_url` → UrlParts (scheme, host, port, path, query, etc.)
31
+ - **Email**: `parse_email` → EmailAddress (normalized case)
32
+
33
+ ### Advanced
34
+ - **Enums**: `parse_enum` (type-safe enum parsing)
35
+ - **Custom**: `create_parser`, `make_parser`, `validated_parser` (parser factories)
36
+
37
+ ## Installation
38
+
39
+ ```bash
40
+ pip install valid8r
41
+ ```
42
+
43
+ ## Quick Start
44
+
45
+ ```python
46
+ from valid8r import (
47
+ parsers,
48
+ prompt,
49
+ validators,
50
+ )
51
+
52
+ # Simple validation
53
+ age = prompt.ask(
54
+ "Enter your age: ",
55
+ parser=parsers.parse_int,
56
+ validator=validators.minimum(0) & validators.maximum(120)
57
+ )
58
+
59
+ print(f"Your age is {age}")
60
+ ```
61
+
62
+ ### IP parsing helpers
63
+
64
+ ```python
65
+ from valid8r.core.maybe import Success, Failure
66
+ from valid8r.core import parsers
67
+
68
+ # IPv4 / IPv6 / generic IP
69
+ for text in ["192.168.0.1", "::1", " 10.0.0.1 "]:
70
+ match parsers.parse_ip(text):
71
+ case Success(addr):
72
+ print("Parsed:", addr)
73
+ case Failure(err):
74
+ print("Error:", err)
75
+
76
+ # CIDR (strict by default)
77
+ match parsers.parse_cidr("10.0.0.0/8"):
78
+ case Success(net):
79
+ print("Network:", net) # 10.0.0.0/8
80
+ case Failure(err):
81
+ print("Error:", err)
82
+
83
+ # Non-strict masks host bits
84
+ match parsers.parse_cidr("10.0.0.1/24", strict=False):
85
+ case Success(net):
86
+ assert str(net) == "10.0.0.0/24"
87
+ ```
88
+
89
+ ### URL and Email helpers
90
+
91
+ ```python
92
+ from valid8r.core.maybe import Success, Failure
93
+ from valid8r.core import parsers
94
+
95
+ # URL parsing with structured result (UrlParts)
96
+ match parsers.parse_url("https://alice:pw@example.com:8443/x?q=1#top"):
97
+ case Success(u):
98
+ print(f"Scheme: {u.scheme}") # https
99
+ print(f"Host: {u.host}") # example.com
100
+ print(f"Port: {u.port}") # 8443
101
+ print(f"Path: {u.path}") # /x
102
+ print(f"Query: {u.query}") # {'q': '1'}
103
+ print(f"Fragment: {u.fragment}") # top
104
+ case Failure(err):
105
+ print("Error:", err)
106
+
107
+ # Email parsing with normalized case (EmailAddress)
108
+ match parsers.parse_email("First.Last+tag@Example.COM"):
109
+ case Success(e):
110
+ print(f"Local: {e.local}") # First.Last+tag
111
+ print(f"Domain: {e.domain}") # example.com (normalized)
112
+ case Failure(err):
113
+ print("Error:", err)
114
+ ```
115
+
116
+ ### Phone Number Parsing
117
+
118
+ ```python
119
+ from valid8r.core.maybe import Success, Failure
120
+ from valid8r.core import parsers
121
+
122
+ # Phone number parsing with NANP validation (PhoneNumber)
123
+ match parsers.parse_phone("+1 (555) 123-4567"):
124
+ case Success(phone):
125
+ print(f"Country: {phone.country_code}") # 1
126
+ print(f"Area: {phone.area_code}") # 555
127
+ print(f"Exchange: {phone.exchange}") # 123
128
+ print(f"Subscriber: {phone.subscriber}") # 4567
129
+
130
+ # Format for display using properties
131
+ print(f"E.164: {phone.e164}") # +15551234567
132
+ print(f"National: {phone.national}") # (555) 123-4567
133
+ case Failure(err):
134
+ print("Error:", err)
135
+
136
+ # Also accepts various formats
137
+ for number in ["5551234567", "(555) 123-4567", "555-123-4567"]:
138
+ result = parsers.parse_phone(number)
139
+ assert result.is_success()
140
+ ```
141
+
142
+ ## Testing Support
143
+
144
+ Valid8r includes comprehensive testing utilities to help you verify your validation logic:
145
+
146
+ ```python
147
+ from valid8r import Maybe, validators, parsers, prompt
148
+ from valid8r.testing import (
149
+ MockInputContext,
150
+ assert_maybe_success,
151
+ assert_maybe_failure,
152
+ )
153
+
154
+ def validate_age(age: int) -> Maybe[int]:
155
+ """Validate age is between 0 and 120."""
156
+ return (validators.minimum(0) & validators.maximum(120))(age)
157
+
158
+ # Test validation functions with assert helpers
159
+ result = validate_age(42)
160
+ assert assert_maybe_success(result, 42)
161
+
162
+ result = validate_age(-5)
163
+ assert assert_maybe_failure(result, "at least 0")
164
+
165
+ # Test prompts with mock input
166
+ with MockInputContext(["yes", "42", "invalid", "25"]):
167
+ # First prompt
168
+ result = prompt.ask("Continue? ", parser=parsers.parse_bool)
169
+ assert result.value_or(False) == True
170
+
171
+ # Second prompt
172
+ age = prompt.ask(
173
+ "Age? ",
174
+ parser=parsers.parse_int,
175
+ validator=validate_age
176
+ )
177
+ assert age == 42
178
+
179
+ # Third prompt will fail, fourth succeeds
180
+ age = prompt.ask(
181
+ "Age again? ",
182
+ parser=parsers.parse_int,
183
+ retries=1 # Retry once after failure
184
+ )
185
+ assert age == 25
186
+ ```
187
+
188
+ ### Testing Utilities Reference
189
+
190
+ - **`assert_maybe_success(result, expected_value)`**: Assert that a Maybe is Success with the expected value
191
+ - **`assert_maybe_failure(result, error_substring)`**: Assert that a Maybe is Failure containing the error substring
192
+ - **`MockInputContext(inputs)`**: Context manager for mocking user input in tests
193
+
194
+ For more examples, see the [documentation](https://valid8r.readthedocs.io/).
195
+
196
+ ## Development
197
+
198
+ This project uses Poetry for dependency management and Tox for testing.
199
+
200
+ ### Setup
201
+
202
+ ```bash
203
+ # Install Poetry
204
+ curl -sSL https://install.python-poetry.org | python3 -
205
+
206
+ # Install dependencies
207
+ poetry install
208
+ ```
209
+
210
+ ### Running Tests
211
+
212
+ ```bash
213
+ # Run all tests
214
+ poetry run tox
215
+
216
+ # Run BDD tests
217
+ poetry run tox -e bdd
218
+ ```
219
+
220
+ ## License
221
+ MIT
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "valid8r"
3
- version = "0.2.7"
3
+ version = "0.2.8"
4
4
  description = "Clean, flexible input validation for Python applications"
5
5
  authors = ["Mike Lane <mikelane@gmail.com>"]
6
6
  license = "MIT"
@@ -1106,6 +1106,42 @@ def parse_url(
1106
1106
  - Unsupported URL scheme
1107
1107
  - URL requires host
1108
1108
  - Invalid host
1109
+
1110
+ Args:
1111
+ text: The URL string to parse
1112
+ allowed_schemes: Iterable of allowed scheme names (default: ('http', 'https'))
1113
+ require_host: Whether to require a host in the URL (default: True)
1114
+
1115
+ Returns:
1116
+ Maybe[UrlParts]: Success with UrlParts containing parsed components, or Failure with error message
1117
+
1118
+ Examples:
1119
+ >>> from valid8r.core.parsers import parse_url
1120
+ >>> from valid8r.core.maybe import Success
1121
+ >>>
1122
+ >>> # Parse a complete URL
1123
+ >>> result = parse_url('https://user:pass@api.example.com:8080/v1/users?active=true#section')
1124
+ >>> isinstance(result, Success)
1125
+ True
1126
+ >>> url = result.value
1127
+ >>> url.scheme
1128
+ 'https'
1129
+ >>> url.host
1130
+ 'api.example.com'
1131
+ >>> url.port
1132
+ 8080
1133
+ >>> url.path
1134
+ '/v1/users'
1135
+ >>> url.query
1136
+ 'active=true'
1137
+ >>> url.fragment
1138
+ 'section'
1139
+ >>>
1140
+ >>> # Access credentials
1141
+ >>> url.username
1142
+ 'user'
1143
+ >>> url.password
1144
+ 'pass'
1109
1145
  """
1110
1146
  if not isinstance(text, str):
1111
1147
  return Maybe.failure('Input must be a string')
@@ -1189,6 +1225,22 @@ def parse_email(text: str) -> Maybe[EmailAddress]:
1189
1225
 
1190
1226
  Returns:
1191
1227
  Maybe[EmailAddress]: Success with EmailAddress or Failure with error message
1228
+
1229
+ Examples:
1230
+ >>> from valid8r.core.parsers import parse_email
1231
+ >>> from valid8r.core.maybe import Success
1232
+ >>>
1233
+ >>> # Parse an email with case normalization
1234
+ >>> result = parse_email('User.Name+tag@Example.COM')
1235
+ >>> isinstance(result, Success)
1236
+ True
1237
+ >>> email = result.value
1238
+ >>> # Local part preserves original case
1239
+ >>> email.local
1240
+ 'User.Name+tag'
1241
+ >>> # Domain is normalized to lowercase
1242
+ >>> email.domain
1243
+ 'example.com'
1192
1244
  """
1193
1245
  if not isinstance(text, str):
1194
1246
  return Maybe.failure('Input must be a string')
valid8r-0.2.7/PKG-INFO DELETED
@@ -1,168 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: valid8r
3
- Version: 0.2.7
4
- Summary: Clean, flexible input validation for Python applications
5
- License: MIT
6
- Keywords: validation,input,cli,maybe-monad
7
- Author: Mike Lane
8
- Author-email: mikelane@gmail.com
9
- Requires-Python: >=3.11,<4.0
10
- Classifier: Development Status :: 3 - Alpha
11
- Classifier: Intended Audience :: Developers
12
- Classifier: License :: OSI Approved :: MIT License
13
- Classifier: Programming Language :: Python :: 3
14
- Classifier: Programming Language :: Python :: 3.11
15
- Classifier: Programming Language :: Python :: 3.12
16
- Classifier: Programming Language :: Python :: 3.13
17
- Classifier: Programming Language :: Python :: 3.14
18
- Requires-Dist: email-validator (>=2.3.0,<3.0.0)
19
- Requires-Dist: pydantic (>=2.0)
20
- Requires-Dist: pydantic-core (>=2.27.0,<3.0.0)
21
- Requires-Dist: uuid-utils (>=0.11.0,<0.12.0)
22
- Project-URL: Repository, https://github.com/mikelane/valid8r
23
- Description-Content-Type: text/markdown
24
-
25
- # Valid8r
26
-
27
- A clean, flexible input validation library for Python applications.
28
-
29
- ## Features
30
-
31
- - **Clean Type Parsing**: Parse strings to various Python types with robust error handling
32
- - **Flexible Validation**: Chain validators and create custom validation rules
33
- - **Monadic Error Handling**: Use Maybe monad for clean error propagation
34
- - **Input Prompting**: Prompt users for input with built-in validation
35
-
36
- ## Installation
37
-
38
- ```bash
39
- pip install valid8r
40
- ```
41
-
42
- ## Quick Start
43
-
44
- ```python
45
- from valid8r import (
46
- parsers,
47
- prompt,
48
- validators,
49
- )
50
-
51
- # Simple validation
52
- age = prompt.ask(
53
- "Enter your age: ",
54
- parser=parsers.parse_int,
55
- validator=validators.minimum(0) & validators.maximum(120)
56
- )
57
-
58
- print(f"Your age is {age}")
59
- ```
60
-
61
- ### IP parsing helpers
62
-
63
- ```python
64
- from valid8r.core.maybe import Success, Failure
65
- from valid8r.core import parsers
66
-
67
- # IPv4 / IPv6 / generic IP
68
- for text in ["192.168.0.1", "::1", " 10.0.0.1 "]:
69
- match parsers.parse_ip(text):
70
- case Success(addr):
71
- print("Parsed:", addr)
72
- case Failure(err):
73
- print("Error:", err)
74
-
75
- # CIDR (strict by default)
76
- match parsers.parse_cidr("10.0.0.0/8"):
77
- case Success(net):
78
- print("Network:", net) # 10.0.0.0/8
79
- case Failure(err):
80
- print("Error:", err)
81
-
82
- # Non-strict masks host bits
83
- match parsers.parse_cidr("10.0.0.1/24", strict=False):
84
- case Success(net):
85
- assert str(net) == "10.0.0.0/24"
86
- ```
87
-
88
- ### URL and Email helpers
89
-
90
- ```python
91
- from valid8r.core.maybe import Success, Failure
92
- from valid8r.core import parsers
93
-
94
- # URL parsing
95
- match parsers.parse_url("https://alice:pw@example.com:8443/x?q=1#top"):
96
- case Success(u):
97
- print(u.scheme, u.username, u.password, u.host, u.port)
98
- case Failure(err):
99
- print("Error:", err)
100
-
101
- # Email parsing
102
- match parsers.parse_email("First.Last+tag@Example.COM"):
103
- case Success(e):
104
- print(e.local, e.domain) # First.Last+tag example.com
105
- case Failure(err):
106
- print("Error:", err)
107
- ```
108
-
109
- ## Testing Support
110
-
111
- Valid8r includes testing utilities to help you verify your validation logic:
112
-
113
- ```python
114
- from valid8r import (
115
- Maybe,
116
- validators,
117
- parsers,
118
- prompt,
119
- )
120
-
121
- from valid8r.testing import (
122
- MockInputContext,
123
- assert_maybe_success,
124
- )
125
-
126
- def validate_age(age: int) -> Maybe[int]:
127
- return validators.minimum(0) & validators.maximum(120)(age)
128
-
129
- # Test prompts with mock input
130
- with MockInputContext(["yes"]):
131
- result = prompt.ask("Continue? ", parser=parsers.parse_bool)
132
- assert result.is_success()
133
- assert result.value_or(False) == True
134
-
135
- # Test validation functions
136
- result = validate_age(42)
137
- assert assert_maybe_success(result, 42)
138
- ```
139
-
140
- For more information, see the [Testing with Valid8r](docs/user_guide/testing.rst) guide.
141
-
142
- ## Development
143
-
144
- This project uses Poetry for dependency management and Tox for testing.
145
-
146
- ### Setup
147
-
148
- ```bash
149
- # Install Poetry
150
- curl -sSL https://install.python-poetry.org | python3 -
151
-
152
- # Install dependencies
153
- poetry install
154
- ```
155
-
156
- ### Running Tests
157
-
158
- ```bash
159
- # Run all tests
160
- poetry run tox
161
-
162
- # Run BDD tests
163
- poetry run tox -e bdd
164
- ```
165
-
166
- ## License
167
- MIT
168
-
valid8r-0.2.7/README.md DELETED
@@ -1,143 +0,0 @@
1
- # Valid8r
2
-
3
- A clean, flexible input validation library for Python applications.
4
-
5
- ## Features
6
-
7
- - **Clean Type Parsing**: Parse strings to various Python types with robust error handling
8
- - **Flexible Validation**: Chain validators and create custom validation rules
9
- - **Monadic Error Handling**: Use Maybe monad for clean error propagation
10
- - **Input Prompting**: Prompt users for input with built-in validation
11
-
12
- ## Installation
13
-
14
- ```bash
15
- pip install valid8r
16
- ```
17
-
18
- ## Quick Start
19
-
20
- ```python
21
- from valid8r import (
22
- parsers,
23
- prompt,
24
- validators,
25
- )
26
-
27
- # Simple validation
28
- age = prompt.ask(
29
- "Enter your age: ",
30
- parser=parsers.parse_int,
31
- validator=validators.minimum(0) & validators.maximum(120)
32
- )
33
-
34
- print(f"Your age is {age}")
35
- ```
36
-
37
- ### IP parsing helpers
38
-
39
- ```python
40
- from valid8r.core.maybe import Success, Failure
41
- from valid8r.core import parsers
42
-
43
- # IPv4 / IPv6 / generic IP
44
- for text in ["192.168.0.1", "::1", " 10.0.0.1 "]:
45
- match parsers.parse_ip(text):
46
- case Success(addr):
47
- print("Parsed:", addr)
48
- case Failure(err):
49
- print("Error:", err)
50
-
51
- # CIDR (strict by default)
52
- match parsers.parse_cidr("10.0.0.0/8"):
53
- case Success(net):
54
- print("Network:", net) # 10.0.0.0/8
55
- case Failure(err):
56
- print("Error:", err)
57
-
58
- # Non-strict masks host bits
59
- match parsers.parse_cidr("10.0.0.1/24", strict=False):
60
- case Success(net):
61
- assert str(net) == "10.0.0.0/24"
62
- ```
63
-
64
- ### URL and Email helpers
65
-
66
- ```python
67
- from valid8r.core.maybe import Success, Failure
68
- from valid8r.core import parsers
69
-
70
- # URL parsing
71
- match parsers.parse_url("https://alice:pw@example.com:8443/x?q=1#top"):
72
- case Success(u):
73
- print(u.scheme, u.username, u.password, u.host, u.port)
74
- case Failure(err):
75
- print("Error:", err)
76
-
77
- # Email parsing
78
- match parsers.parse_email("First.Last+tag@Example.COM"):
79
- case Success(e):
80
- print(e.local, e.domain) # First.Last+tag example.com
81
- case Failure(err):
82
- print("Error:", err)
83
- ```
84
-
85
- ## Testing Support
86
-
87
- Valid8r includes testing utilities to help you verify your validation logic:
88
-
89
- ```python
90
- from valid8r import (
91
- Maybe,
92
- validators,
93
- parsers,
94
- prompt,
95
- )
96
-
97
- from valid8r.testing import (
98
- MockInputContext,
99
- assert_maybe_success,
100
- )
101
-
102
- def validate_age(age: int) -> Maybe[int]:
103
- return validators.minimum(0) & validators.maximum(120)(age)
104
-
105
- # Test prompts with mock input
106
- with MockInputContext(["yes"]):
107
- result = prompt.ask("Continue? ", parser=parsers.parse_bool)
108
- assert result.is_success()
109
- assert result.value_or(False) == True
110
-
111
- # Test validation functions
112
- result = validate_age(42)
113
- assert assert_maybe_success(result, 42)
114
- ```
115
-
116
- For more information, see the [Testing with Valid8r](docs/user_guide/testing.rst) guide.
117
-
118
- ## Development
119
-
120
- This project uses Poetry for dependency management and Tox for testing.
121
-
122
- ### Setup
123
-
124
- ```bash
125
- # Install Poetry
126
- curl -sSL https://install.python-poetry.org | python3 -
127
-
128
- # Install dependencies
129
- poetry install
130
- ```
131
-
132
- ### Running Tests
133
-
134
- ```bash
135
- # Run all tests
136
- poetry run tox
137
-
138
- # Run BDD tests
139
- poetry run tox -e bdd
140
- ```
141
-
142
- ## License
143
- MIT
File without changes
File without changes
File without changes
File without changes