valid8r 0.6.3__tar.gz → 0.7.1__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 (127) hide show
  1. valid8r-0.7.1/.coveragerc +12 -0
  2. valid8r-0.7.1/.cursorrules +325 -0
  3. valid8r-0.7.1/.github/CICD_TEST.md +28 -0
  4. valid8r-0.7.1/.github/CODEOWNERS +33 -0
  5. valid8r-0.7.1/.github/CONVENTIONAL_COMMITS.md +338 -0
  6. valid8r-0.7.1/.github/ISSUE_TEMPLATE/bug_report.yml +95 -0
  7. valid8r-0.7.1/.github/ISSUE_TEMPLATE/documentation.yml +73 -0
  8. valid8r-0.7.1/.github/ISSUE_TEMPLATE/feature_request.yml +77 -0
  9. valid8r-0.7.1/.github/PYPI_TOKEN_SETUP_GUIDE.md +297 -0
  10. valid8r-0.7.1/.github/QUICK_REFERENCE.md +119 -0
  11. valid8r-0.7.1/.github/README.md +423 -0
  12. valid8r-0.7.1/.github/SETUP_CHECKLIST.md +318 -0
  13. valid8r-0.7.1/.github/WORKFLOWS.md +488 -0
  14. valid8r-0.7.1/.github/WORKFLOW_DIAGRAM.md +191 -0
  15. valid8r-0.7.1/.github/dependabot.yml +60 -0
  16. valid8r-0.7.1/.github/labeler.yml +63 -0
  17. valid8r-0.7.1/.github/pull_request_template.md +115 -0
  18. valid8r-0.7.1/.github/release.yml +54 -0
  19. valid8r-0.7.1/.github/workflows/ci.yml +215 -0
  20. valid8r-0.7.1/.github/workflows/labeler.yml +19 -0
  21. valid8r-0.7.1/.github/workflows/publish-pypi.yml +235 -0
  22. valid8r-0.7.1/.github/workflows/semantic-release.yml +56 -0
  23. valid8r-0.7.1/.github/workflows/size-label.yml +31 -0
  24. valid8r-0.7.1/.github/workflows/stale.yml +65 -0
  25. valid8r-0.7.1/.github/workflows/version-and-release.yml +212 -0
  26. valid8r-0.7.1/.github/workflows/welcome.yml +46 -0
  27. valid8r-0.7.1/.gitignore +59 -0
  28. valid8r-0.7.1/.pre-commit-config.yaml +47 -0
  29. valid8r-0.7.1/.python-version +4 -0
  30. valid8r-0.7.1/.readthedocs.yaml +25 -0
  31. valid8r-0.7.1/CICD_SETUP_SUMMARY.md +513 -0
  32. valid8r-0.7.1/CLAUDE.md +376 -0
  33. valid8r-0.7.1/CODE_OF_CONDUCT.md +55 -0
  34. valid8r-0.7.1/CONTRIBUTING.md +472 -0
  35. {valid8r-0.6.3 → valid8r-0.7.1}/PKG-INFO +36 -13
  36. valid8r-0.7.1/QA_REPORT_WEB_PARSERS_V0.6.0.md +449 -0
  37. valid8r-0.7.1/QA_VALIDATION_SUMMARY.md +86 -0
  38. {valid8r-0.6.3 → valid8r-0.7.1}/README.md +24 -0
  39. valid8r-0.7.1/ROADMAP.md +206 -0
  40. valid8r-0.7.1/SECURITY.md +166 -0
  41. valid8r-0.7.1/docs/__init__.py +1 -0
  42. valid8r-0.7.1/docs/_static/css/custom.css +88 -0
  43. valid8r-0.7.1/docs/api/core.rst +760 -0
  44. valid8r-0.7.1/docs/api/prompt.rst +584 -0
  45. valid8r-0.7.1/docs/conf.py +195 -0
  46. valid8r-0.7.1/docs/development/changelog.rst +67 -0
  47. valid8r-0.7.1/docs/development/contributing.rst +188 -0
  48. valid8r-0.7.1/docs/development/testing.rst +264 -0
  49. valid8r-0.7.1/docs/examples/basic_example.rst +486 -0
  50. valid8r-0.7.1/docs/examples/chaining_validators.rst +476 -0
  51. valid8r-0.7.1/docs/examples/custom_validators.rst +619 -0
  52. valid8r-0.7.1/docs/examples/fastapi_integration.rst +481 -0
  53. valid8r-0.7.1/docs/examples/interactive_prompts.rst +833 -0
  54. valid8r-0.7.1/docs/index.rst +389 -0
  55. valid8r-0.7.1/docs/migration-poetry-to-uv.md +310 -0
  56. valid8r-0.7.1/docs/user_guide/advanced_usage.rst +627 -0
  57. valid8r-0.7.1/docs/user_guide/getting_started.rst +244 -0
  58. valid8r-0.7.1/docs/user_guide/maybe_monad.rst +286 -0
  59. valid8r-0.7.1/docs/user_guide/parsers.rst +964 -0
  60. valid8r-0.7.1/docs/user_guide/prompting.rst +390 -0
  61. valid8r-0.7.1/docs/user_guide/testing.rst +227 -0
  62. valid8r-0.7.1/docs/user_guide/validators.rst +759 -0
  63. {valid8r-0.6.3 → valid8r-0.7.1}/pyproject.toml +68 -59
  64. valid8r-0.7.1/scripts/__init__.py +1 -0
  65. valid8r-0.7.1/scripts/docs.py +45 -0
  66. valid8r-0.7.1/smoke_test.py +43 -0
  67. valid8r-0.7.1/tests/bdd/__init__.py +0 -0
  68. valid8r-0.7.1/tests/bdd/conftest.py +0 -0
  69. valid8r-0.7.1/tests/bdd/environment.py +40 -0
  70. valid8r-0.7.1/tests/bdd/features/clean_type_parsing.feature +126 -0
  71. valid8r-0.7.1/tests/bdd/features/collection_parsing.feature +43 -0
  72. valid8r-0.7.1/tests/bdd/features/interactive_prompts.feature +43 -0
  73. valid8r-0.7.1/tests/bdd/features/phone_parsing.feature +426 -0
  74. valid8r-0.7.1/tests/bdd/features/testing_utilities.feature +47 -0
  75. valid8r-0.7.1/tests/bdd/features/url_email_parsing.feature +128 -0
  76. valid8r-0.7.1/tests/bdd/features/validator_combinators.feature +51 -0
  77. valid8r-0.7.1/tests/bdd/features/validators.feature +55 -0
  78. valid8r-0.7.1/tests/bdd/features/web_parsers.feature +329 -0
  79. valid8r-0.7.1/tests/bdd/steps/__init__.py +30 -0
  80. valid8r-0.7.1/tests/bdd/steps/clean_type_parsing_steps.py +337 -0
  81. valid8r-0.7.1/tests/bdd/steps/collection_parsing_steps.py +123 -0
  82. valid8r-0.7.1/tests/bdd/steps/interactive_prompts_steps.py +167 -0
  83. valid8r-0.7.1/tests/bdd/steps/phone_parsing_steps.py +315 -0
  84. valid8r-0.7.1/tests/bdd/steps/testing_utilities_steps.py +275 -0
  85. valid8r-0.7.1/tests/bdd/steps/url_email_parsing_steps.py +244 -0
  86. valid8r-0.7.1/tests/bdd/steps/validator_combinators_steps.py +121 -0
  87. valid8r-0.7.1/tests/bdd/steps/validators_steps.py +115 -0
  88. valid8r-0.7.1/tests/bdd/steps/web_parsers_steps.py +288 -0
  89. valid8r-0.7.1/tests/integration/__init__.py +0 -0
  90. valid8r-0.7.1/tests/integration/test_validator.py +233 -0
  91. valid8r-0.7.1/tests/qa_security_web_parsers.py +447 -0
  92. valid8r-0.7.1/tests/unit/__init__.py +0 -0
  93. valid8r-0.7.1/tests/unit/conftest.py +0 -0
  94. valid8r-0.7.1/tests/unit/test_combinators.py +205 -0
  95. valid8r-0.7.1/tests/unit/test_decimal_parser.py +95 -0
  96. valid8r-0.7.1/tests/unit/test_dict_parser.py +114 -0
  97. valid8r-0.7.1/tests/unit/test_generators.py +268 -0
  98. valid8r-0.7.1/tests/unit/test_ip_parsers.py +192 -0
  99. valid8r-0.7.1/tests/unit/test_list_parser.py +61 -0
  100. valid8r-0.7.1/tests/unit/test_maybe.py +318 -0
  101. valid8r-0.7.1/tests/unit/test_parsers.py +741 -0
  102. valid8r-0.7.1/tests/unit/test_phone_parsing.py +345 -0
  103. valid8r-0.7.1/tests/unit/test_prompt.py +316 -0
  104. valid8r-0.7.1/tests/unit/test_public_api.py +30 -0
  105. valid8r-0.7.1/tests/unit/test_testing_utilities.py +290 -0
  106. valid8r-0.7.1/tests/unit/test_url_email_parsers.py +231 -0
  107. valid8r-0.7.1/tests/unit/test_uuid_parser.py +64 -0
  108. valid8r-0.7.1/tests/unit/test_validators.py +341 -0
  109. valid8r-0.7.1/tests/unit/test_web_parsers.py +172 -0
  110. valid8r-0.7.1/tox.ini +69 -0
  111. valid8r-0.7.1/uv.lock +1755 -0
  112. {valid8r-0.6.3 → valid8r-0.7.1}/valid8r/core/maybe.py +1 -1
  113. valid8r-0.7.1/valid8r/core/validators.py +565 -0
  114. valid8r-0.7.1/valid8r/py.typed +0 -0
  115. valid8r-0.6.3/valid8r/core/validators.py +0 -282
  116. {valid8r-0.6.3 → valid8r-0.7.1}/LICENSE +0 -0
  117. /valid8r-0.6.3/valid8r/py.typed → /valid8r-0.7.1/tests/__init__.py +0 -0
  118. {valid8r-0.6.3 → valid8r-0.7.1}/valid8r/__init__.py +0 -0
  119. {valid8r-0.6.3 → valid8r-0.7.1}/valid8r/core/__init__.py +0 -0
  120. {valid8r-0.6.3 → valid8r-0.7.1}/valid8r/core/combinators.py +0 -0
  121. {valid8r-0.6.3 → valid8r-0.7.1}/valid8r/core/parsers.py +0 -0
  122. {valid8r-0.6.3 → valid8r-0.7.1}/valid8r/prompt/__init__.py +0 -0
  123. {valid8r-0.6.3 → valid8r-0.7.1}/valid8r/prompt/basic.py +0 -0
  124. {valid8r-0.6.3 → valid8r-0.7.1}/valid8r/testing/__init__.py +0 -0
  125. {valid8r-0.6.3 → valid8r-0.7.1}/valid8r/testing/assertions.py +0 -0
  126. {valid8r-0.6.3 → valid8r-0.7.1}/valid8r/testing/generators.py +0 -0
  127. {valid8r-0.6.3 → valid8r-0.7.1}/valid8r/testing/mock_input.py +0 -0
