medicafe 0.250810.4__tar.gz → 0.250810.6__tar.gz

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.
Files changed (74) hide show
  1. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediBot/MediBot.bat +6 -2
  2. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediCafe/__main__.py +46 -29
  3. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediCafe/core_utils.py +116 -12
  4. {medicafe-0.250810.4/medicafe.egg-info → medicafe-0.250810.6}/PKG-INFO +1 -1
  5. {medicafe-0.250810.4 → medicafe-0.250810.6/medicafe.egg-info}/PKG-INFO +1 -1
  6. {medicafe-0.250810.4 → medicafe-0.250810.6}/setup.py +1 -1
  7. {medicafe-0.250810.4 → medicafe-0.250810.6}/LICENSE +0 -0
  8. {medicafe-0.250810.4 → medicafe-0.250810.6}/MANIFEST.in +0 -0
  9. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediBot/MediBot.py +0 -0
  10. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediBot/MediBot_Charges.py +0 -0
  11. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediBot/MediBot_Crosswalk_Library.py +0 -0
  12. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediBot/MediBot_Crosswalk_Utils.py +0 -0
  13. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediBot/MediBot_Post.py +0 -0
  14. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediBot/MediBot_Preprocessor.py +0 -0
  15. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediBot/MediBot_Preprocessor_lib.py +0 -0
  16. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediBot/MediBot_UI.py +0 -0
  17. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediBot/MediBot_dataformat_library.py +0 -0
  18. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediBot/MediBot_docx_decoder.py +0 -0
  19. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediBot/MediBot_smart_import.py +0 -0
  20. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediBot/__init__.py +0 -0
  21. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediBot/get_medicafe_version.py +0 -0
  22. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediBot/update_json.py +0 -0
  23. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediBot/update_medicafe.py +0 -0
  24. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediCafe/MediLink_ConfigLoader.py +0 -0
  25. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediCafe/__init__.py +0 -0
  26. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediCafe/api_core.py +0 -0
  27. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediCafe/api_core_backup.py +0 -0
  28. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediCafe/api_factory.py +0 -0
  29. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediCafe/api_utils.py +0 -0
  30. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediCafe/graphql_utils.py +0 -0
  31. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediCafe/logging_config.py +0 -0
  32. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediCafe/logging_demo.py +0 -0
  33. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediCafe/migration_helpers.py +0 -0
  34. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediCafe/smart_import.py +0 -0
  35. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_837p_cob_library.py +0 -0
  36. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_837p_encoder.py +0 -0
  37. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_837p_encoder_library.py +0 -0
  38. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_837p_utilities.py +0 -0
  39. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_API_Generator.py +0 -0
  40. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_Azure.py +0 -0
  41. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_ClaimStatus.py +0 -0
  42. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_DataMgmt.py +0 -0
  43. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_Decoder.py +0 -0
  44. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_Deductible.py +0 -0
  45. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_Deductible_Validator.py +0 -0
  46. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_Display_Utils.py +0 -0
  47. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_Down.py +0 -0
  48. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_Gmail.py +0 -0
  49. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_Mailer.py +0 -0
  50. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_Parser.py +0 -0
  51. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_PatientProcessor.py +0 -0
  52. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_Scan.py +0 -0
  53. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_Scheduler.py +0 -0
  54. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_UI.py +0 -0
  55. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_Up.py +0 -0
  56. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_insurance_utils.py +0 -0
  57. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_main.py +0 -0
  58. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/MediLink_smart_import.py +0 -0
  59. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/Soumit_api.py +0 -0
  60. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/__init__.py +0 -0
  61. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/insurance_type_integration_test.py +0 -0
  62. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/openssl.cnf +0 -0
  63. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/test.py +0 -0
  64. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/test_cob_library.py +0 -0
  65. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/test_timing.py +0 -0
  66. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/test_validation.py +0 -0
  67. {medicafe-0.250810.4 → medicafe-0.250810.6}/MediLink/webapp.html +0 -0
  68. {medicafe-0.250810.4 → medicafe-0.250810.6}/medicafe.egg-info/SOURCES.txt +0 -0
  69. {medicafe-0.250810.4 → medicafe-0.250810.6}/medicafe.egg-info/dependency_links.txt +0 -0
  70. {medicafe-0.250810.4 → medicafe-0.250810.6}/medicafe.egg-info/entry_points.txt +0 -0
  71. {medicafe-0.250810.4 → medicafe-0.250810.6}/medicafe.egg-info/not-zip-safe +0 -0
  72. {medicafe-0.250810.4 → medicafe-0.250810.6}/medicafe.egg-info/requires.txt +0 -0
  73. {medicafe-0.250810.4 → medicafe-0.250810.6}/medicafe.egg-info/top_level.txt +0 -0
  74. {medicafe-0.250810.4 → medicafe-0.250810.6}/setup.cfg +0 -0
