fixtureforge 2.2.0__tar.gz → 2.3.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.
- fixtureforge-2.3.0/PKG-INFO +455 -0
- fixtureforge-2.3.0/README.md +417 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/pyproject.toml +6 -3
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/__init__.py +422 -424
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/core/batch_engine.py +23 -3
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/core/exporter.py +5 -5
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/core/generator.py +111 -3
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/core/router.py +3 -2
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/core/swarm.py +144 -139
- fixtureforge-2.3.0/src/fixtureforge/enterprise/__init__.py +60 -0
- fixtureforge-2.3.0/src/fixtureforge/enterprise/airgap.py +196 -0
- fixtureforge-2.3.0/src/fixtureforge/enterprise/forge_enterprise.py +251 -0
- fixtureforge-2.3.0/src/fixtureforge/enterprise/provenance.py +182 -0
- fixtureforge-2.3.0/src/fixtureforge/enterprise/tenancy.py +148 -0
- fixtureforge-2.3.0/src/fixtureforge/mcp_server.py +310 -0
- fixtureforge-2.2.0/PKG-INFO +0 -433
- fixtureforge-2.2.0/README.md +0 -399
- fixtureforge-2.2.0/src/fixtureforge/pyproject.toml +0 -15
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/LICENSE +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/ai/__init__.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/ai/_audit_log.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/ai/_groq_client.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/ai/cache.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/ai/engine.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/ai/failure_analyzer.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/ai/prompts.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/ai/semantic_assert.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/cli/__init__.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/cli/commands.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/config/__init__.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/config/flags.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/core/__init__.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/core/analyzer.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/core/compression.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/core/dataset.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/core/parser.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/core/recipe.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/core/streamer.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/integrations/__init__.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/integrations/github.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/integrations/jira.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/library/__init__.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/library/sharing.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/library/storage.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/memory/__init__.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/memory/dream.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/memory/store.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/providers/__init__.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/providers/anthropic.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/providers/base.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/providers/factory.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/providers/gemini.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/providers/groq.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/providers/ollama.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/providers/openai.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/pytest_plugin.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/security/__init__.py +0 -0
- {fixtureforge-2.2.0 → fixtureforge-2.3.0}/src/fixtureforge/security/permissions.py +0 -0
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fixtureforge
|
|
3
|
+
Version: 2.3.0
|
|
4
|
+
Summary: Agentic Test Data Harness: memory, multi-agent swarms, permission gates, coverage analysis. Provider-agnostic (Gemini, OpenAI, Anthropic, Ollama).
|
|
5
|
+
License: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Keywords: pytest,fixtures,test-data,pydantic,faker,factory,ai,testing,mock-data,qa,automation,synthetic-data,llm,test-fixtures,fixture-generator
|
|
8
|
+
Author: Yaniv Metuku
|
|
9
|
+
Requires-Python: >=3.11,<4.0
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
17
|
+
Provides-Extra: all
|
|
18
|
+
Provides-Extra: anthropic
|
|
19
|
+
Provides-Extra: gemini
|
|
20
|
+
Provides-Extra: mcp
|
|
21
|
+
Provides-Extra: openai
|
|
22
|
+
Provides-Extra: sql
|
|
23
|
+
Requires-Dist: anthropic (>=0.18.0,<0.19.0) ; extra == "anthropic" or extra == "all"
|
|
24
|
+
Requires-Dist: click (>=8.1.0,<9.0.0)
|
|
25
|
+
Requires-Dist: faker (>=22.0.0,<23.0.0)
|
|
26
|
+
Requires-Dist: google-genai (>=1.0.0,<2.0.0) ; extra == "gemini" or extra == "all"
|
|
27
|
+
Requires-Dist: mcp (>=2.0.0,<3.0.0) ; extra == "mcp" or extra == "all"
|
|
28
|
+
Requires-Dist: openai (>=1.0.0,<2.0.0) ; extra == "openai" or extra == "all"
|
|
29
|
+
Requires-Dist: pydantic (>=2.5.0,<3.0.0)
|
|
30
|
+
Requires-Dist: pyyaml (>=6.0,<7.0)
|
|
31
|
+
Requires-Dist: requests (>=2.31.0,<3.0.0)
|
|
32
|
+
Requires-Dist: rich (>=13.7.0,<14.0.0)
|
|
33
|
+
Requires-Dist: sqlalchemy (>=2.0.0,<3.0.0) ; extra == "sql" or extra == "all"
|
|
34
|
+
Project-URL: Homepage, https://fixtureforge.dev
|
|
35
|
+
Project-URL: Repository, https://github.com/Yaniv2809/fixtureforge
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
|
|
38
|
+
<p align="center">
|
|
39
|
+
<img src="fixtureforge-logo.png" alt="FixtureForge" width="360"/>
|
|
40
|
+
</p>
|
|
41
|
+
|
|
42
|
+
<h1 align="center">FixtureForge</h1>
|
|
43
|
+
<p align="center"><b>Agentic test data harness for Python — deterministic in CI, AI-powered in dev.</b></p>
|
|
44
|
+
|
|
45
|
+
<p align="center">
|
|
46
|
+
<a href="https://pypi.org/project/fixtureforge/"><img src="https://img.shields.io/pypi/v/fixtureforge.svg" alt="PyPI version"/></a>
|
|
47
|
+
<a href="https://pypi.org/project/fixtureforge/"><img src="https://img.shields.io/pypi/dm/fixtureforge.svg" alt="Downloads"/></a>
|
|
48
|
+
<a href="https://www.python.org/"><img src="https://img.shields.io/badge/python-3.11%2B-blue.svg" alt="Python 3.11+"/></a>
|
|
49
|
+
<a href="https://pypi.org/project/fixtureforge/"><img src="https://img.shields.io/badge/pytest-plugin-orange.svg" alt="pytest plugin"/></a>
|
|
50
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-green.svg" alt="MIT License"/></a>
|
|
51
|
+
</p>
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## The problem with test data today
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
# ❌ Everyone does this. It's brittle and misses real-world edge cases.
|
|
59
|
+
user = User(name="Test User", email="test@test.com", bio="Lorem ipsum...")
|
|
60
|
+
|
|
61
|
+
# ❌ factory_boy is great — but it's static. No surprises, no edge cases.
|
|
62
|
+
UserFactory.create(role="admin")
|
|
63
|
+
|
|
64
|
+
# ❌ Writing 500 of them by hand? Not happening.
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Hardcoded fixtures rot. AI-generated fixtures are unpredictable in CI.
|
|
68
|
+
**FixtureForge solves both** — same codebase, two behaviors:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
Dev mode → AI generates rich, realistic, edge-case-aware fixtures
|
|
72
|
+
CI mode → same fixtures, frozen with seed=42, 100% reproducible
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Quickstart
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install fixtureforge
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from fixtureforge import Forge
|
|
85
|
+
from pydantic import BaseModel
|
|
86
|
+
|
|
87
|
+
class User(BaseModel):
|
|
88
|
+
id: int
|
|
89
|
+
name: str
|
|
90
|
+
email: str
|
|
91
|
+
bio: str
|
|
92
|
+
|
|
93
|
+
forge = Forge() # auto-detects AI provider from env vars
|
|
94
|
+
users = forge.create_batch(User, count=50, context="SaaS platform users")
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
FixtureForge routes each field to the cheapest generator automatically:
|
|
98
|
+
|
|
99
|
+
- **`id`** → sequential counter *(free)*
|
|
100
|
+
- **`name`, `email`** → Faker *(free)*
|
|
101
|
+
- **`bio`** → single batched AI call for all 50 records *(1 API call, not 50)*
|
|
102
|
+
|
|
103
|
+
**No AI key? No problem.** Pure Faker mode works out of the box:
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
forge = Forge(use_ai=False, seed=42) # deterministic, zero network, CI-safe
|
|
107
|
+
users = forge.create_batch(User, count=500)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Intelligent Field Routing
|
|
113
|
+
|
|
114
|
+
Every field is classified into a tier. Only semantic fields hit the AI:
|
|
115
|
+
|
|
116
|
+
| Tier | Fields | Generator | Cost |
|
|
117
|
+
|------|--------|-----------|------|
|
|
118
|
+
| **Structural** | `id`, `user_id`, `order_id` | Counters + FK registry | Free |
|
|
119
|
+
| **Standard** | `name`, `email`, `phone`, `address` | Faker | Free |
|
|
120
|
+
| **Computed** | `@computed_field` | Pydantic | Free |
|
|
121
|
+
| **Semantic** | `bio`, `description`, `review`, `message` | LLM (batched) | API tokens |
|
|
122
|
+
|
|
123
|
+
100 users with 2 semantic fields = **2 API calls**, not 200.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## CI/CD — zero config changes between environments
|
|
128
|
+
|
|
129
|
+
```yaml
|
|
130
|
+
# .github/workflows/test.yml
|
|
131
|
+
- name: Run tests
|
|
132
|
+
env:
|
|
133
|
+
FORGE_SEED: 42 # identical output every run
|
|
134
|
+
# No AI key needed — FixtureForge auto-detects and falls back to Faker
|
|
135
|
+
run: pytest
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
In dev, export any provider key and AI kicks in automatically:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
export ANTHROPIC_API_KEY=sk-ant-... # → Claude
|
|
142
|
+
export OPENAI_API_KEY=sk-... # → GPT
|
|
143
|
+
export GOOGLE_API_KEY=... # → Gemini
|
|
144
|
+
export GROQ_API_KEY=... # → Groq (fast + cheap)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Foreign Key Relationships — automatic
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
# Step 1: generate customers
|
|
153
|
+
customers = forge.create_batch(Customer, count=10)
|
|
154
|
+
|
|
155
|
+
# Step 2: Order.customer_id auto-resolves to a real customer.id
|
|
156
|
+
orders = forge.create_batch(Order, count=100)
|
|
157
|
+
# → every order.customer_id is valid. No manual wiring.
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## DataSwarms — bulk generation, shared cache
|
|
163
|
+
|
|
164
|
+
Generate multiple models in parallel. The first model warms the AI cache;
|
|
165
|
+
every subsequent model inherits it — **~90% cheaper per additional model**.
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
results = forge.swarm(
|
|
169
|
+
models=[User, Order, Product, Payment],
|
|
170
|
+
counts=[10, 50, 100, 30],
|
|
171
|
+
contexts=["SaaS users", "E-commerce orders", None, None],
|
|
172
|
+
)
|
|
173
|
+
# {
|
|
174
|
+
# "User": [...10 users...],
|
|
175
|
+
# "Order": [...50 orders...],
|
|
176
|
+
# "Product": [...100 products...],
|
|
177
|
+
# "Payment": [...30 payments...],
|
|
178
|
+
# }
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
5 models ≈ cost of 1.5 models.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## ForgeMemory — fixtures that remember your domain
|
|
186
|
+
|
|
187
|
+
```python
|
|
188
|
+
forge.memory.add_rule("financial", "Users under 18 get restricted account type")
|
|
189
|
+
forge.memory.add_rule("user", "Israeli phone numbers use format 05x-xxx-xxxx")
|
|
190
|
+
forge.memory.add_rule("orders", "Max 3 active loans per customer at any time")
|
|
191
|
+
|
|
192
|
+
# Rules inject into AI prompts automatically on every generation call
|
|
193
|
+
users = forge.create_batch(User, count=50, context="Israeli SaaS platform")
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Rules survive across sessions. Update a rule — next call respects it immediately.
|
|
197
|
+
**Skeptical Memory** validates stored rules against the live schema before every call.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## pytest plugin — one line per fixture
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
# conftest.py
|
|
205
|
+
from fixtureforge.pytest_plugin import forge_fixture, forge_swarm_fixture
|
|
206
|
+
from pydantic import BaseModel
|
|
207
|
+
|
|
208
|
+
class User(BaseModel):
|
|
209
|
+
id: int; name: str; email: str
|
|
210
|
+
|
|
211
|
+
forge_fixture(User, count=10, seed=42) # → fixture: "users"
|
|
212
|
+
forge_swarm_fixture([User, Order], counts=[5, 20], seed=42) # → "swarm_data"
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
# test_users.py
|
|
217
|
+
def test_signup(users):
|
|
218
|
+
for user in users:
|
|
219
|
+
assert "@" in user.email
|
|
220
|
+
|
|
221
|
+
def test_full_flow(swarm_data):
|
|
222
|
+
users = swarm_data["User"]
|
|
223
|
+
orders = swarm_data["Order"]
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
The `forge` fixture is auto-available in every test with zero config.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Multi-provider support
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
# Be explicit
|
|
234
|
+
forge = Forge(provider_name="anthropic", model="claude-haiku-4-5-20251001")
|
|
235
|
+
forge = Forge(provider_name="openai", model="gpt-4o-mini")
|
|
236
|
+
forge = Forge(provider_name="gemini", model="gemini-2.0-flash")
|
|
237
|
+
forge = Forge(provider_name="groq", model="llama-3.3-70b-versatile")
|
|
238
|
+
forge = Forge(provider_name="ollama", model="llama3.2") # local, zero cost
|
|
239
|
+
forge = Forge(use_ai=False) # pure Faker
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Large datasets — constant AI cost regardless of count
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
# Seed + Interpolation: generates ~1 000 unique AI values, tiles to 100 000
|
|
248
|
+
dataset = forge.create_large(Order, count=100_000, seed_ratio=0.01)
|
|
249
|
+
|
|
250
|
+
# Streaming — one record at a time, never loads all into memory
|
|
251
|
+
for user in forge.create_stream(User, count=1_000_000, filename="users.json"):
|
|
252
|
+
process(user)
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Export
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
from fixtureforge.core.exporter import DataExporter
|
|
261
|
+
|
|
262
|
+
users = forge.create_batch(User, count=100)
|
|
263
|
+
DataExporter.export(users, "users.json") # format inferred from extension
|
|
264
|
+
DataExporter.export(users, "users.csv")
|
|
265
|
+
DataExporter.export(users, "users.sql")
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## FixtureForge vs alternatives
|
|
271
|
+
|
|
272
|
+
| | FixtureForge | factory\_boy | Faker | hypothesis |
|
|
273
|
+
|--|:--:|:--:|:--:|:--:|
|
|
274
|
+
| AI-powered context | ✅ | ❌ | ❌ | ❌ |
|
|
275
|
+
| Deterministic (seed=) | ✅ | ✅ | ✅ | ✅ |
|
|
276
|
+
| FK relationships | **Auto** | Manual | ❌ | ❌ |
|
|
277
|
+
| Batched AI calls | ✅ | ❌ | ❌ | ❌ |
|
|
278
|
+
| Coverage gap analysis | ✅ | ❌ | ❌ | Partial |
|
|
279
|
+
| Large datasets (100k+) | ✅ | Manual | Manual | ❌ |
|
|
280
|
+
| pytest plugin | ✅ | ❌ | ❌ | ❌ |
|
|
281
|
+
| Multi-LLM support | ✅ | ❌ | ❌ | ❌ |
|
|
282
|
+
| Permission gates | ✅ | ❌ | ❌ | ❌ |
|
|
283
|
+
| CI-safe (zero network) | ✅ | ✅ | ✅ | ✅ |
|
|
284
|
+
|
|
285
|
+
FixtureForge is not a replacement for Faker — it uses Faker internally for standard fields.
|
|
286
|
+
It adds the layer between *"I need realistic data"* and *"I need it to feel like production."*
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Installation
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
# Core (deterministic mode, no AI)
|
|
294
|
+
pip install fixtureforge
|
|
295
|
+
|
|
296
|
+
# With your preferred provider
|
|
297
|
+
pip install "fixtureforge[anthropic]" # Claude
|
|
298
|
+
pip install "fixtureforge[openai]" # GPT
|
|
299
|
+
pip install "fixtureforge[gemini]" # Gemini
|
|
300
|
+
pip install "fixtureforge[all]" # All providers
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**Requirements:** Python 3.11+ · pydantic ≥ 2.5 · faker ≥ 22.0
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Enterprise Edition
|
|
308
|
+
|
|
309
|
+
For teams with compliance requirements — GDPR, SOC2, HIPAA, multi-tenant SaaS:
|
|
310
|
+
|
|
311
|
+
| | Community | Enterprise |
|
|
312
|
+
|--|:--:|:--:|
|
|
313
|
+
| AI generation + Faker | ✅ | ✅ |
|
|
314
|
+
| pytest plugin | ✅ | ✅ |
|
|
315
|
+
| Deterministic seeding | ✅ | ✅ |
|
|
316
|
+
| **Cryptographic Provenance Envelope** | ❌ | ✅ |
|
|
317
|
+
| **PII Airgap — fail-closed scanner** | ❌ | ✅ |
|
|
318
|
+
| **Contextual Tenant Enclaves** | ❌ | ✅ |
|
|
319
|
+
| **Cross-tenant FK violation detection** | ❌ | ✅ |
|
|
320
|
+
| **Presidio / custom scanner support** | ❌ | ✅ |
|
|
321
|
+
|
|
322
|
+
```python
|
|
323
|
+
from fixtureforge.enterprise import ForgeEnterprise
|
|
324
|
+
|
|
325
|
+
forge = ForgeEnterprise(use_ai=False)
|
|
326
|
+
users = forge.create_batch(User, count=10)
|
|
327
|
+
|
|
328
|
+
users[0].model_dump()
|
|
329
|
+
# { "id": 1, "name": "...", "bio": "...",
|
|
330
|
+
# "forge_metadata": {
|
|
331
|
+
# "forge_id": "abc-123",
|
|
332
|
+
# "provenance_hash": "sha256:029773ed...", ← immutable audit stamp
|
|
333
|
+
# "tenant_id": "tenant-acme",
|
|
334
|
+
# "source": "faker",
|
|
335
|
+
# ...
|
|
336
|
+
# }
|
|
337
|
+
# }
|
|
338
|
+
|
|
339
|
+
with forge.isolate_tenant("tenant-acme"):
|
|
340
|
+
acme_users = forge.create_batch(User, count=5)
|
|
341
|
+
# FK references from tenant-acme can NEVER resolve to tenant-xyz records
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
**Access:** [yaniv2809@gmail.com](mailto:yaniv2809@gmail.com)
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## Project status
|
|
349
|
+
|
|
350
|
+
| Component | Status |
|
|
351
|
+
|-----------|--------|
|
|
352
|
+
| Core (`Forge`, `create_batch`) | ✅ Stable |
|
|
353
|
+
| DataSwarms | ✅ Stable |
|
|
354
|
+
| ForgeMemory | ✅ Stable |
|
|
355
|
+
| pytest plugin | ✅ v2.2.0 |
|
|
356
|
+
| Anthropic / OpenAI / Gemini / Groq / Ollama | ✅ |
|
|
357
|
+
| Literal / Enum / date / datetime / UUID / Decimal | ✅ v2.2.0 |
|
|
358
|
+
| MCP Server (`fixtureforge-mcp`) | ✅ v2.3.0 |
|
|
359
|
+
| `assert_semantic_match` | ✅ v2.2.0 |
|
|
360
|
+
| `SmartFailureAnalyzer` | ✅ v2.2.0 |
|
|
361
|
+
| Enterprise Edition | ✅ (access by request) |
|
|
362
|
+
| ForgeDream (coverage analysis) | 🔜 Feature-flagged |
|
|
363
|
+
| Async support | 🔜 Planned |
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## Links
|
|
368
|
+
|
|
369
|
+
- **Docs**: https://yaniv2809.github.io/fixtureforge/
|
|
370
|
+
- **PyPI**: https://pypi.org/project/fixtureforge/
|
|
371
|
+
- **Repository**: https://github.com/Yaniv2809/fixtureforge
|
|
372
|
+
- **Issues**: https://github.com/Yaniv2809/fixtureforge/issues
|
|
373
|
+
- **Discussion**: https://github.com/Yaniv2809/fixtureforge/discussions/1
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## MCP Server — use FixtureForge inside Claude Desktop / any MCP client
|
|
378
|
+
|
|
379
|
+
FixtureForge ships a built-in MCP server so Claude Desktop and other MCP-capable
|
|
380
|
+
AI tools can generate test data directly in a conversation.
|
|
381
|
+
|
|
382
|
+
### Install
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
pip install "fixtureforge[mcp]"
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### Add to Claude Desktop (`claude_desktop_config.json`)
|
|
389
|
+
|
|
390
|
+
```json
|
|
391
|
+
{
|
|
392
|
+
"mcpServers": {
|
|
393
|
+
"fixtureforge": {
|
|
394
|
+
"command": "fixtureforge-mcp"
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Restart Claude Desktop — FixtureForge appears in the tool list automatically.
|
|
401
|
+
|
|
402
|
+
### Available tools
|
|
403
|
+
|
|
404
|
+
| Tool | What it does |
|
|
405
|
+
|------|-------------|
|
|
406
|
+
| `generate` | Generate N records for a model described by `{field: type}` |
|
|
407
|
+
| `swarm` | Generate multiple models in parallel with shared AI cache |
|
|
408
|
+
| `add_rule` | Persist a domain rule injected into every AI prompt |
|
|
409
|
+
| `export` | Generate records and save to `.json`, `.csv`, or `.sql` |
|
|
410
|
+
|
|
411
|
+
### Example prompt to Claude
|
|
412
|
+
|
|
413
|
+
> "Use fixtureforge to generate 20 User records with id, name, email and bio fields,
|
|
414
|
+
> then export them to users.json"
|
|
415
|
+
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
## Use with AI coding agents
|
|
419
|
+
|
|
420
|
+
FixtureForge ships an official agent skill so AI coding assistants (Claude Code,
|
|
421
|
+
Cursor, GitHub Copilot, Devin, etc.) know exactly how to use the library.
|
|
422
|
+
|
|
423
|
+
The skill lives at [`skills/fixtureforge/SKILL.md`](skills/fixtureforge/SKILL.md)
|
|
424
|
+
and covers: when to use FixtureForge, install & setup, core API, CI determinism,
|
|
425
|
+
FK wiring, pytest plugin, common mistakes, and provider names.
|
|
426
|
+
|
|
427
|
+
Agents working in a repo that uses FixtureForge will automatically pick up the
|
|
428
|
+
skill and avoid the most common mistakes (hardcoded generators, manual FK wiring,
|
|
429
|
+
`use_ai=True` in CI).
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## Contributing
|
|
434
|
+
|
|
435
|
+
Issues and PRs welcome.
|
|
436
|
+
|
|
437
|
+
```bash
|
|
438
|
+
git clone https://github.com/Yaniv2809/fixtureforge
|
|
439
|
+
cd fixtureforge
|
|
440
|
+
pip install -e ".[dev]"
|
|
441
|
+
PYTHONPATH=src python -m pytest tests/
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## License
|
|
447
|
+
|
|
448
|
+
MIT © [Yaniv2809](https://github.com/Yaniv2809)
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
<p align="center">
|
|
453
|
+
<b>If FixtureForge saved you time, give it a ⭐ — it helps others find it.</b>
|
|
454
|
+
</p>
|
|
455
|
+
|