pydantic-fixturegen 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pydantic-fixturegen might be problematic. Click here for more details.

Files changed (79) hide show
  1. pydantic_fixturegen-1.0.0/.gitignore +18 -0
  2. pydantic_fixturegen-1.0.0/LICENSE +21 -0
  3. pydantic_fixturegen-1.0.0/PKG-INFO +280 -0
  4. pydantic_fixturegen-1.0.0/README.md +228 -0
  5. pydantic_fixturegen-1.0.0/docs/cookbook.md +302 -0
  6. pydantic_fixturegen-1.0.0/docs/quickstart.md +240 -0
  7. pydantic_fixturegen-1.0.0/pydantic_fixturegen/__init__.py +7 -0
  8. pydantic_fixturegen-1.0.0/pydantic_fixturegen/cli/__init__.py +85 -0
  9. pydantic_fixturegen-1.0.0/pydantic_fixturegen/cli/doctor.py +235 -0
  10. pydantic_fixturegen-1.0.0/pydantic_fixturegen/cli/gen/__init__.py +23 -0
  11. pydantic_fixturegen-1.0.0/pydantic_fixturegen/cli/gen/_common.py +139 -0
  12. pydantic_fixturegen-1.0.0/pydantic_fixturegen/cli/gen/explain.py +145 -0
  13. pydantic_fixturegen-1.0.0/pydantic_fixturegen/cli/gen/fixtures.py +283 -0
  14. pydantic_fixturegen-1.0.0/pydantic_fixturegen/cli/gen/json.py +262 -0
  15. pydantic_fixturegen-1.0.0/pydantic_fixturegen/cli/gen/schema.py +164 -0
  16. pydantic_fixturegen-1.0.0/pydantic_fixturegen/cli/list.py +164 -0
  17. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/__init__.py +103 -0
  18. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/ast_discover.py +169 -0
  19. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/config.py +440 -0
  20. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/errors.py +136 -0
  21. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/generate.py +311 -0
  22. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/introspect.py +141 -0
  23. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/io_utils.py +77 -0
  24. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/providers/__init__.py +32 -0
  25. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/providers/collections.py +74 -0
  26. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/providers/identifiers.py +68 -0
  27. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/providers/numbers.py +133 -0
  28. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/providers/registry.py +98 -0
  29. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/providers/strings.py +109 -0
  30. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/providers/temporal.py +42 -0
  31. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/safe_import.py +403 -0
  32. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/schema.py +320 -0
  33. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/seed.py +154 -0
  34. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/strategies.py +193 -0
  35. pydantic_fixturegen-1.0.0/pydantic_fixturegen/core/version.py +52 -0
  36. pydantic_fixturegen-1.0.0/pydantic_fixturegen/emitters/__init__.py +15 -0
  37. pydantic_fixturegen-1.0.0/pydantic_fixturegen/emitters/json_out.py +373 -0
  38. pydantic_fixturegen-1.0.0/pydantic_fixturegen/emitters/pytest_codegen.py +365 -0
  39. pydantic_fixturegen-1.0.0/pydantic_fixturegen/emitters/schema_out.py +84 -0
  40. pydantic_fixturegen-1.0.0/pydantic_fixturegen/plugins/builtin.py +45 -0
  41. pydantic_fixturegen-1.0.0/pydantic_fixturegen/plugins/hookspecs.py +59 -0
  42. pydantic_fixturegen-1.0.0/pydantic_fixturegen/plugins/loader.py +72 -0
  43. pydantic_fixturegen-1.0.0/pyproject.toml +158 -0
  44. pydantic_fixturegen-1.0.0/tests/cli/test_cli_entrypoint.py +30 -0
  45. pydantic_fixturegen-1.0.0/tests/cli/test_cli_errors.py +83 -0
  46. pydantic_fixturegen-1.0.0/tests/cli/test_common_helpers.py +125 -0
  47. pydantic_fixturegen-1.0.0/tests/cli/test_config_loader_errors.py +33 -0
  48. pydantic_fixturegen-1.0.0/tests/cli/test_doctor.py +222 -0
  49. pydantic_fixturegen-1.0.0/tests/cli/test_explain.py +160 -0
  50. pydantic_fixturegen-1.0.0/tests/cli/test_gen_fixtures.py +391 -0
  51. pydantic_fixturegen-1.0.0/tests/cli/test_gen_json.py +433 -0
  52. pydantic_fixturegen-1.0.0/tests/cli/test_gen_schema.py +314 -0
  53. pydantic_fixturegen-1.0.0/tests/cli/test_list.py +136 -0
  54. pydantic_fixturegen-1.0.0/tests/conftest.py +8 -0
  55. pydantic_fixturegen-1.0.0/tests/core/test_ast_discover.py +113 -0
  56. pydantic_fixturegen-1.0.0/tests/core/test_config.py +299 -0
  57. pydantic_fixturegen-1.0.0/tests/core/test_errors.py +45 -0
  58. pydantic_fixturegen-1.0.0/tests/core/test_generate.py +100 -0
  59. pydantic_fixturegen-1.0.0/tests/core/test_introspect.py +101 -0
  60. pydantic_fixturegen-1.0.0/tests/core/test_io_utils.py +58 -0
  61. pydantic_fixturegen-1.0.0/tests/core/test_providers.py +426 -0
  62. pydantic_fixturegen-1.0.0/tests/core/test_safe_import.py +74 -0
  63. pydantic_fixturegen-1.0.0/tests/core/test_schema_constraints.py +236 -0
  64. pydantic_fixturegen-1.0.0/tests/core/test_seed.py +130 -0
  65. pydantic_fixturegen-1.0.0/tests/core/test_strategies.py +80 -0
  66. pydantic_fixturegen-1.0.0/tests/core/test_version.py +55 -0
  67. pydantic_fixturegen-1.0.0/tests/e2e/test_determinism.py +121 -0
  68. pydantic_fixturegen-1.0.0/tests/emitters/test_json_out.py +76 -0
  69. pydantic_fixturegen-1.0.0/tests/emitters/test_json_out_additional.py +84 -0
  70. pydantic_fixturegen-1.0.0/tests/emitters/test_pytest_codegen.py +70 -0
  71. pydantic_fixturegen-1.0.0/tests/emitters/test_pytest_codegen_styles.py +63 -0
  72. pydantic_fixturegen-1.0.0/tests/emitters/test_schema_out.py +48 -0
  73. pydantic_fixturegen-1.0.0/tests/perf/test_json_workers.py +47 -0
  74. pydantic_fixturegen-1.0.0/tests/plugins/test_hooks.py +102 -0
  75. pydantic_fixturegen-1.0.0/tests/providers/test_collections_additional.py +24 -0
  76. pydantic_fixturegen-1.0.0/tests/providers/test_numbers_additional.py +57 -0
  77. pydantic_fixturegen-1.0.0/tests/providers/test_strings_additional.py +14 -0
  78. pydantic_fixturegen-1.0.0/tests/security/test_sandbox.py +91 -0
  79. pydantic_fixturegen-1.0.0/tests/test_imports.py +17 -0