@@ -25,6 +25,8 @@ echo ========================================
25
25
  echo DEBUG MODE (INTERACTIVE)
26
26
  echo ========================================
27
27
  echo Running full diagnostic suite...
28
+ set "MEDICAFE_IMPORT_DEBUG=1"
29
+ set "MEDICAFE_IMPORT_STRICT=0"
28
30
  echo.
29
31
  set "SKIP_CLS_AFTER_DEBUG=1"
30
32
  call "%~dp0full_debug_suite.bat" /interactive
@@ -37,6 +39,8 @@ echo ========================================
37
39
  echo DEBUG MODE (NON-INTERACTIVE)
38
40
  echo ========================================
39
41
  echo Running full diagnostic suite...
42
+ set "MEDICAFE_IMPORT_DEBUG=1"
43
+ set "MEDICAFE_IMPORT_STRICT=0"
40
44
  echo.
41
45
  set "SKIP_CLS_AFTER_DEBUG=1"
42
46
  call "%~dp0full_debug_suite.bat"
@@ -45,6 +49,8 @@ goto normal_mode
45
49
 
46
50
  :start_normal_mode
47
51
  echo Starting Normal Mode...
52
+ set "MEDICAFE_IMPORT_DEBUG=0"
53
+ set "MEDICAFE_IMPORT_STRICT=1"
48
54
  goto normal_mode
49
55
 
50
56
  :normal_mode
@@ -557,7 +563,6 @@ if errorlevel 1 (
557
563
  pause
558
564
  )
559
565
 
560
- pause
561
566
  goto main_menu
562
567
 
563
568
  :: MediLink Flow
@@ -571,7 +576,6 @@ if errorlevel 1 (
571
576
  pause
572
577
  )
573
578
 
574
- pause
575
579
  goto main_menu
576
580
 
577
581
  :toggle_perf_logging
@@ -25,6 +25,7 @@ import sys
25
25
  import os
26
26
  import argparse
27
27
  import subprocess
28
+ from MediCafe.core_utils import import_medilink_module, require_functions, print_import_diagnostics
28
29
 
29
30
  # Set up module paths for proper imports
30
31
  def setup_entry_point_paths():
@@ -44,41 +45,55 @@ def setup_entry_point_paths():
44
45
  while pkg_dir in sys.path:
45
46
  sys.path.remove(pkg_dir)
46
47
 
48
+ def validate_critical_imports():
49
+ """Validate key modules and capabilities before launching subprocesses.
50
+ - Ensures we resolve the in-repo MediLink_DataMgmt and it exposes required functions.
51
+ Behavior depends on env flags handled inside core_utils.require_functions.
52
+ """
53
+ try:
54
+ datamgmt = import_medilink_module('MediLink_DataMgmt')
55
+ if datamgmt is not None:
56
+ print_import_diagnostics('MediLink_DataMgmt', datamgmt)
57
+ # These are used by both MediBot and MediLink flows
58
+ require_functions(datamgmt, ['read_general_fixed_width_data', 'read_fixed_width_data', 'parse_fixed_width_data'])
59
+ except Exception as e:
60
+ # Fail fast only if strict mode is enabled (exception originates from require_functions)
61
+ print("Import validation warning: {}".format(e))
62
+
47
63
  def run_medibot(config_file=None):
