Skip to content

Commit 46255ca

Browse files
authored
+generate DynamoDB data generate_dynamo_data.py (#188)
* +generate DynamoDB data generate_dynamo_data.py * +generate DynamoDB data generate_dynamo_data.py * +generate DynamoDB data generate_dynamo_data.py
1 parent b8ebea2 commit 46255ca

File tree

6 files changed

+120
-1614
lines changed

6 files changed

+120
-1614
lines changed

tests/e2e/data/dynamoDB/AUTO_RSV_SB_006.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
{
4040
"NHS_NUMBER": "5000000006",
4141
"ATTRIBUTE_TYPE": "RSV",
42-
"LAST_SUCCESSFUL_DATE": "<<DATE_LAST_WEEK>>"
42+
"LAST_SUCCESSFUL_DATE": "<<DATE_DAY_-7>>"
4343
}
4444
]
4545
}

tests/e2e/data/dynamoDB/AUTO_RSV_SB_007.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
{
4040
"NHS_NUMBER": "5000000007",
4141
"ATTRIBUTE_TYPE": "RSV",
42-
"LAST_SUCCESSFUL_DATE": "<<DATE_LAST_WEEK>>"
42+
"LAST_SUCCESSFUL_DATE": "<<DATE_DAY_-7>>"
4343
}
4444
]
4545
}

tests/e2e/data/dynamoDB/AUTO_RSV_SB_012.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
{
3030
"NHS_NUMBER": "5000000012",
3131
"ATTRIBUTE_TYPE": "RSV",
32-
"LAST_SUCCESSFUL_DATE": "<<DATE_LAST_WEEK>>"
32+
"LAST_SUCCESSFUL_DATE": "<<DATE_DAY_-7>>"
3333
}
3434
]
3535
}

tests/e2e/data/dynamoDB/AUTO_RSV_SB_013.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
{
4040
"NHS_NUMBER": "50000000014",
4141
"ATTRIBUTE_TYPE": "RSV",
42-
"LAST_SUCCESSFUL_DATE": "<<DATE_LAST_WEEK>>"
42+
"LAST_SUCCESSFUL_DATE": "<<DATE_DAY_-7>>"
4343
}
4444
]
4545
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import json
2+
import logging
3+
import os
4+
import re
5+
from datetime import datetime, timedelta, timezone
6+
from pathlib import Path
7+
from typing import Any
8+
9+
OUTPUT_ROOT = "out"
10+
DATE_FORMAT = "%Y%m%d"
11+
VAR_PATTERN = re.compile(r"<<([^<>]+)>>")
12+
REQUIRED_TOKEN_PARTS = 3
13+
14+
logger = logging.getLogger(__name__)
15+
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s")
16+
17+
18+
class DateVariableResolver:
19+
def __init__(self, today: datetime | None = None):
20+
self.today = today or datetime.now(tz=timezone.UTC)
21+
22+
def resolve(self, token: str) -> str:
23+
logger.debug("Resolving variable: %s", token)
24+
parts = token.split("_")
25+
if len(parts) < REQUIRED_TOKEN_PARTS or parts[0].upper() != "DATE":
26+
msg = f"Unsupported variable format: {token}"
27+
raise ValueError(msg)
28+
_, unit, value = parts[0], parts[1].lower(), parts[2]
29+
try:
30+
offset = int(value)
31+
except ValueError as err:
32+
msg = f"Invalid offset value: {value}"
33+
raise ValueError(msg) from err
34+
if unit == "day":
35+
return (self.today + timedelta(days=offset)).strftime(DATE_FORMAT)
36+
if unit == "week":
37+
return (self.today + timedelta(weeks=offset)).strftime(DATE_FORMAT)
38+
if unit == "year":
39+
return (self.today.replace(year=self.today.year + offset)).strftime(DATE_FORMAT)
40+
if unit == "age":
41+
try:
42+
birth_date = self.today.replace(year=self.today.year - offset)
43+
except ValueError:
44+
birth_date = self.today.replace(month=2, day=28, year=self.today.year - offset)
45+
return birth_date.strftime(DATE_FORMAT)
46+
msg = f"Unsupported calculation unit: {unit}"
47+
raise ValueError(msg)
48+
49+
50+
class JsonTestDataProcessor:
51+
def __init__(self, input_dir: Path, output_dir: Path, resolver: DateVariableResolver):
52+
self.input_dir = input_dir
53+
self.output_dir = output_dir
54+
self.resolver = resolver
55+
56+
def resolve_placeholders(self, obj: Any) -> Any:
57+
if isinstance(obj, dict):
58+
return {k: self.resolve_placeholders(v) for k, v in obj.items()}
59+
if isinstance(obj, list):
60+
return [self.resolve_placeholders(item) for item in obj]
61+
if isinstance(obj, str):
62+
return VAR_PATTERN.sub(self._replace_token, obj)
63+
return obj
64+
65+
def _replace_token(self, match: re.Match) -> str:
66+
token = match.group(1)
67+
try:
68+
return self.resolver.resolve(token)
69+
except ValueError:
70+
logger.warning("Failed to resolve variable: %s", token)
71+
return match.group(0)
72+
73+
def process_file(self, file_path: Path):
74+
logger.info("Processing file: %s", file_path)
75+
try:
76+
with file_path.open() as f:
77+
content = json.load(f)
78+
except Exception:
79+
logger.exception("Failed to read file: %s", file_path)
80+
return
81+
try:
82+
resolved = self.resolve_placeholders(content)
83+
except Exception:
84+
logger.exception("Failed to resolve placeholders in file: %s", file_path)
85+
return
86+
if "data" not in resolved:
87+
logger.error("Missing 'data' key in file: %s", file_path)
88+
return
89+
relative_path = file_path.relative_to(self.input_dir)
90+
output_path = self.output_dir / relative_path
91+
output_path.parent.mkdir(parents=True, exist_ok=True)
92+
try:
93+
with output_path.open("w") as f:
94+
json.dump(resolved["data"], f, indent=2)
95+
logger.info("Written resolved file: %s", output_path)
96+
except Exception:
97+
logger.exception("Failed to write output to: %s", output_path)
98+
99+
100+
def main():
101+
input_dir = Path()
102+
output_dir = Path(OUTPUT_ROOT)
103+
resolver = DateVariableResolver()
104+
processor = JsonTestDataProcessor(input_dir, output_dir, resolver)
105+
logger.info("Scanning for JSON files in directory: %s", input_dir)
106+
for root, _, files in os.walk(input_dir):
107+
for file in files:
108+
file_path = Path(root) / file
109+
if file.endswith(".json"):
110+
processor.process_file(file_path)
111+
else:
112+
logger.debug("Skipping non-JSON file: %s", file)
113+
114+
115+
if __name__ == "__main__":
116+
main()

0 commit comments

Comments
 (0)