medicafe 0.240613.0__py3-none-any.whl → 0.240716.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of medicafe might be problematic. Click here for more details.

MediBot/MediBot.bat CHANGED
@@ -11,6 +11,8 @@ set "medicafe_package=medicafe"
11
11
  set "upgrade_medicafe=F:\Medibot\update_medicafe.py"
12
12
  set "temp_file=F:\Medibot\last_update_timestamp.txt"
13
13
  set "firefox_path=C:\Program Files\Mozilla Firefox\firefox.exe"
14
+ set "claims_status_script=..\MediLink\MediLink_ClaimStatus.py"
15
+ set "deductible_script=..\MediLink\MediLink_Deductible.py"
14
16
  set "package_version="
15
17
  set PYTHONWARNINGS=ignore
16
18
 
@@ -99,14 +101,18 @@ if "!internet_available!"=="1" (
99
101
  echo 1. Check for MediCafe Package Updates
100
102
  echo 2. Download Email de Carol
101
103
  echo 3. MediLink Claims
104
+ echo 4. United Claims Status
105
+ echo 5. United Deductible
102
106
  )
103
- echo 4. Run MediBot
104
- echo 5. Exit
107
+ echo 6. Run MediBot
108
+ echo 7. Exit
105
109
  echo.
106
110
  set /p choice=Enter your choice:
107
111
 
108
- if "!choice!"=="5" goto end_script
109
- if "!choice!"=="4" goto medibot_flow
112
+ if "!choice!"=="7" goto end_script
113
+ if "!choice!"=="6" goto medibot_flow
114
+ if "!choice!"=="5" goto united_deductible
115
+ if "!choice!"=="4" goto united_claims_status
110
116
  if "!choice!"=="3" goto medilink_flow
111
117
  if "!choice!"=="2" goto download_emails
112
118
  if "!choice!"=="1" goto check_updates
@@ -168,6 +174,32 @@ if errorlevel 1 echo MediLink failed to execute.
168
174
  pause
169
175
  goto main_menu
170
176
 
177
+ :: United Claims Status
178
+ :united_claims_status
179
+ if "!internet_available!"=="0" (
180
+ echo No internet connection available.
181
+ goto main_menu
182
+ )
183
+ cls
184
+ echo Checking United Claims Status...
185
+ py "%claims_status_script%"
186
+ if errorlevel 1 echo Failed to check United Claims Status.
187
+ pause
188
+ goto main_menu
189
+
190
+ :: United Deductible
191
+ :united_deductible
192
+ if "!internet_available!"=="0" (
193
+ echo No internet connection available.
194
+ goto main_menu
195
+ )
196
+ cls
197
+ echo Checking United Deductible...
198
+ py "%deductible_script%"
199
+ if errorlevel 1 echo Failed to check United Deductible.
200
+ pause
201
+ goto main_menu
202
+
171
203
  :: Process CSV Files
172
204
  :process_csvs
