valid8r 0.6.2__tar.gz → 0.7.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.

Potentially problematic release.


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

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: valid8r
3
- Version: 0.6.2
3
+ Version: 0.7.0
4
4
  Summary: Clean, flexible input validation for Python applications
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -78,6 +78,30 @@ A clean, flexible input validation library for Python applications.
78
78
  - **Enums**: `parse_enum` (type-safe enum parsing)
79
79
  - **Custom**: `create_parser`, `make_parser`, `validated_parser` (parser factories)
80
80
 
81
+ ## Available Validators
82
+
83
+ ### Numeric Validators
84
+ - **`minimum(min_value)`** - Ensures value is at least the minimum (inclusive)
85
+ - **`maximum(max_value)`** - Ensures value is at most the maximum (inclusive)
86
+ - **`between(min_value, max_value)`** - Ensures value is within range (inclusive)
87
+
88
+ ### String Validators
89
+ - **`non_empty_string()`** - Rejects empty strings and whitespace-only strings
90
+ - **`matches_regex(pattern)`** - Validates string matches regex pattern (string or compiled)
91
+ - **`length(min_length, max_length)`** - Validates string length within bounds
92
+
93
+ ### Collection Validators
94
+ - **`in_set(allowed_values)`** - Ensures value is in set of allowed values
95
+ - **`unique_items()`** - Ensures all items in a list are unique
96
+ - **`subset_of(allowed_set)`** - Validates set is subset of allowed values
97
+ - **`superset_of(required_set)`** - Validates set is superset of required values
98
+ - **`is_sorted(reverse=False)`** - Ensures list is sorted (ascending or descending)
99
+
100
+ ### Custom Validators
101
+ - **`predicate(func, error_message)`** - Create custom validator from any predicate function
102
+
103
+ **Note**: All validators support custom error messages and can be combined using `&` (and), `|` (or), and `~` (not) operators.
104
+
81
105
  ## Installation
82
106
 
83
107
  **Requirements**: Python 3.11 or higher
@@ -168,21 +192,21 @@ from valid8r.core.maybe import Success, Failure
168
192
  from valid8r.core import parsers
169
193
 
170
194
  # Phone number parsing with NANP validation (PhoneNumber)
171
- match parsers.parse_phone("+1 (555) 123-4567"):
195
+ match parsers.parse_phone("+1 (415) 555-2671"):
172
196
  case Success(phone):
173
197
  print(f"Country: {phone.country_code}") # 1
174
- print(f"Area: {phone.area_code}") # 555
175
- print(f"Exchange: {phone.exchange}") # 123
176
- print(f"Subscriber: {phone.subscriber}") # 4567
198
+ print(f"Area: {phone.area_code}") # 415
199
+ print(f"Exchange: {phone.exchange}") # 555
200
+ print(f"Subscriber: {phone.subscriber}") # 2671
177
201
 
178
202
  # Format for display using properties
179
- print(f"E.164: {phone.e164}") # +15551234567
180
- print(f"National: {phone.national}") # (555) 123-4567
203
+ print(f"E.164: {phone.e164}") # +14155552671
204
+ print(f"National: {phone.national}") # (415) 555-2671
181
205
  case Failure(err):
182
206
  print("Error:", err)
183
207
 
184
208
  # Also accepts various formats
185
- for number in ["5551234567", "(555) 123-4567", "555-123-4567"]:
209
+ for number in ["4155552671", "(415) 555-2671", "415-555-2671"]:
186
210
  result = parsers.parse_phone(number)
187
211
  assert result.is_success()
188
212
  ```
@@ -212,24 +236,26 @@ assert assert_maybe_failure(result, "at least 0")
212
236
 
213
237
  # Test prompts with mock input
214
238
  with MockInputContext(["yes", "42", "invalid", "25"]):
215
- # First prompt
239
+ # First prompt - returns Maybe, unwrap with value_or()
216
240
  result = prompt.ask("Continue? ", parser=parsers.parse_bool)
217
241
  assert result.value_or(False) == True
218
242
 
219
- # Second prompt
220
- age = prompt.ask(
243
+ # Second prompt - unwrap the Maybe result
244
+ result = prompt.ask(
221
245
  "Age? ",
222
246
  parser=parsers.parse_int,
223
247
  validator=validate_age
224
248
  )
249
+ age = result.value_or(None)
225
250
  assert age == 42
226
251
 
227
- # Third prompt will fail, fourth succeeds
228
- age = prompt.ask(
252
+ # Third prompt will fail, fourth succeeds - unwrap result
253
+ result = prompt.ask(
229
254
  "Age again? ",
230
255
  parser=parsers.parse_int,
231
- retries=1 # Retry once after failure
256
+ retry=1 # Retry once after failure
232
257
  )
258
+ age = result.value_or(None)
233
259
  assert age == 25
234
260
  ```
235
261
 
@@ -47,6 +47,30 @@ A clean, flexible input validation library for Python applications.
47
47
  - **Enums**: `parse_enum` (type-safe enum parsing)
48
48
  - **Custom**: `create_parser`, `make_parser`, `validated_parser` (parser factories)
49
49
 
