pydantic-marshmallow 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.
- pydantic_marshmallow-1.0.0/.github/instructions/Change_Size.instructions.md +41 -0
- pydantic_marshmallow-1.0.0/.github/instructions/Compatibility_Analysis.instructions.md +375 -0
- pydantic_marshmallow-1.0.0/.github/instructions/Coverage.instructions.md +121 -0
- pydantic_marshmallow-1.0.0/.github/instructions/Default.instructions.md +140 -0
- pydantic_marshmallow-1.0.0/.github/instructions/Git.instructions.md +85 -0
- pydantic_marshmallow-1.0.0/.github/instructions/Implementation.instructions.md +216 -0
- pydantic_marshmallow-1.0.0/.github/workflows/ci.yml +91 -0
- pydantic_marshmallow-1.0.0/.github/workflows/docs.yml +54 -0
- pydantic_marshmallow-1.0.0/.github/workflows/release.yml +88 -0
- pydantic_marshmallow-1.0.0/.gitignore +209 -0
- pydantic_marshmallow-1.0.0/.releaserc.json +37 -0
- pydantic_marshmallow-1.0.0/CAPABILITY_MATRIX.md +314 -0
- pydantic_marshmallow-1.0.0/LICENSE +21 -0
- pydantic_marshmallow-1.0.0/PKG-INFO +367 -0
- pydantic_marshmallow-1.0.0/README.md +309 -0
- pydantic_marshmallow-1.0.0/SECURITY.md +21 -0
- pydantic_marshmallow-1.0.0/benchmarks/__init__.py +22 -0
- pydantic_marshmallow-1.0.0/benchmarks/benchmark_framework.py +605 -0
- pydantic_marshmallow-1.0.0/benchmarks/run_benchmarks.py +834 -0
- pydantic_marshmallow-1.0.0/docs/api/errors.md +75 -0
- pydantic_marshmallow-1.0.0/docs/api/hybrid.md +90 -0
- pydantic_marshmallow-1.0.0/docs/api/index.md +33 -0
- pydantic_marshmallow-1.0.0/docs/api/schema.md +29 -0
- pydantic_marshmallow-1.0.0/docs/api/validators.md +77 -0
- pydantic_marshmallow-1.0.0/docs/changelog.md +37 -0
- pydantic_marshmallow-1.0.0/docs/examples.md +204 -0
- pydantic_marshmallow-1.0.0/docs/getting-started/installation.md +43 -0
- pydantic_marshmallow-1.0.0/docs/getting-started/quickstart.md +103 -0
- pydantic_marshmallow-1.0.0/docs/guide/basic-usage.md +144 -0
- pydantic_marshmallow-1.0.0/docs/guide/ecosystem.md +180 -0
- pydantic_marshmallow-1.0.0/docs/guide/field-options.md +138 -0
- pydantic_marshmallow-1.0.0/docs/guide/hooks.md +186 -0
- pydantic_marshmallow-1.0.0/docs/guide/nested-models.md +144 -0
- pydantic_marshmallow-1.0.0/docs/index.md +53 -0
- pydantic_marshmallow-1.0.0/examples/usage.py +250 -0
- pydantic_marshmallow-1.0.0/mkdocs.yml +84 -0
- pydantic_marshmallow-1.0.0/pydantic-marshmallow.code-workspace +156 -0
- pydantic_marshmallow-1.0.0/pyproject.toml +262 -0
- pydantic_marshmallow-1.0.0/setup.cfg +4 -0
- pydantic_marshmallow-1.0.0/src/pydantic_marshmallow/__init__.py +79 -0
- pydantic_marshmallow-1.0.0/src/pydantic_marshmallow/bridge.py +1187 -0
- pydantic_marshmallow-1.0.0/src/pydantic_marshmallow/errors.py +154 -0
- pydantic_marshmallow-1.0.0/src/pydantic_marshmallow/field_conversion.py +137 -0
- pydantic_marshmallow-1.0.0/src/pydantic_marshmallow/py.typed +2 -0
- pydantic_marshmallow-1.0.0/src/pydantic_marshmallow/type_mapping.py +138 -0
- pydantic_marshmallow-1.0.0/src/pydantic_marshmallow/validators.py +207 -0
- pydantic_marshmallow-1.0.0/src/pydantic_marshmallow.egg-info/PKG-INFO +367 -0
- pydantic_marshmallow-1.0.0/src/pydantic_marshmallow.egg-info/SOURCES.txt +78 -0
- pydantic_marshmallow-1.0.0/src/pydantic_marshmallow.egg-info/dependency_links.txt +1 -0
- pydantic_marshmallow-1.0.0/src/pydantic_marshmallow.egg-info/requires.txt +33 -0
- pydantic_marshmallow-1.0.0/src/pydantic_marshmallow.egg-info/top_level.txt +1 -0
- pydantic_marshmallow-1.0.0/tests/__init__.py +1 -0
- pydantic_marshmallow-1.0.0/tests/compatibility/__init__.py +16 -0
- pydantic_marshmallow-1.0.0/tests/compatibility/test_apispec.py +540 -0
- pydantic_marshmallow-1.0.0/tests/compatibility/test_connexion.py +348 -0
- pydantic_marshmallow-1.0.0/tests/compatibility/test_flask_marshmallow.py +396 -0
- pydantic_marshmallow-1.0.0/tests/compatibility/test_flask_rebar.py +480 -0
- pydantic_marshmallow-1.0.0/tests/compatibility/test_flask_smorest.py +482 -0
- pydantic_marshmallow-1.0.0/tests/compatibility/test_marshmallow_dataclass.py +411 -0
- pydantic_marshmallow-1.0.0/tests/compatibility/test_oneofschema.py +387 -0
- pydantic_marshmallow-1.0.0/tests/compatibility/test_sqlalchemy.py +277 -0
- pydantic_marshmallow-1.0.0/tests/compatibility/test_webargs.py +477 -0
- pydantic_marshmallow-1.0.0/tests/conftest.py +387 -0
- pydantic_marshmallow-1.0.0/tests/test_advanced_hooks.py +392 -0
- pydantic_marshmallow-1.0.0/tests/test_bridge.py +377 -0
- pydantic_marshmallow-1.0.0/tests/test_combinations.py +1118 -0
- pydantic_marshmallow-1.0.0/tests/test_compatibility.py +379 -0
- pydantic_marshmallow-1.0.0/tests/test_computed_fields.py +216 -0
- pydantic_marshmallow-1.0.0/tests/test_dump_options.py +293 -0
- pydantic_marshmallow-1.0.0/tests/test_edge_cases.py +630 -0
- pydantic_marshmallow-1.0.0/tests/test_error_handling.py +370 -0
- pydantic_marshmallow-1.0.0/tests/test_extended_coverage.py +615 -0
- pydantic_marshmallow-1.0.0/tests/test_extended_performance.py +525 -0
- pydantic_marshmallow-1.0.0/tests/test_hooks.py +409 -0
- pydantic_marshmallow-1.0.0/tests/test_partial_and_unknown.py +446 -0
- pydantic_marshmallow-1.0.0/tests/test_performance.py +429 -0
- pydantic_marshmallow-1.0.0/tests/test_return_instance.py +259 -0
- pydantic_marshmallow-1.0.0/tests/test_schema_parameters.py +455 -0
- pydantic_marshmallow-1.0.0/tests/test_validation.py +468 -0
- pydantic_marshmallow-1.0.0/uv.lock +2345 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: '**/*.py'
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Change Size Management
|
|
6
|
+
|
|
7
|
+
## PR Size Guidelines
|
|
8
|
+
|
|
9
|
+
| Size | Lines Changed | Guideline |
|
|
10
|
+
|:-----|:-------------:|:----------|
|
|
11
|
+
| Small | <200 | Preferred |
|
|
12
|
+
| Medium | 200-500 | Acceptable |
|
|
13
|
+
| Large | 500-1000 | Needs justification |
|
|
14
|
+
| Very Large | >1000 | Split into smaller PRs |
|
|
15
|
+
|
|
16
|
+
## Decomposition Strategy for This Project
|
|
17
|
+
|
|
18
|
+
### Type Mapping Changes
|
|
19
|
+
- **One PR per type category**: Add all `datetime` types together, all `collection` types together
|
|
20
|
+
- **Include tests inline**: Type mapping + tests in same PR
|
|
21
|
+
|
|
22
|
+
### Hook/Bridge Changes
|
|
23
|
+
- **Separate structural changes** from feature additions
|
|
24
|
+
- **Test file can be separate** if change is complex
|
|
25
|
+
|
|
26
|
+
### New Ecosystem Integration
|
|
27
|
+
- **Integration + tests in one PR**
|
|
28
|
+
- **docs/README update can be separate**
|
|
29
|
+
|
|
30
|
+
## When Large PRs Are OK
|
|
31
|
+
|
|
32
|
+
- Initial project setup/bootstrap
|
|
33
|
+
- Major internal refactoring (if intermediate states would break tests)
|
|
34
|
+
- Auto-generated code (migrations, type stubs)
|
|
35
|
+
- Documentation overhauls
|
|
36
|
+
|
|
37
|
+
## Review Considerations
|
|
38
|
+
|
|
39
|
+
- Each PR should have **focused tests** for its changes
|
|
40
|
+
- Smaller PRs = easier rollbacks if issues arise
|
|
41
|
+
- **Prefer multiple small PRs** over one large PR with unrelated changes
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
# Compatibility Analysis Instructions
|
|
2
|
+
|
|
3
|
+
This document provides systematic guidance for analyzing and validating compatibility when Marshmallow or Pydantic releases new features.
|
|
4
|
+
|
|
5
|
+
## When to Run Compatibility Analysis
|
|
6
|
+
|
|
7
|
+
1. **Marshmallow releases a new version** (check https://github.com/marshmallow-code/marshmallow/releases)
|
|
8
|
+
2. **Pydantic releases a new version** (check https://github.com/pydantic/pydantic/releases)
|
|
9
|
+
3. **Before any major release** of pydantic-marshmallow
|
|
10
|
+
4. **When adding new bridge features**
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Step 1: Gather Release Information
|
|
15
|
+
|
|
16
|
+
### For Marshmallow Updates
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Check current installed version
|
|
20
|
+
pip show marshmallow
|
|
21
|
+
|
|
22
|
+
# Check latest version
|
|
23
|
+
pip index versions marshmallow
|
|
24
|
+
|
|
25
|
+
# Review changelog
|
|
26
|
+
# https://marshmallow.readthedocs.io/en/stable/changelog.html
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Key areas to review:**
|
|
30
|
+
- New Schema methods or parameters
|
|
31
|
+
- New field types
|
|
32
|
+
- New Meta options
|
|
33
|
+
- Hook changes (pre_load, post_load, pre_dump, post_dump)
|
|
34
|
+
- Validation changes
|
|
35
|
+
- Error handling changes
|
|
36
|
+
- Deprecations
|
|
37
|
+
|
|
38
|
+
### For Pydantic Updates
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Check current installed version
|
|
42
|
+
pip show pydantic
|
|
43
|
+
|
|
44
|
+
# Check latest version
|
|
45
|
+
pip index versions pydantic
|
|
46
|
+
|
|
47
|
+
# Review changelog
|
|
48
|
+
# https://docs.pydantic.dev/latest/changelog/
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Key areas to review:**
|
|
52
|
+
- New ConfigDict options
|
|
53
|
+
- New Field() parameters
|
|
54
|
+
- New validator decorators or modes
|
|
55
|
+
- New type annotations
|
|
56
|
+
- Serialization changes (model_dump, model_dump_json)
|
|
57
|
+
- Validation changes (model_validate, model_validate_json)
|
|
58
|
+
- Error structure changes
|
|
59
|
+
- Deprecations
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Step 2: Update Capability Matrix
|
|
64
|
+
|
|
65
|
+
After reviewing changelogs, update the capability matrix below:
|
|
66
|
+
|
|
67
|
+
1. Add new features to the appropriate section
|
|
68
|
+
2. Mark initial status as ❌ (not yet supported)
|
|
69
|
+
3. Assess implementation complexity
|
|
70
|
+
4. Prioritize based on user impact
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Step 3: Write Compatibility Tests
|
|
75
|
+
|
|
76
|
+
For each new feature, create tests in `tests/test_compatibility.py`:
|
|
77
|
+
|
|
78
|
+
### Test Template
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
class TestMarshmallow_X_Y_Features:
|
|
82
|
+
"""Tests for Marshmallow X.Y new features."""
|
|
83
|
+
|
|
84
|
+
def test_new_feature_name(self):
|
|
85
|
+
"""Test [feature description].
|
|
86
|
+
|
|
87
|
+
Added in: Marshmallow X.Y
|
|
88
|
+
Docs: [URL]
|
|
89
|
+
"""
|
|
90
|
+
# Arrange
|
|
91
|
+
class TestModel(BaseModel):
|
|
92
|
+
field: str
|
|
93
|
+
|
|
94
|
+
schema = schema_for(TestModel)()
|
|
95
|
+
|
|
96
|
+
# Act
|
|
97
|
+
result = schema.load({"field": "value"})
|
|
98
|
+
|
|
99
|
+
# Assert
|
|
100
|
+
assert result.field == "value"
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class TestPydantic_X_Y_Features:
|
|
104
|
+
"""Tests for Pydantic X.Y new features."""
|
|
105
|
+
|
|
106
|
+
def test_new_feature_name(self):
|
|
107
|
+
"""Test [feature description].
|
|
108
|
+
|
|
109
|
+
Added in: Pydantic X.Y
|
|
110
|
+
Docs: [URL]
|
|
111
|
+
"""
|
|
112
|
+
# Test implementation
|
|
113
|
+
pass
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Step 4: Run Full Test Suite
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Run all tests with verbose output
|
|
122
|
+
pytest tests/ -v --tb=long
|
|
123
|
+
|
|
124
|
+
# Run with coverage
|
|
125
|
+
pytest tests/ --cov=pydantic_marshmallow --cov-report=term-missing --cov-report=html
|
|
126
|
+
|
|
127
|
+
# Run specific compatibility tests
|
|
128
|
+
pytest tests/test_compatibility.py -v
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Step 5: Analyze Failures
|
|
134
|
+
|
|
135
|
+
### Failure Categories
|
|
136
|
+
|
|
137
|
+
1. **Breaking Change**: Existing functionality no longer works
|
|
138
|
+
- Priority: CRITICAL
|
|
139
|
+
- Action: Fix immediately before release
|
|
140
|
+
|
|
141
|
+
2. **New Feature Gap**: New upstream feature not supported
|
|
142
|
+
- Priority: Based on user impact
|
|
143
|
+
- Action: Add to backlog, implement as needed
|
|
144
|
+
|
|
145
|
+
3. **Deprecation Warning**: Using deprecated API
|
|
146
|
+
- Priority: MEDIUM
|
|
147
|
+
- Action: Update to new API before it's removed
|
|
148
|
+
|
|
149
|
+
4. **Behavioral Change**: Same API, different behavior
|
|
150
|
+
- Priority: HIGH
|
|
151
|
+
- Action: Document and adapt
|
|
152
|
+
|
|
153
|
+
### Failure Analysis Template
|
|
154
|
+
|
|
155
|
+
```markdown
|
|
156
|
+
## [Feature Name] - [Marshmallow/Pydantic] X.Y
|
|
157
|
+
|
|
158
|
+
**Status**: ❌ Failing / ⚠️ Warning / ✅ Passing
|
|
159
|
+
|
|
160
|
+
**Type**: Breaking Change / New Feature / Deprecation / Behavioral Change
|
|
161
|
+
|
|
162
|
+
**Description**:
|
|
163
|
+
[What changed and how it affects the bridge]
|
|
164
|
+
|
|
165
|
+
**Error Message**:
|
|
166
|
+
```
|
|
167
|
+
[Paste error]
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Root Cause**:
|
|
171
|
+
[Why this is happening]
|
|
172
|
+
|
|
173
|
+
**Fix Required**:
|
|
174
|
+
[What needs to change in bridge.py]
|
|
175
|
+
|
|
176
|
+
**Test**:
|
|
177
|
+
```python
|
|
178
|
+
def test_feature():
|
|
179
|
+
# Minimal reproduction
|
|
180
|
+
pass
|
|
181
|
+
```
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Step 6: Implement Fixes
|
|
187
|
+
|
|
188
|
+
### For Bridge Architecture Changes
|
|
189
|
+
|
|
190
|
+
Update `src/pydantic_marshmallow/bridge.py`:
|
|
191
|
+
|
|
192
|
+
1. **Hook ordering**: Modify `_do_load()` method
|
|
193
|
+
2. **New Meta options**: Update `PydanticSchema.Meta` class
|
|
194
|
+
3. **Field mapping**: Update `_type_to_marshmallow_field()` method
|
|
195
|
+
4. **Validation**: Update `_validate_with_pydantic()` method
|
|
196
|
+
5. **Serialization**: Update `dump()` method
|
|
197
|
+
|
|
198
|
+
### For New Feature Support
|
|
199
|
+
|
|
200
|
+
1. Add implementation to bridge.py or type_mapping.py
|
|
201
|
+
2. Add tests to appropriate test file
|
|
202
|
+
3. Update capability matrix status below to ✅
|
|
203
|
+
4. Update README.md if user-facing
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Step 7: Validate Ecosystem Compatibility
|
|
208
|
+
|
|
209
|
+
Test with ecosystem tools:
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
# tests/test_ecosystem.py
|
|
213
|
+
|
|
214
|
+
def test_flask_rebar_compatibility():
|
|
215
|
+
"""Verify flask-rebar still works."""
|
|
216
|
+
# Mock or real test
|
|
217
|
+
pass
|
|
218
|
+
|
|
219
|
+
def test_webargs_compatibility():
|
|
220
|
+
"""Verify webargs still works."""
|
|
221
|
+
pass
|
|
222
|
+
|
|
223
|
+
def test_apispec_compatibility():
|
|
224
|
+
"""Verify apispec still works."""
|
|
225
|
+
pass
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Step 8: Document Changes
|
|
231
|
+
|
|
232
|
+
### Update Files
|
|
233
|
+
|
|
234
|
+
1. **README.md**: Update if APIs changed
|
|
235
|
+
2. **This file**: Update capability matrix status
|
|
236
|
+
3. **pyproject.toml**: Update version and dependencies
|
|
237
|
+
|
|
238
|
+
### Release Notes
|
|
239
|
+
|
|
240
|
+
When releasing, create GitHub Release notes with:
|
|
241
|
+
- **Added**: New features and type support
|
|
242
|
+
- **Changed**: Minimum version requirements
|
|
243
|
+
- **Fixed**: Compatibility fixes
|
|
244
|
+
- **Deprecated**: Deprecated APIs (with migration path)
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Automated Compatibility Checks
|
|
249
|
+
|
|
250
|
+
### GitHub Actions Workflow
|
|
251
|
+
|
|
252
|
+
Create `.github/workflows/compatibility.yml`:
|
|
253
|
+
|
|
254
|
+
```yaml
|
|
255
|
+
name: Compatibility Check
|
|
256
|
+
|
|
257
|
+
on:
|
|
258
|
+
schedule:
|
|
259
|
+
- cron: '0 0 * * 1' # Weekly on Monday
|
|
260
|
+
workflow_dispatch:
|
|
261
|
+
|
|
262
|
+
jobs:
|
|
263
|
+
check-versions:
|
|
264
|
+
runs-on: ubuntu-latest
|
|
265
|
+
strategy:
|
|
266
|
+
matrix:
|
|
267
|
+
marshmallow: ['3.18', '3.19', '3.20', '3.21', 'latest']
|
|
268
|
+
pydantic: ['2.0', '2.5', '2.6', '2.7', 'latest']
|
|
269
|
+
|
|
270
|
+
steps:
|
|
271
|
+
- uses: actions/checkout@v4
|
|
272
|
+
|
|
273
|
+
- name: Set up Python
|
|
274
|
+
uses: actions/setup-python@v5
|
|
275
|
+
with:
|
|
276
|
+
python-version: '3.10'
|
|
277
|
+
|
|
278
|
+
- name: Install dependencies
|
|
279
|
+
run: |
|
|
280
|
+
pip install -e ".[dev]"
|
|
281
|
+
pip install "marshmallow==${{ matrix.marshmallow }}" "pydantic==${{ matrix.pydantic }}"
|
|
282
|
+
|
|
283
|
+
- name: Run tests
|
|
284
|
+
run: pytest tests/ -v
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Quick Reference: API Locations
|
|
290
|
+
|
|
291
|
+
### Marshmallow APIs We Use
|
|
292
|
+
|
|
293
|
+
| API | Location | Our Usage |
|
|
294
|
+
|:----|:---------|:----------|
|
|
295
|
+
| `Schema` | `marshmallow.Schema` | Base class |
|
|
296
|
+
| `fields.*` | `marshmallow.fields` | Field mapping |
|
|
297
|
+
| `pre_load` | `marshmallow.decorators` | Hook support |
|
|
298
|
+
| `post_load` | `marshmallow.decorators` | Hook support |
|
|
299
|
+
| `pre_dump` | `marshmallow.decorators` | Hook support |
|
|
300
|
+
| `post_dump` | `marshmallow.decorators` | Hook support |
|
|
301
|
+
| `ValidationError` | `marshmallow.exceptions` | Error handling |
|
|
302
|
+
| `RAISE/EXCLUDE/INCLUDE` | `marshmallow` | Unknown handling |
|
|
303
|
+
| `_invoke_load_processors` | `Schema` (internal) | Hook ordering |
|
|
304
|
+
| `_do_load` | `Schema` (internal) | Load override |
|
|
305
|
+
|
|
306
|
+
### Pydantic APIs We Use
|
|
307
|
+
|
|
308
|
+
| API | Location | Our Usage |
|
|
309
|
+
|:----|:---------|:----------|
|
|
310
|
+
| `BaseModel` | `pydantic` | Model class |
|
|
311
|
+
| `ConfigDict` | `pydantic` | Model config |
|
|
312
|
+
| `Field` | `pydantic` | Field options |
|
|
313
|
+
| `ValidationError` | `pydantic` | Error handling |
|
|
314
|
+
| `model_validate` | `BaseModel` | Validation |
|
|
315
|
+
| `model_dump` | `BaseModel` | Serialization |
|
|
316
|
+
| `model_fields` | `BaseModel` | Field introspection |
|
|
317
|
+
| `field_validator` | `pydantic` | Custom validation |
|
|
318
|
+
| `model_validator` | `pydantic` | Model validation |
|
|
319
|
+
| `PydanticUndefined` | `pydantic_core` | Default detection |
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## Version Compatibility Matrix
|
|
324
|
+
|
|
325
|
+
Update this when testing new versions:
|
|
326
|
+
|
|
327
|
+
| pydantic-marshmallow | Marshmallow | Pydantic | Python | Status |
|
|
328
|
+
|:---------------------|:------------|:---------|:-------|:------:|
|
|
329
|
+
| 0.1.x | 3.18+ | 2.0+ | 3.9-3.14 | ✅ |
|
|
330
|
+
|
|
331
|
+
**CI tests against:** Python 3.9, 3.10, 3.11, 3.12, 3.13, 3.14 on Ubuntu/Windows/macOS
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## Checklist for New Version Compatibility
|
|
336
|
+
|
|
337
|
+
- [ ] Review Marshmallow changelog
|
|
338
|
+
- [ ] Review Pydantic changelog
|
|
339
|
+
- [ ] Update [CAPABILITY_MATRIX.md](/CAPABILITY_MATRIX.md) with new features
|
|
340
|
+
- [ ] Write tests for new features
|
|
341
|
+
- [ ] Run full test suite
|
|
342
|
+
- [ ] Analyze and fix failures
|
|
343
|
+
- [ ] Test ecosystem tools
|
|
344
|
+
- [ ] Update documentation
|
|
345
|
+
- [ ] Update version constraints in pyproject.toml
|
|
346
|
+
- [ ] Create PR with changes
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Feature Capability Matrix
|
|
351
|
+
|
|
352
|
+
**See [CAPABILITY_MATRIX.md](/CAPABILITY_MATRIX.md) in the project root for the complete capability matrix.**
|
|
353
|
+
|
|
354
|
+
The matrix documents:
|
|
355
|
+
- All Marshmallow features → Bridge support status
|
|
356
|
+
- All Pydantic features → Available via bridge
|
|
357
|
+
- Type mappings (Pydantic → Marshmallow fields)
|
|
358
|
+
- Ecosystem tool compatibility
|
|
359
|
+
- Version compatibility
|
|
360
|
+
|
|
361
|
+
**Test Suite**: 375+ tests | **Tested Versions**: Marshmallow 3.x, Pydantic 2.x
|
|
362
|
+
|
|
363
|
+
### Quick Reference: Key Features
|
|
364
|
+
|
|
365
|
+
| Category | Status |
|
|
366
|
+
|:---------|:------:|
|
|
367
|
+
| Hook ordering (@pre_load → Pydantic → @post_load) | ✅ |
|
|
368
|
+
| All Marshmallow field types | ✅ |
|
|
369
|
+
| All Pydantic validators | ✅ |
|
|
370
|
+
| Partial loading | ✅ |
|
|
371
|
+
| Unknown field handling (RAISE/EXCLUDE/INCLUDE) | ✅ |
|
|
372
|
+
| Error format conversion | ✅ |
|
|
373
|
+
| Ecosystem tools (Flask-Rebar, webargs, apispec, etc.) | ✅ |
|
|
374
|
+
|
|
375
|
+
```
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: '**/*.py'
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Test Coverage Requirements
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Run tests with coverage
|
|
11
|
+
pytest tests/ --cov=pydantic_marshmallow --cov-report=term-missing
|
|
12
|
+
|
|
13
|
+
# Generate HTML report
|
|
14
|
+
pytest tests/ --cov=pydantic_marshmallow --cov-report=html
|
|
15
|
+
# Open htmlcov/index.html
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Coverage Targets
|
|
19
|
+
|
|
20
|
+
### Overall Coverage
|
|
21
|
+
- **Minimum**: All tests must pass
|
|
22
|
+
- **Target**: ≥90% line coverage for core bridge code
|
|
23
|
+
- PRs must not decrease overall coverage
|
|
24
|
+
|
|
25
|
+
### Per-Module Coverage
|
|
26
|
+
| Module | Target | Notes |
|
|
27
|
+
|:-------|:------:|:------|
|
|
28
|
+
| `bridge.py` | ≥90% | Core functionality, critical |
|
|
29
|
+
| `type_mapping.py` | ≥85% | Type conversion logic |
|
|
30
|
+
| `errors.py` | ≥80% | Error handling utilities |
|
|
31
|
+
| `validators.py` | ≥80% | Validator decorators |
|
|
32
|
+
|
|
33
|
+
### New Code Requirements
|
|
34
|
+
- **All new code must have tests** - no exceptions
|
|
35
|
+
- New type mappings require tests in `test_edge_cases.py`
|
|
36
|
+
- New hooks require tests in `test_hooks.py` or `test_advanced_hooks.py`
|
|
37
|
+
- Error paths require tests that trigger them
|
|
38
|
+
|
|
39
|
+
## Testing Patterns
|
|
40
|
+
|
|
41
|
+
### Schema Load/Dump Tests
|
|
42
|
+
```python
|
|
43
|
+
def test_feature_load(self):
|
|
44
|
+
"""Test loading with [feature]."""
|
|
45
|
+
class Model(BaseModel):
|
|
46
|
+
field: str
|
|
47
|
+
|
|
48
|
+
schema = schema_for(Model)()
|
|
49
|
+
result = schema.load({"field": "value"})
|
|
50
|
+
|
|
51
|
+
assert isinstance(result, Model)
|
|
52
|
+
assert result.field == "value"
|
|
53
|
+
|
|
54
|
+
def test_feature_dump(self):
|
|
55
|
+
"""Test dumping with [feature]."""
|
|
56
|
+
model = Model(field="value")
|
|
57
|
+
result = schema.dump(model)
|
|
58
|
+
|
|
59
|
+
assert result == {"field": "value"}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Validation Error Tests
|
|
63
|
+
```python
|
|
64
|
+
def test_validation_error(self):
|
|
65
|
+
"""Test validation error for [scenario]."""
|
|
66
|
+
schema = schema_for(Model)()
|
|
67
|
+
|
|
68
|
+
with pytest.raises(ValidationError) as exc:
|
|
69
|
+
schema.load({"field": "invalid"})
|
|
70
|
+
|
|
71
|
+
assert "field" in exc.value.messages
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Parameterized Tests
|
|
75
|
+
```python
|
|
76
|
+
@pytest.mark.parametrize("input_value,expected", [
|
|
77
|
+
("123", 123),
|
|
78
|
+
(123, 123),
|
|
79
|
+
("0", 0),
|
|
80
|
+
])
|
|
81
|
+
def test_type_coercion(self, input_value, expected):
|
|
82
|
+
"""Test type coercion for various inputs."""
|
|
83
|
+
result = schema.load({"value": input_value})
|
|
84
|
+
assert result.value == expected
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Test Organization
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
tests/
|
|
91
|
+
├── conftest.py # Shared fixtures (schemas, models)
|
|
92
|
+
├── test_bridge.py # Core schema load/dump tests
|
|
93
|
+
├── test_hooks.py # Marshmallow hook tests
|
|
94
|
+
├── test_advanced_hooks.py # Complex hook scenarios
|
|
95
|
+
├── test_validation.py # Pydantic validation constraints
|
|
96
|
+
├── test_edge_cases.py # Type edge cases
|
|
97
|
+
├── test_combinations.py # Feature combinations
|
|
98
|
+
├── test_error_handling.py # Error behavior tests
|
|
99
|
+
├── test_performance.py # Performance benchmarks
|
|
100
|
+
├── test_compatibility.py # Marshmallow/Pydantic version compatibility
|
|
101
|
+
├── test_computed_fields.py # Pydantic computed_field support
|
|
102
|
+
├── test_dump_options.py # Dump configuration tests
|
|
103
|
+
├── test_partial_and_unknown.py # Partial loading, unknown fields
|
|
104
|
+
└── test_sqlalchemy_integration.py # SQLAlchemy integration tests
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Running Tests
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# All tests
|
|
111
|
+
pytest tests/ -v
|
|
112
|
+
|
|
113
|
+
# Specific test file
|
|
114
|
+
pytest tests/test_bridge.py -v
|
|
115
|
+
|
|
116
|
+
# Specific test
|
|
117
|
+
pytest tests/test_bridge.py::TestPydanticSchemaBasic::test_from_model_basic -v
|
|
118
|
+
|
|
119
|
+
# With coverage for specific module
|
|
120
|
+
pytest tests/ --cov=pydantic_marshmallow.bridge --cov-report=term-missing
|
|
121
|
+
```
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: '**/*.py'
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# pydantic-marshmallow Development Guidelines
|
|
6
|
+
|
|
7
|
+
## Project Overview
|
|
8
|
+
|
|
9
|
+
This is a **pure Python library** that bridges Pydantic models with the Marshmallow ecosystem:
|
|
10
|
+
- **Input**: Pydantic models with validators
|
|
11
|
+
- **Output**: Marshmallow-compatible schemas
|
|
12
|
+
- **Value**: Use Pydantic's Rust-powered validation with Flask-Rebar, webargs, apispec, etc.
|
|
13
|
+
|
|
14
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Setup
|
|
18
|
+
python -m venv .venv
|
|
19
|
+
.venv\Scripts\activate # Windows
|
|
20
|
+
pip install -e ".[dev]"
|
|
21
|
+
|
|
22
|
+
# Test
|
|
23
|
+
pytest tests/ -v
|
|
24
|
+
|
|
25
|
+
# Type check
|
|
26
|
+
mypy src/
|
|
27
|
+
|
|
28
|
+
# Lint
|
|
29
|
+
ruff check src/ tests/
|
|
30
|
+
ruff format src/ tests/
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Pre-Commit Verification
|
|
34
|
+
|
|
35
|
+
**Before committing:** Run `pytest tests/ -v && mypy src/ && ruff check src/ tests/`
|
|
36
|
+
|
|
37
|
+
See [Git.instructions.md](Git.instructions.md) for full CI/CD workflow.
|
|
38
|
+
|
|
39
|
+
## Architecture
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
src/pydantic_marshmallow/
|
|
43
|
+
├── __init__.py # Public API exports
|
|
44
|
+
├── bridge.py # Core PydanticSchema, schema_for(), HybridModel
|
|
45
|
+
├── field_conversion.py # Advanced field conversion logic
|
|
46
|
+
├── type_mapping.py # Python types → Marshmallow fields
|
|
47
|
+
├── validators.py # Validator decorator utilities
|
|
48
|
+
└── errors.py # BridgeValidationError
|
|
49
|
+
|
|
50
|
+
tests/
|
|
51
|
+
├── conftest.py # Shared fixtures
|
|
52
|
+
├── test_bridge.py # Core schema tests
|
|
53
|
+
├── test_hooks.py # Marshmallow hook tests
|
|
54
|
+
├── test_validation.py # Validation constraint tests
|
|
55
|
+
├── test_compatibility.py # Version compatibility tests
|
|
56
|
+
└── test_*.py # Other test modules
|
|
57
|
+
|
|
58
|
+
benchmarks/
|
|
59
|
+
├── benchmark_framework.py # Statistical benchmarking utilities
|
|
60
|
+
├── run_benchmarks.py # CLI for running benchmarks
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Code Quality Standards
|
|
64
|
+
|
|
65
|
+
### Type Annotations
|
|
66
|
+
- **All** functions and methods must have type hints
|
|
67
|
+
- Use modern syntax: `list[str]` not `List[str]`, `str | None` not `Optional[str]`
|
|
68
|
+
- Use `from __future__ import annotations` for forward references
|
|
69
|
+
|
|
70
|
+
### Docstrings
|
|
71
|
+
Use Google-style docstrings:
|
|
72
|
+
```python
|
|
73
|
+
def function_name(param: str) -> bool:
|
|
74
|
+
"""Brief description.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
param: Description of parameter.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Description of return value.
|
|
81
|
+
|
|
82
|
+
Raises:
|
|
83
|
+
ValueError: When parameter is invalid.
|
|
84
|
+
"""
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Naming Conventions
|
|
88
|
+
- `snake_case` for functions, variables, module names
|
|
89
|
+
- `PascalCase` for class names
|
|
90
|
+
- `UPPER_CASE` for constants
|
|
91
|
+
- Prefix private methods with `_`
|
|
92
|
+
|
|
93
|
+
### Testing Requirements
|
|
94
|
+
- **All new code must have tests**
|
|
95
|
+
- Test both success and error cases
|
|
96
|
+
- Use `pytest.raises()` for exception testing
|
|
97
|
+
- Use parameterized tests for multiple similar cases
|
|
98
|
+
|
|
99
|
+
## Key Implementation Details
|
|
100
|
+
|
|
101
|
+
### Hook Ordering (Critical)
|
|
102
|
+
```
|
|
103
|
+
Input → @pre_load → PYDANTIC VALIDATES → @validates → @validates_schema → @post_load → Output
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### PydanticSchemaMeta
|
|
107
|
+
Custom metaclass that adds Pydantic fields BEFORE Marshmallow processes Meta.fields/exclude.
|
|
108
|
+
This ensures field filtering works correctly with dynamically generated fields.
|
|
109
|
+
|
|
110
|
+
### Error Handling
|
|
111
|
+
- Convert Pydantic ValidationError → Marshmallow ValidationError format
|
|
112
|
+
- Preserve field paths: `loc` tuple → dotted path (e.g., "items.0.name")
|
|
113
|
+
- Include `valid_data` for partial success scenarios
|
|
114
|
+
|
|
115
|
+
## Common Tasks
|
|
116
|
+
|
|
117
|
+
### Adding a New Pydantic Type Mapping
|
|
118
|
+
1. Edit `type_mapping.py`
|
|
119
|
+
2. Add case in `_type_to_marshmallow_field()`
|
|
120
|
+
3. Add test in `tests/test_edge_cases.py`
|
|
121
|
+
|
|
122
|
+
### Adding a New Marshmallow Hook
|
|
123
|
+
1. Ensure hook is called in `_do_load()` in `bridge.py`
|
|
124
|
+
2. Add test in `tests/test_hooks.py` or `tests/test_advanced_hooks.py`
|
|
125
|
+
|
|
126
|
+
### Adding Ecosystem Integration
|
|
127
|
+
1. Add test in `tests/test_compatibility.py` or create dedicated test file
|
|
128
|
+
2. Update README.md with usage example
|
|
129
|
+
3. Add optional dependency to `pyproject.toml` if needed
|
|
130
|
+
|
|
131
|
+
## Dependencies
|
|
132
|
+
|
|
133
|
+
**Runtime:**
|
|
134
|
+
- pydantic >= 2.0
|
|
135
|
+
- marshmallow >= 3.18
|
|
136
|
+
|
|
137
|
+
**Development:**
|
|
138
|
+
- pytest, pytest-cov
|
|
139
|
+
- mypy
|
|
140
|
+
- ruff
|