|
| 1 | +--- |
| 2 | +name: Model Refinement |
| 3 | +about: Refine generated models to eliminate more repetition and improve type accuracy |
| 4 | +title: 'Refine generated models: additional mixins and optional field review' |
| 5 | +labels: enhancement, models, code-generation |
| 6 | +assignees: '' |
| 7 | +--- |
| 8 | + |
| 9 | +## Overview |
| 10 | + |
| 11 | +While we've made significant improvements to the generated models (enums, mixins, snake_case, required fields), there are opportunities for further refinement. |
| 12 | + |
| 13 | +## Current State |
| 14 | + |
| 15 | +✅ **Completed:** |
| 16 | +- 22 enum types with 210 values |
| 17 | +- 18 field mixins (629 fields eliminated, 52.9% reduction) |
| 18 | +- 29 method mixins (~141 helper methods) |
| 19 | +- 894 required fields (64%) |
| 20 | +- 100% snake_case with aliases |
| 21 | +- Comprehensive validation |
| 22 | + |
| 23 | +## Areas for Further Refinement |
| 24 | + |
| 25 | +### 1. Additional Field Mixins |
| 26 | + |
| 27 | +Some repeated fields could potentially be moved to mixins: |
| 28 | + |
| 29 | +**Candidate fields for new mixins:** |
| 30 | +- `time` field (appears in 8 models) - could be `TimeFields` mixin |
| 31 | +- `id` field (appears in 5 models) - could be `IdFields` mixin |
| 32 | +- `metadata` field (appears in 55 wrapper models) - could be `MetadataFields` mixin |
| 33 | +- `data` field (appears in 130 wrapper models) - could be `DataFields` mixin |
| 34 | +- `bid` + `offer` fields - could be part of `BidOfferFields` mixin (currently only methods) |
| 35 | +- `margin` field (appears in 7 models) - could be `MarginFields` mixin |
| 36 | +- `surplus` field (appears in 6 models) - could be `SurplusFields` mixin |
| 37 | + |
| 38 | +**Potential impact:** |
| 39 | +- Could eliminate another ~100-150 field definitions |
| 40 | +- Would increase mixin coverage from 50% to 60%+ |
| 41 | + |
| 42 | +### 2. Optional Field Review |
| 43 | + |
| 44 | +Some fields marked as `Optional` might actually be required based on API behavior: |
| 45 | + |
| 46 | +**Fields to investigate:** |
| 47 | +```python |
| 48 | +# Example from BidOfferDatasetResponse: |
| 49 | +bid: Optional[float] = Field(...) # Has example - might be required? |
| 50 | +offer: Optional[float] = Field(...) # Has example - might be required? |
| 51 | + |
| 52 | +# Example from various models: |
| 53 | +time: Optional[datetime] = Field(...) # Appears in 8 models with examples |
| 54 | +``` |
| 55 | + |
| 56 | +**Approach:** |
| 57 | +1. Make actual API calls to test endpoints |
| 58 | +2. Analyze which fields are consistently present (>90% of responses) |
| 59 | +3. Update `inferred_required_fields` in `tools/generate_models.py` |
| 60 | +4. Regenerate models |
| 61 | + |
| 62 | +**Tool available:** |
| 63 | +- `tools/infer_required_fields.py` - Tests actual API responses |
| 64 | + |
| 65 | +### 3. Wrapper Model Optimization |
| 66 | + |
| 67 | +Many `*_DatasetResponse` and `*_ResponseWithMetadata` models are very similar: |
| 68 | + |
| 69 | +```python |
| 70 | +class SomeModel_DatasetResponse(BaseModel): |
| 71 | + data: Optional[List[SomeModel]] = None |
| 72 | + |
| 73 | +class AnotherModel_DatasetResponse(BaseModel): |
| 74 | + data: Optional[List[AnotherModel]] = None |
| 75 | +``` |
| 76 | + |
| 77 | +**Potential solutions:** |
| 78 | +- Generic wrapper with TypeVar |
| 79 | +- Shared base class for all wrapper models |
| 80 | +- Factory function for creating wrappers |
| 81 | + |
| 82 | +### 4. Additional Validations |
| 83 | + |
| 84 | +Some fields could benefit from validation: |
| 85 | + |
| 86 | +**Candidates:** |
| 87 | +- `frequency` - Already has FrequencyMixin, ensure all frequency fields use it |
| 88 | +- `temperature` - Already has TemperatureMixin, ensure all temperature fields use it |
| 89 | +- `percentage` fields - Validate 0-100 range |
| 90 | +- `capacity` fields - Validate positive values |
| 91 | +- `volume` fields - Could validate reasonable ranges |
| 92 | + |
| 93 | +### 5. More Comprehensive Enums |
| 94 | + |
| 95 | +Some string fields might have limited value sets that could be enums: |
| 96 | + |
| 97 | +**Fields to investigate:** |
| 98 | +- `status` field (appears in multiple models) |
| 99 | +- `priceDirection` field |
| 100 | +- `cause` field (might have common values) |
| 101 | +- `service` field |
| 102 | +- `dataType` field |
| 103 | + |
| 104 | +## Implementation Plan |
| 105 | + |
| 106 | +### Phase 1: Data Collection (Low effort) |
| 107 | +- [ ] Run `tools/infer_required_fields.py` with API key |
| 108 | +- [ ] Analyze actual API responses for field presence |
| 109 | +- [ ] Document findings in `tools/field_analysis.md` |
| 110 | + |
| 111 | +### Phase 2: Additional Field Mixins (Medium effort) |
| 112 | +- [ ] Create `TimeFields`, `IdFields`, `MarginFields`, `SurplusFields` mixins |
| 113 | +- [ ] Update `tools/generate_models.py` to detect these patterns |
| 114 | +- [ ] Regenerate models |
| 115 | +- [ ] Test with `test_all_improvements.py` |
| 116 | + |
| 117 | +### Phase 3: Optional Field Refinement (Medium effort) |
| 118 | +- [ ] Review fields with examples that are marked Optional |
| 119 | +- [ ] Update `inferred_required_fields` based on API testing |
| 120 | +- [ ] Regenerate models |
| 121 | +- [ ] Update tests to handle new required fields |
| 122 | + |
| 123 | +### Phase 4: Wrapper Model Optimization (Low-Medium effort) |
| 124 | +- [ ] Design generic wrapper approach |
| 125 | +- [ ] Implement in `tools/generate_models.py` |
| 126 | +- [ ] Test with existing code |
| 127 | + |
| 128 | +### Phase 5: Additional Validations (Low effort) |
| 129 | +- [ ] Add percentage validation |
| 130 | +- [ ] Add positive value validation for capacity/volume |
| 131 | +- [ ] Ensure all frequency/temperature fields use appropriate mixins |
| 132 | + |
| 133 | +## Success Criteria |
| 134 | + |
| 135 | +- [ ] Field mixin coverage >60% (currently 50%) |
| 136 | +- [ ] Required field percentage >70% (currently 64%) |
| 137 | +- [ ] Additional 100-150 field definitions eliminated |
| 138 | +- [ ] All tests passing |
| 139 | +- [ ] Documentation updated |
| 140 | + |
| 141 | +## Notes |
| 142 | + |
| 143 | +- Maintain backward compatibility where possible |
| 144 | +- Use `populate_by_name=True` to support both snake_case and camelCase |
| 145 | +- Keep API compatibility via aliases |
| 146 | +- Ensure all changes are tested |
| 147 | + |
| 148 | +## Related Files |
| 149 | + |
| 150 | +- `elexon_bmrs/generated_models.py` - Generated models |
| 151 | +- `elexon_bmrs/field_mixins.py` - Field mixin definitions |
| 152 | +- `elexon_bmrs/validators.py` - Method mixin definitions |
| 153 | +- `elexon_bmrs/enums.py` - Enum definitions |
| 154 | +- `tools/generate_models.py` - Model generator |
| 155 | +- `tools/generate_enums.py` - Enum generator |
| 156 | +- `tools/infer_required_fields.py` - API testing tool |
| 157 | + |
0 commit comments