48
64
  """Run MediBot application"""
49
65
  try:
50
66
  print("Starting MediBot...")
51
-
52
- # Set up command line arguments
67
+
68
+ # Resolve workspace root and MediBot.py path
69
+ current_dir = os.path.dirname(os.path.abspath(__file__))
70
+ workspace_root = os.path.dirname(current_dir)
71
+ medibot_path = os.path.join(workspace_root, 'MediBot', 'MediBot.py')
72
+
73
+ if not os.path.exists(medibot_path):
74
+ print("Error: MediBot.py not found at {}".format(medibot_path))
75
+ return 1
76
+
77
+ # Pre-flight import validation (no-op unless strict/debug enabled)
78
+ validate_critical_imports()
79
+
80
+ # Build subprocess arguments
81
+ args = [sys.executable, medibot_path]
53
82
  if config_file:
54
- sys.argv = ['MediBot.py', config_file]
83
+ args.append(config_file)
84
+
85
+ # Ensure subprocess can import project packages
86
+ env = os.environ.copy()
87
+ python_path = workspace_root
88
+ if 'PYTHONPATH' in env:
89
+ env['PYTHONPATH'] = python_path + os.pathsep + env['PYTHONPATH']
55
90
  else:
56
- sys.argv = ['MediBot.py']
57
-
58
- # Import and run MediBot directly
59
- try:
60
- from MediBot import MediBot
61
- # If MediBot has a main function, call it
62
- if hasattr(MediBot, 'main'):
63
- return MediBot.main()
64
- else:
65
- # Otherwise, just import it (it will run its own code)
66
- return 0
67
- except ImportError:
68
- # Fallback: try to run the file directly
69
- import subprocess
70
- medibot_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'MediBot', 'MediBot.py')
71
- if os.path.exists(medibot_path):
72
- # Use subprocess.call for Python 3.4.4 compatibility
73
- result = subprocess.call([sys.executable, medibot_path] + sys.argv[1:],
74
- cwd=os.path.dirname(medibot_path))
75
- return result
76
- else:
77
- raise ImportError("MediBot.py not found at {}".format(medibot_path))
78
-
79
- except ImportError as e:
80
- print("Error: Unable to import MediBot: {}".format(e))
81
- return 1
91
+ env['PYTHONPATH'] = python_path
92
+
93
+ # Run MediBot as a script so its __main__ block executes
94
+ result = subprocess.call(args, cwd=os.path.dirname(medibot_path), env=env)
95
+ return result
96
+
82
97
  except Exception as e:
83
98
  print("Error running MediBot: {}".format(e))
84
99
  return 1
@@ -87,6 +102,8 @@ def run_medilink():
87
102
  """Run MediLink application"""
88
103
  try:
89
104
  print("Starting MediLink...")
105
+ # Pre-flight import validation (no-op unless strict/debug enabled)
106
+ validate_critical_imports()
90
107
  # Use subprocess.call for Python 3.4.4 compatibility
91
108
 
92
109
  # Get the path to MediLink_main.py
@@ -29,6 +29,62 @@ for _p in list(sys.path):
29
29
  DEFAULT_CONFIG_PATH = os.path.join(project_dir, 'json', 'config.json')
30
30
  DEFAULT_CROSSWALK_PATH = os.path.join(project_dir, 'json', 'crosswalk.json')
31
31
 
