Skip to content

Commit 657f005

Browse files
committed
Merge remote branch into local branch
2 parents 8c5d07d + 59ab753 commit 657f005

21 files changed

+449
-361
lines changed

README.md

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ Steps:
147147
AWS_PROFILE={your_profile}
148148
IMMUNIZATION_ENV=local
149149
```
150+
For unit tests to run successfully, you may also need to add an environment variable for PYTHONPATH. This should be:
151+
```
152+
PYTHONPATH=src:tests
153+
```
150154
151155
4. Configure `direnv` by creating a `.envrc` file in the backend folder. This points direnv to the `.venv` created by poetry and loads env variables specified in the `.env` file
152156
```
@@ -163,6 +167,10 @@ Steps:
163167
```
164168
Test if environment variables have been loaded into shell: `echo $IMMUNIZATION_ENV`.
165169
170+
#### Running Unit Tests from the Command Line
171+
172+
It is not necessary to activate the virtual environment (using `source .venv/bin/activate`) before running a unit test suite from the command line; `direnv` will pick up the correct configurations for us. Run `pip list` to verify that the expected packages are installed. You should for example see that `recordprocessor` is specifically running `moto` v4, regardless of which if any `.venv` is active.
173+
166174
### Setting up the root level environment
167175
The root-level virtual environment is primarily used for linting, as we create separate virtual environments for each folder that contains Lambda functions.
168176
Steps:
@@ -178,20 +186,38 @@ The current team uses VS Code mainly. So this setup is targeted towards VS code.
178186
179187
### VS Code
180188
181-
The project must be opened as a multi-root workspace for VS Code to know that `backend` has its own environment.
189+
The project must be opened as a multi-root workspace for VS Code to know that specific lambdas (e.g. `backend`) have their own environment.
190+
This example is for `backend`; substitute another lambda name in where applicable.
182191
183192
- Open the workspace `immunisation-fhir-api.code-workspace`.
184193
- Copy `backend/.vscode/settings.json.default` to `backend/.vscode/settings.json`, or merge the contents with
185194
your existing file.
195+
- Similarly, copy or merge `backend/.vscode/launch.json.default` to `backend/.vscode/launch.json`.
186196
187197
VS Code will automatically use the `backend` environment when you're editing a file under `backend`.
188198
189199
Depending on your existing setup VS Code might automatically choose the wrong virtualenvs. Change it
190200
with `Python: Select Interpreter`.
191201
192-
The root (`immunisation-fhir-api`) should point to `/mnt/d/Source/immunisation-fhir-api/.venv/bin/python`.
202+
The root (`immunisation-fhir-api`) should point to the root `.venv`, e.g. `/mnt/d/Source/immunisation-fhir-api/.venv/bin/python`.
203+
204+
Meanwhile, `backend` should be pointing at (e.g.) `/mnt/d/Source/immunisation-fhir-api/backend/.venv/bin/python`
205+
206+
#### Running Unit Tests
207+
208+
Note that unit tests can be run from the command line without VSCode configuration.
209+
210+
In order that VSCode can resolve modules in unit tests, it needs the PYTHONPATH. This should be setup in `backend/.vscode/launch.json` (see above).
193211
194-
`backend` should be pointing at `/mnt/d/Source/immunisation-fhir-api/backend/.venv/bin/python`
212+
**NOTE:** In order to run unit test suites, you may need to manually switch to the correct virtual environment each time you wish to
213+
run a different set of tests. To do this:
214+
- Show and Run Commands (Ctrl-Shift-P on Windows)
215+
- Python: Create Environment
216+
- Venv
217+
- Select the `.venv` named for the test suite you wish to run, e.g. `backend`
218+
- Use Existing
219+
- VSCode should now display a toast saying that the following environment is selected:
220+
- (e.g.) `/mnt/d/Source/immunisation-fhir-api/backend/.venv/bin/python`
195221
196222
### IntelliJ
197223

ack_backend/src/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import os
44

5-
SOURCE_BUCKET_NAME = f"immunisation-batch-{os.getenv('ENVIRONMENT')}-data-sources"
5+
SOURCE_BUCKET_NAME = os.getenv("SOURCE_BUCKET_NAME")
66
ACK_BUCKET_NAME = os.getenv("ACK_BUCKET_NAME")
77
AUDIT_TABLE_NAME = os.getenv("AUDIT_TABLE_NAME")
88
AUDIT_TABLE_FILENAME_GSI = "filename_index"

ack_backend/tests/utils/mock_environment_variables.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@ class Firehose:
2121
"ACK_BUCKET_NAME": BucketNames.DESTINATION,
2222
"FIREHOSE_STREAM_NAME": Firehose.STREAM_NAME,
2323
"AUDIT_TABLE_NAME": "immunisation-batch-internal-dev-audit-table",
24-
"ENVIRONMENT": "internal-dev",
24+
"SOURCE_BUCKET_NAME": BucketNames.SOURCE
2525
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"version": "0.2.0",
3+
"configurations": [
4+
{
5+
"name": "File",
6+
"type": "debugpy",
7+
"request": "launch",
8+
"module": "unittest",
9+
"args": [
10+
"${fileBasenameNoExtension}" // Run tests in the current file
11+
],
12+
"console": "integratedTerminal",
13+
"env": {
14+
"PYTHONPATH": "${workspaceFolder}:${workspaceFolder}/src:${workspaceFolder}/tests" // Add root, src, and tests
15+
}
16+
},
17+
{
18+
"name": "Here",
19+
"type": "debugpy",
20+
"request": "launch",
21+
"module": "unittest",
22+
"args": [
23+
"-k",
24+
"${selectedText}" // Run the test method or class under the cursor
25+
],
26+
"console": "integratedTerminal",
27+
"justMyCode": true,
28+
"env": {
29+
"PYTHONPATH": "${workspaceFolder}:${workspaceFolder}/src:${workspaceFolder}/tests" // Add root, src, and tests
30+
}
31+
}
32+
]
33+
}

backend/src/models/fhir_immunization_pre_validators.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -626,16 +626,16 @@ def pre_validate_protocol_applied(self, values: dict) -> dict:
626626
PreValidation.for_list(field_value, "protocolApplied", defined_length=1)
627627
except KeyError:
628628
pass
629-
629+
DOSE_NUMBER_MAX_VALUE = 9
630630
def pre_validate_dose_number_positive_int(self, values: dict) -> dict:
631631
"""
632632
Pre-validate that, if protocolApplied[0].doseNumberPositiveInt (legacy CSV field : dose_sequence)
633-
exists, then it is an integer from 1 to 9
633+
exists, then it is an integer from 1 to 9 (DOSE_NUMBER_MAX_VALUE)
634634
"""
635635
field_location = "protocolApplied[0].doseNumberPositiveInt"
636636
try:
637637
field_value = values["protocolApplied"][0]["doseNumberPositiveInt"]
638-
PreValidation.for_positive_integer(field_value, field_location)
638+
PreValidation.for_positive_integer(field_value, field_location, self.DOSE_NUMBER_MAX_VALUE)
639639
except (KeyError, IndexError):
640640
pass
641641

backend/tests/test_immunization_pre_validator.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from utils.pre_validation_test_utils import ValidatorModelTests
2626
from utils.values_for_tests import ValidValues, InvalidValues
2727
from models.constants import Constants
28+
from models.fhir_immunization_pre_validators import PreValidators
2829

2930
class TestImmunizationModelPreValidationRules(unittest.TestCase):
3031
"""Test immunization pre validation rules on the FHIR model using the covid sample data"""
@@ -819,6 +820,33 @@ def test_pre_validate_protocol_applied(self):
819820
)
820821

821822
def test_pre_validate_protocol_applied_dose_number_positive_int(self):
823+
"""
824+
Test pre_validate_protocol_applied_dose_number_positive_int accepts valid values and
825+
rejects invalid values
826+
"""
827+
for value in range(1, PreValidators.DOSE_NUMBER_MAX_VALUE + 1):
828+
data = {
829+
"protocolApplied": [
830+
{"doseNumberPositiveInt": value}
831+
]
832+
}
833+
validator = PreValidators(data)
834+
# Should not raise
835+
validator.pre_validate_dose_number_positive_int(data)
836+
837+
def test_out_of_range_dose_number(self):
838+
# Invalid: doseNumberPositiveInt < 1 or > 9
839+
for value in [0, PreValidators.DOSE_NUMBER_MAX_VALUE + 1, -1]:
840+
data = {
841+
"protocolApplied": [
842+
{"doseNumberPositiveInt": value}
843+
]
844+
}
845+
validator = PreValidators(data)
846+
with self.assertRaises(ValueError):
847+
validator.pre_validate_dose_number_positive_int(data)
848+
849+
def test_test_positive_integer_value(self):
822850
"""
823851
Test pre_validate_protocol_applied_dose_number_positive_int accepts valid values and
824852
rejects invalid values

config/dev/permissions_config.json

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,28 @@
11
[
22
{
33
"supplier": "DPSFULL",
4-
"permissions": ["COVID19.CRUDS", "FLU.CRUDS", "MMR.CRUDS", "RSV.CRUDS"],
4+
"permissions": [
5+
"COVID19.CRUDS",
6+
"FLU.CRUDS",
7+
"MMR.CRUDS",
8+
"RSV.CRUDS",
9+
"HPV.CRUDS",
10+
"MENACWY.CRUDS",
11+
"3IN1.CRUDS"
12+
],
513
"ods_codes": ["DPSFULL"]
614
},
715
{
816
"supplier": "DPSREDUCED",
9-
"permissions": ["COVID19.CRUD", "FLU.CRUD", "MMR.CRUD", "RSV.CRUD"],
17+
"permissions": [
18+
"COVID19.CRUDS",
19+
"FLU.CRUDS",
20+
"MMR.CRUDS",
21+
"RSV.CRUDS",
22+
"HPV.CRUDS",
23+
"MENACWY.CRUDS",
24+
"3IN1.CRUDS"
25+
],
1026
"ods_codes": ["DPSREDUCED"]
1127
},
1228
{
@@ -33,11 +49,7 @@
3349
{
3450
"supplier": "RAVS",
3551
"permissions": ["RSV.CRUDS", "MMR.CRUDS"],
36-
"ods_codes": ["X26"]
37-
},
38-
{
39-
"supplier": "AGEM-RAVS-Integration",
40-
"permissions": ["RSV.CRUDS", "MMR.CRUDS"]
52+
"ods_codes": ["X26", "X8E5B"]
4153
},
4254
{
4355
"supplier": "EMIS",
@@ -125,7 +137,6 @@
125137
"RSV.CRUDS",
126138
"HPV.CRUDS",
127139
"MENACWY.CRUDS",
128-
"PERTUSSIS.CRUDS",
129140
"3IN1.CRUDS"
130141
]
131142
},
@@ -138,16 +149,7 @@
138149
"RSV.CRUDS",
139150
"HPV.CRUDS",
140151
"MENACWY.CRUDS",
141-
"PERTUSSIS.CRUDS",
142152
"3IN1.CRUDS"
143153
]
144-
},
145-
{
146-
"supplier": "EVA",
147-
"ods_codes": ["8HA94"]
148-
},
149-
{
150-
"supplier": "SONAR",
151-
"ods_codes": ["8HK48"]
152154
}
153155
]

config/preprod/permissions_config.json

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,28 @@
11
[
22
{
33
"supplier": "DPSFULL",
4-
"permissions": ["COVID19.CRUDS", "FLU.CRUDS", "MMR.CRUDS", "RSV.CRUDS"],
4+
"permissions": [
5+
"COVID19.CRUDS",
6+
"FLU.CRUDS",
7+
"MMR.CRUDS",
8+
"RSV.CRUDS",
9+
"HPV.CRUDS",
10+
"MENACWY.CRUDS",
11+
"3IN1.CRUDS"
12+
],
513
"ods_codes": ["DPSFULL"]
614
},
715
{
816
"supplier": "DPSREDUCED",
9-
"permissions": ["COVID19.CRUDS", "FLU.CRUDS", "MMR.CRUDS", "RSV.CRUDS"],
17+
"permissions": [
18+
"COVID19.CRUDS",
19+
"FLU.CRUDS",
20+
"MMR.CRUDS",
21+
"RSV.CRUDS",
22+
"HPV.CRUDS",
23+
"MENACWY.CRUDS",
24+
"3IN1.CRUDS"
25+
],
1026
"ods_codes": ["DPSREDUCED"]
1127
},
1228
{
@@ -23,11 +39,7 @@
2339
{
2440
"supplier": "RAVS",
2541
"permissions": ["RSV.CRUDS", "MMR.CRUDS"],
26-
"ods_codes": ["X26"]
27-
},
28-
{
29-
"supplier": "AGEM-RAVS-Integration",
30-
"permissions": ["RSV.CRUDS", "MMR.CRUDS"]
42+
"ods_codes": ["X26", "X8E5B"]
3143
},
3244
{
3345
"supplier": "EMIS",
@@ -71,7 +83,6 @@
7183
"RSV.CRUDS",
7284
"HPV.CRUDS",
7385
"MENACWY.CRUDS",
74-
"PERTUSSIS.CRUDS",
7586
"3IN1.CRUDS"
7687
]
7788
},
@@ -84,7 +95,6 @@
8495
"RSV.CRUDS",
8596
"HPV.CRUDS",
8697
"MENACWY.CRUDS",
87-
"PERTUSSIS.CRUDS",
8898
"3IN1.CRUDS"
8999
]
90100
},

config/prod/permissions_config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
{
1717
"supplier": "RAVS",
1818
"permissions": ["RSV.RS"],
19-
"ods_codes": ["X26"]
19+
"ods_codes": ["X26", "X8E5B"]
2020
},
2121
{
2222
"supplier": "PINNACLE",

filenameprocessor/src/constants.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
"""Constants for the filenameprocessor lambda"""
22

33
import os
4+
from enum import StrEnum
5+
46
from errors import (
57
VaccineTypePermissionsError,
68
InvalidFileKeyError,
@@ -15,6 +17,8 @@
1517
AUDIT_TABLE_NAME = os.getenv("AUDIT_TABLE_NAME")
1618
AUDIT_TABLE_QUEUE_NAME_GSI = "queue_name_index"
1719
AUDIT_TABLE_FILENAME_GSI = "filename_index"
20+
DATA_SOURCES_BUCKET_SUFFIX = "data-sources"
21+
VALID_VERSIONS = ["V5"]
1822

1923
SUPPLIER_PERMISSIONS_HASH_KEY = "supplier_permissions"
2024
VACCINE_TYPE_TO_DISEASES_HASH_KEY = "vacc_to_diseases"
@@ -31,7 +35,7 @@
3135
}
3236

3337

34-
class FileStatus:
38+
class FileStatus(StrEnum):
3539
"""File status constants"""
3640

3741
QUEUED = "Queued"
@@ -40,16 +44,11 @@ class FileStatus:
4044
DUPLICATE = "Not processed - duplicate"
4145

4246

43-
class AuditTableKeys:
47+
class AuditTableKeys(StrEnum):
4448
"""Audit table keys"""
4549

4650
FILENAME = "filename"
4751
MESSAGE_ID = "message_id"
4852
QUEUE_NAME = "queue_name"
4953
STATUS = "status"
5054
TIMESTAMP = "timestamp"
51-
52-
53-
class Constants:
54-
"""Constants for the filenameprocessor lambda"""
55-
VALID_VERSIONS = ["V5"]

0 commit comments

Comments
 (0)