173
205
  for /f "tokens=1-5 delims=/: " %%a in ('echo %time%') do (
@@ -203,4 +235,4 @@ goto :eof
203
235
  :end_script
204
236
  echo Exiting MediCafe.
205
237
  pause
206
- exit /b
238
+ exit /b
@@ -14,10 +14,10 @@ except ImportError:
14
14
  from MediLink import MediLink_ConfigLoader
15
15
 
16
16
  try:
17
- from MediLink_API_v2 import fetch_payer_name_from_api
17
+ from MediLink_API_v3 import fetch_payer_name_from_api
18
18
  except ImportError:
19
- from MediLink import MediLink_API_v2
20
- fetch_payer_name_from_api = MediLink_API_v2.fetch_payer_name_from_api
19
+ from MediLink import MediLink_API_v3
20
+ fetch_payer_name_from_api = MediLink_API_v3.fetch_payer_name_from_api
21
21
 
22
22
  try:
23
23
  from MediBot import MediBot_Preprocessor_lib
@@ -127,7 +127,7 @@ def initialize_crosswalk_from_mapat():
127
127
  validate_and_correct_payer_ids(crosswalk, config)
128
128
 
129
129
  # Save the initial crosswalk
130
- if save_crosswalk(config['MediLink_Config']['crosswalkPath'], crosswalk):
130
+ if save_crosswalk(config, crosswalk):
131
131
  message = "Crosswalk initialized with mappings for {} payers.".format(len(crosswalk.get('payer_id', {})))
132
132
  print(message)
133
133
  MediLink_ConfigLoader.log(message, config, level="INFO")
@@ -197,7 +197,7 @@ def crosswalk_update(config, crosswalk):
197
197
  crosswalk['payer_id'][payer_id]['medisoft_medicare_id'] = list(crosswalk['payer_id'][payer_id]['medisoft_medicare_id'])
198
198
 
199
199
  # Save the updated crosswalk to the specified file
200
- return save_crosswalk(config['MediLink_Config']['crosswalkPath'], crosswalk)
200
+ return save_crosswalk(config, crosswalk)
201
201
 
202
202
  def update_crosswalk_with_corrected_payer_id(old_payer_id, corrected_payer_id, config, crosswalk):
203
203
  """Updates the crosswalk with the corrected payer ID."""
@@ -216,7 +216,7 @@ def update_crosswalk_with_corrected_payer_id(old_payer_id, corrected_payer_id, c
216
216
  MediLink_ConfigLoader.log("Crosswalk csv_replacements updated: added {} -> {}".format(old_payer_id, corrected_payer_id), config, level="INFO")
217
217
 
218
218
  # Save the updated crosswalk
219
- return save_crosswalk(config['MediLink_Config']['crosswalkPath'], crosswalk)
219
+ return save_crosswalk(config, crosswalk)
220
220
 
221
221
  def update_crosswalk_with_new_payer_id(insurance_name, payer_id, config):
222
222
  """Updates the crosswalk with a new payer ID."""
@@ -229,14 +229,14 @@ def update_crosswalk_with_new_payer_id(insurance_name, payer_id, config):
229
229
  crosswalk['payer_id'][payer_id] = {"medisoft_id": [medisoft_id_str], "medisoft_medicare_id": []}
230
230
  else:
231
231
  crosswalk['payer_id'][payer_id]['medisoft_id'].append(medisoft_id_str)
232
- save_crosswalk(config['MediLink_Config']['crosswalkPath'], crosswalk)
232
+ save_crosswalk(config, crosswalk)
233
233
  MediLink_ConfigLoader.log("Updated crosswalk with new payer ID {} for insurance name {}".format(payer_id, insurance_name), config, level="INFO")
234
234
  else:
235
235
  message = "Failed to update crosswalk: Medisoft ID not found for insurance name {}".format(insurance_name)
236
236
  print(message)
237
237
  MediLink_ConfigLoader.log(message, config, level="ERROR")
238
238
 
239
- def save_crosswalk(crosswalk_path, crosswalk):
239
+ def save_crosswalk(config, crosswalk):
240
240
  """
241
241
  Saves the updated crosswalk to a JSON file.
242
242
  Args:
@@ -245,6 +245,13 @@ def save_crosswalk(crosswalk_path, crosswalk):
245
245
  Returns:
246
246
  bool: True if the file was successfully saved, False otherwise.
247
247
  """
248
+ # Attempt to fetch crosswalkPath from MediLink_Config
249
+ try:
250
+ crosswalk_path = config['MediLink_Config']['crosswalkPath']
251
+ except KeyError:
252
+ # If KeyError occurs, fall back to fetching crosswalkPath directly
253
+ crosswalk_path = config.get('crosswalkPath', None) # Replace None with a default value if needed
254
+
248
255
  try:
249
256
  # Initialize 'payer_id' key if not present
250
257
  if 'payer_id' not in crosswalk:
@@ -238,10 +238,19 @@ def parse_patient_id(text):
238
238
 
239
239
  def parse_diagnosis_code(text):
240
240
  try:
241
- if '(' in text and ')' in text: # Extract the diagnosis code before the '/'
242
- full_code = text[text.index('(')+1:text.index(')')]
243
- return full_code.split('/')[0]
244
- return text.split('/')[0]
241
+ # Regular expression to find all ICD-10 codes starting with 'H' and containing a period
242
+ pattern = re.compile(r'H\d{2}\.\d+')
243
+ matches = pattern.findall(text)
244
+
245
+ if matches:
246
+ return matches[0] # Return the first match
247
+ else:
248
+ # Fallback to original method if no match is found
249
+ if '(' in text and ')' in text: # Extract the diagnosis code before the '/'
250
+ full_code = text[text.index('(')+1:text.index(')')]
251
+ return full_code.split('/')[0]
252
+ return text.split('/')[0]
253
+
245
254
  except Exception as e:
246
255
  MediLink_ConfigLoader.log("Error parsing diagnosis code: {}. Error: {}".format(text, e))
247
256
  return "Unknown"
@@ -268,7 +277,6 @@ def parse_femto_yes_or_no(text):
268
277
  MediLink_ConfigLoader.log("Error parsing femto yes or no: {}. Error: {}".format(text, e))
269
278
  return False
270
279
 
271
-
272
280
  def rotate_docx_files(directory):
273
281
  # List all files in the directory
274
282
  files = os.listdir(directory)
MediLink/MediLink.py CHANGED
@@ -2,7 +2,6 @@ import os
2
2
  import MediLink_Down
3
3
  import MediLink_Up
4
4
  import MediLink_ConfigLoader
5
- import MediLink_837p_encoder
6
5
  import MediLink_DataMgmt
7
6
 
8
7
  # For UI Functions
@@ -19,73 +18,31 @@ from MediBot import MediBot_Preprocessor_lib
19
18
  load_insurance_data_from_mains = MediBot_Preprocessor_lib.load_insurance_data_from_mains
20
19
  from MediBot import MediBot_Crosswalk_Library
21
20
 
22
- # Define insurance options with codes and descriptions.
23
- # TODO This needs to move to the config file
24
- insurance_options = {
25
- "11": "Other Non-Federal Programs",
26
- "12": "Preferred Provider Organization (PPO)",
27
- "13": "Point of Service (POS)",
28
- "14": "Exclusive Provider Organization (EPO)",
29
- "15": "Indemnity Insurance",
30
- "16": "Health Maintenance Organization (HMO) Medicare Risk",
31
- "17": "Dental Maintenance Organization",
32
- "AM": "Automobile Medical",
33
- "BL": "Blue Cross/Blue Shield",
34
- "CH": "Champus",
35
- "CI": "Commercial Insurance Co.",
36
- "DS": "Disability",
37
- "FI": "Federal Employees Program",
38
- "HM": "Health Maintenance Organization",
39
- "LM": "Liability Medical",
40
- "MA": "Medicare Part A",
41
- "MB": "Medicare Part B",
42
- "MC": "Medicaid",
43
- "OF": "Other Federal Program",
44
- "TV": "Title V",
45
- "VA": "Veterans Affairs Plan",
46
- "WC": "Workers Compensation Health Claim",
47
- "ZZ": "Mutually Defined"
48
- }
49
-
50
- def detect_and_display_file_summaries(directory_path, config, crosswalk):
21
+ # Retrieve insurance options with codes and descriptions
22
+ config, _ = MediLink_ConfigLoader.load_configuration()
23
+ insurance_options = config['MediLink_Config'].get('insurance_options')
24
+
25
+ def collect_detailed_patient_data(selected_files, config, crosswalk):
51
26
  """
52
- Detects new files in the specified directory and prepares detailed patient data for processing,
53
- including suggestions for endpoints based on insurance provider information found in the config.
27
+ Collects detailed patient data from the selected files.
54
28
 
55
- :param directory_path: Path to the directory containing files to be detected.
29
+ :param selected_files: List of selected file paths.
56
30
  :param config: Configuration settings loaded from a JSON file.
57
31
  :param crosswalk: Crosswalk data for mapping purposes.
58
- :return: A tuple containing a list of new file paths and the detailed patient data.
32
+ :return: A list of detailed patient data.
59
33
  """
60
- try:
61
- new_files, file_flagged = MediLink_DataMgmt.detect_new_files(directory_path)
62
- if not new_files:
63
- print("No new claims detected. Check Medisoft claims output.")
64
- MediLink_ConfigLoader.log("No new claims detected. Check Medisoft claims output.")
65
- return False, []
66
-
67
- if not file_flagged:
68
- selected_files = MediLink_UI.user_select_files(new_files)
69
- else:
70
- # Extract the newest single latest file from the list
71
- selected_files = [max(new_files, key=os.path.getctime)]
72
-
73
- detailed_patient_data = [] # Initialize list for detailed patient data
74
- for file_path in selected_files:
75
- detailed_data = extract_and_suggest_endpoint(file_path, config, crosswalk)
76
- detailed_patient_data.extend(detailed_data) # Accumulate detailed data for processing
77
-
78
- # Enrich the detailed patient data with insurance type
79
- detailed_patient_data = enrich_with_insurance_type(detailed_patient_data, insurance_options)
34
+ detailed_patient_data = []
35
+ for file_path in selected_files:
36
+ detailed_data = extract_and_suggest_endpoint(file_path, config, crosswalk)
37
+ detailed_patient_data.extend(detailed_data) # Accumulate detailed data for processing
80
38
 
81
- # Display summaries and provide an option for bulk edit
82
- MediLink_UI.display_patient_summaries(detailed_patient_data)
39
+ # Enrich the detailed patient data with insurance type
40
+ detailed_patient_data = enrich_with_insurance_type(detailed_patient_data, insurance_options)
41
+
42
+ # Display summaries and provide an option for bulk edit
43
+ MediLink_UI.display_patient_summaries(detailed_patient_data)
83
44
 
84
- # Return the list of new files and the enriched detailed patient data
85
- return selected_files, detailed_patient_data
86
- except Exception as e:
87
- MediLink_ConfigLoader.log("Error in detect_and_display_file_summaries: {}".format(e))
88
- return False, []
45
+ return detailed_patient_data
89
46
 
90
47
  def enrich_with_insurance_type(detailed_patient_data, patient_insurance_type_mapping=None):
91
48
  """
@@ -299,17 +256,14 @@ def main_menu():
299
256
  # Normalize the directory path for file operations.
300
257
  directory_path = os.path.normpath(config['MediLink_Config']['inputFilePath'])
301
258
 
302
- # Detect new files and collect detailed patient data if available.
303
- new_files, detailed_patient_data = detect_and_display_file_summaries(directory_path, config, crosswalk)
304
-
305
- if new_files:
306
- handle_submission(detailed_patient_data, config)
259
+ # Detect files and determine if a new file is flagged.
260
+ all_files, file_flagged = MediLink_DataMgmt.detect_new_files(directory_path)
307
261
 
308
262
  while True:
309
263
  # Define the menu options. Base options include checking remittances and exiting the program.
310
264
  options = ["Check for new remittances", "Exit"]
311
- # If new files are detected, add the option to submit claims.
312
- if new_files:
265
+ # If any files are detected, add the option to submit claims.
266
+ if all_files:
313
267
  options.insert(1, "Submit claims")
314
268
 
315
269
  # Display the dynamically adjusted menu options.
@@ -320,11 +274,22 @@ def main_menu():
320
274
  if choice == '1':
321
275
  # Handle remittance checking.
322
276
  check_for_new_remittances(config)
323
- elif choice == '2' and new_files:
324
- # Handle the claims submission flow if new files are present.
325
- handle_submission(detailed_patient_data, config) # Since we have the bulk edit, we should actually go there first
326
- elif choice == '3' or (choice == '2' and not new_files):
327
- # Exit the program if the user chooses to exit or if no new files are present.
277
+ elif choice == '2' and all_files:
278
+ # Handle the claims submission flow if any files are present.
279
+ if file_flagged:
280
+ # Extract the newest single latest file from the list if a new file is flagged.
281
+ selected_files = [max(all_files, key=os.path.getctime)]
282
+ else:
283
+ # Prompt the user to select files if no new file is flagged.
284
+ selected_files = MediLink_UI.user_select_files(all_files)
285
+
286
+ # Collect detailed patient data for selected files.
287
+ detailed_patient_data = collect_detailed_patient_data(selected_files, config, crosswalk)
288
+
289
+ # Process the claims submission.
290
+ handle_submission(detailed_patient_data, config)
291
+ elif choice == '3' or (choice == '2' and not all_files):
292
+ # Exit the program if the user chooses to exit or if no files are present.
328
293
  MediLink_UI.display_exit_message()
329
294
  break
330
295
  else:
@@ -12,7 +12,7 @@ sys.path.append(project_dir)
12
12
  from MediBot import MediBot_Preprocessor_lib
13
13
  load_insurance_data_from_mains = MediBot_Preprocessor_lib.load_insurance_data_from_mains
14
14
  from MediBot import MediBot_Crosswalk_Library
15
- from MediLink_API_v2 import fetch_payer_name_from_api
15
+ from MediLink_API_v3 import fetch_payer_name_from_api
16
16
 
17
17
  # Converts date format from one format to another.
18
18
  def convert_date_format(date_str):
@@ -520,32 +520,9 @@ def insurance_type_selection(parsed_data):
520
520
 
521
521
  print("\nInsurance Type Validation Error: Select the insurance type for patient {}: ".format(parsed_data['LAST']))
522
522
 
523
- # Define insurance options with codes and descriptions
524
- insurance_options = {
525
- "11": "Other Non-Federal Programs",
526
- "12": "Preferred Provider Organization (PPO)",
527
- "13": "Point of Service (POS)",
528
- "14": "Exclusive Provider Organization (EPO)",
529
- "15": "Indemnity Insurance",
530
- "16": "Health Maintenance Organization (HMO) Medicare Risk",
531
- "17": "Dental Maintenance Organization",
532
- "AM": "Automobile Medical",
533
- "BL": "Blue Cross/Blue Shield",
534
- "CH": "Champus",
535
- "CI": "Commercial Insurance Co.",
536
- "DS": "Disability",
537
- "FI": "Federal Employees Program",
538
- "HM": "Health Maintenance Organization",
539
- "LM": "Liability Medical",
540
- "MA": "Medicare Part A",
541
- "MB": "Medicare Part B",
542
- "MC": "Medicaid",
543
- "OF": "Other Federal Program",
544
- "TV": "Title V",
545
- "VA": "Veterans Affairs Plan",
546
- "WC": "Workers Compensation Health Claim",
547
- "ZZ": "Mutually Defined"
548
- }
523
+ # Retrieve insurance options with codes and descriptions
524
+ config, _ = MediLink_ConfigLoader.load_configuration()
525
+ insurance_options = config['MediLink_Config'].get('insurance_options')
549
526
 
550
527
  def prompt_display_insurance_options():
551
528
  # Prompt to display full list
@@ -0,0 +1,246 @@
1
+ # This script requires Python 3.11 and is to be used for intalling new API clients.
2
+ import os
3
+ import time
4
+ import subprocess
5
+ import shutil
6
+ import tempfile
7
+ from pathlib import Path
8
+ from watchdog.observers import Observer
9
+ from watchdog.events import FileSystemEventHandler
10
+ from MediLink_API_v3 import ConfigLoader
11
+ import shlex
12
+ import re
13
+
14
+ class SwaggerHandler(FileSystemEventHandler):
15
+ def __init__(self, json_folder):
16
+ self.json_folder = json_folder
17
+
18
+ def on_created(self, event):
19
+ if event.is_directory:
20
+ return
21
+ if event.src_path.endswith('.yaml') or event.src_path.endswith('.json'):
22
+ print(f"New file detected: {event.src_path}")
23
+ time.sleep(2) # Add a short delay to ensure the file is ready for reading
24
+ self.process_swagger_file(event.src_path)
25
+
26
+ def process_swagger_file(self, file_path):
27
+ print(f"Processing file: {file_path}")
28
+ # Sanitize filename to replace spaces with underscores
29
+ sanitized_file_path = os.path.join(os.path.dirname(file_path), sanitize_filename(os.path.basename(file_path)))
30
+ if sanitized_file_path != file_path:
31
+ os.rename(file_path, sanitized_file_path)
32
+ print(f"Renamed file to: {sanitized_file_path}")
33
+ file_path = sanitized_file_path
34
+
35
+ with tempfile.TemporaryDirectory() as temp_dir:
36
+ temp_dir_path = Path(temp_dir)
37
+ temp_file_path = temp_dir_path / Path(file_path).name
38
+ config_path = temp_dir_path / 'openapi_config.json'
39
+ output_dir = temp_dir_path / "generated_client"
40
+
41
+ shutil.copy(file_path, temp_file_path)
42
+ config_source_path = Path(__file__).parent.parent / 'json' / 'openapi_config.json'
43
+ shutil.copy(config_source_path, config_path)
44
+ print(f"Copied files to: {temp_file_path} and {config_path}")
45
+
46
+ swagger_definitions = ConfigLoader.load_swagger_file(str(temp_file_path))
47
+ if swagger_definitions:
48
+ print(f"Swagger definitions loaded successfully from: {temp_file_path}")
49
+ if generate_api_client(temp_file_path, output_dir, config_path):
50
+ backport_code(output_dir)
51
+ move_generated_client(temp_dir, file_path)
52
+ provide_instructions(file_path)
53
+ else:
54
+ print(f"Failed to load Swagger definitions from: {temp_file_path}")
55
+
56
+ def sanitize_filename(filename):
57
+ return filename.replace(' ', '_')
58
+
59
+ def find_executable(name):
60
+ """Find the full path to an executable."""
61
+ for path in os.environ["PATH"].split(os.pathsep):
62
+ full_path = Path(path) / name
63
+ if full_path.is_file():
64
+ return str(full_path)
65
+ return None
66
+
67
+ def generate_api_client(swagger_path, output_path, config_path):
68
+ """
69
+ Generate the API client using openapi-generator-cli.
70
+ """
71
+ openapi_generator_path = find_executable('openapi-generator-cli.cmd')
72
+ if not openapi_generator_path:
73
+ print("openapi-generator-cli not found in PATH.")
74
+ return False
75
+
76
+ command = [
77
+ openapi_generator_path,
78
+ 'generate',
79
+ '-i', str(swagger_path),
80
+ '-g', 'python',
81
+ '-o', str(output_path),
82
+ '-c', str(config_path)
83
+ ]
84
+
85
+ print(f"Attempting command: {' '.join(command)}")
86
+
87
+ try:
88
+ result = subprocess.run(command, check=True, capture_output=True, text=True)
89
+ print("API client generated successfully.")
90
+ print(result.stdout)
91
+ print(result.stderr)
92
+ return True
93
+ except subprocess.CalledProcessError as e:
94
+ print("First attempt failed.")
95
+ print("Error generating API client:")
96
+ print(e.stdout)
97
+ print(e.stderr)
98
+
99
+ try:
100
+ print("Attempting with shell=True.")
101
+ result = subprocess.run(' '.join(command), check=True, shell=True, capture_output=True, text=True)
102
+ print("API client generated successfully with shell=True.")
103
+ print(result.stdout)
104
+ print(result.stderr)
105
+ return True
106
+ except subprocess.CalledProcessError as e:
107
+ print("Second attempt with shell=True failed.")
108
+ print("Error generating API client:")
109
+ print(e.stdout)
110
+ print(e.stderr)
111
+
112
+ try:
113
+ quoted_command = [
114
+ openapi_generator_path,
115
+ 'generate',
116
+ '-i', shlex.quote(str(swagger_path)),
117
+ '-g', 'python',
118
+ '-o', shlex.quote(str(output_path)),
119
+ '-c', shlex.quote(str(config_path))
120
+ ]
121
+ print(f"Attempting quoted command: {' '.join(quoted_command)}")
122
+ result = subprocess.run(' '.join(quoted_command), check=True, shell=True, capture_output=True, text=True)
123
+ print("API client generated successfully with quoted command.")
124
+ print(result.stdout)
125
+ print(result.stderr)
126
+ return True
127
+ except subprocess.CalledProcessError as e:
128
+ print("Third attempt with quoted command failed.")
129
+ print("Error generating API client:")
130
+ print(e.stdout)
131
+ print(e.stderr)
132
+
133
+ try:
134
+ print("Attempting with batch script.")
135
+ batch_script_content = f"""
136
+ @echo off
137
+ {openapi_generator_path} generate -i "{swagger_path}" -g python -o "{output_path}" -c "{config_path}"
138
+ """
139
+ batch_script_path = Path(tempfile.gettempdir()) / "generate_client.bat"
140
+ with open(batch_script_path, 'w') as batch_script:
141
+ batch_script.write(batch_script_content)
142
+
143
+ result = subprocess.run(str(batch_script_path), check=True, shell=True, capture_output=True, text=True)
144
+ print("API client generated successfully with batch script.")
145
+ print(result.stdout)
146
+ print(result.stderr)
147
+ return True
148
+ except subprocess.CalledProcessError as e:
149
+ print("Fourth attempt with batch script failed.")
150
+ print("Error generating API client:")
151
+ print(e.stdout)
152
+ print(e.stderr)
153
+
154
+ print("All attempts to generate API client failed.")
155
+ return False
156
+
157
+ def backport_code(output_dir):
158
+ for root, _, files in os.walk(output_dir):
159
+ for file in files:
160
+ if file.endswith('.py'):
161
+ file_path = os.path.join(root, file)
162
+ with open(file_path, 'r') as f:
163
+ code = f.read()
164
+
165
+ code = re.sub(r'f"(.*?)"', r'"\1".format', code) # Replace f-strings
166
+ code = re.sub(r'async def', 'def', code) # Remove async syntax
167
+ code = re.sub(r'await ', '', code) # Remove await syntax
168
+ code = re.sub(r':\s*\w+ =', '=', code) # Remove type hints in variable assignments
169
+ code = re.sub(r'def (\w+)\(.*?\) -> .*?:', r'def \1(', code) # Remove type hints in function definitions
170
+ code = re.sub(r'(from pydantic import.*)', '# \1', code) # Comment out pydantic imports
171
+ code = re.sub(r'(import pydantic)', '# \1', code) # Comment out pydantic imports
172
+
173
+ with open(file_path, 'w') as f:
174
+ f.write(code)
175
+ print(f"Backported {file_path}")
176
+
177
+ def move_generated_client(temp_dir, original_file_path):
178
+ api_name = Path(original_file_path).stem
179
+ destination_dir = Path('generated_clients') / api_name
180
+ if destination_dir.exists():
181
+ shutil.rmtree(destination_dir)
182
+ try:
183
+ shutil.move(str(Path(temp_dir) / 'generated_client'), str(destination_dir))
184
+ print(f"Moved generated client to {destination_dir}")
185
+ except FileNotFoundError as e:
186
+ print(f"Error moving generated client: {e}")
187
+ except Exception as e:
188
+ print(f"Unexpected error moving generated client: {e}")
189
+
190
+ def provide_instructions(swagger_path):
191
+ api_name = Path(swagger_path).stem
192
+ instructions = f"""
193
+ API Client for {api_name} has been generated successfully.
194
+
195
+ Integration Steps:
196
+ 1. Locate the generated client code in the 'generated_clients/{api_name}' directory.
197
+ 2. Integrate the generated client code into your project by following these steps:
198
+ a. Copy the generated client directory to your project's client directory.
199
+ b. Import the client classes in your project as needed.
200
+ c. Ensure that the generated client adheres to the BaseAPIClient interface if integrating with the existing system.
201
+ 3. Update your configuration to include the new API endpoint details.
202
+ 4. Test the integration thoroughly to ensure compatibility and functionality.
203
+
204
+ Example Integration:
205
+ from clients.generated.{api_name}.api_client import ApiClient as {api_name}Client
206
+
207
+ class New{api_name}APIClient(BaseAPIClient):
208
+ def __init__(self, config):
209
+ super().__init__(config)
210
+ self.generated_client = {api_name}Client()
211
+
212
+ def get_access_token(self, endpoint_name):
213
+ # Implement token retrieval logic
214
+ pass
215
+
216
+ def make_api_call(self, endpoint_name, call_type, url_extension="", params=None, data=None):
217
+ # Use the generated client to make the API call
218
+ if call_type == 'GET':
219
+ response = self.generated_client.call_api(url_extension, 'GET', params=params, header_params=headers)
220
+ elif call_type == 'POST':
221
+ response = self.generated_client.call_api(url_extension, 'POST', body=data, header_params=headers)
222
+ elif call_type == 'DELETE':
223
+ response = self.generated_client.call_api(url_extension, 'DELETE', header_params=headers)
224
+ else:
225
+ raise ValueError("Unsupported call type")
226
+ return response
227
+
228
+ """
229
+ print(instructions)
230
+
231
+ def main():
232
+ json_folder = os.path.normpath(os.path.join(os.path.dirname(__file__), '..', 'json'))
233
+ event_handler = SwaggerHandler(json_folder)
234
+ observer = Observer()
235
+ observer.schedule(event_handler, path=json_folder, recursive=False)
236
+ observer.start()
237
+ print(f"Monitoring folder: {json_folder}")
238
+ try:
239
+ while True:
240
+ time.sleep(1)
241
+ except KeyboardInterrupt:
242
+ observer.stop()
243
+ observer.join()
244
+
245
+ if __name__ == "__main__":
246
+ main()
@@ -1,3 +1,5 @@
1
+ # Unused archive backup. This has been superceded by API_v3
2
+
1
3
  import time
2
4
  import requests
3
5