valid8r 0.7.1__tar.gz → 0.7.3__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.

Files changed (128) hide show
  1. {valid8r-0.7.1 → valid8r-0.7.3}/.github/CONVENTIONAL_COMMITS.md +4 -4
  2. {valid8r-0.7.1 → valid8r-0.7.3}/.github/QUICK_REFERENCE.md +3 -3
  3. {valid8r-0.7.1 → valid8r-0.7.3}/.github/README.md +8 -8
  4. {valid8r-0.7.1 → valid8r-0.7.3}/.github/SETUP_CHECKLIST.md +7 -7
  5. {valid8r-0.7.1 → valid8r-0.7.3}/.github/WORKFLOWS.md +6 -6
  6. {valid8r-0.7.1 → valid8r-0.7.3}/.github/pull_request_template.md +6 -6
  7. {valid8r-0.7.1 → valid8r-0.7.3}/.readthedocs.yaml +5 -7
  8. {valid8r-0.7.1 → valid8r-0.7.3}/CLAUDE.md +14 -3
  9. {valid8r-0.7.1 → valid8r-0.7.3}/CONTRIBUTING.md +28 -20
  10. valid8r-0.7.3/PKG-INFO +305 -0
  11. valid8r-0.7.3/README.md +274 -0
  12. {valid8r-0.7.1 → valid8r-0.7.3}/docs/development/contributing.rst +17 -14
  13. {valid8r-0.7.1 → valid8r-0.7.3}/docs/development/testing.rst +21 -18
  14. {valid8r-0.7.1 → valid8r-0.7.3}/docs/index.rst +7 -1
  15. {valid8r-0.7.1 → valid8r-0.7.3}/docs/user_guide/getting_started.rst +8 -2
  16. {valid8r-0.7.1 → valid8r-0.7.3}/pyproject.toml +1 -1
  17. {valid8r-0.7.1 → valid8r-0.7.3}/uv.lock +1 -1
  18. valid8r-0.7.1/PKG-INFO +0 -298
  19. valid8r-0.7.1/README.md +0 -267
  20. {valid8r-0.7.1 → valid8r-0.7.3}/.coveragerc +0 -0
  21. {valid8r-0.7.1 → valid8r-0.7.3}/.cursorrules +0 -0
  22. {valid8r-0.7.1 → valid8r-0.7.3}/.github/CICD_TEST.md +0 -0
  23. {valid8r-0.7.1 → valid8r-0.7.3}/.github/CODEOWNERS +0 -0
  24. {valid8r-0.7.1 → valid8r-0.7.3}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  25. {valid8r-0.7.1 → valid8r-0.7.3}/.github/ISSUE_TEMPLATE/documentation.yml +0 -0
  26. {valid8r-0.7.1 → valid8r-0.7.3}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  27. {valid8r-0.7.1 → valid8r-0.7.3}/.github/PYPI_TOKEN_SETUP_GUIDE.md +0 -0
  28. {valid8r-0.7.1 → valid8r-0.7.3}/.github/WORKFLOW_DIAGRAM.md +0 -0
  29. {valid8r-0.7.1 → valid8r-0.7.3}/.github/dependabot.yml +0 -0
  30. {valid8r-0.7.1 → valid8r-0.7.3}/.github/labeler.yml +0 -0
  31. {valid8r-0.7.1 → valid8r-0.7.3}/.github/release.yml +0 -0
  32. {valid8r-0.7.1 → valid8r-0.7.3}/.github/workflows/ci.yml +0 -0
  33. {valid8r-0.7.1 → valid8r-0.7.3}/.github/workflows/labeler.yml +0 -0
  34. {valid8r-0.7.1 → valid8r-0.7.3}/.github/workflows/publish-pypi.yml +0 -0
  35. {valid8r-0.7.1 → valid8r-0.7.3}/.github/workflows/semantic-release.yml +0 -0
  36. {valid8r-0.7.1 → valid8r-0.7.3}/.github/workflows/size-label.yml +0 -0
  37. {valid8r-0.7.1 → valid8r-0.7.3}/.github/workflows/stale.yml +0 -0
  38. {valid8r-0.7.1 → valid8r-0.7.3}/.github/workflows/version-and-release.yml +0 -0
  39. {valid8r-0.7.1 → valid8r-0.7.3}/.github/workflows/welcome.yml +0 -0
  40. {valid8r-0.7.1 → valid8r-0.7.3}/.gitignore +0 -0
  41. {valid8r-0.7.1 → valid8r-0.7.3}/.pre-commit-config.yaml +0 -0
  42. {valid8r-0.7.1 → valid8r-0.7.3}/.python-version +0 -0
  43. {valid8r-0.7.1 → valid8r-0.7.3}/CICD_SETUP_SUMMARY.md +0 -0
  44. {valid8r-0.7.1 → valid8r-0.7.3}/CODE_OF_CONDUCT.md +0 -0
  45. {valid8r-0.7.1 → valid8r-0.7.3}/LICENSE +0 -0
  46. {valid8r-0.7.1 → valid8r-0.7.3}/QA_REPORT_WEB_PARSERS_V0.6.0.md +0 -0
  47. {valid8r-0.7.1 → valid8r-0.7.3}/QA_VALIDATION_SUMMARY.md +0 -0
  48. {valid8r-0.7.1 → valid8r-0.7.3}/ROADMAP.md +0 -0
  49. {valid8r-0.7.1 → valid8r-0.7.3}/SECURITY.md +0 -0
  50. {valid8r-0.7.1 → valid8r-0.7.3}/docs/__init__.py +0 -0
  51. {valid8r-0.7.1 → valid8r-0.7.3}/docs/_static/css/custom.css +0 -0
  52. {valid8r-0.7.1 → valid8r-0.7.3}/docs/api/core.rst +0 -0
  53. {valid8r-0.7.1 → valid8r-0.7.3}/docs/api/prompt.rst +0 -0
  54. {valid8r-0.7.1 → valid8r-0.7.3}/docs/conf.py +0 -0
  55. {valid8r-0.7.1 → valid8r-0.7.3}/docs/development/changelog.rst +0 -0
  56. {valid8r-0.7.1 → valid8r-0.7.3}/docs/examples/basic_example.rst +0 -0
  57. {valid8r-0.7.1 → valid8r-0.7.3}/docs/examples/chaining_validators.rst +0 -0
  58. {valid8r-0.7.1 → valid8r-0.7.3}/docs/examples/custom_validators.rst +0 -0
  59. {valid8r-0.7.1 → valid8r-0.7.3}/docs/examples/fastapi_integration.rst +0 -0
  60. {valid8r-0.7.1 → valid8r-0.7.3}/docs/examples/interactive_prompts.rst +0 -0
  61. {valid8r-0.7.1 → valid8r-0.7.3}/docs/migration-poetry-to-uv.md +0 -0
  62. {valid8r-0.7.1 → valid8r-0.7.3}/docs/user_guide/advanced_usage.rst +0 -0
  63. {valid8r-0.7.1 → valid8r-0.7.3}/docs/user_guide/maybe_monad.rst +0 -0
  64. {valid8r-0.7.1 → valid8r-0.7.3}/docs/user_guide/parsers.rst +0 -0
  65. {valid8r-0.7.1 → valid8r-0.7.3}/docs/user_guide/prompting.rst +0 -0
  66. {valid8r-0.7.1 → valid8r-0.7.3}/docs/user_guide/testing.rst +0 -0
  67. {valid8r-0.7.1 → valid8r-0.7.3}/docs/user_guide/validators.rst +0 -0
  68. {valid8r-0.7.1 → valid8r-0.7.3}/scripts/__init__.py +0 -0
  69. {valid8r-0.7.1 → valid8r-0.7.3}/scripts/docs.py +0 -0
  70. {valid8r-0.7.1 → valid8r-0.7.3}/smoke_test.py +0 -0
  71. {valid8r-0.7.1 → valid8r-0.7.3}/tests/__init__.py +0 -0
  72. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/__init__.py +0 -0
  73. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/conftest.py +0 -0
  74. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/environment.py +0 -0
  75. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/features/clean_type_parsing.feature +0 -0
  76. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/features/collection_parsing.feature +0 -0
  77. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/features/interactive_prompts.feature +0 -0
  78. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/features/phone_parsing.feature +0 -0
  79. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/features/testing_utilities.feature +0 -0
  80. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/features/url_email_parsing.feature +0 -0
  81. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/features/validator_combinators.feature +0 -0
  82. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/features/validators.feature +0 -0
  83. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/features/web_parsers.feature +0 -0
  84. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/steps/__init__.py +0 -0
  85. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/steps/clean_type_parsing_steps.py +0 -0
  86. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/steps/collection_parsing_steps.py +0 -0
  87. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/steps/interactive_prompts_steps.py +0 -0
  88. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/steps/phone_parsing_steps.py +0 -0
  89. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/steps/testing_utilities_steps.py +0 -0
  90. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/steps/url_email_parsing_steps.py +0 -0
  91. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/steps/validator_combinators_steps.py +0 -0
  92. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/steps/validators_steps.py +0 -0
  93. {valid8r-0.7.1 → valid8r-0.7.3}/tests/bdd/steps/web_parsers_steps.py +0 -0
  94. {valid8r-0.7.1 → valid8r-0.7.3}/tests/integration/__init__.py +0 -0
  95. {valid8r-0.7.1 → valid8r-0.7.3}/tests/integration/test_validator.py +0 -0
  96. {valid8r-0.7.1 → valid8r-0.7.3}/tests/qa_security_web_parsers.py +0 -0
  97. {valid8r-0.7.1 → valid8r-0.7.3}/tests/unit/__init__.py +0 -0
  98. {valid8r-0.7.1 → valid8r-0.7.3}/tests/unit/conftest.py +0 -0
  99. {valid8r-0.7.1 → valid8r-0.7.3}/tests/unit/test_combinators.py +0 -0
  100. {valid8r-0.7.1 → valid8r-0.7.3}/tests/unit/test_decimal_parser.py +0 -0
  101. {valid8r-0.7.1 → valid8r-0.7.3}/tests/unit/test_dict_parser.py +0 -0
  102. {valid8r-0.7.1 → valid8r-0.7.3}/tests/unit/test_generators.py +0 -0
  103. {valid8r-0.7.1 → valid8r-0.7.3}/tests/unit/test_ip_parsers.py +0 -0
  104. {valid8r-0.7.1 → valid8r-0.7.3}/tests/unit/test_list_parser.py +0 -0
  105. {valid8r-0.7.1 → valid8r-0.7.3}/tests/unit/test_maybe.py +0 -0
  106. {valid8r-0.7.1 → valid8r-0.7.3}/tests/unit/test_parsers.py +0 -0
  107. {valid8r-0.7.1 → valid8r-0.7.3}/tests/unit/test_phone_parsing.py +0 -0
  108. {valid8r-0.7.1 → valid8r-0.7.3}/tests/unit/test_prompt.py +0 -0
  109. {valid8r-0.7.1 → valid8r-0.7.3}/tests/unit/test_public_api.py +0 -0
  110. {valid8r-0.7.1 → valid8r-0.7.3}/tests/unit/test_testing_utilities.py +0 -0
  111. {valid8r-0.7.1 → valid8r-0.7.3}/tests/unit/test_url_email_parsers.py +0 -0
  112. {valid8r-0.7.1 → valid8r-0.7.3}/tests/unit/test_uuid_parser.py +0 -0
  113. {valid8r-0.7.1 → valid8r-0.7.3}/tests/unit/test_validators.py +0 -0
  114. {valid8r-0.7.1 → valid8r-0.7.3}/tests/unit/test_web_parsers.py +0 -0
  115. {valid8r-0.7.1 → valid8r-0.7.3}/tox.ini +0 -0
  116. {valid8r-0.7.1 → valid8r-0.7.3}/valid8r/__init__.py +0 -0
  117. {valid8r-0.7.1 → valid8r-0.7.3}/valid8r/core/__init__.py +0 -0
  118. {valid8r-0.7.1 → valid8r-0.7.3}/valid8r/core/combinators.py +0 -0
  119. {valid8r-0.7.1 → valid8r-0.7.3}/valid8r/core/maybe.py +0 -0
  120. {valid8r-0.7.1 → valid8r-0.7.3}/valid8r/core/parsers.py +0 -0
  121. {valid8r-0.7.1 → valid8r-0.7.3}/valid8r/core/validators.py +0 -0
  122. {valid8r-0.7.1 → valid8r-0.7.3}/valid8r/prompt/__init__.py +0 -0
  123. {valid8r-0.7.1 → valid8r-0.7.3}/valid8r/prompt/basic.py +0 -0
  124. {valid8r-0.7.1 → valid8r-0.7.3}/valid8r/py.typed +0 -0
  125. {valid8r-0.7.1 → valid8r-0.7.3}/valid8r/testing/__init__.py +0 -0
  126. {valid8r-0.7.1 → valid8r-0.7.3}/valid8r/testing/assertions.py +0 -0
  127. {valid8r-0.7.1 → valid8r-0.7.3}/valid8r/testing/generators.py +0 -0
  128. {valid8r-0.7.1 → valid8r-0.7.3}/valid8r/testing/mock_input.py +0 -0
