66import logging
77import os
88from datetime import datetime
9- from typing import Final , Optional , TypedDict
9+ from typing import Final , Literal , Optional , TypedDict , cast
1010
1111from sqlalchemy import create_engine , event
1212from sqlalchemy .engine import Engine
3636)
3737
3838# Database connection parameters:
39- HLA_DB_USER : Final [str ] = os .environ .get ("HLA_DB_USER" )
40- HLA_DB_PASSWORD : Final [str ] = os .environ .get ("HLA_DB_PASSWORD" )
39+ HLA_DB_USER : Final [Optional [ str ] ] = os .environ .get ("HLA_DB_USER" )
40+ HLA_DB_PASSWORD : Final [Optional [ str ] ] = os .environ .get ("HLA_DB_PASSWORD" )
4141HLA_DB_HOST : Final [str ] = os .environ .get ("HLA_DB_HOST" , "192.168.67.7" )
42- HLA_DB_PORT : Final [int ] = os .environ .get ("HLA_DB_PORT" , 1521 )
42+ HLA_DB_PORT : Final [int ] = int ( os .environ .get ("HLA_DB_PORT" , 1521 ) )
4343HLA_DB_SERVICE_NAME : Final [str ] = os .environ .get ("HLA_DB_SERVICE_NAME" , "cfe" )
4444
45- HLA_ORACLE_LIB_PATH : Final [str ] = os .environ .get ("HLA_ORACLE_LIB_PATH" )
46-
47- # These are the "configuration files" that the algorithm uses; these are or may
48- # be updated, in which case you specify the path to the new version in the
49- # environment.
50- HLA_STANDARDS : Final [str ] = os .environ .get ("HLA_STANDARDS" )
51- HLA_FREQUENCIES : Final [str ] = os .environ .get ("HLA_FREQUENCIES" )
52-
53-
54- def prepare_interpretation_for_serialization (
55- interpretation : HLAInterpretation ,
56- locus : HLA_LOCUS ,
57- processing_datetime : datetime ,
58- ) -> HLASequenceA | HLASequenceB | HLASequenceC :
59- """
60- Prepare an HLA interpretation for output.
61- """
62- if locus == "A" :
63- return HLASequenceA .build_from_interpretation (
64- interpretation , processing_datetime
65- )
66- elif locus == "B" :
67- return HLASequenceB .build_from_interpretation (
68- interpretation , processing_datetime
69- )
70- return HLASequenceC .build_from_interpretation (interpretation , processing_datetime )
45+ HLA_ORACLE_LIB_PATH : Final [str ] = os .environ .get (
46+ "HLA_ORACLE_LIB_PATH" , "/opt/oracle/instant_client"
47+ )
7148
7249
7350class SequencesByLocus (TypedDict ):
@@ -91,10 +68,10 @@ def interpret_sequences(
9168
9269def clinical_hla_driver (
9370 input_dir : str ,
71+ hla_a_results : str ,
72+ hla_b_results : str ,
73+ hla_c_results : str ,
9474 db_engine : Optional [Engine ] = None ,
95- hla_a_results : Optional [str ] = None ,
96- hla_b_results : Optional [str ] = None ,
97- hla_c_results : Optional [str ] = None ,
9875 standards_path : Optional [str ] = None ,
9976 frequencies_path : Optional [str ] = None ,
10077) -> None :
@@ -105,7 +82,8 @@ def clinical_hla_driver(
10582 "C" : [],
10683 }
10784 for locus in ("B" , "C" ):
108- sequences [locus ] = read_bc_sequences (input_dir , locus , logger )
85+ b_or_c : Literal ["B" , "C" ] = cast (Literal ["B" , "C" ], locus )
86+ sequences [b_or_c ] = read_bc_sequences (input_dir , b_or_c , logger )
10987
11088 # Perform interpretations:
11189 interpretations : dict [HLA_LOCUS , list [HLAInterpretation ]] = {
@@ -116,25 +94,30 @@ def clinical_hla_driver(
11694 processing_datetime : datetime = datetime .now ()
11795 easyhla : EasyHLA = EasyHLA .use_config (standards_path , frequencies_path )
11896 for locus in ("A" , "B" , "C" ):
119- interpretations [locus ] = interpret_sequences (easyhla , sequences [locus ])
97+ interpretations [cast (HLA_LOCUS , locus )] = interpret_sequences (
98+ easyhla , sequences [cast (HLA_LOCUS , locus )]
99+ )
120100
121101 # Prepare the interpretations for output:
122102 seqs_for_db : SequencesByLocus = {
123103 "A" : [],
124104 "B" : [],
125105 "C" : [],
126106 }
127- for locus in ("A" , "B" , "C" ):
128- # Each locus has a slightly different schema in the database, so we
129- # customize for each one.
130- for interp in interpretations [locus ]:
131- seqs_for_db [locus ].append (
132- prepare_interpretation_for_serialization (
133- interp ,
134- locus ,
135- processing_datetime ,
136- )
137- )
107+ # This next bit looks repetitive but mypy didn't like my solution for doing
108+ # this in a loop (because each one is a different type).
109+ for interp in interpretations ["A" ]:
110+ seqs_for_db ["A" ].append (
111+ HLASequenceA .build_from_interpretation (interp , processing_datetime )
112+ )
113+ for interp in interpretations ["B" ]:
114+ seqs_for_db ["B" ].append (
115+ HLASequenceB .build_from_interpretation (interp , processing_datetime )
116+ )
117+ for interp in interpretations ["C" ]:
118+ seqs_for_db ["C" ].append (
119+ HLASequenceC .build_from_interpretation (interp , processing_datetime )
120+ )
138121
139122 # First, write to the output files:
140123 output_files : dict [HLA_LOCUS , str ] = {
@@ -148,19 +131,23 @@ def clinical_hla_driver(
148131 "C" : HLASequenceC .CSV_HEADER ,
149132 }
150133 for locus in ("A" , "B" , "C" ):
151- if len (seqs_for_db [locus ]) > 0 :
152- with open (output_files [locus ], "w" ) as f :
134+ if len (seqs_for_db [cast ( HLA_LOCUS , locus ) ]) > 0 :
135+ with open (output_files [cast ( HLA_LOCUS , locus ) ], "w" ) as f :
153136 result_csv : csv .DictWriter = csv .DictWriter (
154- f , fieldnames = csv_headers [locus ], extrasaction = "ignore"
137+ f ,
138+ fieldnames = csv_headers [cast (HLA_LOCUS , locus )],
139+ extrasaction = "ignore" ,
155140 )
156141 result_csv .writeheader ()
157- result_csv .writerows (dataclasses .asdict (x ) for x in seqs_for_db [locus ])
142+ result_csv .writerows (
143+ dataclasses .asdict (x ) for x in seqs_for_db [cast (HLA_LOCUS , locus )]
144+ )
158145
159146 # Finally, write to the DB.
160147 if db_engine is not None :
161148 with Session (db_engine ) as session :
162149 for locus in ("A" , "B" , "C" ):
163- session .add_all (seqs_for_db [locus ])
150+ session .add_all (seqs_for_db [cast ( HLA_LOCUS , locus ) ])
164151 session .commit ()
165152
166153
@@ -246,10 +233,10 @@ def schema_workaround(dbapi_connection, _):
246233
247234 clinical_hla_driver (
248235 args .input_dir ,
249- db_engine ,
250236 args .hla_a_results ,
251237 args .hla_b_results ,
252238 args .hla_c_results ,
239+ db_engine ,
253240 args .hla_standards ,
254241 args .hla_frequencies ,
255242 )
0 commit comments