Skip to content

Commit 42b49b4

Browse files
committed
CCM-12896: Initial version of python type generation
1 parent 6487e77 commit 42b49b4

File tree

21 files changed

+827
-0
lines changed

21 files changed

+827
-0
lines changed

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ output
2626
/schemas
2727
.env
2828

29+
# Python
30+
__pycache__/
31+
.Python
32+
.venv/
33+
venv/
34+
35+
# Testing
36+
.pytest_cache/
37+
.coverage
38+
htmlcov/
39+
coverage.xml
40+
2941
# Coverage reports
3042
htmlcov/
3143
.coverage

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ dependencies: # Install dependencies needed to build and test the project @Pipel
1414

1515
generate: # Generate any autogenerated output @Pipeline
1616
npm run generate-dependencies
17+
$(MAKE) -C src/pydantic-model-generator generate
1718

1819
build: # Build the project artefact @Pipeline
1920
$(MAKE) -C docs build
@@ -32,6 +33,7 @@ clean:: # Clean-up project resources (main) @Operations
3233
$(MAKE) -C src/cloudevents clean
3334
$(MAKE) -C src/eventcatalogasyncapiimporter clean
3435
$(MAKE) -C src/eventcatalogasyncapiimporter clean-output
36+
$(MAKE) -C src/pydantic-model-generator clean
3537
rm -f .version
3638
npm run clean
3739