@@ -25,7 +25,7 @@ This is a quick reference guide for writing conventional commits for the valid8r
25
25
  | `test` | 🔼 **patch** | Adding or updating tests | `test: add edge cases for validators` |
26
26
  | `chore` | 🔼 **patch** | Maintenance tasks | `chore: update dependencies` |
27
27
  | `ci` | ⚪ **none** | CI/CD changes | `ci: add Python 3.13 to matrix` |
28
- | `build` | ⚪ **none** | Build system changes | `build: update poetry config` |
28
+ | `build` | ⚪ **none** | Build system changes | `build: update uv config` |
29
29
 
30
30
  ## Breaking Changes (Major Bump)
31
31
 
@@ -268,9 +268,9 @@ Before committing, check:
268
268
 
269
269
  ```bash
270
270
  # Run checks before committing
271
- poetry run ruff check .
272
- poetry run mypy valid8r
273
- poetry run pytest
271
+ uv run ruff check .
272
+ uv run mypy valid8r
273
+ uv run pytest
274
274
 
275
275
  # Then commit
276
276
  git commit -m "feat(parsers): add parse_phone_number"
@@ -31,9 +31,9 @@ git commit -m "feat(parsers): add phone validation"
31
31
  gh pr create --fill
32
32
 
33
33
  # Run checks locally
34
- poetry run pytest
35
- poetry run mypy valid8r
36
- poetry run ruff check .
34
+ uv run pytest
35
+ uv run mypy valid8r
36
+ uv run ruff check .
37
37
  ```