32
+ # Environment flags controlling import behavior
33
+ _STRICT_IMPORT = os.environ.get('MEDICAFE_IMPORT_STRICT', '0').strip().lower() in ('1', 'true', 'yes', 'y')
34
+ _DEBUG_IMPORT = os.environ.get('MEDICAFE_IMPORT_DEBUG', '0').strip().lower() in ('1', 'true', 'yes', 'y')
35
+
36
+ # Simple memoization cache for resolved imports
37
+ _IMPORT_CACHE = {}
38
+
39
+ def _cache_get(key):
40
+ try:
41
+ return _IMPORT_CACHE.get(key)
42
+ except Exception:
43
+ return None
44
+
45
+ def _cache_set(key, value):
46
+ try:
47
+ _IMPORT_CACHE[key] = value
48
+ except Exception:
49
+ pass
50
+
51
+ def _module_provenance_ok(module):
52
+ """Return True if module appears to come from this workspace."""
53
+ try:
54
+ module_file = getattr(module, '__file__', '') or ''
55
+ return os.path.abspath(project_dir) in os.path.abspath(module_file)
56
+ except Exception:
57
+ return False
58
+
59
+ def require_functions(module, names):
60
+ """Ensure the module exposes all required attributes; raise RuntimeError on failure in strict mode; return bool otherwise."""
61
+ missing = [name for name in names if not hasattr(module, name)]
62
+ if missing:
63
+ message = "Missing required symbols {} in module {}".format(missing, getattr(module, '__name__', 'unknown'))
64
+ if _STRICT_IMPORT:
65
+ raise RuntimeError(message)
66
+ if _DEBUG_IMPORT:
67
+ try:
68
+ print("[IMPORT DIAG] {} (file: {})".format(message, getattr(module, '__file__', 'unknown')))
69
+ except Exception:
70
+ pass
71
+ return False
72
+ return True
73
+
74
+ def print_import_diagnostics(label, module):
75
+ """Print a single-line diagnostic about a resolved module (debug only)."""
76
+ if not _DEBUG_IMPORT:
77
+ return
78
+ try:
79
+ print("[IMPORT DIAG] {} -> name={} file={} workspace_provenance={}".format(
80
+ label,
81
+ getattr(module, '__name__', 'unknown'),
82
+ getattr(module, '__file__', 'unknown'),
83
+ _module_provenance_ok(module)
84
+ ))
85
+ except Exception:
86
+ pass
87
+
32
88
  def setup_project_path(file_path=None):
33
89
  """
34
90
  Standard project path setup function used by all entry points.
@@ -122,12 +178,26 @@ def smart_import(import_specs, default_value=None):
122
178
  try:
123
179
  if isinstance(spec, str):
124
180
  # Simple string - direct import
125
- return __import__(spec)
181
+ # If dotted path, ensure we get the submodule, not just the top-level package
182
+ cached = _cache_get(('str', spec))
183
+ if cached is not None:
184
+ return cached
185
+ if '.' in spec:
186
+ result = __import__(spec, fromlist=['*'])
187
+ else:
188
+ result = __import__(spec)
189
+ _cache_set(('str', spec), result)
190
+ return result
126
191
  elif isinstance(spec, tuple):
127
192
  # Tuple - (path, function_name)
128
193
  path, function_name = spec
194
+ cached = _cache_get(('tuple', path, function_name))
195
+ if cached is not None:
196
+ return cached
129
197
  module = __import__(path, fromlist=[function_name])
130
- return getattr(module, function_name)
198
+ result = getattr(module, function_name)
199
+ _cache_set(('tuple', path, function_name), result)
200
+ return result
131
201
  elif isinstance(spec, dict):
132
202
  # Dict with fallback
133
203
  path = spec['path']
@@ -135,19 +205,38 @@ def smart_import(import_specs, default_value=None):
135
205
  fallback = spec.get('fallback')
136
206
 
137
207
  try:
208
+ cache_key = ('dict', path, function_name)
209
+ cached = _cache_get(cache_key)
210
+ if cached is not None:
211
+ return cached
138
212
  if function_name:
139
213
  module = __import__(path, fromlist=[function_name])
140
- return getattr(module, function_name)
214
+ result = getattr(module, function_name)
141
215
  else:
142
- return __import__(path)
216
+ # If dotted, use fromlist to return the submodule
217
+ if '.' in path:
218
+ result = __import__(path, fromlist=['*'])
219
+ else:
220
+ result = __import__(path)
221
+ _cache_set(cache_key, result)
222
+ return result
143
223
  except ImportError:
144
224
  if fallback:
145
225
  try:
226
+ cache_key = ('dict_fallback', fallback, function_name)
227
+ cached = _cache_get(cache_key)
228
+ if cached is not None:
229
+ return cached
146
230
  if function_name:
147
231
  module = __import__(fallback, fromlist=[function_name])
148
- return getattr(module, function_name)
232
+ result = getattr(module, function_name)
149
233
  else:
150
- return __import__(fallback)
234
+ if '.' in fallback:
235
+ result = __import__(fallback, fromlist=['*'])
236
+ else:
237
+ result = __import__(fallback)
238
+ _cache_set(cache_key, result)
239
+ return result
151
240
  except ImportError:
152
241
  continue
153
242
  continue
@@ -252,14 +341,16 @@ def import_medilink_module(module_name, function_name=None):
252
341
  Returns:
253
342
  The imported module/function or None
254
343
  """
