Skip to content

Commit 03ed227

Browse files
Merge pull request #720 from NHSDigital/feature/made14-NRL-829-pydantic2
[NRL-829] Update to Pydantic v2
2 parents e946b8e + 90c6bdf commit 03ed227

File tree

61 files changed

+1503
-1303
lines changed

Some content is hidden

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

61 files changed

+1503
-1303
lines changed

Makefile

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,5 +191,25 @@ truststore-pull-ca: check-warn ## Pull a CA certificate
191191
swagger-merge: check-warn ## Generate Swagger Documentation
192192
@./scripts/swagger.sh merge "$(TYPE)"
193193

194-
generate-model: check-warn ## Generate Pydantic Models
195-
@./scripts/swagger.sh generate-model "$(TYPE)"
194+
generate-models: check-warn ## Generate Pydantic Models
195+
@echo "Generating producer models"
196+
mkdir -p ./layer/nrlf/producer/fhir/r4
197+
poetry run datamodel-codegen \
198+
--input ./api/producer/swagger.yaml \
199+
--input-file-type openapi \
200+
--output ./layer/nrlf/producer/fhir/r4/model.py \
201+
--output-model-type "pydantic_v2.BaseModel"
202+
poetry run datamodel-codegen \
203+
--strict-types {str,bytes,int,float,bool} \
204+
--input ./api/producer/swagger.yaml \
205+
--input-file-type openapi \
206+
--output ./layer/nrlf/producer/fhir/r4/strict_model.py \
207+
--output-model-type "pydantic_v2.BaseModel"
208+
209+
@echo "Generating consumer model"
210+
mkdir -p ./layer/nrlf/consumer/fhir/r4
211+
poetry run datamodel-codegen \
212+
--input ./api/consumer/swagger.yaml \
213+
--input-file-type openapi \
214+
--output ./layer/nrlf/consumer/fhir/r4/model.py \
215+
--output-model-type "pydantic_v2.BaseModel"

api/consumer/countDocumentReference/tests/test_count_document_reference.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def test_count_document_reference_missing_nhs_number():
8181
}
8282
]
8383
},
84-
"diagnostics": "Invalid query parameter (subject:identifier: field required)",
84+
"diagnostics": "Invalid query parameter (subject:identifier: Field required)",
8585
"expression": ["subject:identifier"],
8686
}
8787
],

api/consumer/readDocumentReference/read_document_reference.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def handler(
5757
)
5858

5959
try:
60-
document_reference = DocumentReference.parse_raw(result.document)
60+
document_reference = DocumentReference.model_validate_json(result.document)
6161
except ValidationError as exc:
6262
logger.log(
6363
LogReference.CONREAD003,

api/consumer/readDocumentReference/tests/test_read_document_reference_consumer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def test_read_document_reference_happy_path(repository: DocumentPointerRepositor
3636
}
3737

3838
parsed_body = json.loads(body)
39-
assert parsed_body == doc_ref.dict(exclude_none=True)
39+
assert parsed_body == doc_ref.model_dump(exclude_none=True)
4040

4141

4242
@mock_aws
@@ -105,7 +105,7 @@ def test_read_document_reference_missing_id():
105105
}
106106
]
107107
},
108-
"diagnostics": "Invalid path parameter (id: field required)",
108+
"diagnostics": "Invalid path parameter (id: Field required)",
109109
"expression": ["id"],
110110
}
111111
],

api/consumer/searchDocumentReference/search_document_reference.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,16 @@ def handler(
5959
)
6060

6161
custodian_id = (
62-
params.custodian_identifier.__root__.split("|", maxsplit=1)[1]
62+
params.custodian_identifier.root.split("|", maxsplit=1)[1]
6363
if params.custodian_identifier
6464
else None
6565
)
6666
if custodian_id:
6767
self_link += f"&custodian:identifier=https://fhir.nhs.uk/Id/ods-organization-code|{custodian_id}"
6868