50
+ ## Available Validators
51
+
52
+ ### Numeric Validators
53
+ - **`minimum(min_value)`** - Ensures value is at least the minimum (inclusive)
54
+ - **`maximum(max_value)`** - Ensures value is at most the maximum (inclusive)
55
+ - **`between(min_value, max_value)`** - Ensures value is within range (inclusive)
56
+
57
+ ### String Validators
58
+ - **`non_empty_string()`** - Rejects empty strings and whitespace-only strings
59
+ - **`matches_regex(pattern)`** - Validates string matches regex pattern (string or compiled)
60
+ - **`length(min_length, max_length)`** - Validates string length within bounds
61
+
62
+ ### Collection Validators
63
+ - **`in_set(allowed_values)`** - Ensures value is in set of allowed values
64
+ - **`unique_items()`** - Ensures all items in a list are unique
65
+ - **`subset_of(allowed_set)`** - Validates set is subset of allowed values
66
+ - **`superset_of(required_set)`** - Validates set is superset of required values
67
+ - **`is_sorted(reverse=False)`** - Ensures list is sorted (ascending or descending)
68
+
69
+ ### Custom Validators
70
+ - **`predicate(func, error_message)`** - Create custom validator from any predicate function
71
+
72
+ **Note**: All validators support custom error messages and can be combined using `&` (and), `|` (or), and `~` (not) operators.
73
+
50
74
  ## Installation
51
75
 
52
76
  **Requirements**: Python 3.11 or higher
@@ -137,21 +161,21 @@ from valid8r.core.maybe import Success, Failure
137
161
  from valid8r.core import parsers
138
162
 
139
163
  # Phone number parsing with NANP validation (PhoneNumber)
140
- match parsers.parse_phone("+1 (555) 123-4567"):
164
+ match parsers.parse_phone("+1 (415) 555-2671"):
141
165
  case Success(phone):
142
166
  print(f"Country: {phone.country_code}") # 1
143
- print(f"Area: {phone.area_code}") # 555
144
- print(f"Exchange: {phone.exchange}") # 123
145
- print(f"Subscriber: {phone.subscriber}") # 4567
167
+ print(f"Area: {phone.area_code}") # 415
168
+ print(f"Exchange: {phone.exchange}") # 555
169
+ print(f"Subscriber: {phone.subscriber}") # 2671
146
170
 
147
171
  # Format for display using properties
148
- print(f"E.164: {phone.e164}") # +15551234567
149
- print(f"National: {phone.national}") # (555) 123-4567
172
+ print(f"E.164: {phone.e164}") # +14155552671
173
+ print(f"National: {phone.national}") # (415) 555-2671
150
174
  case Failure(err):
151
175
  print("Error:", err)
152
176
 
153
177
  # Also accepts various formats
154
- for number in ["5551234567", "(555) 123-4567", "555-123-4567"]:
178
+ for number in ["4155552671", "(415) 555-2671", "415-555-2671"]:
155
179
  result = parsers.parse_phone(number)
156
180
  assert result.is_success()
157
181
  ```
@@ -181,24 +205,26 @@ assert assert_maybe_failure(result, "at least 0")
181
205
 
182
206
  # Test prompts with mock input
183
207
  with MockInputContext(["yes", "42", "invalid", "25"]):
184
- # First prompt
208
+ # First prompt - returns Maybe, unwrap with value_or()
185
209
  result = prompt.ask("Continue? ", parser=parsers.parse_bool)
186
210
  assert result.value_or(False) == True
187
211
 
188
- # Second prompt
189
- age = prompt.ask(
212
+ # Second prompt - unwrap the Maybe result
213
+ result = prompt.ask(
190
214
  "Age? ",
191
215
  parser=parsers.parse_int,
192
216
  validator=validate_age
193
217
  )
218
+ age = result.value_or(None)
194
219
  assert age == 42
195
220
 
196
- # Third prompt will fail, fourth succeeds
197
- age = prompt.ask(
221
+ # Third prompt will fail, fourth succeeds - unwrap result
222
+ result = prompt.ask(
198
223
  "Age again? ",
199
224
  parser=parsers.parse_int,
200
- retries=1 # Retry once after failure
225
+ retry=1 # Retry once after failure
201
226
  )
227
+ age = result.value_or(None)
202
228
  assert age == 25
203
229
  ```
204
230
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "valid8r"
3
- version = "0.6.2"
3
+ version = "0.7.0"
4
4
  description = "Clean, flexible input validation for Python applications"
5
5
  authors = ["Mike Lane <mikelane@gmail.com>"]
6
6
  license = "MIT"
@@ -108,6 +108,10 @@ class Success(Maybe[T]):
108
108
  """Get a string representation."""
109
109
  return f'Success({self.value})'
110
110
 
111
+ def __repr__(self) -> str:
112
+ """Get a repr representation for debugging and doctests."""
113
+ return f'Success({self.value!r})'
114
+
111
115
 
112
116
  class Failure(Maybe[T]):
113
117
  """Represents a failed computation with an error message."""
@@ -160,3 +164,7 @@ class Failure(Maybe[T]):
160
164
  def __str__(self) -> str:
161
165
  """Get a string representation."""
162
166
  return f'Failure({self.error})'
167
+
168
+ def __repr__(self) -> str:
169
+ """Get a repr representation for debugging and doctests."""
170
+ return f'Failure({self.error!r})'