38
38
 
39
39
  ### Manual Workflow Triggers
@@ -184,9 +184,9 @@ git checkout -b feat/add-parser
184
184
  # ... edit code ...
185
185
 
186
186
  # 3. Run tests locally
187
- poetry run pytest
188
- poetry run mypy valid8r
189
- poetry run ruff check .
187
+ uv run pytest
188
+ uv run mypy valid8r
189
+ uv run ruff check .
190
190
 
191
191
  # 4. Commit with conventional format
192
192
  git commit -m "feat(parsers): add phone number parser"
@@ -284,11 +284,11 @@ gh workflow run stale.yml
284
284
 
285
285
  **Run locally**:
286
286
  ```bash
287
- poetry run ruff check .
288
- poetry run ruff format --check .
289
- poetry run mypy valid8r
290
- poetry run pytest
291
- poetry run behave tests/bdd/features
287
+ uv run ruff check .
288
+ uv run ruff format --check .
289
+ uv run mypy valid8r
290
+ uv run pytest
291
+ uv run behave tests/bdd/features
292
292
  ```
293
293
 
294
294
  Fix issues and push again.
@@ -121,17 +121,16 @@ Create `test-pypi` environment (optional):
121
121
 
122
122
  ```bash
123
123
  # Ensure version is 0.1.0 in pyproject.toml
124
- poetry version 0.1.0
124
+ # Version is managed by semantic-release, but for first publish verify it's set correctly
125
125
 
126
126
  # Build the package
127
- poetry build
127
+ uv build
128
128
 
129
129
  # Publish to Test PyPI first (to verify)
130
- poetry config repositories.testpypi https://test.pypi.org/legacy/
131
- poetry publish -r testpypi --username __token__ --password pypi-...
130
+ uv publish --publish-url https://test.pypi.org/legacy/ --token pypi-...
132
131
 
133
132
  # If test publish succeeds, publish to production PyPI
134
- poetry publish --username __token__ --password pypi-...
133
+ uv publish --token pypi-...
135
134
  ```