scripts/config/vale/styles/config/vocabularies/words/accept.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ Podman
6969
producedby
7070
projectRoot
7171
Protobuf
72+
Pydantic
7273
pylint
7374
Python
7475
quotingType
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Models directory (auto-generated)
2+
models/
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<!-- vale Vale.Terms = NO -->
2+
<!-- vale Vale.Avoid = NO -->
3+
# digital-letters-events-python
4+
<!-- vale Vale.Terms = YES -->
5+
<!-- vale Vale.Avoid = YES -->
6+
7+
<!-- vale Vale.Terms = NO -->
8+
This package contains the automatically-generated Pydantic v2 models that the [pydantic-model-generator](../pydantic-model-generator/) tool produces.
9+
<!-- vale Vale.Terms = YES -->
10+
11+
The source files in this package should not be edited directly. If changes are required, update the schemas in the [schemas/digital-letters/2025-10-draft/events](../../schemas/digital-letters/2025-10-draft/events) directory and use the `pydantic-model-generator` tool to regenerate them.
12+
13+
## Using this Package
14+
15+
### Using Event Models
16+
17+
The Pydantic models can be used by installing the `digital-letters-events-python` package and importing the desired model:
18+
19+
```python
20+
from digital_letters_events_python import PDMResourceSubmitted
21+
22+
try:
23+
# Validate and parse an event
24+
event_data = {
25+
"type": "uk.nhs.notify.digital.letters.pdm.resource.submitted.v1",
26+
"source": "/nhs/england/notify/staging/dev-647563337/data-plane/digitalletters/pdm",
27+
"dataschema": "https://notify.nhs.uk/cloudevents/schemas/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-submitted-data.schema.json",
28+
"specversion": "1.0",
29+
"id": "0249e529-f947-4012-819e-b634eb71be79",
30+
"subject": "pdm-resource-123",
31+
"time": "2025-12-11T10:00:00Z",
32+
"data": {
33+
"something": "example value"
34+
}
35+
}
36+
37+
# Create and validate the event
38+
event = PDMResourceSubmitted(**event_data)
39+
40+
# Access validated fields
41+
print(event.id)
42+
print(event.type)
43+
print(event.data.something)
44+
except Exception as e:
45+
print(e)
46+
```
47+
48+
### Type Safety and Validation
49+
50+
All generated models include:
51+
52+
- Type hints for all fields
53+
- Runtime validation via Pydantic
54+
- Automatic conversion of types where appropriate
55+
- Clear error messages for validation failures
56+
57+
## Development
58+
59+
This package is automatically generated. Do not edit the files in the [`models`](./models/) directory directly.
60+
61+
To regenerate the models:
62+
63+
```bash
64+
cd ../pydantic-model-generator
65+
make generate
66+
```
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""Digital Letters Events package.
2+
3+
This package contains automatically-generated Pydantic v2 models for NHS Notify
4+
Digital Letters events. These models are generated from JSON schemas by the
5+
pydantic-model-generator tool.
6+
7+
DO NOT EDIT: Files in this package are auto-generated. Any manual changes will
8+
be overwritten when the models are regenerated.
9+
"""
10+
11+
from .models import *
12+
13+
__all__ = ["models"]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pydantic>=2.0.0,<3.0.0
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Variables
2+
SCHEMA_SRC_DIR := ../../schemas/digital-letters/2025-10-draft/events
3+
OUTPUT_DIR := ../digital-letters-events-python/models
4+
SCRIPTS_DIR := scripts
5+
6+
# Python settings
7+
VENV_DIR := ../../.venv
8+
VENV_PYTHON := $(VENV_DIR)/bin/python
9+
VENV_PIP := $(VENV_DIR)/bin/pip
10+
11+
# Default target
12+
.PHONY: all clean generate install install-dev test coverage help
13+
14+
all: generate
15+
16+
# Install production dependencies (uses repo-level venv)
17+
install:
18+
@echo "Installing production dependencies..."
19+
@$(VENV_PIP) install -r requirements.txt
20+
@echo "Production dependencies installed!"
21+
22+
# Install development dependencies (uses repo-level venv)
23+
install-dev:
24+
@echo "Installing development dependencies..."
25+
@$(VENV_PIP) install -r requirements-dev.txt
26+
@echo "Development dependencies installed!"
27+
28+
# Generate Pydantic models from JSON schemas
29+
generate: install
30+
@echo "Generating Pydantic models from JSON schemas..."
31+
@mkdir -p $(OUTPUT_DIR)
32+
@$(VENV_PYTHON) $(SCRIPTS_DIR)/generate_models.py \
33+
--input-dir $(SCHEMA_SRC_DIR) \
34+
--output-dir $(OUTPUT_DIR)
35+
@echo "Pydantic models generated in $(OUTPUT_DIR)/"
36+
37+
# Run tests
38+
test: install-dev
39+
@echo "Running tests..."
40+
@cd ../.. && pytest src/pydantic-model-generator/tests/
41+
42+
# Generate coverage report
43+
coverage: install-dev
44+
@echo "Generating coverage report..."
45+
@cd ../.. && pytest src/pydantic-model-generator/tests/ \
46+
--cov=src/pydantic-model-generator \
47+
--cov-config=src/pydantic-model-generator/pytest.ini \
48+
--cov-report=html:src/pydantic-model-generator/htmlcov \
49+
--cov-report=term-missing \
50+
--cov-report=xml:src/pydantic-model-generator/coverage.xml \
51+
--cov-branch
52+
@echo "Coverage report generated in htmlcov/"
53+
54+
# Clean output directory and generated files
55+
clean:
56+
@echo "Cleaning generated models..."
57+
@rm -rf $(OUTPUT_DIR) htmlcov .pytest_cache coverage.xml
58+
@echo "Clean complete!"
59+
60+
# Show help
61+
help:
62+
@echo "Available targets:"
63+
@echo " all - Generate Pydantic models (default)"
64+
@echo " install - Install production dependencies"
65+
@echo " install-dev - Install development dependencies"
66+
@echo " generate - Generate Pydantic models from JSON schemas"
67+
@echo " test - Run tests"
68+
@echo " coverage - Generate coverage report"
69+
@echo " clean - Clean output directories"
70+
@echo " help - Show this help message"
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<!-- vale Vale.Terms = NO -->
2+
# pydantic-model-generator
3+
<!-- vale Vale.Terms = YES -->
4+
5+
This package provides a tool that generates Pydantic v2 models for the events
6+
that are defined in the JSON schemas that are built as part of this repository.
7+
The generated Pydantic models can be used to validate and parse NHS Notify
8+
Digital Letters events.
9+
10+
## Setup
11+
12+
Use `make install-dev` to install the necessary dependencies for this application.
13+
14+
## Generating Models
15+
16+
In order for this tool to function, you must first build the JSON schemas for
17+
the Digital Letters events. The simplest way to build these schemas is to run
18+
the `npm run generate-dependencies` command from the root of this repository.
19+
20+
### Using the Generator
21+
22+
Once the JSON schemas have been built, Pydantic models can be generated by running:
23+
24+
```bash
25+
make generate
26+
```
27+
28+
This will:
29+
30+
- Read all JSON event schemas from `schemas/digital-letters/2025-10-draft/events/`
31+
- Generate Pydantic v2 models using `datamodel-code-generator`
32+
- Output the models to `../digital-letters-events-python/models/`
33+
34+
### Configuration
35+
36+
The generator can be configured through:
37+
38+
- Command-line arguments
39+
- Environment variables
40+
- Configuration file (if needed)
41+
42+
### Output Structure
43+
44+
<!-- vale Vale.Terms = NO -->
45+
<!-- vale Vale.Avoid = NO -->
46+
Generated models are placed in the
47+
[digital-letters-events-python](../digital-letters-events-python/) package:
48+
<!-- vale Vale.Terms = YES -->
49+
<!-- vale Vale.Avoid = YES -->
50+
51+
- `../digital-letters-events-python/models/` - Individual Pydantic model files
52+
- `../digital-letters-events-python/models/__init__.py` - Combined index for easy imports
53+
54+
## Testing
55+
56+
Run tests using:
57+
58+
```bash
59+
make test
60+
```
61+
62+
For coverage reporting:
63+
64+
```bash
65+
make coverage
66+
```
67+
68+
## Development
69+
70+
### Prerequisites
71+
72+
- Python 3.11+
73+
- pip or poetry for dependency management
74+
75+
### Installing Development Dependencies
76+
77+
```bash
78+
make install-dev
79+
```
80+
81+
### Running Tests
82+
83+
```bash
84+
make test
85+
```
86+
87+
## Usage
88+
89+
Once generated, the models can be used in your code as follows:
90+
91+
```python
92+
from digital_letters_event_python import PrintLetterAvailable, CloudEventEnvelope
93+
94+
# Validate incoming event
95+
event_data = CloudEventEnvelope(**raw_event)
96+
if event_data.type == "uk.nhs.notify.digital.letters.letter.available.v1":
97+
letter_available = PrintLetterAvailable(**raw_event)
98+
# Process the validated event
99+
```
100+
101+
## Architecture
102+
103+
The generator consists of:
104+
105+
- `scripts/generate_models.py` - Main CLI script
106+
- `scripts/schema_processor.py` - Schema loading and processing
107+
- `scripts/model_generator.py` - Pydantic model generation logic
108+
- `scripts/file_utils.py` - File system utilities
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
[pytest]
2+
testpaths = tests
3+
python_files = test_*.py
4+
python_classes = Test*
5+
python_functions = test_*
6+
addopts =
7+
-v
8+
--tb=short
9+
10+
[coverage:run]
11+
relative_files = True
12+
omit =
13+
*/tests/*
14+
*/test_*.py
15+
test_*.py
16+
*/venv/*
17+
*/.venv/*
18+
*/__pycache__/*
19+
20+
[coverage:xml]
21+
output = coverage.xml

0 commit comments

Comments
 (0)