344
+ # Prefer importing from the in-repo MediLink package first to avoid
345
+ # accidentally picking up a similarly named top-level/site-packages module.
255
346
  import_specs = [
256
- # Direct import first
257
- module_name,
258
- # Then try with MediLink prefix
347
+ # Prefer package-qualified import first (local codebase)
259
348
  'MediLink.{}'.format(module_name),
349
+ # Then try direct import (legacy/installed module)
350
+ module_name,
260
351
  # Then try relative import
261
352
  '.{}'.format(module_name),
262
- # Finally try as a submodule
353
+ # Finally try as a submodule with fallback
263
354
  {'path': 'MediLink.{}'.format(module_name), 'fallback': module_name}
264
355
  ]
265
356
 
@@ -275,9 +366,22 @@ def import_medilink_module(module_name, function_name=None):
275
366
  'function': function_name,
276
367
  'fallback': spec.get('fallback')
277
368
  })
278
- return smart_import(function_specs)
369
+ result = smart_import(function_specs)
370
+ if result is not None and _DEBUG_IMPORT:
371
+ try:
372
+ print_import_diagnostics('import_medilink_module:{}:function'.format(module_name), result)
373
+ except Exception:
374
+ pass
375
+ return result
279
376
  else:
280
- return smart_import(import_specs)
377
+ result = smart_import(import_specs)
378
+ if result is not None:
379
+ # In strict mode, verify provenance and capabilities if demanded by callers
380
+ if _STRICT_IMPORT and not _module_provenance_ok(result):
381
+ raise RuntimeError("Imported module '{}' from outside workspace: {}".format(
382
+ module_name, getattr(result, '__file__', 'unknown')))
383
+ print_import_diagnostics('import_medilink_module:{}'.format(module_name), result)
384
+ return result
281
385
 
282
386
  def get_shared_config_loader():
283
387
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: medicafe
3
- Version: 0.250810.4
3
+ Version: 0.250810.6
4
4
  Summary: MediCafe
5
5
  Home-page: https://github.com/katanada2
6
6
  Author: Daniel Vidaud
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: medicafe
3
- Version: 0.250810.4
3
+ Version: 0.250810.6
4
4
  Summary: MediCafe
5
5
  Home-page: https://github.com/katanada2
6
6
  Author: Daniel Vidaud
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name='medicafe',
5
- version="0.250810.4",
5
+ version="0.250810.6",
6
6
  description='MediCafe',
7
7
  long_description="""
8
8
  # Project Overview: MediCafe
File without changes
File without changes
File without changes