136
135
 
137
136
  **Option B: Trusted Publisher** (More secure, no tokens needed)
@@ -219,8 +218,9 @@ Final verification checklist:
219
218
  **Expected behavior**: The workflow skips publishing if version exists.
220
219
 
221
220
  **If you need to republish**:
222
- 1. Bump version manually: `poetry version patch`
223
- 2. Commit and push to trigger new release
221
+ 1. Version bump happens automatically via semantic-release based on conventional commits
222
+ 2. Commit with appropriate conventional commit type and push to trigger new release
223
+ 3. Or manually trigger version bump: `gh workflow run semantic-release.yml`
224
224
 
225
225
  ### Issue: Required checks not appearing in branch protection
226
226
 
@@ -240,7 +240,7 @@ vim valid8r/core/parsers.py
240
240
  vim tests/unit/test_parsers.py
241
241
 
242
242
  # Run tests locally
243
- poetry run pytest
243
+ uv run pytest
244
244
 
245
245
  # Commit with conventional format
246
246
  git add .
@@ -386,11 +386,11 @@ gh workflow run version-and-release.yml -f version_bump=patch
386
386
  1. Check workflow run logs in GitHub Actions tab
387
387
  2. Run same checks locally:
388
388
  ```bash
389
- poetry run ruff check .
390
- poetry run ruff format --check .
391
- poetry run mypy valid8r
392
- poetry run pytest
393
- poetry run behave tests/bdd/features
389
+ uv run ruff check .
390
+ uv run ruff format --check .
391
+ uv run mypy valid8r
392
+ uv run pytest
393
+ uv run behave tests/bdd/features
394
394
  ```
395
395
  3. Fix issues and push again
396
396
 
@@ -31,7 +31,7 @@ Fixes #
31
31
 
32
32
  - [ ] Unit tests added/updated
33
33
  - [ ] BDD tests added/updated (if applicable)
34
- - [ ] All tests pass locally (`poetry run tox`)
34
+ - [ ] All tests pass locally (`uv run tox`)
35
35
  - [ ] Test coverage maintained or improved
36
36
 
37
37
  ## Test Evidence
@@ -40,7 +40,7 @@ Fixes #
40
40
 
