Skip to content

Commit 69f1c82

Browse files
authored
CCM-12896: Generate Python Models (#151)
* CCM-12896: Python model class generation * CCM-12896: Make python models build in the pipeline
1 parent f509cf4 commit 69f1c82

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2083
-188
lines changed

.gitignore

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

29+
# Python
30+
__pycache__/
31+
.Python
32+
.venv/
33+
venv/
34+
*.egg-info/
35+
36+
# Testing
37+
.pytest_cache/
38+
.coverage
39+
htmlcov/
40+
coverage.xml
41+
2942
# Coverage reports
3043
htmlcov/
3144
.coverage

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ clean:: # Clean-up project resources (main) @Operations
3232
$(MAKE) -C src/cloudevents clean
3333
$(MAKE) -C src/eventcatalogasyncapiimporter clean
3434
$(MAKE) -C src/eventcatalogasyncapiimporter clean-output
35+
$(MAKE) -C src/python-schema-generator clean
3536
rm -f .version
3637
npm run clean
3738

package-lock.json

Lines changed: 946 additions & 130 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@
4242
"react": "^19.0.0"
4343
},
4444
"scripts": {
45+
"build-schemas": "make -C src/cloudevents/domains/digital-letters build-no-bundle publish-bundled-json",
4546
"clean": "npm run clean --workspaces --if-present",
46-
"generate-dependencies": "make -C src/cloudevents/domains/digital-letters build-no-bundle publish-bundled-json && npm run generate-dependencies --workspaces --if-present",
47+
"generate-dependencies": "npm run build-schemas && npm run generate-dependencies --workspaces --if-present && npm run generate-python-dependencies",
48+
"generate-python-dependencies": "make -C src/python-schema-generator generate",
4749
"lint": "npm run lint --workspaces",
4850
"lint:fix": "npm run lint:fix --workspaces",
4951
"start": "npm run start --workspace frontend",
@@ -61,6 +63,7 @@
6163
"utils/sender-management",
6264
"src/cloudevents",
6365
"src/digital-letters-events",
66+
"src/python-schema-generator",
6467
"src/typescript-schema-generator",
6568
"tests/playwright"
6669
]