@@ -0,0 +1,12 @@
1
+ [run]
2
+ source = valid8r
3
+ omit = tests/*, .tox/*
4
+
5
+ [report]
6
+ exclude_lines =
7
+ pragma: no cover
8
+ def __repr__
9
+ raise NotImplementedError
10
+ if __name__ == .__main__.:
11
+ pass
12
+ if TYPE_CHECKING:
@@ -0,0 +1,325 @@
1
+ # .cursorrules
2
+ # Goal: Make Cursor an excellent software engineering companion. Combine general, language-agnostic engineering rules
3
+ # with repo-specific testing/style guidance already in use.
4
+
5
+ Cursor Project Rules
6
+
7
+ [available_instructions]
8
+
9
+ # ---------- Language-agnostic AI operating rules ----------
10
+ ai_alignment:
11
+ # Clarify the ask and fit the context
12
+ • Restate the task, inputs, outputs, constraints, and success criteria before writing code.
13
+ • Detect and follow the project’s stack, runtime, CI, testing style, and naming/layout conventions.
14
+ • Surface tradeoffs: propose a primary approach and at least one viable alternative with pros/cons.
15
+
16
+ ai_small_steps:
17
+ # Keep changes tiny and reversible
18
+ • Prefer minimal, incremental diffs gated by tests; one responsibility per change.
19
+ • Use feature flags/toggles or adapters for risky changes.
20
+ • Avoid speculative generality; implement the smallest thing that could possibly work.
21
+
22
+ ai_correct_first:
23
+ # Make it work before making it fast/fancy
24
+ • Provide runnable examples and tests that demonstrate behavior.
25
+ • Specify behavior via public surfaces; avoid coupling tests to internals.
26
+ • Cover golden path, edge cases, and failure modes.
27
+
28
+ ai_readability:
29
+ # Clear beats clever
30
+ • Favor descriptive names, short functions, cohesive modules.
31
+ • Remove duplication; maintain a single source of truth.
32
+ • Isolate complex logic behind simple interfaces.
33
+
34
+ ai_design_for_change:
35
+ # Stable boundaries, evolvable internals
36
+ • Program to interfaces/abstractions; hide implementation details.
37
+ • Validate at the edges; keep core logic working on trusted data.
38
+ • For legacy code, prefer strangler patterns and incremental replacement over rewrites.
39
+
40
+ ai_refactoring:
41
+ # Improve safely with a net
42
+ • Refactor only with passing tests; preserve behavior.
43
+ • Apply the scout rule: leave touched code cleaner.
44
+ • For perf-sensitive areas, capture before/after metrics.
45
+
46
+ ai_security_reliability:
47
+ # Non-optional requirements
48
+ • Enforce least privilege for code, data, secrets, and CI.
49
+ • Validate and sanitize all inputs (type/range/format); fail closed with secure defaults.
50
+ • Add observability at service/module boundaries: structured logs, key metrics, trace points.
51
+
52
+ ai_performance:
53
+ # Pragmatic optimization
54
+ • Make it work, then measure; optimize only with evidence.
55
+ • Prefer simpler algorithms until data proves otherwise.
56
+ • Call out expected time/space/IO complexity and resource budgets.
57
+
58
+ ai_dependency_hygiene:
59
+ # Keep the supply chain tidy
60
+ • Prefer standard libraries and fewer dependencies when reasonable.
61
+ • Track versions, licenses, and security advisories; pin/lock where appropriate.
62
+ • Wrap third-party libraries behind thin, swappable adapters.
63
+
64
+ ai_docs:
65
+ # Documentation that earns its keep
66
+ • Update API/module docs when behavior or surfaces change; describe behavior, inputs, outputs, invariants.
67
+ • Prefer runnable examples to prose where possible.
68
+ • Delete or update stale docs; stale docs are bugs.
69
+
70
+ ai_vcs_etiquette:
71
+ # Version control best practices
72
+ • Make atomic commits with messages that explain “why” before “what.”
73
+ • Ensure tests/linters/static analysis pass locally before opening a PR/MR.
74
+ • PR/MR descriptions should include context, decisions, risks, and validation notes.
75
+
76
+ ai_collaboration:
77
+ # Human-friendly by default
78
+ • Ask clarifying questions when requirements are ambiguous; do not guess silently.
79
+ • Offer 2–3 options with consequences when tradeoffs exist.
80
+ • Match the project’s code style, directory layout, and tooling.
81
+
82
+ ai_ethics_guardrails:
83
+ # Do the right thing
84
+ • Respect licenses; verify compatibility before suggesting code.
85
+ • Attribute significant ideas/snippets that are not original.
86
+ • Never expose secrets or PII in code, logs, examples, or test data.
87
+
88
+ ai_definition_of_done:
89
+ # Quality bar for AI-produced changes
90
+ • Task restated; constraints and acceptance criteria confirmed.
91
+ • Approach and alternatives documented (in PR/MR or design note).
92
+ • Code compiles/runs cleanly; linting/formatting/static analysis are clean.
93
+ • Tests exist, pass locally, and demonstrate behavior and edge cases.
94
+ • Security, error handling, and observability addressed where relevant.
95
+ • Public surfaces documented; docs/doctests updated.
96
+
97
+ ai_escalation:
98
+ # Know when to pause and propose a design
99
+ • Conflicting requirements or missing success criteria.
100
+ • Meaningful risk of data loss/security exposure without a rollback plan.
101
+ • Changes imply architectural shifts; produce a short design note first.
102
+
103
+ ai_operating_sequence:
104
+ # Step-by-step workflow for Cursor
105
+ 1. Confirm: restate task/constraints/acceptance criteria; ask blocking questions.
106
+ 2. Plan: outline a tiny increment that delivers user value; note tradeoffs.
107
+ 3. Propose: show tests first, then implementation; keep diff small.
108
+ 4. Validate: enumerate edge cases, security checks, and perf notes.
109
+ 5. Refine: simplify names/structure; remove duplication.
110
+ 6. Deliver: provide patch + tests + concise PR description with rationale and follow-ups.
111
+ 7. Iterate: accept feedback; repeat in small steps.
112
+
113
+ # ---------- Existing repo-specific testing/style guidance ----------
114
+ pytest_naming:
115
+ Use pytest discovery configuration from pyproject.toml:
116
+ • test paths: tests
117
+ • test files: it_*.py, test_*.py
118
+ • test classes: Describe[A-Z]*
119
+ • test functions: it_*
120
+ When creating new tests:
121
+ • Mirror src/valid8r/... structure under tests/....
122
+ • Use classes like DescribeThing with methods it_describes_behavior.
123
+ • Prefer @pytest.mark.parametrize (see parametrization_policy).
124
+ • For async code, mark tests with @pytest.mark.asyncio.
125
+
126
+ testing_principles:
127
+ Adopt Software Engineering at Google testing practices:
128
+ • Test behavior, not implementation (assert on public surface; avoid peeking at internals/private state).
129
+ • Small and hermetic: no network, no real filesystem (use tmp_path), no time dependence (inject a clock or freeze time).
130
+ • Deterministic: seed randomness; avoid sleeps and flakiness; keep timeouts tight.
131
+ • DAMP not DRY in tests: prioritize clarity over reuse; duplication in tests is fine when it improves readability.
132
+ • One concept per test: each test should fail for a single understandable reason.
133
+ • Clear names as specification: DescribeFoo.it_rejects_empty_input style; prefer long, descriptive names.
134
+ • Use fakes over mocks when possible; prefer dependency injection to make seams explicit.
135
+ • Don’t assert on log messages unless the log is a defined behavior.
136
+ • Coverage is a byproduct, not the goal; prioritize risk and critical paths.
137
+ • Keep fixtures simple and local; avoid deep fixture hierarchies that obscure intent.
138
+
139
+ fixtures_and_mocks:
140
+ • Prefer pytest fixtures for setup; avoid xUnit setup/teardown.
141
+ • Use MagicMock/AsyncMock sparingly; favor fakes/simple test doubles.
142
+ • For static data, use pytest_lambda.static_fixture.
143
+ • Use monkeypatch for env vars and module-level patching.
144
+ • Isolate global state; reset or inject dependencies per test.
145
+
146
+ io_and_time_isolation:
147
+ • Use tmp_path/tmp_path_factory for any filesystem work.
148
+ • For time, inject a clock callable or use freezegun.freeze_time in tests.
149
+
150
+ parametrization_policy:
151
+ Prefer parametrized tests. Use indirect parametrization when constructing objects/fixtures is non-trivial or when parameters map to fixtures.
152
+
153
+ Direct example:
154
+
155
+ @pytest.mark.parametrize(
156
+ "raw,expected",
157
+ [
158
+ pytest.param("42", 42, id="pos-42"),
159
+ pytest.param("0", 0, id="zero"),
160
+ pytest.param("-1", -1, id="neg-1"),
161
+ ],
162
+ )
163
+ def it_parses_integers(raw, expected):
164
+ assert parsers.int(raw) == expected
165
+
166
+ Indirect example:
167
+
168
+ @pytest.fixture
169
+ def user(request):
170
+ return User(name=request.param["name"], role=request.param["role"])
171
+
172
+ @pytest.mark.parametrize(
173
+ "user,allowed",
174
+ [
175
+ pytest.param({"name": "alice", "role": "admin"}, True, id="admin-allowed"),
176
+ pytest.param({"name": "bob", "role": "viewer"}, False, id="viewer-denied"),
177
+ ],
178
+ indirect=["user"],
179
+ )
180
+ def it_checks_access(user, allowed):
181
+ assert can_access(user) is allowed
182
+
183
+ IDs:
184
+ Provide excellent, human-readable ids for each case:
185
+ • Short, kebab-case descriptions of behavior (e.g., empty-input, admin-allowed, viewer-denied).
186
+ • Include critical parameter hints when useful (e.g., neg-1, boundary-0, unicode-snowman).
187
+ • Avoid opaque numeric-only ids.
188
+
189
+ public_api_reexports:
190
+ valid8r top-level must re-export:
191
+ • modules: parsers, validators, combinators, and prompt (with ask exposed in valid8r.prompt).
192
+ • types: Maybe from valid8r.core.maybe.
193
+ Maintain backward compatibility for deep imports.
194
+ When changing exports:
195
+ • Update __all__ in valid8r/__init__.py and valid8r/prompt/__init__.py.
196
+ • Update public API tests (see public_api_test_template).
197
+ • Public API code should have high-quality docstrings and doctests (see public_api_docs).
198
+
199
+ Mini __init__.py export pattern:
200
+
201
+ # valid8r/__init__.py
202
+ from __future__ import annotations
203
+
204
+ from . import parsers, validators, combinators, prompt
205
+ from .core.maybe import Maybe
206
+
207
+ __all__ = [
208
+ "parsers",
209
+ "validators",
210
+ "combinators",
211
+ "prompt",
212
+ "Maybe",
213
+ ]
214
+
215
+ # valid8r/prompt/__init__.py
216
+ from __future__ import annotations
217
+
218
+ from .ask import ask
219
+
220
+ __all__ = ["ask"]
221
+
222
+ Tiny indirect parametrized test using the public API:
223
+
224
+ import pytest
225
+ from valid8r import prompt
226
+
227
+ @pytest.fixture
228
+ def question(request):
229
+ # Imagine 'ask' uses this question text internally
230
+ return request.param
231
+
232
+ @pytest.mark.parametrize(
233
+ "question,expected_callable",
234
+ [
235
+ pytest.param("What is your name?", True, id="simple-question"),
236
+ pytest.param("Choose an option: [a/b]", True, id="multiple-choice"),
237
+ ],
238
+ indirect=["question"],
239
+ )
240
+ def it_exposes_prompt_ask_as_callable(question, expected_callable):
241
+ # Public API behavior: 'ask' must always be callable
242
+ assert callable(prompt.ask) is expected_callable
243
+
244
+ public_api_test_template:
245
+ Create/maintain tests/it_public_api.py:
246
+
247
+ import importlib
248
+
249
+ def it_exposes_expected_symbols():
250
+ v = importlib.import_module("valid8r")
251
+ assert hasattr(v, "parsers")
252
+ assert hasattr(v, "validators")
253
+ assert hasattr(v, "combinators")
254
+ from valid8r import prompt, Maybe # noqa: F401
255
+ assert callable(prompt.ask)
256
+
257
+ def it_preserves_deep_imports_for_backcompat():
258
+ assert importlib.import_module("valid8r.core.maybe").Maybe is not None
259
+
260
+ public_api_docs:
261
+ Public API must include detailed docstrings with realistic doctests (serve as examples and executable checks).
262
+ • Write WHY in comments/docstrings; code should explain WHAT via names/types.
263
+ • Example:
264
+
265
+ def parse_positive_int(text: str) -> int:
266
+ """
267
+ Parse a string into a positive integer.
268
+
269
+ Accepts optional leading/trailing whitespace and '+' sign.
270
+ Raises ValueError for non-integer or non-positive values.
271
+
272
+ Examples:
273
+ >>> parse_positive_int(" +7 ")
274
+ 7
275
+ >>> parse_positive_int("0")
276
+ Traceback (most recent call last):
277
+ ...
278
+ ValueError: expected a positive integer
279
+ """
280
+ ...
281
+
282
+ • Keep doctests fast and hermetic; avoid I/O and network.
283
+
284
+ comment_policy:
285
+ Keep comments minimal. Only explain WHY something is done if it is non-obvious or encodes a business rule.
286
+ • Do not narrate obvious steps.
287
+ • Public API is the exception: include rich docstrings + doctests.
288
+
289
+ typing_and_style:
290
+ • All new/changed Python must be fully type-annotated.
291
+ • Code must pass mypy (repo config) and ruff (repo rules).
292
+ • Avoid unrelated reformatting; only change lines necessary for the task.
293
+
294
+ run_tests_locally:
295
+ In constrained environments without pytest installed, create smoke_test.py:
296
+
297
+ from valid8r import parsers, validators, prompt, Maybe
298
+ assert callable(prompt.ask)
299
+ print("ok")
300
+
301
+ Make it runnable with: python smoke_test.py
302
+
303
+ ci_expectations:
304
+ • Follow TDD: write a failing test, write the minimum code to pass, then refactor both.
305
+ • Unit tests should be fast (<1s each where practical); mark slower ones @pytest.mark.slow.
306
+ • Tests are hermetic by default; mark any external integrations as @pytest.mark.integration.
307
+
308
+ # ---------- Defaults applied to all requests ----------
309
+ [default]
310
+ # Operating mode summary (language-agnostic)
311
+ • Apply ai_operating_sequence; keep changes small and reversible.
312
+ • Follow ai_alignment, ai_correct_first, ai_readability, ai_design_for_change.
313
+ • Enforce ai_security_reliability, ai_performance, ai_dependency_hygiene.
314
+ • Honor ai_vcs_etiquette, ai_docs, ai_collaboration, ai_ethics_guardrails.
315
+ • Meet ai_definition_of_done; use ai_escalation when needed.
316
+
317
+ # Repo-specific testing/style
318
+ • Use Describe*/it_* names that read like a spec; mirror src under tests.
319
+ • Apply Google testing principles: behavior-based, small, hermetic, deterministic, DAMP.
320
+ • Prefer parametrization; use indirect parametrization for non-trivial setup; use pytest.param with excellent ids.
321
+ • Keep comments minimal (WHY only). Public API gets rich docstrings + doctests.
322
+ • Prefer fixtures + (Async)MagicMock (sparingly) + pytest_lambda.static_fixture.
323
+ • Use tmp_path, monkeypatch, and frozen/injected time for isolation.
324
+ • Maintain public API exports and back-compat; keep public API tests and docs in sync.
325
+ • Match repo style (ruff) and types (mypy); avoid drive-by reformatting.
@@ -0,0 +1,28 @@
1
+ # CI/CD Pipeline Test
2
+
3
+ This file was created to test the automated CI/CD pipeline for valid8r.
4
+
5
+ ## Test Purpose
6
+
7
+ Verify that the complete automation workflow functions correctly:
8
+
9
+ 1. ✅ CI runs on PR (tests, linting, type checking)
10
+ 2. ✅ Auto version bump on merge to main (0.1.0 → 0.2.0)
11
+ 3. ✅ GitHub Release created automatically
12
+ 4. ✅ Package builds and publishes to PyPI
13
+ 5. ✅ `pip install valid8r` installs the latest version
14
+
15
+ ## Test Date
16
+
17
+ 2025-10-21
18
+
19
+ ## Expected Result
20
+
21
+ - Version bumps from 0.1.0 to 0.2.0 (feat: triggers minor bump)
22
+ - GitHub Release created with changelog
23
+ - Package available on PyPI
24
+ - Installable via: `pip install valid8r==0.2.0`
25
+
26
+ ## Notes
27
+
28
+ This test uses a conventional commit with `feat:` prefix to trigger a minor version bump.
@@ -0,0 +1,33 @@
1
+ # CODEOWNERS
2
+ # This file defines code ownership for the valid8r project.
3
+ # Each line is a file pattern followed by one or more owners.
4
+ # These owners will be automatically requested for review when a PR modifies matching files.
5
+ #
6
+ # More information: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
7
+
8
+ # Default owner for everything in the repo
9
+ * @mikelane
10
+
11
+ # Core library code
12
+ /valid8r/core/ @mikelane
13
+ /valid8r/prompt/ @mikelane
14
+ /valid8r/testing/ @mikelane
15
+
16
+ # Tests
17
+ /tests/ @mikelane
18
+
19
+ # Documentation
20
+ /docs/ @mikelane
21
+ *.md @mikelane
22
+ CLAUDE.md @mikelane
23
+
24
+ # Configuration files
25
+ pyproject.toml @mikelane
26
+ poetry.lock @mikelane
27
+ tox.ini @mikelane
28
+
29
+ # GitHub workflows and templates
30
+ /.github/ @mikelane
31
+
32
+ # CI/CD
33
+ /.github/workflows/ @mikelane