41
41
  ```
42
42
  # Example:
43
- $ poetry run pytest tests/unit/test_my_feature.py
43
+ $ uv run pytest tests/unit/test_my_feature.py
44
44
  ================================ test session starts =================================
45
45
  collected 15 items
46
46
 
@@ -52,9 +52,9 @@ tests/unit/test_my_feature.py ............... [100%]
52
52
 
53
53
  ## Checklist
54
54
 
55
- - [ ] Code follows the project's style guidelines (`poetry run ruff check .`)
56
- - [ ] Code is formatted properly (`poetry run ruff format .`)
57
- - [ ] Type hints are complete and pass mypy (`poetry run mypy valid8r`)
55
+ - [ ] Code follows the project's style guidelines (`uv run ruff check .`)
56
+ - [ ] Code is formatted properly (`uv run ruff format .`)
57
+ - [ ] Type hints are complete and pass mypy (`uv run mypy valid8r`)
58
58
  - [ ] Docstrings added/updated for public API
59
59
  - [ ] `__all__` exports updated if public API changed
60
60
  - [ ] CLAUDE.md updated if architecture/patterns changed
@@ -72,7 +72,7 @@ N/A
72
72
  - [ ] README.md updated (if needed)
73
73
  - [ ] API documentation updated (docstrings)
74
74
  - [ ] Usage examples added (if new feature)
75
- - [ ] Sphinx docs build successfully (`poetry run docs-build`)
75
+ - [ ] Sphinx docs build successfully (`uv run docs-build`)
76
76
 
77
77
  # Additional Notes
78
78
 
@@ -10,14 +10,12 @@ build:
10
10
  tools:
11
11
  python: "3.11"
12
12
  commands:
13
- # Install poetry
14
- - pip install poetry
15
- # Configure poetry to not create virtualenvs
16
- - poetry config virtualenvs.create false
13
+ # Install uv
14
+ - pip install uv
17
15
  # Install all dependencies including the project itself
18
- - poetry install --with docs --no-interaction
19
- # Let Poetry run Sphinx to avoid dependency conflicts
20
- - poetry run sphinx-build -b html docs $READTHEDOCS_OUTPUT/html
16
+ - uv sync --group docs
17
+ # Let uv run Sphinx to avoid dependency conflicts
18
+ - uv run sphinx-build -b html docs $READTHEDOCS_OUTPUT/html
21
19
 
22
20
  # Build documentation formats
23
21
  formats:
@@ -77,7 +77,11 @@ All new features MUST follow this exact workflow using the specialized agents de
77
77
 
78
78
  ## Common Development Commands
79
79
 
80
- **Note**: This project uses `uv` for dependency management (not Poetry). Install it with:
80
+ **Note**: This project uses `uv` for dependency management. The migration from Poetry to uv was completed in November 2025 (PR #48), bringing 60% faster CI pipelines and 300x+ faster dependency resolution.
81
+
82
+ See `docs/migration-poetry-to-uv.md` for the complete migration guide, including command comparisons and troubleshooting.
83
+
84
+ **Install uv:**
81
85
  ```bash
82
86
  curl -LsSf https://astral.sh/uv/install.sh | sh
83
87
  ```
@@ -156,15 +160,22 @@ uv run python smoke_test.py
156
160
 
157
161
  ### Dependency Management
158
162
  ```bash
159
- # Add a new dependency
163
+ # Add a production dependency
160
164
  uv add requests
161
165
 
162
166
  # Add a dev dependency
163
- uv add --dev pytest-timeout
167
+ uv add --group dev pytest-timeout
168
+
169
+ # Add to specific dependency groups
170
+ uv add --group test pytest-mock
171
+ uv add --group docs sphinx-theme
164
172
 
165
173
  # Update all dependencies
166
174
  uv lock --upgrade
167
175
 
176
+ # Update a specific package
177
+ uv lock --upgrade-package requests
178
+
168
179
  # Export requirements for other tools
169
180
  uv export > requirements.txt
170
181
  ```
@@ -24,8 +24,8 @@ This project adheres to the [Contributor Covenant Code of Conduct](CODE_OF_CONDU
24
24
 
25
25
  ### Prerequisites
26
26
 
27
- - Python 3.11 or higher
28
- - [Poetry](https://python-poetry.org/) for dependency management
27
+ - Python 3.11 or higher (3.11-3.14 supported)
28
+ - [uv](https://docs.astral.sh/uv/) for dependency management (10-100x faster than Poetry)
29
29
  - [pyenv](https://github.com/pyenv/pyenv) (recommended for managing Python versions)
30
30
  - Git
31
31
 
@@ -56,24 +56,32 @@ pyenv install 3.14.0
56
56
  pyenv local 3.11.11 3.12.9 3.13.5 3.14.0
57
57
  ```
58
58
 
59
- ### 2. Install Poetry
59
+ ### 2. Install uv
60
60
 
61
61
  ```bash
62
- curl -sSL https://install.python-poetry.org | python3 -
62
+ curl -LsSf https://astral.sh/uv/install.sh | sh
63
+ ```
64
+
65
+ **Verify installation:**
66
+ ```bash
67
+ uv --version
68
+ # Should show: uv 0.9.x or later
63
69
  ```
64
70
 
65
71
  ### 3. Install Dependencies
66
72
 
67
73
  ```bash
68
- poetry install
74
+ uv sync
69
75
  ```
70
76
 
71
77
  This installs all dependencies including dev, test, lint, and docs groups.
72
78
 
79
+ **Note**: If you previously used Poetry, see [docs/migration-poetry-to-uv.md](../docs/migration-poetry-to-uv.md) for migration instructions.
80
+
73
81
  ### 4. Set Up Pre-commit Hooks
74
82
 
75
83
  ```bash
76
- poetry run pre-commit install
84
+ uv run pre-commit install
77
85
  ```
78
86
 
79
87
  Pre-commit hooks automatically:
@@ -101,16 +109,16 @@ Write clean, well-tested code following our style guidelines.
101
109
 