project.code-workspace

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@
7979
},
8080
"terminal.integrated.scrollback": 10000,
8181
"jest.virtualFolders": [
82-
8382
{ "name": "key-generation", "rootPath": "lambdas/key-generation" },
8483
{ "name": "mesh-poll", "rootPath": "lambdas/mesh-poll" },
8584
{ "name": "refresh-apim-access-token", "rootPath": "lambdas/refresh-apim-access-token" },
85+
{ "name": "python-schema-generator", "rootPath": "src/python-schema-generator" },
8686
{ "name": "ttl-create-lambda", "rootPath": "lambdas/ttl-create-lambda/" },
8787
{ "name": "ttl-handle-expiry-lambda", "rootPath": "lambdas/ttl-handle-expiry-lambda" },
8888
{ "name": "ttl-poll-lambda", "rootPath": "lambdas/ttl-poll-lambda" },

scripts/config/sonar-scanner.properties

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ sonar.host.url=https://sonarcloud.io
44
sonar.qualitygate.wait=true
55
sonar.sourceEncoding=UTF-8
66
sonar.sources=.
7-
sonar.tests=tests/, src/asyncapigenerator/tests, src/cloudeventjekylldocs/tests, src/eventcatalogasyncapiimporter/tests, src/cloudevents/tools/builder/__tests__, src/cloudevents/tools/cache/__tests__, src/cloudevents/tools/generator/__tests__, lambdas/mesh-poll/src/__tests__, lambdas/ttl-create-lambda/src/__tests__, lambdas/ttl-poll-lambda/src/__tests__, utils/utils/src/__tests__, utils/sender-management/src/__tests__
7+
sonar.tests=tests/, src/asyncapigenerator/tests, src/cloudeventjekylldocs/tests, src/eventcatalogasyncapiimporter/tests, src/python-schema-generator/tests, src/cloudevents/tools/builder/__tests__, src/cloudevents/tools/cache/__tests__, src/cloudevents/tools/generator/__tests__, lambdas/mesh-poll/src/__tests__, lambdas/ttl-create-lambda/src/__tests__, lambdas/ttl-poll-lambda/src/__tests__, utils/utils/src/__tests__, utils/sender-management/src/__tests__
88
sonar.test.inclusions=tests/**, src/**/tests/**, src/**/__tests__/**, lambdas/**/src/__tests__/**, utils/utils/src/__tests__/**, utils/sender-management/src/__tests__/**
99
sonar.terraform.provider.aws.version=5.54.1
1010
sonar.cpd.exclusions=**.test.*
11-
sonar.coverage.exclusions=tests/**, src/**/tests/**, src/**/__tests__/**, **/*.dev.*, lambdas/**/src/__tests__/**, **/jest.config.ts, **/jest.config.cjs, scripts/**/*.*, docs/**/*.*, utils/utils/src/__tests__/**, src/asyncapigenerator/example_usage.py, src/asyncapigenerator/test_generator.py, src/eventcatalogasyncapiimporter/examples.py
11+
sonar.coverage.exclusions=tests/**, src/**/tests/**, src/**/__tests__/**, **/*.dev.*, lambdas/**/src/__tests__/**, **/jest.config.ts, **/jest.config.cjs, scripts/**/*.*, docs/**/*.*, utils/utils/src/__tests__/**, src/asyncapigenerator/example_usage.py, src/asyncapigenerator/test_generator.py, src/eventcatalogasyncapiimporter/examples.py, src/digital-letters-events/**
1212

13-
sonar.python.coverage.reportPaths=src/asyncapigenerator/coverage.xml,src/cloudeventjekylldocs/coverage.xml,src/eventcatalogasyncapiimporter/coverage.xml
13+
sonar.python.coverage.reportPaths=src/asyncapigenerator/coverage.xml,src/cloudeventjekylldocs/coverage.xml,src/eventcatalogasyncapiimporter/coverage.xml,src/python-schema-generator/coverage.xml
1414
sonar.javascript.lcov.reportPaths=lcov.info,src/cloudevents/coverage/lcov.info
1515
sonar.typescript.lcov.reportPaths=lcov.info,src/cloudevents/coverage/lcov.info

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

scripts/tests/unit.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ echo "Setting up and running eventcatalogasyncapiimporter tests..."
3434
make -C ./src/eventcatalogasyncapiimporter install-dev
3535
make -C ./src/eventcatalogasyncapiimporter coverage # Run with coverage to generate coverage.xml for SonarCloud
3636

37+
# Python projects - python-schema-generator
38+
echo "Setting up and running python-schema-generator tests..."
39+
make -C ./src/python-schema-generator install-dev
40+
make -C ./src/python-schema-generator coverage # Run with coverage to generate coverage.xml for SonarCloud
41+
3742
# TypeScript/JavaScript projects (npm workspace)
3843
# Note: src/cloudevents is included in workspaces, so it will be tested here
3944
npm ci
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
validators
22
types
3+
models

src/digital-letters-events/README.md

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
# digital-letters-events
22

3+
<!-- vale Vale.Avoid = NO -->
4+
<!-- vale Vale.Terms = NO -->
35
This package contains the automatically-generated code that the
4-
[typescript-schema-generator](../typescript-schema-generator/) tool produces.
6+
[typescript-schema-generator](../typescript-schema-generator/) and the
7+
[python-schema-generator](../python-schema-generator/) tools produce.
8+
<!-- vale Vale.Avoid = YES -->
9+
<!-- vale Vale.Terms = YES -->
510

611
The source files in this package should not be edited directly. If changes are
712
required, update the schemas in the
813
[src/cloudevents/domains](../cloudevents/domains) directory and use the
9-
`typescript-schema-generator` tool to regenerate them.
14+
`typescript-schema-generator` and `python-schema-generator` tools to regenerate
15+
them.
1016

1117
## Using this Package
1218

13-
### Using Event Types
19+
### TypeScript
20+
21+
#### Using Event Types
1422

1523
The event types can be used by simply installing the
1624
`digital-letters-events` package as a dependency and then importing
@@ -51,7 +59,7 @@ const pdmResourceSubmittedEvent: PDMResourceSubmitted = {
5159
};
5260
```
5361

54-
### Using Event Validator Functions
62+
#### Using Event Validator Functions
5563

5664
Validator functions for an event can be used by importing the default export
5765
from the relevant JS file in
@@ -74,3 +82,54 @@ if (isEventValid) {
7482
Note: You will need to make sure the
7583
[`allowJs`](https://www.typescriptlang.org/tsconfig/#allowJs) option is set in
7684
your package's `tsconfig.json` in order to import the JS files.
85+
86+
### Python
87+
88+
#### Using Event Models
89+
90+
The Pydantic models can be used by installing the `digital-letters-events` package and importing the desired model:
91+
92+
```python
93+
from digital_letters_events import PDMResourceSubmitted
94+
95+
try:
96+
# Validate and parse an event
97+
event_data = {
98+
"type": "uk.nhs.notify.digital.letters.pdm.resource.submitted.v1",
99+
"source": "/nhs/england/notify/staging/dev-647563337/data-plane/digitalletters/pdm",
100+
"dataschema": "https://notify.nhs.uk/cloudevents/schemas/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-submitted-data.schema.json",
101+
"specversion": "1.0",
102+
"id": "0249e529-f947-4012-819e-b634eb71be79",
103+
"subject": "customer/7ff8ed41-cd5f-20e4-ef4e-34f96d8cc8ac/75027ace-9b8c-bcfe-866e-6c24242cffc3/q58dnxk5e/4cbek805wwx/yiaw7bl0d/her/1ccb7eb8-c6fe-0a42-279a-2a0e48ff1ca9/zk",
104+
"time": "2025-11-21T16:01:52.268Z",
105+
"datacontenttype": "application/json",
106+
"traceparent": "00-ee4790eb6821064c645406abe918b3da-3a4e6957ce2a15de-01",
107+
"tracestate": "nisi quis",
108+
"partitionkey": "customer-7ff8ed41",
109+
"recordedtime": "2025-11-21T16:01:53.268Z",
110+
"sampledrate": 1,
111+
"sequence": "00000000000350773861",
112+
"severitytext": "INFO",
113+
"severitynumber": 2,
114+
"dataclassification": "restricted",
115+
"dataregulation": "ISO-27001",
116+
"datacategory": "non-sensitive",
117+
"data": {
118+
"messageReference": "incididunt Ut aute laborum",
119+
"senderId": "officia voluptate culpa Ut dolor",
120+
"resourceId": "a2bcbb42-ab7e-42b6-88d6-74f8d3ca4a09",
121+
"retryCount": 97_903_257,
122+
},
123+
}
124+
125+
# Create and validate the event
126+
event = PDMResourceSubmitted(**event_data)
127+
128+
# Access validated fields
129+
print(event.id)
130+
print(event.type)
131+
print(event.data.messageReference)
132+
except Exception as e:
133+
print(e)
134+
raise ValueError("Error processing event") from e
135+
```

0 commit comments

Comments
 (0)