@@ -0,0 +1,18 @@
1
+ # Byte-compiled / cache
2
+ __pycache__/
3
+ .mypy_cache/
4
+ .ruff_cache/
5
+ .pytest_cache/
6
+
7
+ # Coverage
8
+ .coverage
9
+ htmlcov/
10
+
11
+ # Environments
12
+ .venv/
13
+ .tox/
14
+
15
+ # Editors
16
+ .idea/
17
+ .vscode/
18
+ dist
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 pydantic-fixturegen contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,280 @@
1
+ Metadata-Version: 2.4
2
+ Name: pydantic-fixturegen
3
+ Version: 1.0.0
4
+ Summary: Deterministic fixture generator for Pydantic models.
5
+ Project-URL: Homepage, https://github.com/casper-kristiansson/pydantic-fixturegen
6
+ Project-URL: Documentation, https://github.com/casper-kristiansson/pydantic-fixturegen
7
+ Project-URL: Repository, https://github.com/casper-kristiansson/pydantic-fixturegen
8
+ Author: Fixturegen Developers
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Requires-Python: <3.14,>=3.10
20
+ Requires-Dist: faker>=24.0.0
21
+ Requires-Dist: pluggy>=1.5.0
22
+ Requires-Dist: pydantic>=2.8.0
23
+ Requires-Dist: tomli>=2.0.1; python_version < '3.11'
24
+ Requires-Dist: typer>=0.12.3
25
+ Provides-Extra: all
26
+ Requires-Dist: hypothesis>=6.100.0; extra == 'all'
27
+ Requires-Dist: orjson>=3.10.0; extra == 'all'
28
+ Requires-Dist: rstr>=3.2.0; extra == 'all'
29
+ Provides-Extra: all-dev
30
+ Requires-Dist: hypothesis>=6.100.0; extra == 'all-dev'
31
+ Requires-Dist: mypy>=1.11; extra == 'all-dev'
32
+ Requires-Dist: orjson>=3.10.0; extra == 'all-dev'
33
+ Requires-Dist: pytest-cov>=5.0; extra == 'all-dev'
34
+ Requires-Dist: pytest>=8.3; extra == 'all-dev'
35
+ Requires-Dist: rstr>=3.2.0; extra == 'all-dev'
36
+ Requires-Dist: ruff>=0.6.5; extra == 'all-dev'
37
+ Provides-Extra: dev
38
+ Requires-Dist: mypy>=1.11; extra == 'dev'
39
+ Provides-Extra: docs
40
+ Provides-Extra: hypothesis
41
+ Requires-Dist: hypothesis>=6.100.0; extra == 'hypothesis'
42
+ Provides-Extra: lint
43
+ Requires-Dist: ruff>=0.6.5; extra == 'lint'
44
+ Provides-Extra: orjson
45
+ Requires-Dist: orjson>=3.10.0; extra == 'orjson'
46
+ Provides-Extra: regex
47
+ Requires-Dist: rstr>=3.2.0; extra == 'regex'
48
+ Provides-Extra: test
49
+ Requires-Dist: pytest-cov>=5.0; extra == 'test'
50
+ Requires-Dist: pytest>=8.3; extra == 'test'
51
+ Description-Content-Type: text/markdown
52
+
53
+ # pydantic-fixturegen: Deterministic Pydantic fixtures for fast, safe tests (pydantic-fixturegen)
54
+
55
+ > Deterministic Pydantic fixtures and JSON generation via a secure sandboxed CLI and Pluggy plugins.
56
+
57
+ [![PyPI version](https://img.shields.io/pypi/v/pydantic-fixturegen.svg "PyPI")](https://pypi.org/project/pydantic-fixturegen/)
58
+ ![Python versions](https://img.shields.io/pypi/pyversions/pydantic-fixturegen.svg "Python 3.10–3.13")
59
+ ![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg "MIT License")
60
+
61
+ `pydantic-fixturegen` is a **deterministic data generation toolkit for Pydantic v2 models**. It discovers models, builds generation strategies, creates instances, and **emits artifacts**—JSON, **pytest fixtures**, and JSON Schema—through a composable CLI and a **Pluggy** plugin layer.
62
+
63
+ - **Deterministic seeds** cascade per model/field across Python `random`, **Faker**, and optional **NumPy** RNGs.
64
+ - **Safe-import sandbox** executes untrusted model modules with **network lockdown**, **filesystem jail**, and **resource caps**.
65
+ - **Emitters** write JSON/JSONL, pytest fixture modules, and schema files with **atomic writes** and reproducibility metadata.
66
+ - **Config precedence**: **CLI args** → **`PFG_*` env vars** → **`[tool.pydantic_fixturegen]`** in `pyproject.toml` or YAML → defaults.
67
+
68
+ ---
69
+
70
+ ## Why pydantic-fixturegen (why)
71
+
72
+ - **Deterministic test data** for reproducible CI.
73
+ - **Secure safe-import sandbox** for third-party models.
74
+ - **Pluggy-powered data providers** for extension without forks.
75
+ - **CLI first**: `pfg list | gen json | gen fixtures | gen schema | gen explain | doctor`.
76
+
77
+ ---
78
+
79
+ ## Features at a glance (features)
80
+
81
+ | Area | Highlights |
82
+ | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
83
+ | **Discovery** | `pfg list` via AST or sandboxed import; include/exclude patterns; public-only; machine-readable errors (`--json-errors`, code `20`). |
84
+ | **Generation** | Depth-first builder with recursion/instance budgets; per-field policies (enums/unions/`p_none`). |
85
+ | **Emitters** | JSON/JSONL with optional **orjson**, sharding, metadata header when indenting; pytest fixtures with banner (seed/version/digest) and Ruff/Black formatting; JSON Schema via `model_json_schema()` with **atomic writes**. |
86
+ | **Providers** | Built-in numbers, strings (regex via optional `rstr`), collections, temporal, identifiers. Extensible via `pfg_register_providers`. |
87
+ | **Strategies** | `core/strategies.py` merges schema, policies, and plugin adjustments (`pfg_modify_strategy`). |
88
+ | **Security** | Sandbox blocks sockets, scrubs env (`NO_PROXY=*`, proxies cleared, `PYTHONSAFEPATH=1`), redirects HOME/tmp, jails filesystem writes, caps memory (`RLIMIT_AS`, `RLIMIT_DATA`), **timeout exit code 40**. |
89
+ | **Config** | CLI > `PFG_*` env > `pyproject`/YAML > defaults. String booleans accepted (`true/false/1/0`). |
90
+ | **Quality** | Mypy + Ruff; pytest across Linux/macOS/Windows, Python **3.10–3.13**; coverage ≥ **90%**. |
91
+ | **Release** | Hatch builds; GitHub Actions matrices; PyPI **Trusted Publishing** with signing + attestations. |
92
+
93
+ ---
94
+
95
+ ## Install
96
+
97
+ ### pip
98
+
99
+ ```bash
100
+ pip install pydantic-fixturegen
101
+ # Extras
102
+ pip install 'pydantic-fixturegen[orjson]'
103
+ pip install 'pydantic-fixturegen[regex]'
104
+ pip install 'pydantic-fixturegen[hypothesis]'
105
+ pip install 'pydantic-fixturegen[all]' # runtime extras bundle
106
+ pip install 'pydantic-fixturegen[all-dev]' # dev tools + runtime extras
107
+ ```
108
+
109
+ ### Poetry
110
+
111
+ ```bash
112
+ poetry add pydantic-fixturegen
113
+ poetry run pfg --help
114
+ ```
115
+
116
+ ### Hatch
117
+
118
+ ```toml
119
+ # pyproject.toml
120
+ [project]
121
+ dependencies = ["pydantic-fixturegen"]
122
+ ```
123
+
124
+ ```bash
125
+ hatch run pfg --help
126
+ ```
127
+
128
+ ---
129
+
130
+ ## 60-second quickstart (quickstart)
131
+
132
+ **1) Define models**
133
+
134
+ ```python
135
+ # models.py
136
+ from pydantic import BaseModel
137
+
138
+ class Address(BaseModel):
139
+ street: str
140
+
141
+ class User(BaseModel):
142
+ id: int
143
+ name: str
144
+ nickname: str | None = None
145
+ address: Address
146
+ ```
147
+
148
+ **2) Discover models**
149
+
150
+ ```bash
151
+ pfg list ./models.py
152
+ # outputs:
153
+ # models.User
154
+ # models.Address
155
+ ```
156
+
157
+ **3) Generate JSON samples**
158
+
159
+ ```bash
160
+ pfg gen json ./models.py --include models.User --n 2 --indent 2 --out ./out/User
161
+ # writes out/User.json with a metadata header comment when indenting
162
+
163
+ > **Note:** When a module declares more than one model, `--include` narrows generation to the desired `module.Model`.
164
+ ```
165
+
166
+ Example file (excerpt):
167
+
168
+ ```json
169
+ /* seed=42 version=1.0.0 digest=<sha256> */
170
+ [
171
+ {
172
+ "id": 1,
173
+ "name": "Alice",
174
+ "nickname": null,
175
+ "address": { "street": "42 Main St" }
176
+ },
177
+ {
178
+ "id": 2,
179
+ "name": "Bob",
180
+ "nickname": "b",
181
+ "address": { "street": "1 Side Rd" }
182
+ }
183
+ ]
184
+ ```
185
+
186
+ **4) Generate pytest fixtures**
187
+
188
+ ```bash
189
+ pfg gen fixtures ./models.py \
190
+ --out tests/fixtures/test_user_fixtures.py \
191
+ --style functions --scope module --cases 3 --return-type model
192
+ # produces a module with a banner and deduped imports, formatted by Ruff/Black
193
+ ```
194
+
195
+ Fixture excerpt:
196
+
197
+ ```python
198
+ # pydantic-fixturegen v1.0.0 seed=42 digest=<sha256>
199
+ import pytest
200
+ from models import User, Address
201
+
202
+ @pytest.fixture(scope="module", params=[0,1,2], ids=lambda i: f"user_case_{i}")
203
+ def user(request) -> User:
204
+ # deterministic across runs/machines
205
+ ...
206
+ ```
207
+
208
+ ---
209
+
210
+ ## Configuration precedence (configuration-precedence)
211
+
212
+ ```toml
213
+ # pyproject.toml
214
+ [tool.pydantic_fixturegen]
215
+ seed = 42
216
+ locale = "en_US"
217
+ union_policy = "weighted"
218
+ enum_policy = "random"
219
+ emitters.json.indent = 2
220
+ emitters.json.orjson = false
221
+ fixtures.style = "functions"
222
+ fixtures.scope = "module"
223
+ ```
224
+
225
+ Environment variables mirror keys using `PFG_` (e.g., `PFG_SEED=99`). **CLI flags override everything**.
226
+
227
+ ---
228
+
229
+ ## CLI overview (cli)
230
+
231
+ - `pfg list <module_or_path>` — enumerate models (AST and/or sandboxed import).
232
+ - `pfg gen json <target>` — deterministic JSON/JSONL (`--n`, `--jsonl`, `--indent`, `--orjson/--no-orjson`, `--shard-size`, `--out`, `--seed`).
233
+ - `pfg gen schema <target>` — emit JSON Schema (`--out` required; atomic writes; `--json-errors`).
234
+ - `pfg gen fixtures <target>` — emit pytest fixtures (`--style {functions,factory,class}`, `--scope {function,module,session}`, `--p-none`, `--cases`, `--return-type {model,dict}`).
235
+ - `pfg gen explain <target>` — print provider/strategy tree per field; optional `--json` if exposed.
236
+ - `pfg doctor <target>` — audit coverage, constraints, risky imports (`--fail-on-warn`, `--json-errors`).
237
+
238
+ ---
239
+
240
+ ## Architecture in one diagram (architecture)
241
+
242
+ ```
243
+ Models → Discovery (AST ⟷ Safe-Import Sandbox) → Strategies (policies + hooks)
244
+ → ProviderRegistry (built-ins + plugins) → Instance Builder
245
+ → Emitters (JSON | Fixtures | Schema, atomic IO, worker pools)
246
+ → Artifacts on disk (with seed/version/digest metadata)
247
+ ```
248
+
249
+ **Sandbox guards**: sockets blocked; env scrubbed (`NO_PROXY=*`, proxies cleared, `PYTHONSAFEPATH=1`); HOME/tmp redirected; writes outside workdir denied; memory caps (`RLIMIT_AS`, `RLIMIT_DATA`); **timeout exit code 40**.
250
+
251
+ ---
252
+
253
+ ## Comparison: pydantic-fixturegen vs alternatives (comparison)
254
+
255
+ | Use Case | Learning Curve | Determinism | Security Controls | Best Fit |
256
+ | ------------------------------------- | -------------- | -------------------------------------------------- | --------------------------------------- | -------------------------------------------------------------------- |
257
+ | **pydantic-fixturegen** | Low | Strong, cascaded seeds across `random`/Faker/NumPy | Sandbox, atomic IO, JSON error taxonomy | Teams needing **deterministic Pydantic fixtures** and CLI automation |
258
+ | Hand-written fixtures | Medium–High | Depends on reviewer discipline | None by default | Small codebases with few models |
259
+ | Factory libraries (e.g., factory_boy) | Medium | Often stochastic unless manually seeded | Varies, not sandboxed | App-level object factories where ORM integration is key |
260
+ | `hypothesis.extra.pydantic` | Medium–High | Property-based, not fixed by default | Not sandboxed | Generative testing exploring model spaces |
261
+
262
+ ---
263
+
264
+ ## Community & support (community)
265
+
266
+ - Issues and contributions are welcome. Open an issue for bugs or feature discussions, and submit PRs with tests and docs.
267
+ - Security posture includes a sandbox and atomic writes; please report any bypass findings responsibly.
268
+
269
+ ---
270
+
271
+ ## License (license)
272
+
273
+ MIT. See `LICENSE`.
274
+
275
+ ---
276
+
277
+ ## Next steps (next-steps)
278
+
279
+ - Start with the **[Quickstart](./docs/quickstart.md)**.
280
+ - Dive deeper with the **[Cookbook](./docs/cookbook.md)**.
@@ -0,0 +1,228 @@
1
+ # pydantic-fixturegen: Deterministic Pydantic fixtures for fast, safe tests (pydantic-fixturegen)
2
+
3
+ > Deterministic Pydantic fixtures and JSON generation via a secure sandboxed CLI and Pluggy plugins.
4
+
5
+ [![PyPI version](https://img.shields.io/pypi/v/pydantic-fixturegen.svg "PyPI")](https://pypi.org/project/pydantic-fixturegen/)
6
+ ![Python versions](https://img.shields.io/pypi/pyversions/pydantic-fixturegen.svg "Python 3.10–3.13")
7
+ ![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg "MIT License")
8
+
9
+ `pydantic-fixturegen` is a **deterministic data generation toolkit for Pydantic v2 models**. It discovers models, builds generation strategies, creates instances, and **emits artifacts**—JSON, **pytest fixtures**, and JSON Schema—through a composable CLI and a **Pluggy** plugin layer.
10
+
11
+ - **Deterministic seeds** cascade per model/field across Python `random`, **Faker**, and optional **NumPy** RNGs.
12
+ - **Safe-import sandbox** executes untrusted model modules with **network lockdown**, **filesystem jail**, and **resource caps**.
13
+ - **Emitters** write JSON/JSONL, pytest fixture modules, and schema files with **atomic writes** and reproducibility metadata.
14
+ - **Config precedence**: **CLI args** → **`PFG_*` env vars** → **`[tool.pydantic_fixturegen]`** in `pyproject.toml` or YAML → defaults.
15
+
16
+ ---
17
+
18
+ ## Why pydantic-fixturegen (why)
19
+
20
+ - **Deterministic test data** for reproducible CI.
21
+ - **Secure safe-import sandbox** for third-party models.
22
+ - **Pluggy-powered data providers** for extension without forks.
23
+ - **CLI first**: `pfg list | gen json | gen fixtures | gen schema | gen explain | doctor`.
24
+
25
+ ---
26
+
27
+ ## Features at a glance (features)
28
+
29
+ | Area | Highlights |
30
+ | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
31
+ | **Discovery** | `pfg list` via AST or sandboxed import; include/exclude patterns; public-only; machine-readable errors (`--json-errors`, code `20`). |
32
+ | **Generation** | Depth-first builder with recursion/instance budgets; per-field policies (enums/unions/`p_none`). |
33
+ | **Emitters** | JSON/JSONL with optional **orjson**, sharding, metadata header when indenting; pytest fixtures with banner (seed/version/digest) and Ruff/Black formatting; JSON Schema via `model_json_schema()` with **atomic writes**. |
34
+ | **Providers** | Built-in numbers, strings (regex via optional `rstr`), collections, temporal, identifiers. Extensible via `pfg_register_providers`. |
35
+ | **Strategies** | `core/strategies.py` merges schema, policies, and plugin adjustments (`pfg_modify_strategy`). |
36
+ | **Security** | Sandbox blocks sockets, scrubs env (`NO_PROXY=*`, proxies cleared, `PYTHONSAFEPATH=1`), redirects HOME/tmp, jails filesystem writes, caps memory (`RLIMIT_AS`, `RLIMIT_DATA`), **timeout exit code 40**. |
37
+ | **Config** | CLI > `PFG_*` env > `pyproject`/YAML > defaults. String booleans accepted (`true/false/1/0`). |
38
+ | **Quality** | Mypy + Ruff; pytest across Linux/macOS/Windows, Python **3.10–3.13**; coverage ≥ **90%**. |
39
+ | **Release** | Hatch builds; GitHub Actions matrices; PyPI **Trusted Publishing** with signing + attestations. |
40
+
41
+ ---
42
+
43
+ ## Install
44
+
45
+ ### pip
46
+
47
+ ```bash
48
+ pip install pydantic-fixturegen
49
+ # Extras
50
+ pip install 'pydantic-fixturegen[orjson]'
51
+ pip install 'pydantic-fixturegen[regex]'
52
+ pip install 'pydantic-fixturegen[hypothesis]'
53
+ pip install 'pydantic-fixturegen[all]' # runtime extras bundle
54
+ pip install 'pydantic-fixturegen[all-dev]' # dev tools + runtime extras
55
+ ```
56
+
57
+ ### Poetry
58
+
59
+ ```bash
60
+ poetry add pydantic-fixturegen
61
+ poetry run pfg --help
62
+ ```
63
+
64
+ ### Hatch
65
+
66
+ ```toml
67
+ # pyproject.toml
68
+ [project]
69
+ dependencies = ["pydantic-fixturegen"]
70
+ ```
71
+
72
+ ```bash
73
+ hatch run pfg --help
74
+ ```
75
+
76
+ ---
77
+
78
+ ## 60-second quickstart (quickstart)
79
+
80
+ **1) Define models**
81
+
82
+ ```python
83
+ # models.py
84
+ from pydantic import BaseModel
85
+
86
+ class Address(BaseModel):
87
+ street: str
88
+
89
+ class User(BaseModel):
90
+ id: int
91
+ name: str
92
+ nickname: str | None = None
93
+ address: Address
94
+ ```
95
+
96
+ **2) Discover models**
97
+
98
+ ```bash
99
+ pfg list ./models.py
100
+ # outputs:
101
+ # models.User
102
+ # models.Address
103
+ ```
104
+
105
+ **3) Generate JSON samples**
106
+
107
+ ```bash
108
+ pfg gen json ./models.py --include models.User --n 2 --indent 2 --out ./out/User
109
+ # writes out/User.json with a metadata header comment when indenting
110
+
111
+ > **Note:** When a module declares more than one model, `--include` narrows generation to the desired `module.Model`.
112
+ ```
113
+
114
+ Example file (excerpt):
115
+
116
+ ```json
117
+ /* seed=42 version=1.0.0 digest=<sha256> */
118
+ [
119
+ {
120
+ "id": 1,
121
+ "name": "Alice",
122
+ "nickname": null,
123
+ "address": { "street": "42 Main St" }
124
+ },
125
+ {
126
+ "id": 2,
127
+ "name": "Bob",
128
+ "nickname": "b",
129
+ "address": { "street": "1 Side Rd" }
130
+ }
131
+ ]
132
+ ```
133
+
134
+ **4) Generate pytest fixtures**
135
+
136
+ ```bash
137
+ pfg gen fixtures ./models.py \
138
+ --out tests/fixtures/test_user_fixtures.py \
139
+ --style functions --scope module --cases 3 --return-type model
140
+ # produces a module with a banner and deduped imports, formatted by Ruff/Black
141
+ ```
142
+
143
+ Fixture excerpt:
144
+
145
+ ```python
146
+ # pydantic-fixturegen v1.0.0 seed=42 digest=<sha256>
147
+ import pytest
148
+ from models import User, Address
149
+
150
+ @pytest.fixture(scope="module", params=[0,1,2], ids=lambda i: f"user_case_{i}")
151
+ def user(request) -> User:
152
+ # deterministic across runs/machines
153
+ ...
154
+ ```
155
+
156
+ ---
157
+
158
+ ## Configuration precedence (configuration-precedence)
159
+
160
+ ```toml
161
+ # pyproject.toml
162
+ [tool.pydantic_fixturegen]
163
+ seed = 42
164
+ locale = "en_US"
165
+ union_policy = "weighted"
166
+ enum_policy = "random"
167
+ emitters.json.indent = 2
168
+ emitters.json.orjson = false
169
+ fixtures.style = "functions"
170
+ fixtures.scope = "module"
171
+ ```
172
+
173
+ Environment variables mirror keys using `PFG_` (e.g., `PFG_SEED=99`). **CLI flags override everything**.
174
+
175
+ ---
176
+
177
+ ## CLI overview (cli)
178
+
179
+ - `pfg list <module_or_path>` — enumerate models (AST and/or sandboxed import).
180
+ - `pfg gen json <target>` — deterministic JSON/JSONL (`--n`, `--jsonl`, `--indent`, `--orjson/--no-orjson`, `--shard-size`, `--out`, `--seed`).
181
+ - `pfg gen schema <target>` — emit JSON Schema (`--out` required; atomic writes; `--json-errors`).
182
+ - `pfg gen fixtures <target>` — emit pytest fixtures (`--style {functions,factory,class}`, `--scope {function,module,session}`, `--p-none`, `--cases`, `--return-type {model,dict}`).
183
+ - `pfg gen explain <target>` — print provider/strategy tree per field; optional `--json` if exposed.
184
+ - `pfg doctor <target>` — audit coverage, constraints, risky imports (`--fail-on-warn`, `--json-errors`).
185
+
186
+ ---
187
+
188
+ ## Architecture in one diagram (architecture)
189
+
190
+ ```
191
+ Models → Discovery (AST ⟷ Safe-Import Sandbox) → Strategies (policies + hooks)
192
+ → ProviderRegistry (built-ins + plugins) → Instance Builder
193
+ → Emitters (JSON | Fixtures | Schema, atomic IO, worker pools)
194
+ → Artifacts on disk (with seed/version/digest metadata)
195
+ ```
196
+
197
+ **Sandbox guards**: sockets blocked; env scrubbed (`NO_PROXY=*`, proxies cleared, `PYTHONSAFEPATH=1`); HOME/tmp redirected; writes outside workdir denied; memory caps (`RLIMIT_AS`, `RLIMIT_DATA`); **timeout exit code 40**.
198
+
199
+ ---
200
+
201
+ ## Comparison: pydantic-fixturegen vs alternatives (comparison)
202
+
203
+ | Use Case | Learning Curve | Determinism | Security Controls | Best Fit |
204
+ | ------------------------------------- | -------------- | -------------------------------------------------- | --------------------------------------- | -------------------------------------------------------------------- |
205
+ | **pydantic-fixturegen** | Low | Strong, cascaded seeds across `random`/Faker/NumPy | Sandbox, atomic IO, JSON error taxonomy | Teams needing **deterministic Pydantic fixtures** and CLI automation |
206
+ | Hand-written fixtures | Medium–High | Depends on reviewer discipline | None by default | Small codebases with few models |
207
+ | Factory libraries (e.g., factory_boy) | Medium | Often stochastic unless manually seeded | Varies, not sandboxed | App-level object factories where ORM integration is key |
208
+ | `hypothesis.extra.pydantic` | Medium–High | Property-based, not fixed by default | Not sandboxed | Generative testing exploring model spaces |
209
+
210
+ ---
211
+
212
+ ## Community & support (community)
213
+
214
+ - Issues and contributions are welcome. Open an issue for bugs or feature discussions, and submit PRs with tests and docs.
215
+ - Security posture includes a sandbox and atomic writes; please report any bypass findings responsibly.
216
+
217
+ ---
218
+
219
+ ## License (license)
220
+
221
+ MIT. See `LICENSE`.
222
+
223
+ ---
224
+
225
+ ## Next steps (next-steps)
226
+
227
+ - Start with the **[Quickstart](./docs/quickstart.md)**.
228
+ - Dive deeper with the **[Cookbook](./docs/cookbook.md)**.