102
110
  ```bash
103
111
  # Run all tests with coverage
104
- poetry run tox
112
+ uv run tox
105
113
 
106
114
  # Run only unit tests
107
- poetry run pytest tests/unit
115
+ uv run pytest tests/unit
108
116
 
109
117
  # Run BDD tests
110
- poetry run tox -e bdd
118
+ uv run tox -e bdd
111
119
 
112
120
  # Run linting
113
- poetry run tox -e lint
121
+ uv run tox -e lint
114
122
  ```
115
123
 
116
124
  ### 4. Commit Your Changes
@@ -145,13 +153,13 @@ Then create a Pull Request on GitHub.
145
153
 
146
154
  ```bash
147
155
  # Format code with ruff
148
- poetry run ruff format .
156
+ uv run ruff format .
149
157
 
150
158
  # Check and fix linting issues
151
- poetry run ruff check . --fix
159
+ uv run ruff check . --fix
152
160
 
153
161
  # Check type hints
154
- poetry run mypy valid8r
162
+ uv run mypy valid8r
155
163
  ```
156
164
 
157
165
  ### Code Patterns
@@ -312,7 +320,7 @@ See [.github/CONVENTIONAL_COMMITS.md](.github/CONVENTIONAL_COMMITS.md) for more
312
320
 
313
321
  ### Before Submitting
314
322
 
315
- 1. Ensure all tests pass: `poetry run tox`
323
+ 1. Ensure all tests pass: `uv run tox`
316
324
  2. Update documentation if needed
317
325
  3. Add changelog entry if applicable
318
326
  4. Verify your commits follow the conventional commit format
@@ -403,10 +411,10 @@ def parse_email(text: str) -> Maybe[EmailAddress]:
403
411
 
404
412
  ```bash
405
413
  # Build documentation
406
- poetry run docs-build
414
+ uv run docs-build
407
415
 
408
416
  # Serve with live reload
409
- poetry run docs-serve
417
+ uv run docs-serve
410
418
  ```
411
419
 
412
420
  View at http://localhost:8000
@@ -431,17 +439,17 @@ View at http://localhost:8000
431
439
 
432
440
  ```bash
433
441
  # Run smoke test
434
- python smoke_test.py
442
+ uv run python smoke_test.py
435
443
 
436
444
  # Check coverage
437
- poetry run pytest --cov=valid8r --cov-report=html tests/unit
445
+ uv run pytest --cov=valid8r --cov-report=html tests/unit
438
446
  # View at htmlcov/index.html
439
447
 
440
448
  # Run specific test
441
- poetry run pytest tests/unit/test_parsers.py::DescribeParseInt::it_parses_positive_integers
449
+ uv run pytest tests/unit/test_parsers.py::DescribeParseInt::it_parses_positive_integers
442
450
 
443
451
  # Watch mode (requires pytest-watch)
444
- poetry run ptw tests/unit
452
+ uv run ptw tests/unit
445
453
  ```
446
454
 
447
455
  ### Debugging