69-
pointer_types = [params.type.__root__] if params.type else metadata.pointer_types
69+
pointer_types = [params.type.root] if params.type else metadata.pointer_types
7070
if params.type:
71-
self_link += f"&type={params.type.__root__}"
71+
self_link += f"&type={params.type.root}"
7272

7373
bundle = {
7474
"resourceType": "Bundle",
@@ -91,10 +91,10 @@ def handler(
9191
pointer_types=pointer_types,
9292
):
9393
try:
94-
document_reference = DocumentReference.parse_raw(result.document)
94+
document_reference = DocumentReference.model_validate_json(result.document)
9595
bundle["total"] += 1
9696
bundle["entry"].append(
97-
{"resource": document_reference.dict(exclude_none=True)}
97+
{"resource": document_reference.model_dump(exclude_none=True)}
9898
)
9999
logger.log(
100100
LogReference.CONSEARCH004,
@@ -114,7 +114,7 @@ def handler(
114114
diagnostics="An error occurred whilst parsing the document reference search results",
115115
) from exc
116116

117-
response = Response.from_resource(Bundle.parse_obj(bundle))
117+
response = Response.from_resource(Bundle.model_validate(bundle))
118118
logger.log(LogReference.CONSEARCH999)
119119

120120
return response

api/consumer/searchDocumentReference/tests/test_search_document_reference_consumer.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def test_search_document_reference_happy_path(repository: DocumentPointerReposit
4949
}
5050
],
5151
"total": 1,
52-
"entry": [{"resource": doc_ref.dict(exclude_none=True)}],
52+
"entry": [{"resource": doc_ref.model_dump(exclude_none=True)}],
5353
}
5454

5555

@@ -90,7 +90,7 @@ def test_search_document_reference_happy_path_with_custodian(
9090
}
9191
],
9292
"total": 1,
93-
"entry": [{"resource": doc_ref.dict(exclude_none=True)}],
93+
"entry": [{"resource": doc_ref.model_dump(exclude_none=True)}],
9494
}
9595

9696

@@ -131,7 +131,7 @@ def test_search_document_reference_happy_path_with_type(
131131
}
132132
],
133133
"total": 1,
134-
"entry": [{"resource": doc_ref.dict(exclude_none=True)}],
134+
"entry": [{"resource": doc_ref.model_dump(exclude_none=True)}],
135135
}
136136

137137

@@ -178,7 +178,7 @@ def test_search_document_reference_happy_path_with_nicip_type(
178178
}
179179
],
180180
"total": 1,
181-
"entry": [{"resource": doc_ref.dict(exclude_none=True)}],
181+
"entry": [{"resource": doc_ref.model_dump(exclude_none=True)}],
182182
}
183183

184184

@@ -248,7 +248,7 @@ def test_search_document_reference_missing_nhs_number(
248248
}
249249
]
250250
},
251-
"diagnostics": "Invalid query parameter (subject:identifier: field required)",
251+
"diagnostics": "Invalid query parameter (subject:identifier: Field required)",
252252
"expression": ["subject:identifier"],
253253
}
254254
],

api/consumer/searchPostDocumentReference/search_post_document_reference.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,16 @@ def handler(
6262
)
6363

6464
custodian_id = (
65-
body.custodian_identifier.__root__.split("|", maxsplit=1)[1]
65+
body.custodian_identifier.root.split("|", maxsplit=1)[1]
6666
if body.custodian_identifier
6767
else None
6868
)
6969
if custodian_id:
7070
self_link += f"&custodian:identifier=https://fhir.nhs.uk/Id/ods-organization-code|{custodian_id}"
7171

72-
pointer_types = [body.type.__root__] if body.type else metadata.pointer_types
72+
pointer_types = [body.type.root] if body.type else metadata.pointer_types
7373
if body.type:
74-
self_link += f"&type={body.type.__root__}"
74+
self_link += f"&type={body.type.root}"
7575

