medicafe 0.240419.2__py3-none-any.whl → 0.240613.0__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.

Files changed (38) hide show
  1. MediBot/MediBot.bat +174 -38
  2. MediBot/MediBot.py +80 -77
  3. MediBot/MediBot_Charges.py +0 -28
  4. MediBot/MediBot_Crosswalk_Library.py +281 -0
  5. MediBot/MediBot_Post.py +0 -0
  6. MediBot/MediBot_Preprocessor.py +138 -211
  7. MediBot/MediBot_Preprocessor_lib.py +496 -0
  8. MediBot/MediBot_UI.py +80 -35
  9. MediBot/MediBot_dataformat_library.py +79 -35
  10. MediBot/MediBot_docx_decoder.py +295 -0
  11. MediBot/update_medicafe.py +46 -8
  12. MediLink/MediLink.py +207 -108
  13. MediLink/MediLink_837p_encoder.py +299 -214
  14. MediLink/MediLink_837p_encoder_library.py +445 -245
  15. MediLink/MediLink_API_v2.py +174 -0
  16. MediLink/MediLink_APIs.py +139 -0
  17. MediLink/MediLink_ConfigLoader.py +44 -32
  18. MediLink/MediLink_DataMgmt.py +297 -89
  19. MediLink/MediLink_Decoder.py +63 -0
  20. MediLink/MediLink_Down.py +73 -102
  21. MediLink/MediLink_ERA_decoder.py +4 -4
  22. MediLink/MediLink_Gmail.py +479 -4
  23. MediLink/MediLink_Mailer.py +0 -0
  24. MediLink/MediLink_Parser.py +111 -0
  25. MediLink/MediLink_Scan.py +0 -0
  26. MediLink/MediLink_Scheduler.py +2 -131
  27. MediLink/MediLink_StatusCheck.py +0 -4
  28. MediLink/MediLink_UI.py +87 -27
  29. MediLink/MediLink_Up.py +301 -45
  30. MediLink/MediLink_batch.bat +1 -1
  31. MediLink/test.py +74 -0
  32. medicafe-0.240613.0.dist-info/METADATA +55 -0
  33. medicafe-0.240613.0.dist-info/RECORD +43 -0
  34. {medicafe-0.240419.2.dist-info → medicafe-0.240613.0.dist-info}/WHEEL +5 -5
  35. medicafe-0.240419.2.dist-info/METADATA +0 -19
  36. medicafe-0.240419.2.dist-info/RECORD +0 -32
  37. {medicafe-0.240419.2.dist-info → medicafe-0.240613.0.dist-info}/LICENSE +0 -0
  38. {medicafe-0.240419.2.dist-info → medicafe-0.240613.0.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,23 @@
1
1
  import re
2
2
  from datetime import datetime
3
3
  import re #for addresses
4
- from MediBot_Preprocessor import open_csv_for_editing, config, initialize
5
- from MediBot_UI import manage_script_pause
4
+
5
+ # Add parent directory of the project to the Python path
6
+ import os
7
+ import sys
8
+ project_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
9
+ sys.path.append(project_dir)
10
+
11
+ try:
12
+ from MediLink import MediLink_ConfigLoader
13
+ config, crosswalk = MediLink_ConfigLoader.load_configuration()
14
+ except ImportError:
15
+ from MediLink_ConfigLoader import load_configuration
16
+ config, crosswalk = load_configuration()
17
+
18
+ from MediBot_Preprocessor_lib import open_csv_for_editing, initialize
19
+ from MediBot_UI import manage_script_pause, app_control
20
+
6
21
 
7
22
  # Bring in all the constants
8
23
  initialize(config)
@@ -11,11 +26,13 @@ initialize(config)
11
26
  def format_name(value):
12
27
  if ',' in value:
13
28
  return value
14
- hyphenated_name_pattern = r'(?P<First>[\w-]+)\s+(?P<Middle>[\w-]+)?\s+(?P<Last>[\w-]+)'
29
+ hyphenated_name_pattern = r'(?P<First>[\w-]+)\s+(?P<Middle>[\w-]?)\s+(?P<Last>[\w-]+)'
15
30
  match = re.match(hyphenated_name_pattern, value)
16
31
  if match:
17
32
  first_name = match.group('First')
18
33
  middle_name = match.group('Middle') or ''
34
+ if len(middle_name) > 1:
35
+ middle_name = middle_name[0] # take only the first character
19
36
  last_name = match.group('Last')
20
37
  return '{}, {} {}'.format(last_name, first_name, middle_name).strip()
21
38
  parts = value.split()
@@ -43,70 +60,97 @@ def format_policy(value):
43
60
  def format_gender(value):
44
61
  return value[0].upper()
45
62
 
63
+ def enforce_significant_length(output):
64
+ # Replace spaces with a placeholder that counts as one significant digit
65
+ temp_output = output.replace('{Space}', ' ')
66
+
67
+ # Check if the number of significant digits exceeds 30
68
+ if len(temp_output) > 30:
69
+
70
+ # First line of defense: Replace ' APT ' with ' #' if the original length is longer than 30 characters.
71
+ temp_output = temp_output.replace(' APT ', ' #')
72
+
73
+ # Remove spaces in a controlled manner from right to left if still too long
74
+ while len(temp_output) > 30:
75
+ # Find the last space
76
+ last_space_index = temp_output.rfind(' ')
77
+ if last_space_index == -1:
78
+ break
79
+ # Remove the last space
80
+ temp_output = temp_output[:last_space_index] + temp_output[last_space_index+7:]
81
+
82
+ # If still greater than 30, truncate to 30 characters
83
+ if len(temp_output) > 30:
84
+ temp_output = temp_output[:30]
85
+
86
+ # Replace placeholder back with actual space for final return
87
+ return temp_output.replace(' ', '{Space}')
88
+
46
89
  def format_street(value, csv_data, reverse_mapping, parsed_address_components):
47
- global script_paused
48
- script_paused = False
90
+ # Temporarily disable script pause status
91
+ app_control.set_pause_status(False)
49
92
 
50
- # Remove periods from the input (seems to be an XP-only issue?)
93
+ # Remove period characters.
51
94
  value = value.replace('.', '')
52
95
 
53
- # Only proceed with parsing if a comma is present in the value
96
+ # Proceed only if there's a comma, indicating a likely full address
54
97
  if ',' in value:
55
98
  try:
56
- # Access the common cities from the loaded configuration
99
+ MediLink_ConfigLoader.log("Attempting to resolve address via regex...")
100
+ # Retrieve common city names from configuration and prepare a regex pattern
57
101
  common_cities = config.get('cities', [])
58
-
59
- # Convert cities to a case-insensitive regex pattern
60
102
  city_pattern = '|'.join(re.escape(city) for city in common_cities)
61
103
  city_regex_pattern = r'(?P<City>{})'.format(city_pattern)
62
104
  city_regex = re.compile(city_regex_pattern, re.IGNORECASE)
63
105
 
64
- # Check if the address contains one of the common cities
106
+ # Search for a common city in the address
65
107
  city_match = city_regex.search(value)
66
108
 
67
109
  if city_match:
68
- city = city_match.group('City').upper() # Normalize city name to uppercase
110
+ # Extract city name and partition the value around it
111
+ city = city_match.group('City').upper()
69
112
  street, _, remainder = value.partition(city)
70
-
71
- # Extract state and zip code from the remainder
113
+
114
+ # Regex pattern to find state and zip code in the remainder
72
115
  address_pattern = r',\s*(?P<State>[A-Z]{2})\s*(?P<Zip>\d{5}(?:-\d{4})?)?'
73
-
74
116
  match = re.search(address_pattern, remainder)
75
-
117
+
76
118
  if match:
77
- # Update global parsed address components
119
+ # Update parsed address components
78
120
  parsed_address_components['City'] = city
79
121
  parsed_address_components['State'] = match.group('State')
80
122
  parsed_address_components['Zip Code'] = match.group('Zip')
81
-
82
- return street.strip() # Return formatted street address
123
+ # Return formatted street address, enforcing significant length
124
+ return enforce_significant_length(street.strip())
83
125
  else:
84
- # Fallback to old regex
85
- # value = street + ', ' + city + remainder
126
+ # Fallback regex for parsing addresses without a common city
86
127
  address_pattern = r'(?P<Street>[\w\s]+),?\s+(?P<City>[\w\s]+),\s*(?P<State>[A-Z]{2})\s*(?P<Zip>\d{5}(-\d{4})?)'
87
128
  match = re.match(address_pattern, value)
88
129
 
89
130
  if match:
90
- # Update global parsed address components
131
+ # Update parsed address components
91
132
  parsed_address_components['City'] = match.group('City')
92
133
  parsed_address_components['State'] = match.group('State')
93
134
  parsed_address_components['Zip Code'] = match.group('Zip')
94
-
95
- return match.group('Street').strip() # Return formatted street address
135
+ # Return formatted street address, enforcing significant length
136
+ return enforce_significant_length(match.group('Street').strip())
96
137
 
97
138
  except Exception as e:
139
+ # Handle exceptions by logging and offering to correct data manually
98
140
  print("Address format error: Unable to parse address '{}'. Error: {}".format(value, e))
99
- print("Please update the CSV file for this record.")
100
- script_paused = True
101
- open_csv_for_editing(CSV_FILE_PATH) # Offer to open the CSV for manual correction
102
- manage_script_pause(csv_data, e, reverse_mapping)
103
- return value.replace(' ', '{Space}') # Fallback to return original value with spaces escaped
141
+ app_control.set_pause_status(True)
142
+ open_csv_for_editing(CSV_FILE_PATH)
143
+ manage_script_pause(csv_data, e, reverse_mapping)
144
+ # Return original value with spaces formatted, enforcing significant length
145
+ return enforce_significant_length(value.replace(' ', '{Space}'))
104
146
  else:
105
- # If no comma is present, return the value as is, assuming it's just a street name
106
- return value.replace(' ', '{Space}')
107
-
108
- # This return acts as a fallback in case the initial comma check passes but no address components are matched
109
- return value.replace(' ', '{Space}')
147
+ # If no comma is present, treat the input as a simple street name
148
+ formatted_value = value.replace(' ', '{Space}')
149
+ enforced_format = enforce_significant_length(formatted_value)
150
+ return enforced_format
151
+
152
+ # Fallback return in case no address components are matched even though a comma was present
153
+ return enforce_significant_length(value.replace(' ', '{Space}'))
110
154
 
111
155
  def format_zip(value):
112
156
  # Ensure the value is a string, in case it's provided as an integer
@@ -138,7 +182,7 @@ def format_data(medisoft_field, value, csv_data, reverse_mapping, parsed_address
138
182
  elif medisoft_field == 'Secondary Group Number':
139
183
  formatted_value = format_policy(value)
140
184
  else:
141
- formatted_value = value
185
+ formatted_value = str(value) # Ensure value is always a string
142
186
 
143
187
  formatted_value = formatted_value.replace(',', '{,}').replace(' ', '{Space}')
144
188
  ahk_command = 'SendInput, {}{{Enter}}'.format(formatted_value)
@@ -0,0 +1,295 @@
1
+ from docx import Document
2
+ import re
3
+ from lxml import etree
4
+ import zipfile
5
+ from datetime import datetime
6
+ import os
7
+ import sys
8
+ from collections import OrderedDict
9
+
10
+ # Add parent directory of the project to the Python path
11
+ project_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
12
+ sys.path.append(project_dir)
13
+
14
+ try:
15
+ import MediLink_ConfigLoader
16
+ except ImportError:
17
+ from MediLink import MediLink_ConfigLoader
18
+
19
+ def parse_docx(filepath):
20
+ try:
21
+ doc = Document(filepath) # Open the .docx file
22
+ except Exception as e:
23
+ MediLink_ConfigLoader.log("Error opening document: {}".format(e)) # Log error
24
+ return {}
25
+
26
+ patient_data = OrderedDict() # Initialize OrderedDict to store data
27
+ MediLink_ConfigLoader.log("Extracting Date of Service from {}".format(filepath), level="DEBUG")
28
+
29
+ date_of_service = extract_date_of_service(filepath) # Extract date of service
30
+ MediLink_ConfigLoader.log("Date of Service recorded as: {}".format(date_of_service), level="DEBUG")
31
+
32
+ for table in doc.tables: # Iterate over tables in the document
33
+ for row in table.rows:
34
+ cells = [cell.text.strip() for cell in row.cells]
35
+ if len(cells) > 4 and cells[3].startswith('#'):
36
+ try:
37
+ patient_id = parse_patient_id(cells[3])
38
+ diagnosis_code = parse_diagnosis_code(cells[4])
39
+ left_or_right_eye = parse_left_or_right_eye(cells[4])
40
+ femto_yes_or_no = parse_femto_yes_or_no(cells[4])
41
+
42
+ if patient_id not in patient_data:
43
+ patient_data[patient_id] = {}
44
+
45
+ if date_of_service in patient_data[patient_id]:
46
+ MediLink_ConfigLoader.log("Duplicate entry for patient ID {} on date {}. Skipping.".format(patient_id, date_of_service))
47
+ else:
48
+ patient_data[patient_id][date_of_service] = [diagnosis_code, left_or_right_eye, femto_yes_or_no]
49
+ except Exception as e:
50
+ MediLink_ConfigLoader.log("Error processing row: {}. Error: {}".format(cells, e))
51
+
52
+ # Validation steps
53
+ validate_unknown_entries(patient_data)
54
+ validate_diagnostic_code(patient_data)
55
+
56
+ return patient_data
57
+
58
+ def validate_unknown_entries(patient_data):
59
+ for patient_id, dates in list(patient_data.items()):
60
+ for date, details in list(dates.items()):
61
+ if 'Unknown' in details:
62
+ warning_message = "Warning: 'Unknown' entry found. Patient ID: {}, Date: {}, Details: {}".format(patient_id, date, details)
63
+ MediLink_ConfigLoader.log(warning_message, level="WARNING")
64
+ print(warning_message)
65
+ del patient_data[patient_id][date]
66
+ if not patient_data[patient_id]: # If no dates left for the patient, remove the patient
67
+ del patient_data[patient_id]
68
+
69
+ def validate_diagnostic_code(patient_data):
70
+ for patient_id, dates in patient_data.items():
71
+ for date, details in dates.items():
72
+ diagnostic_code, eye, _ = details
73
+ if diagnostic_code[-1].isdigit():
74
+ if eye == 'Left' and not diagnostic_code.endswith('2'):
75
+ log_and_warn(patient_id, date, diagnostic_code, eye)
76
+ elif eye == 'Right' and not diagnostic_code.endswith('1'):
77
+ log_and_warn(patient_id, date, diagnostic_code, eye)
78
+
79
+ def log_and_warn(patient_id, date, diagnostic_code, eye):
80
+ warning_message = (
81
+ "Warning: Mismatch found for Patient ID: {}, Date: {}, "
82
+ "Diagnostic Code: {}, Eye: {}".format(patient_id, date, diagnostic_code, eye)
83
+ )
84
+ MediLink_ConfigLoader.log(warning_message, level="WARNING")
85
+ print(warning_message)
86
+
87
+ # Extract and parse the date of service from the .docx file
88
+ def extract_date_of_service(docx_path):
89
+ extract_to = "extracted_docx"
90
+ try:
91
+ if not os.path.exists(extract_to):
92
+ os.makedirs(extract_to)
93
+ with zipfile.ZipFile(docx_path, 'r') as docx:
94
+ docx.extractall(extract_to)
95
+ MediLink_ConfigLoader.log("Extracted DOCX to: {}".format(extract_to), level="DEBUG")
96
+
97
+ file_path = find_text_in_xml(extract_to, "Surgery Schedule")
98
+ if file_path:
99
+ return extract_date_from_file(file_path)
100
+ else:
101
+ MediLink_ConfigLoader.log("Target text 'Surgery Schedule' not found in any XML files.", level="WARNING")
102
+ return None
103
+ finally:
104
+ # Clean up the extracted files
105
+ remove_directory(extract_to)
106
+ MediLink_ConfigLoader.log("Cleaned up extracted files in: {}".format(extract_to), level="DEBUG")
107
+
108
+ def remove_directory(path):
109
+ if os.path.exists(path):
110
+ for root, dirs, files in os.walk(path, topdown=False):
111
+ for name in files:
112
+ os.remove(os.path.join(root, name))
113
+ for name in dirs:
114
+ os.rmdir(os.path.join(root, name))
115
+ os.rmdir(path)
116
+
117
+ # Find the target text in the extracted XML files
118
+ def find_text_in_xml(directory, target_text):
119
+ for root_dir, dirs, files in os.walk(directory):
120
+ for file in files:
121
+ if file.endswith('.xml'):
122
+ file_path = os.path.join(root_dir, file)
123
+ try:
124
+ tree = etree.parse(file_path)
125
+ root = tree.getroot()
126
+ namespaces = {'w': 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'} # hardcoded for XP handling BUG
127
+ for elem in root.xpath('//w:t', namespaces=namespaces):
128
+ if elem.text and target_text in elem.text:
129
+ MediLink_ConfigLoader.log("Found target text in file: {}".format(file_path), level="DEBUG")
130
+ return file_path
131
+ except Exception as e:
132
+ MediLink_ConfigLoader.log("Error parsing XML file {}: {}".format(file_path, e))
133
+ print("Error parsing XML file {}: {}".format(file_path, e))
134
+ return None
135
+
136
+ # Normalize month and day abbreviations
137
+ def normalize_text(text):
138
+ month_map = {
139
+ 'JAN': 'JANUARY', 'FEB': 'FEBRUARY', 'MAR': 'MARCH', 'APR': 'APRIL',
140
+ 'MAY': 'MAY', 'JUN': 'JUNE', 'JUL': 'JULY', 'AUG': 'AUGUST',
141
+ 'SEP': 'SEPTEMBER', 'OCT': 'OCTOBER', 'NOV': 'NOVEMBER', 'DEC': 'DECEMBER'
142
+ }
143
+ day_map = {
144
+ 'MON': 'MONDAY', 'TUE': 'TUESDAY', 'WED': 'WEDNESDAY', 'THU': 'THURSDAY',
145
+ 'FRI': 'FRIDAY', 'SAT': 'SATURDAY', 'SUN': 'SUNDAY'
146
+ }
147
+
148
+ for abbr, full in month_map.items():
149
+ text = re.sub(r'\b' + abbr + r'\b', full, text, flags=re.IGNORECASE)
150
+ for abbr, full in day_map.items():
151
+ text = re.sub(r'\b' + abbr + r'\b', full, text, flags=re.IGNORECASE)
152
+
153
+ return text
154
+
155
+ def reassemble_year(text):
156
+ # First, handle the most common case where a 4-digit year is split as (3,1), (1,3), or (2,2)
157
+ text = re.sub(r'(\d{3}) (\d{1})', r'\1\2', text)
158
+ text = re.sub(r'(\d{1}) (\d{3})', r'\1\2', text)
159
+ text = re.sub(r'(\d{2}) (\d{2})', r'\1\2', text)
160
+
161
+ # Handle the less common cases where the year might be split as (1,1,2) or (2,1,1) or (1,2,1)
162
+ parts = re.findall(r'\b(\d{1,2})\b', text)
163
+ if len(parts) >= 4:
164
+ for i in range(len(parts) - 3):
165
+ candidate = ''.join(parts[i:i + 4])
166
+ if len(candidate) == 4 and candidate.isdigit():
167
+ combined_year = candidate
168
+ text = re.sub(r'\b' + r'\b \b'.join(parts[i:i + 4]) + r'\b', combined_year, text)
169
+ break
170
+
171
+ return text
172
+
173
+ # Extract and parse the date from the file
174
+ def extract_date_from_file(file_path):
175
+ try:
176
+ tree = etree.parse(file_path)
177
+ root = tree.getroot()
178
+ collected_text = []
179
+
180
+ namespaces = {'w': 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'} # hardcoded for XP handling BUG
181
+ for elem in root.xpath('//w:t', namespaces=namespaces):
182
+ if elem.text:
183
+ collected_text.append(elem.text.strip())
184
+
185
+ for elem in root.iter():
186
+ if elem.tag.endswith('t') and elem.text:
187
+ collected_text.append(elem.text.strip())
188
+
189
+ combined_text = ' '.join(collected_text)
190
+ combined_text = reassemble_year(combined_text) # Fix OCR splitting years
191
+ # combined_text = re.sub(r'(\d{3}) (\d{1})', r'\1\2', combined_text) # initial year regex.
192
+ combined_text = normalize_text(combined_text) # Normalize abbreviations
193
+ combined_text = re.sub(r',', '', combined_text) # Remove commas if they exist
194
+
195
+ # Log the combined text
196
+ MediLink_ConfigLoader.log("Combined text: {}".format(combined_text), level="DEBUG")
197
+ # print("DEBUG: Combined text: {}".format(combined_text))
198
+
199
+ day_week_pattern = r"(MONDAY|TUESDAY|WEDNESDAY|THURSDAY|FRIDAY|SATURDAY|SUNDAY)"
200
+ month_day_pattern = r"(JANUARY|FEBRUARY|MARCH|APRIL|MAY|JUNE|JULY|AUGUST|SEPTEMBER|OCTOBER|NOVEMBER|DECEMBER) \d{1,2}"
201
+ year_pattern = r"\d{4}"
202
+
203
+ day_of_week = re.search(day_week_pattern, combined_text, re.IGNORECASE)
204
+ month_day = re.search(month_day_pattern, combined_text, re.IGNORECASE)
205
+ year_match = re.search(year_pattern, combined_text, re.IGNORECASE)
206
+
207
+ # Log the results of the regex searches
208
+ MediLink_ConfigLoader.log("Day of week found: {}".format(day_of_week.group() if day_of_week else 'None'), level="DEBUG")
209
+ MediLink_ConfigLoader.log("Month and day found: {}".format(month_day.group() if month_day else 'None'), level="DEBUG")
210
+ MediLink_ConfigLoader.log("Year found: {}".format(year_match.group() if year_match else 'None'), level="DEBUG")
211
+
212
+ if day_of_week and month_day and year_match:
213
+ date_str = "{} {} {}".format(day_of_week.group(), month_day.group(), year_match.group())
214
+ try:
215
+ date_obj = datetime.strptime(date_str, '%A %B %d %Y')
216
+ return date_obj.strftime('%m-%d-%Y')
217
+ except ValueError as e:
218
+ MediLink_ConfigLoader.log("Error converting date: {}. Error: {}".format(date_str, e), level="ERROR")
219
+ else:
220
+ MediLink_ConfigLoader.log("Date components not found or incomplete in the text. Combined text: {}, Day of week: {}, Month and day: {}, Year: {}"
221
+ .format(combined_text,
222
+ day_of_week.group() if day_of_week else 'None',
223
+ month_day.group() if month_day else 'None',
224
+ year_match.group() if year_match else 'None'),
225
+ level="WARNING")
226
+ except Exception as e:
227
+ MediLink_ConfigLoader.log("Error extracting date from file: {}. Error: {}".format(file_path, e))
228
+ print("Error extracting date from file: {}. Error: {}".format(file_path, e))
229
+
230
+ return None
231
+
232
+ def parse_patient_id(text):
233
+ try:
234
+ return text.split()[0].lstrip('#') # Extract patient ID number (removing the '#')
235
+ except Exception as e:
236
+ MediLink_ConfigLoader.log("Error parsing patient ID: {}. Error: {}".format(text, e))
237
+ return None
238
+
239
+ def parse_diagnosis_code(text):
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]
245
+ except Exception as e:
246
+ MediLink_ConfigLoader.log("Error parsing diagnosis code: {}. Error: {}".format(text, e))
247
+ return "Unknown"
248
+
249
+ def parse_left_or_right_eye(text):
250
+ try:
251
+ if 'LEFT EYE' in text.upper():
252
+ return 'Left'
253
+ elif 'RIGHT EYE' in text.upper():
254
+ return 'Right'
255
+ else:
256
+ return 'Unknown'
257
+ except Exception as e:
258
+ MediLink_ConfigLoader.log("Error parsing left or right eye: {}. Error: {}".format(text, e))
259
+ return 'Unknown'
260
+
261
+ def parse_femto_yes_or_no(text):
262
+ try:
263
+ if 'FEMTO' in text.upper():
264
+ return True
265
+ else:
266
+ return False
267
+ except Exception as e:
268
+ MediLink_ConfigLoader.log("Error parsing femto yes or no: {}. Error: {}".format(text, e))
269
+ return False
270
+
271
+
272
+ def rotate_docx_files(directory):
273
+ # List all files in the directory
274
+ files = os.listdir(directory)
275
+
276
+ # Filter files that contain "DR" and "SS" in the filename
277
+ filtered_files = [file for file in files if "DR" in file and "SS" in file]
278
+
279
+ # Iterate through filtered files
280
+ for filename in filtered_files:
281
+ filepath = os.path.join(directory, filename)
282
+ # Parse each document and print the resulting dictionary
283
+ patient_data_dict = parse_docx(filepath)
284
+ print("Data from file '{}':".format(filename))
285
+ import pprint
286
+ pprint.pprint(patient_data_dict)
287
+ print()
288
+
289
+ def main():
290
+ # Call the function with the directory containing your .docx files
291
+ directory = "C:\\Users\\danie\\Downloads\\"
292
+ rotate_docx_files(directory)
293
+
294
+ if __name__ == "__main__":
295
+ main()
@@ -1,17 +1,55 @@
1
1
  import subprocess
2
2
  import sys
3
3
  from tqdm import tqdm
4
+ import requests
5
+ import time
6
+
7
+ def check_internet_connection():
8
+ try:
9
+ requests.get("http://www.google.com", timeout=5)
10
+ return True
11
+ except requests.ConnectionError:
12
+ return False
4
13
 
5
14
  def upgrade_medicafe(package):
6
15
  try:
7
- # Use tqdm to create a progress bar
8
- with tqdm(total=100, desc="Upgrading %s" % package, unit="%") as progress_bar:
9
- subprocess.check_call([sys.executable, '-m', 'pip', 'install', '--upgrade', package, '--no-deps', '--disable-pip-version-check'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
10
- # Update progress bar to 100% upon completion
11
- progress_bar.update(100 - progress_bar.n)
12
- print("Update successful.")
13
- except subprocess.CalledProcessError:
14
- print("Update failed. Please check your internet connection and try again later.")
16
+ # Check internet connection
17
+ if not check_internet_connection():
18
+ print("Error: No internet connection detected. Please check your internet connection and try again.")
19
+ sys.exit(1)
20
+
21
+ total_progress = 200 # Total progress for two runs
22
+
23
+ with tqdm(total=total_progress, desc="Upgrading %s" % package, unit="%") as progress_bar:
24
+ stdout_accumulator = b""
25
+ stderr_accumulator = b""
26
+
27
+ for _ in range(2): # Run pip install twice
28
+ process = subprocess.Popen([sys.executable, '-m', 'pip', 'install', '--upgrade', package, '--no-cache-dir', '--disable-pip-version-check', '--no-deps'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
29
+ stdout, stderr = process.communicate()
30
+ stdout_accumulator += stdout
31
+ stderr_accumulator += stderr
32
+
33
+ if process.returncode != 0:
34
+ # If the return code is non-zero, print error details
35
+ print("Error: Upgrade failed. Details:")
36
+ print("stdout:", stdout)
37
+ print("stderr:", stderr)
38
+ sys.exit(1)
39
+
40
+ progress_bar.update(total_progress // 2) # Update progress bar
41
+
42
+ # Add a 3-second sleep between runs
43
+ time.sleep(3)
44
+
45
+ progress_bar.update(total_progress // 2) # Update progress bar
46
+ print("stdout:", stdout_accumulator.decode("utf-8"))
47
+ print("stderr:", stderr_accumulator.decode("utf-8"))
48
+ time.sleep(1)
49
+ except Exception as e:
50
+ # Log any other exceptions
51
+ print("Error:", e)
52
+ time.sleep(3)
15
53
  sys.exit(1)
16
54
 
17
55
  if __name__ == "__main__":