1
1
import argparse
2
2
from datetime import datetime
3
3
import logging
4
+ import os
4
5
from pathlib import Path
6
+ import subprocess
5
7
from tempfile import TemporaryDirectory
6
8
import time
7
9
from typing import Optional , List , Tuple , Dict , Any
26
28
)
27
29
from sr .utils import (
28
30
download_cid_files ,
29
- download_file ,
31
+ download_files ,
30
32
compare_checksums ,
31
33
calculate_checksums ,
32
34
)
41
43
TABLE_O1 = PART_16 + "/chapter_O.html"
42
44
TABLE_D1 = PART_16 + "/chapter_D.html"
43
45
44
- WORKERS = 32
45
-
46
46
47
47
def run (
48
48
src : Optional [Path ] = None ,
@@ -86,9 +86,11 @@ def run(
86
86
attempts = 0
87
87
while attempts < 5 :
88
88
try :
89
- download_cid_files ((CID_HOST , CID_PATH ), src , WORKERS )
90
- download_file (TABLE_D1 , src / "part16_d1.html" )
91
- download_file (TABLE_O1 , src / "part16_o1.html" )
89
+ download_cid_files ((CID_HOST , CID_PATH ), src )
90
+ download_files (
91
+ [TABLE_D1 , TABLE_O1 ],
92
+ [src / "part16_d1.html" , src / "part16_o1.html" ],
93
+ )
92
94
break
93
95
except TimeoutError as exc :
94
96
LOGGER .exception (exc )
@@ -102,12 +104,16 @@ def run(
102
104
paths = sorted (cid_paths + table_paths )
103
105
104
106
# 1. Compare the data in `src` against the reference hashes
105
- if compare_checksums (paths , HASH_FILE ) and not force_regeneration :
107
+ checksums_match = compare_checksums (paths , HASH_FILE )
108
+ if checksums_match and not force_regeneration :
106
109
LOGGER .info ("No change in source data found, exiting..." )
107
110
return False
108
111
109
112
# 2. Source data has changed, regenerate the tables and update the package
110
- LOGGER .info ("Source data has changed - updating package" )
113
+ if not checksums_match :
114
+ LOGGER .info ("Source data has changed - updating package" )
115
+ else :
116
+ LOGGER .debug ("'--force-regeneration' used - updating package" )
111
117
112
118
table_o1 = src / "part16_o1.html"
113
119
table_d1 = src / "part16_d1.html"
@@ -153,7 +159,7 @@ def write_hash_file(paths: List[Path]) -> None:
153
159
else :
154
160
LOGGER .warning ("No checksums available to write to 'hashes.json'" )
155
161
156
- f .write ("}" )
162
+ f .write ("}\n " )
157
163
158
164
LOGGER .info (f"'hashes.json' written with { len (checksums )} entries" )
159
165
@@ -182,10 +188,13 @@ def write_snomed_file(codes: List[Tuple[str, str, str]]) -> None:
182
188
"# 'SRT': {snomed_id1: concept_id1, snomed_id2: ...},\n " ,
183
189
"# }\n " ,
184
190
"\n " ,
191
+ "from typing import Dict\n " ,
192
+ "\n \n " ,
185
193
]
186
194
)
187
195
188
- f .write ("mapping = {}\n " )
196
+ f .write ("mapping: Dict[str, Dict[str, str]] = {}\n " )
197
+
189
198
# Write the SCT to SRT mappings
190
199
f .write ("\n mapping['SCT'] = {\n " )
191
200
for sct , srt , meaning in sorted (codes , key = lambda x : int (x [0 ])):
@@ -229,10 +238,12 @@ def write_cid_file(cid_lists: CIDListType, name_for_cid: NameForCIDType) -> None
229
238
"# {scheme designator: <list of keywords for current cid>\n " ,
230
239
"# scheme_designator: ...}\n " ,
231
240
"\n " ,
241
+ "from typing import Dict, List\n " ,
242
+ "\n \n " ,
232
243
]
233
244
)
234
- f .write ("name_for_cid = {}\n " )
235
- f .write ("cid_concepts = {}\n " )
245
+ f .write ("name_for_cid: Dict[int, str] = {}\n " )
246
+ f .write ("cid_concepts: Dict[int, Dict[str, List[str]]] = {}\n " )
236
247
for cid , value in cid_lists .items ():
237
248
# cid: int
238
249
# value: Dict[str, List[str]]
@@ -273,12 +284,14 @@ def write_concept_files(concepts: ConceptType) -> None:
273
284
f"# Auto-generated by pydicom-data-sr\n " ,
274
285
"# -*- coding: utf-8 -*-\n " ,
275
286
"\n " ,
287
+ "from typing import Dict, List, Tuple\n " ,
288
+ "\n \n " ,
276
289
]
277
290
278
291
imports = []
279
292
top_indent = " " * 4
280
293
m_indent = " " * 8
281
- for scheme , top_value in concepts .items ():
294
+ for scheme , attr_codes in concepts .items ():
282
295
module = f"_concepts_{ scheme } "
283
296
variable = f"concepts_{ scheme } "
284
297
imports .append ((scheme , module , variable ))
@@ -292,21 +305,21 @@ def write_concept_files(concepts: ConceptType) -> None:
292
305
# concepts_scheme: {
293
306
# <top_value>,
294
307
# }
295
- f .write (f"{ variable } = {{\n " )
296
- for name , middle_value in sorted (top_value .items (), key = lambda x : x [0 ]):
297
- # name : str
298
- # middle_value : Dict[str, Tuple[str, List[int]]]
308
+ f .write (f"{ variable } : Dict[str, Dict[str, Tuple[str, List[int]]]] = {{\n " )
309
+ for attr , codes in sorted (attr_codes .items (), key = lambda x : x [0 ]):
310
+ # attr : str
311
+ # codes : Dict[str, Tuple[str, List[int]]]
299
312
# Write as:
300
- # name : {
313
+ # cc_name : {
301
314
# <middle_value>,
302
315
# },
303
- f .write (f'{ top_indent } "{ name } ": {{\n ' )
304
- for key , val in sorted (middle_value .items (), key = lambda x : x [0 ]):
305
- # key : str
306
- # val : Tuple[str, List[int]]
316
+ f .write (f'{ top_indent } "{ attr } ": {{\n ' )
317
+ for code , ( meaning , cids ) in sorted (codes .items (), key = lambda x : x [0 ]):
318
+ # code : str
319
+ # (meaning, cids) : Tuple[str, List[int]]
307
320
# Write as:
308
- # key : (str, List[int]),
309
- f .write (f'{ m_indent } "{ key } ": ("{ val [ 0 ] } ", { sorted (val [ 1 ] )} ),\n ' )
321
+ # code : (str, List[int]),
322
+ f .write (f'{ m_indent } "{ code } ": ("{ meaning } ", { sorted (cids )} ),\n ' )
310
323
311
324
f .write (f"{ top_indent } }},\n " )
312
325
@@ -317,11 +330,13 @@ def write_concept_files(concepts: ConceptType) -> None:
317
330
with open (CONCEPTS_FILE , "w" , encoding = "utf8" ) as f :
318
331
f .writelines (header )
319
332
for _ , module , variable in imports :
320
- # from sr.tables._cid_concepts_ <scheme> import _concepts_ <scheme>
333
+ # from sr.tables._concepts_ <scheme> import concepts_ <scheme>
321
334
f .write (f"from sr.tables.{ module } import { variable } \n " )
322
335
323
336
f .write ("\n \n " )
324
- f .write ("concepts = {\n " )
337
+ f .write (
338
+ "concepts: Dict[str, Dict[str, Dict[str, Tuple[str, List[int]]]]] = {\n "
339
+ )
325
340
for scheme , _ , variable in imports :
326
341
f .write (f' "{ scheme } ": { variable } ,\n ' )
327
342
f .write ("}\n " )
@@ -331,9 +346,6 @@ def write_version_file(dicom_version: str) -> None:
331
346
"""Write a new _version.py file"""
332
347
333
348
new_version = datetime .now ().strftime ("%Y.%m.%d" )
334
- if new_version == __version__ :
335
- raise RuntimeError ("Error updating the package: no change in version number" )
336
-
337
349
with open (VERSION_FILE , "w" ) as f :
338
350
f .write (f'__version__: str = "{ new_version } "\n ' )
339
351
f .write (f'__dicom_version__: str = "{ dicom_version } "\n ' )
@@ -348,27 +360,15 @@ def _setup_argparser() -> Any:
348
360
349
361
# General Options
350
362
gen_opts = parser .add_argument_group ("General Options" )
351
- gen_opts .add_argument (
352
- "-d" ,
353
- "--dev" ,
354
- help = "enable dev mode" ,
355
- action = "store_true" ,
356
- )
357
363
gen_opts .add_argument (
358
364
"--force-download" ,
359
- help = "force downloading the data tables" ,
365
+ help = "force downloading the data tables to a local directory " ,
360
366
action = "store_true" ,
361
367
default = False ,
362
368
)
363
369
gen_opts .add_argument (
364
370
"--force-regeneration" ,
365
- help = "force regenerating the data tables" ,
366
- action = "store_true" ,
367
- default = False ,
368
- )
369
- gen_opts .add_argument (
370
- "--clean" ,
371
- help = "remove all data files" ,
371
+ help = "force regenerating the data tables from local source data" ,
372
372
action = "store_true" ,
373
373
default = False ,
374
374
)
@@ -381,11 +381,14 @@ def _setup_argparser() -> Any:
381
381
logging .basicConfig (level = logging .DEBUG )
382
382
args = _setup_argparser ()
383
383
384
- src = None
385
- if args .dev :
386
- src = PACKAGE_DIR / "temp"
384
+ LOCAL_DIR = PACKAGE_DIR / "temp"
387
385
388
- if args .clean :
389
- pass
386
+ src = None
387
+ if args .force_regeneration or args .force_download :
388
+ src = LOCAL_DIR
390
389
391
- run (src , args .force_download , args .force_regeneration )
390
+ result = run (src , args .force_download , args .force_regeneration )
391
+ if "GITHUB_ACTION" in os .environ :
392
+ subprocess .run (
393
+ f"echo 'PACKAGE_UPDATED={ str (result )} ' >> $GITHUB_ENV" , shell = True
394
+ )
0 commit comments