valid8r-0.7.3/PKG-INFO ADDED
@@ -0,0 +1,305 @@
1
+ Metadata-Version: 2.4
2
+ Name: valid8r
3
+ Version: 0.7.3
4
+ Summary: Clean, flexible input validation for Python applications
5
+ Project-URL: Homepage, https://valid8r.readthedocs.io/
6
+ Project-URL: Repository, https://github.com/mikelane/valid8r
7
+ Project-URL: Documentation, https://valid8r.readthedocs.io/
8
+ Project-URL: Issues, https://github.com/mikelane/valid8r/issues
9
+ Author-email: Mike Lane <mikelane@gmail.com>
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: cli,functional-programming,input,maybe-monad,parsing,validation
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Topic :: Software Development :: Quality Assurance
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.11
26
+ Requires-Dist: email-validator>=2.3.0
27
+ Requires-Dist: pydantic-core>=2.27.0
28
+ Requires-Dist: pydantic>=2.0
29
+ Requires-Dist: uuid-utils>=0.11.0
30
+ Description-Content-Type: text/markdown
31
+
32
+ # Valid8r
33
+
34
+ [![PyPI version](https://img.shields.io/pypi/v/valid8r.svg)](https://pypi.org/project/valid8r/)
35
+ [![Python versions](https://img.shields.io/pypi/pyversions/valid8r.svg)](https://pypi.org/project/valid8r/)
36
+ [![License](https://img.shields.io/github/license/mikelane/valid8r.svg)](https://github.com/mikelane/valid8r/blob/main/LICENSE)
37
+ [![CI Status](https://img.shields.io/github/actions/workflow/status/mikelane/valid8r/ci.yml?branch=main)](https://github.com/mikelane/valid8r/actions)
38
+ [![codecov](https://codecov.io/gh/mikelane/valid8r/branch/main/graph/badge.svg)](https://codecov.io/gh/mikelane/valid8r)
39
+ [![Documentation](https://img.shields.io/readthedocs/valid8r.svg)](https://valid8r.readthedocs.io/)
40
+
41
+ **Clean, composable input validation for Python using functional programming patterns.**
42
+
43
+ Valid8r makes input validation elegant and type-safe by using the Maybe monad for error handling. No more try-except blocks or boolean validation chains—just clean, composable parsers that tell you exactly what went wrong.
44
+
45
+ ```python
46
+ from valid8r import parsers, validators, prompt
47
+
48
+ # Parse and validate user input with rich error messages
49
+ age = prompt.ask(
50
+ "Enter your age: ",
51
+ parser=parsers.parse_int,
52
+ validator=validators.minimum(0) & validators.maximum(120)
53
+ )
54
+
55
+ print(f"Your age is {age}")
56
+ ```
57
+
58
+ ## Why Valid8r?
59
+
60
+ **Type-Safe Parsing**: Every parser returns `Maybe[T]` (Success or Failure), making error handling explicit and composable.
61
+
62
+ **Rich Structured Results**: Network parsers return dataclasses with parsed components—no more manual URL/email splitting.
63
+
64
+ **Chainable Validators**: Combine validators using `&` (and), `|` (or), and `~` (not) operators for complex validation logic.
65
+
66
+ **Zero Dependencies**: Core library uses only Python's standard library (with optional `uuid-utils` for faster UUID parsing).
67
+
68
+ **Interactive Prompts**: Built-in user input prompting with automatic retry and validation.
69
+
70
+ ## Quick Start
71
+
72
+ ### Installation
73
+
74
+ ```bash
75
+ pip install valid8r
76
+ ```
77
+
78
+ **Requirements**: Python 3.11 or higher
79
+
80
+ ### Basic Parsing
81
+
82
+ ```python
83
+ from valid8r import parsers
84
+ from valid8r.core.maybe import Success, Failure
85
+
86
+ # Parse integers with automatic error handling
87
+ match parsers.parse_int("42"):
88
+ case Success(value):
89
+ print(f"Parsed: {value}") # Parsed: 42
90
+ case Failure(error):
91
+ print(f"Error: {error}")
92
+
93
+ # Parse dates (ISO 8601 format)
94
+ result = parsers.parse_date("2025-01-15")
95
+ assert result.is_success()
96
+
97
+ # Parse UUIDs with version validation
98
+ result = parsers.parse_uuid("550e8400-e29b-41d4-a716-446655440000", version=4)
99
+ assert result.is_success()
100
+ ```
101
+
102
+ ### Validation with Combinators
103
+
104
+ ```python
105
+ from valid8r import validators
106
+
107
+ # Combine validators using operators
108
+ age_validator = validators.minimum(0) & validators.maximum(120)
109
+ result = age_validator(42)
110
+ assert result.is_success()
111
+
112
+ # String validation
113
+ password_validator = (
114
+ validators.length(8, 128) &
115
+ validators.matches_regex(r'^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d@$!%*#?&]')
116
+ )
117
+
118
+ # Set validation
119
+ tags_validator = validators.subset_of({'python', 'rust', 'go', 'typescript'})
120
+ ```
121
+
122
+ ### Structured Network Parsing
123
+
124
+ ```python
125
+ from valid8r import parsers
126
+
127
+ # Parse URLs into structured components
128
+ match parsers.parse_url("https://user:pass@example.com:8443/path?query=1#fragment"):
129
+ case Success(url):
130
+ print(f"Scheme: {url.scheme}") # https
131
+ print(f"Host: {url.host}") # example.com
132
+ print(f"Port: {url.port}") # 8443
133
+ print(f"Path: {url.path}") # /path
134
+ print(f"Query: {url.query}") # {'query': '1'}
135
+ print(f"Fragment: {url.fragment}") # fragment
136
+
137
+ # Parse emails with normalized domains
138
+ match parsers.parse_email("User@Example.COM"):
139
+ case Success(email):
140
+ print(f"Local: {email.local}") # User
141
+ print(f"Domain: {email.domain}") # example.com (normalized)
142
+
143
+ # Parse phone numbers (NANP format)
144
+ match parsers.parse_phone("+1 (415) 555-2671"):
145
+ case Success(phone):
146
+ print(f"E.164: {phone.e164}") # +14155552671
147
+ print(f"National: {phone.national}") # (415) 555-2671
148
+ ```
149
+
150
+ ### Collection Parsing
151
+
152
+ ```python
153
+ from valid8r import parsers
154
+
155
+ # Parse lists with element validation
156
+ result = parsers.parse_list("1,2,3,4,5", element_parser=parsers.parse_int)
157
+ assert result.value_or([]) == [1, 2, 3, 4, 5]
158
+
159
+ # Parse dictionaries with key/value parsers
160
+ result = parsers.parse_dict(
161
+ "name=Alice,age=30",
162
+ key_parser=lambda x: Success(x),
163
+ value_parser=lambda x: parsers.parse_int(x) if x.isdigit() else Success(x)
164
+ )
165
+ ```
166
+
167
+ ### Interactive Prompting
168
+
169
+ ```python
170
+ from valid8r import prompt, parsers, validators
171
+
172
+ # Prompt with validation and automatic retry
173
+ email = prompt.ask(
174
+ "Email address: ",
175
+ parser=parsers.parse_email,
176
+ retry=2 # Retry twice on invalid input
177
+ )
178
+
179
+ # Combine parsing and validation
180
+ port = prompt.ask(
181
+ "Server port: ",
182
+ parser=parsers.parse_int,
183
+ validator=validators.between(1024, 65535),
184
+ retry=3
185
+ )
186
+ ```
187
+
188
+ ## Features
189
+
190
+ ### Parsers
191
+
192
+ **Basic Types**:
193
+ - `parse_int`, `parse_float`, `parse_bool`, `parse_decimal`, `parse_complex`
194
+ - `parse_date` (ISO 8601), `parse_uuid` (with version validation)
195
+
196
+ **Collections**:
197
+ - `parse_list`, `parse_dict`, `parse_set` (with element parsers)
198
+
199
+ **Network & Communication**:
200
+ - `parse_ipv4`, `parse_ipv6`, `parse_ip`, `parse_cidr`
201
+ - `parse_url` → `UrlParts` (structured URL components)
202
+ - `parse_email` → `EmailAddress` (normalized domain)
203
+ - `parse_phone` → `PhoneNumber` (NANP validation with E.164 formatting)
204
+
205
+ **Advanced**:
206
+ - `parse_enum` (type-safe enum parsing)
207
+ - `create_parser`, `make_parser`, `validated_parser` (custom parser factories)
208
+
209
+ ### Validators
210
+
211
+ **Numeric**: `minimum`, `maximum`, `between`
212
+
213
+ **String**: `non_empty_string`, `matches_regex`, `length`
214
+
215
+ **Collection**: `in_set`, `unique_items`, `subset_of`, `superset_of`, `is_sorted`
216
+
217
+ **Custom**: `predicate` (create validators from any function)
218
+
219
+ **Combinators**: Combine validators using `&` (and), `|` (or), `~` (not)
220
+
221
+ ### Testing Utilities
222
+
223
+ ```python
224
+ from valid8r.testing import (
225
+ assert_maybe_success,
226
+ assert_maybe_failure,
227
+ MockInputContext,
228
+ )
229
+
230
+ # Test validation logic
231
+ result = validators.minimum(0)(42)
232
+ assert assert_maybe_success(result, 42)
233
+
234
+ result = validators.minimum(0)(-5)
235
+ assert assert_maybe_failure(result, "at least 0")
236
+
237
+ # Mock user input for testing prompts
238
+ with MockInputContext(["invalid", "valid@example.com"]):
239
+ result = prompt.ask("Email: ", parser=parsers.parse_email, retry=1)
240
+ assert result.is_success()
241
+ ```
242
+
243
+ ## Documentation
244
+
245
+ **Full documentation**: [valid8r.readthedocs.io](https://valid8r.readthedocs.io/)
246
+
247
+ - [API Reference](https://valid8r.readthedocs.io/en/latest/api.html)
248
+ - [Parser Guide](https://valid8r.readthedocs.io/en/latest/parsers.html)
249
+ - [Validator Guide](https://valid8r.readthedocs.io/en/latest/validators.html)
250
+ - [Testing Guide](https://valid8r.readthedocs.io/en/latest/testing.html)
251
+
252
+ ## Contributing
253
+
254
+ We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
255
+
256
+ **Quick links**:
257
+ - [Code of Conduct](CODE_OF_CONDUCT.md)
258
+ - [Development Setup](CONTRIBUTING.md#development-setup)
259
+ - [Commit Message Format](CONTRIBUTING.md#commit-messages)
260
+ - [Pull Request Process](CONTRIBUTING.md#pull-request-process)
261
+
262
+ ### Development Quick Start
263
+
264
+ ```bash
265
+ # Install uv (fast dependency manager)
266
+ curl -LsSf https://astral.sh/uv/install.sh | sh
267
+
268
+ # Clone and install dependencies
269
+ git clone https://github.com/mikelane/valid8r
270
+ cd valid8r
271
+ uv sync
272
+
273
+ # Run tests
274
+ uv run tox
275
+
276
+ # Run linters
277
+ uv run ruff check .
278
+ uv run ruff format .
279
+ uv run mypy valid8r
280
+ ```
281
+
282
+ ## Project Status
283
+
284
+ Valid8r is in active development (v0.7.x). The API is stabilizing but may change before v1.0.0.
285
+
286
+ - ✅ Core parsers and validators
287
+ - ✅ Maybe monad error handling
288
+ - ✅ Interactive prompting
289
+ - ✅ Network parsers (URL, Email, IP, Phone)
290
+ - ✅ Collection parsers
291
+ - ✅ Comprehensive testing utilities
292
+ - 🚧 Additional validators (in progress)
293
+ - 🚧 Custom error types (planned)
294
+
295
+ See [ROADMAP.md](ROADMAP.md) for planned features.
296
+
297
+ ## License
298
+
299
+ MIT License - see [LICENSE](LICENSE) for details.
300
+
301
+ Copyright (c) 2025 Mike Lane
302
+
303
+ ---
304
+
305
+ **Made with ❤️ for the Python community**