7676
bundle = {
7777
"resourceType": "Bundle",
@@ -92,10 +92,10 @@ def handler(
9292
nhs_number=body.nhs_number, custodian=custodian_id, pointer_types=pointer_types
9393
):
9494
try:
95-
document_reference = DocumentReference.parse_raw(result.document)
95+
document_reference = DocumentReference.model_validate_json(result.document)
9696
bundle["total"] += 1
9797
bundle["entry"].append(
98-
{"resource": document_reference.dict(exclude_none=True)}
98+
{"resource": document_reference.model_dump(exclude_none=True)}
9999
)
100100
logger.log(
101101
LogReference.CONPOSTSEARCH004,
@@ -115,7 +115,7 @@ def handler(
115115
diagnostics="An error occurred whilst parsing the document reference search results",
116116
) from exc
117117

118-
response = Response.from_resource(Bundle.parse_obj(bundle))
118+
response = Response.from_resource(Bundle.model_validate(bundle))
119119
logger.log(LogReference.CONPOSTSEARCH999)
120120

121121
return response

api/consumer/searchPostDocumentReference/tests/test_search_post_document_reference_consumer.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def test_search_post_document_reference_happy_path(
5454
}
5555
],
5656
"total": 1,
57-
"entry": [{"resource": doc_ref.dict(exclude_none=True)}],
57+
"entry": [{"resource": doc_ref.model_dump(exclude_none=True)}],
5858
}
5959

6060

@@ -97,7 +97,7 @@ def test_search_post_document_reference_happy_path_with_custodian(
9797
}
9898
],
9999
"total": 1,
100-
"entry": [{"resource": doc_ref.dict(exclude_none=True)}],
100+
"entry": [{"resource": doc_ref.model_dump(exclude_none=True)}],
101101
}
102102

103103

@@ -140,7 +140,7 @@ def test_search_post_document_reference_happy_path_with_type(
140140
}
141141
],
142142
"total": 1,
143-
"entry": [{"resource": doc_ref.dict(exclude_none=True)}],
143+
"entry": [{"resource": doc_ref.model_dump(exclude_none=True)}],
144144
}
145145

146146

@@ -212,7 +212,7 @@ def test_search_post_document_reference_missing_nhs_number(
212212
}
213213
]
214214
},
215-
"diagnostics": "Request body could not be parsed (subject:identifier: field required)",
215+
"diagnostics": "Request body could not be parsed (subject:identifier: Field required)",
216216
"expression": ["subject:identifier"],
217217
}
218218
],

api/consumer/swagger.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,11 @@ components:
10691069
format:
10701070
$ref: "#/components/schemas/Coding"
10711071
description: An identifier of the document encoding, structure, and template that the document conforms to beyond the base format indicated in the mimeType.
1072+
extension:
1073+
type: array
1074+
items:
1075+
$ref: "#/components/schemas/Extension"
1076+
description: Additional content defined by implementations.
10721077
required:
10731078
- attachment
10741079
DocumentReferenceRelatesTo:
@@ -1143,6 +1148,11 @@ components:
11431148
type: string
11441149
pattern: "[ \\r\\n\\t\\S]+"
11451150
description: A human language representation of the concept as seen/selected/uttered by the user who entered the data and/or which represents the intended meaning of the user.
1151+
extension:
1152+
type: array
1153+
items:
1154+
$ref: "#/components/schemas/Extension"
1155+
description: Additional content defined by implementations.
11461156
Coding:
11471157
type: object
11481158
properties:
@@ -1169,6 +1179,16 @@ components:
11691179
userSelected:
11701180
type: boolean
11711181
description: Indicates that this coding was chosen by a user directly – e.g. off a pick list of available items (codes or displays).
1182+
Extension:
1183+
type: object
1184+
properties:
1185+
valueCodeableConcept:
1186+
$ref: "#/components/schemas/CodeableConcept"
1187+
description: A name which details the functional use for this link – see [http://www.iana.org/assignments/link–relations/link–relations.xhtml#link–relations–1](http://www.iana.org/assignments/link–relations/link–relations.xhtml#link–relations–1).
1188+
url:
1189+
type: string
1190+
pattern: \S*
1191+
description: The reference details for the link.
11721192
Identifier:
11731193
type: object
11741194
properties:

0 commit comments

Comments
 (0)