ins-pricing 0.4.4__py3-none-any.whl → 0.5.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.
Files changed (96) hide show
  1. ins_pricing/README.md +74 -56
  2. ins_pricing/__init__.py +142 -90
  3. ins_pricing/cli/BayesOpt_entry.py +52 -50
  4. ins_pricing/cli/BayesOpt_incremental.py +832 -898
  5. ins_pricing/cli/Explain_Run.py +31 -23
  6. ins_pricing/cli/Explain_entry.py +532 -579
  7. ins_pricing/cli/Pricing_Run.py +31 -23
  8. ins_pricing/cli/bayesopt_entry_runner.py +1440 -1438
  9. ins_pricing/cli/utils/cli_common.py +256 -256
  10. ins_pricing/cli/utils/cli_config.py +375 -375
  11. ins_pricing/cli/utils/import_resolver.py +382 -365
  12. ins_pricing/cli/utils/notebook_utils.py +340 -340
  13. ins_pricing/cli/watchdog_run.py +209 -201
  14. ins_pricing/frontend/README.md +573 -419
  15. ins_pricing/frontend/__init__.py +10 -10
  16. ins_pricing/frontend/config_builder.py +1 -0
  17. ins_pricing/frontend/example_workflows.py +1 -1
  18. ins_pricing/governance/__init__.py +20 -20
  19. ins_pricing/governance/release.py +159 -159
  20. ins_pricing/modelling/README.md +67 -0
  21. ins_pricing/modelling/__init__.py +147 -92
  22. ins_pricing/modelling/bayesopt/README.md +59 -0
  23. ins_pricing/modelling/{core/bayesopt → bayesopt}/__init__.py +64 -102
  24. ins_pricing/modelling/{core/bayesopt → bayesopt}/config_preprocess.py +562 -550
  25. ins_pricing/modelling/{core/bayesopt → bayesopt}/core.py +965 -962
  26. ins_pricing/modelling/{core/bayesopt → bayesopt}/model_explain_mixin.py +296 -296
  27. ins_pricing/modelling/{core/bayesopt → bayesopt}/model_plotting_mixin.py +482 -548
  28. ins_pricing/modelling/{core/bayesopt → bayesopt}/models/__init__.py +27 -27
  29. ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_ft_trainer.py +915 -913
  30. ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_gnn.py +788 -785
  31. ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_resn.py +448 -446
  32. ins_pricing/modelling/bayesopt/trainers/__init__.py +19 -0
  33. ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_base.py +1308 -1308
  34. ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_ft.py +3 -3
  35. ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_glm.py +197 -198
  36. ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_gnn.py +344 -344
  37. ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_resn.py +283 -283
  38. ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_xgb.py +346 -347
  39. ins_pricing/modelling/bayesopt/utils/__init__.py +67 -0
  40. ins_pricing/modelling/bayesopt/utils/constants.py +21 -0
  41. ins_pricing/modelling/bayesopt/utils/io_utils.py +7 -0
  42. ins_pricing/modelling/bayesopt/utils/losses.py +27 -0
  43. ins_pricing/modelling/bayesopt/utils/metrics_and_devices.py +17 -0
  44. ins_pricing/modelling/{core/bayesopt → bayesopt}/utils/torch_trainer_mixin.py +623 -623
  45. ins_pricing/modelling/{core/evaluation.py → evaluation.py} +113 -104
  46. ins_pricing/modelling/explain/__init__.py +55 -55
  47. ins_pricing/modelling/explain/metrics.py +27 -174
  48. ins_pricing/modelling/explain/permutation.py +237 -237
  49. ins_pricing/modelling/plotting/__init__.py +40 -36
  50. ins_pricing/modelling/plotting/compat.py +228 -0
  51. ins_pricing/modelling/plotting/curves.py +572 -572
  52. ins_pricing/modelling/plotting/diagnostics.py +163 -163
  53. ins_pricing/modelling/plotting/geo.py +362 -362
  54. ins_pricing/modelling/plotting/importance.py +121 -121
  55. ins_pricing/pricing/__init__.py +27 -27
  56. ins_pricing/production/__init__.py +35 -25
  57. ins_pricing/production/{predict.py → inference.py} +140 -57
  58. ins_pricing/production/monitoring.py +8 -21
  59. ins_pricing/reporting/__init__.py +11 -11
  60. ins_pricing/setup.py +1 -1
  61. ins_pricing/tests/production/test_inference.py +90 -0
  62. ins_pricing/utils/__init__.py +116 -83
  63. ins_pricing/utils/device.py +255 -255
  64. ins_pricing/utils/features.py +53 -0
  65. ins_pricing/utils/io.py +72 -0
  66. ins_pricing/{modelling/core/bayesopt/utils → utils}/losses.py +125 -129
  67. ins_pricing/utils/metrics.py +158 -24
  68. ins_pricing/utils/numerics.py +76 -0
  69. ins_pricing/utils/paths.py +9 -1
  70. {ins_pricing-0.4.4.dist-info → ins_pricing-0.5.0.dist-info}/METADATA +55 -35
  71. ins_pricing-0.5.0.dist-info/RECORD +131 -0
  72. ins_pricing/CHANGELOG.md +0 -272
  73. ins_pricing/RELEASE_NOTES_0.2.8.md +0 -344
  74. ins_pricing/docs/LOSS_FUNCTIONS.md +0 -78
  75. ins_pricing/docs/modelling/BayesOpt_USAGE.md +0 -945
  76. ins_pricing/docs/modelling/README.md +0 -34
  77. ins_pricing/frontend/QUICKSTART.md +0 -152
  78. ins_pricing/modelling/core/BayesOpt.py +0 -146
  79. ins_pricing/modelling/core/__init__.py +0 -1
  80. ins_pricing/modelling/core/bayesopt/PHASE2_REFACTORING_SUMMARY.md +0 -449
  81. ins_pricing/modelling/core/bayesopt/PHASE3_REFACTORING_SUMMARY.md +0 -406
  82. ins_pricing/modelling/core/bayesopt/REFACTORING_SUMMARY.md +0 -247
  83. ins_pricing/modelling/core/bayesopt/trainers/__init__.py +0 -19
  84. ins_pricing/modelling/core/bayesopt/utils/__init__.py +0 -86
  85. ins_pricing/modelling/core/bayesopt/utils/constants.py +0 -183
  86. ins_pricing/modelling/core/bayesopt/utils/io_utils.py +0 -126
  87. ins_pricing/modelling/core/bayesopt/utils/metrics_and_devices.py +0 -555
  88. ins_pricing/modelling/core/bayesopt/utils.py +0 -105
  89. ins_pricing/modelling/core/bayesopt/utils_backup.py +0 -1503
  90. ins_pricing/tests/production/test_predict.py +0 -233
  91. ins_pricing-0.4.4.dist-info/RECORD +0 -137
  92. /ins_pricing/modelling/{core/bayesopt → bayesopt}/config_components.py +0 -0
  93. /ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_ft_components.py +0 -0
  94. /ins_pricing/modelling/{core/bayesopt → bayesopt}/utils/distributed_utils.py +0 -0
  95. {ins_pricing-0.4.4.dist-info → ins_pricing-0.5.0.dist-info}/WHEEL +0 -0
  96. {ins_pricing-0.4.4.dist-info → ins_pricing-0.5.0.dist-info}/top_level.txt +0 -0
ins_pricing/README.md CHANGED
@@ -1,74 +1,92 @@
1
- # Ins-Pricing
2
-
3
- Distribution name: Ins-Pricing (import package is `ins_pricing`, legacy alias `user_packages` still works).
4
-
5
- Reusable modelling and pricing utilities organized as a small toolbox with clear boundaries
6
- between modelling, production, governance, and reporting.
7
-
8
- ## Architecture
9
-
10
- - `cli/`: CLI entry points + shared utilities.
1
+ # ins_pricing
2
+
3
+ Distribution name: ins_pricing (import package is `ins_pricing`; legacy alias `user_packages` still works).
4
+
5
+ Reusable modelling and pricing utilities organized as a small toolbox with clear boundaries
6
+ between modelling, production, governance, and reporting.
7
+
8
+ ## Architecture
9
+
10
+ - `cli/`: CLI entry points and shared utilities.
11
11
  - `modelling/`
12
- - `core/`: BayesOpt training core (GLM / XGB / ResNet / FT / GNN).
12
+ - `bayesopt/`: BayesOpt training core (GLM / XGB / ResNet / FT / GNN).
13
13
  - `plotting/`: model-agnostic curves and geo visualizations.
14
14
  - `explain/`: permutation, gradients, and SHAP helpers.
15
- - `docs/modelling/`: modelling documentation.
16
- - `examples/modelling/`: demo configs + notebooks (repo only; not packaged).
17
- - `pricing/`: factor tables, calibration, exposure, monitoring.
18
- - `production/`: scoring, metrics, drift/PSI.
19
- - `governance/`: registry, release, audit, approval workflow.
20
- - `reporting/`: report builder + scheduler.
21
-
22
- ## Call flow (typical)
23
-
24
- 1. Model training
25
- - Python API: `from ins_pricing.modelling import BayesOptModel`
26
- - CLI: `python ins_pricing/cli/BayesOpt_entry.py --config-json ...`
27
- 2. Evaluation & visualization
28
- - Curves: `from ins_pricing.plotting import curves`
29
- - Importance: `from ins_pricing.plotting import importance`
30
- - Geo: `from ins_pricing.plotting import geo`
31
- 3. Explainability
32
- - `from ins_pricing.explain import permutation_importance, integrated_gradients_torch`
33
- 4. Pricing loop
34
- - `from ins_pricing.pricing import build_factor_table, rate_premium`
35
- 5. Production & governance
15
+ - `evaluation.py`: calibration, metrics, and evaluation utilities.
16
+ - `examples/`: demo configs and notebooks (repo only; not packaged).
17
+ - `pricing/`: factor tables, calibration, exposure, monitoring.
18
+ - `production/`: scoring, metrics, drift/PSI.
19
+ - `governance/`: registry, approval, audit workflows.
20
+ - `reporting/`: report builder and scheduler.
21
+
22
+ ## Call flow (typical)
23
+
24
+ 1. Model training
25
+ - Python API: `from ins_pricing.modelling import BayesOptModel`
26
+ - CLI: `python ins_pricing/cli/BayesOpt_entry.py --config-json ...`
27
+ 2. Evaluation and visualization
28
+ - Curves: `from ins_pricing.plotting import curves`
29
+ - Importance: `from ins_pricing.plotting import importance`
30
+ - Geo: `from ins_pricing.plotting import geo`
31
+ 3. Explainability
32
+ - `from ins_pricing.explain import permutation_importance, integrated_gradients_torch`
33
+ 4. Pricing loop
34
+ - `from ins_pricing.pricing import build_factor_table, rate_premium`
35
+ 5. Production and governance
36
36
  - `from ins_pricing.production import batch_score, psi_report`
37
+ - Inference: `from ins_pricing.production import load_predictor_from_config`
37
38
  - `from ins_pricing.governance import ModelRegistry, ReleaseManager`
38
- 6. Reporting
39
- - `from ins_pricing.reporting import build_report, write_report, schedule_daily`
40
-
39
+ 6. Reporting
40
+ - `from ins_pricing.reporting import build_report, write_report, schedule_daily`
41
+
41
42
  ## Import notes
42
43
 
43
- - `ins_pricing` exposes lightweight lazy imports so that `pricing/production/governance`
44
+ - `ins_pricing` exposes lightweight lazy imports so that pricing/production/governance
44
45
  can be used without installing heavy ML dependencies.
45
- - Migration note: CLI entry points now live under `ins_pricing/cli/` and demo assets are under
46
- `ins_pricing/examples/modelling/`. Update any scripts that referenced `ins_pricing/modelling/cli/*` or
47
- `ins_pricing/modelling/examples/*`.
48
- - Demo notebooks/configs live in the repo under `ins_pricing/examples/modelling/` and are not shipped in the PyPI package.
46
+ - Demo notebooks/configs live in the repo under `examples/` and are not shipped
47
+ in the PyPI package.
49
48
  - Heavy dependencies are only required when you import or use the related modules:
50
49
  - BayesOpt: `torch`, `optuna`, `xgboost`, etc.
51
50
  - Explain: `torch` (gradients), `shap` (SHAP).
52
51
  - Geo plotting on basemap: `contextily`.
53
52
  - Plotting: `matplotlib`.
53
+ - Inference: `torch` only when loading FT/ResNet/GNN models.
54
54
 
55
- ## Multi-platform & GPU installation notes
55
+ ## Inference interface (new)
56
56
 
57
- - **Install PyTorch first**: Use the correct PyTorch build for your platform/GPU (CUDA/ROCm/MPS)
58
- before installing the `bayesopt`, `explain`, or `gnn` extras. This avoids incompatible wheels.
59
- - **GNN dependencies**: `torch-geometric` and its companion packages are platform-specific. Follow
60
- the official PyG install guide for your CUDA/ROCm/CPU environment, then install
61
- `ins_pricing[gnn]`.
62
- - **Multi-GPU**: Training utilities will select CUDA/MPS/CPU automatically. Multi-GPU uses DDP or
63
- DataParallel when supported; on Windows, CUDA DDP is disabled and will fall back to single-GPU or
64
- DataParallel where available.
57
+ - `production.inference` provides a small registry-based interface so inference
58
+ does not hard-code model loaders:
59
+ - `ModelSpec` describes the saved model location and config.
60
+ - `PredictorRegistry` lets you plug in custom model loaders.
61
+ - `load_predictor_from_config` remains backward compatible.
65
62
 
66
- ## Backward-compatible imports
63
+ Example:
67
64
 
68
- Legacy import paths continue to work:
65
+ ```
66
+ from ins_pricing.production import load_predictor_from_config
69
67
 
70
- - `import user_packages`
71
- - `import user_packages.bayesopt`
72
- - `import user_packages.plotting`
73
- - `import user_packages.explain`
74
- - `import user_packages.BayesOpt`
68
+ predictor = load_predictor_from_config(
69
+ "config.json",
70
+ "resn",
71
+ device="cuda", # or "mps"/"cpu"
72
+ )
73
+ preds = predictor.predict(df)
74
+ ```
75
+
76
+ ## Multi-platform and GPU notes
77
+
78
+ - Install the correct PyTorch build for your platform/GPU before installing extras.
79
+ - Torch Geometric requires platform-specific wheels; follow the official PyG install guide.
80
+ - Multi-GPU uses DDP or DataParallel where supported; Windows disables CUDA DDP.
81
+ CLI usage prefers `python -m ins_pricing.cli.BayesOpt_entry ...` but the
82
+ direct script path (`python ins_pricing/cli/BayesOpt_entry.py ...`) still works.
83
+
84
+ ## Backward-compatible imports
85
+
86
+ Legacy import paths continue to work:
87
+
88
+ - `import user_packages`
89
+ - `import user_packages.bayesopt`
90
+ - `import user_packages.plotting`
91
+ - `import user_packages.explain`
92
+ - `import user_packages.BayesOpt`
ins_pricing/__init__.py CHANGED
@@ -1,94 +1,146 @@
1
- from __future__ import annotations
2
-
3
- from importlib import import_module
4
- from pathlib import Path
5
- import sys
6
- import types
7
-
8
- _ROOT_SUBPACKAGES = {
9
- "modelling": "ins_pricing.modelling",
10
- "pricing": "ins_pricing.pricing",
11
- "production": "ins_pricing.production",
12
- "governance": "ins_pricing.governance",
13
- "reporting": "ins_pricing.reporting",
14
- }
15
-
16
- _MODELLING_EXPORTS = {
17
- "BayesOptConfig",
18
- "BayesOptModel",
19
- "IOUtils",
20
- "TrainingUtils",
21
- "free_cuda",
22
- }
23
-
1
+ from __future__ import annotations
2
+
3
+ from importlib import import_module
4
+ from pathlib import Path
5
+ import sys
6
+ import types
7
+
8
+ _ROOT_SUBPACKAGES = {
9
+ "modelling": "ins_pricing.modelling",
10
+ "pricing": "ins_pricing.pricing",
11
+ "production": "ins_pricing.production",
12
+ "governance": "ins_pricing.governance",
13
+ "reporting": "ins_pricing.reporting",
14
+ }
15
+
16
+ _MODELLING_EXPORTS = {
17
+ "BayesOptConfig",
18
+ "BayesOptModel",
19
+ }
20
+
21
+ _BAYESOPT_EXPORTS = {
22
+ "BayesOptConfig",
23
+ "DatasetPreprocessor",
24
+ "OutputManager",
25
+ "VersionManager",
26
+ "BayesOptModel",
27
+ "FeatureTokenizer",
28
+ "FTTransformerCore",
29
+ "FTTransformerSklearn",
30
+ "GraphNeuralNetSklearn",
31
+ "MaskedTabularDataset",
32
+ "ResBlock",
33
+ "ResNetSequential",
34
+ "ResNetSklearn",
35
+ "ScaledTransformerEncoderLayer",
36
+ "SimpleGraphLayer",
37
+ "SimpleGNN",
38
+ "TabularDataset",
39
+ "FTTrainer",
40
+ "GLMTrainer",
41
+ "GNNTrainer",
42
+ "ResNetTrainer",
43
+ "TrainerBase",
44
+ "XGBTrainer",
45
+ "_xgb_cuda_available",
46
+ }
47
+
48
+ _LEGACY_EXPORTS = {
49
+ "IOUtils": "ins_pricing.utils",
50
+ "DeviceManager": "ins_pricing.utils",
51
+ "GPUMemoryManager": "ins_pricing.utils",
52
+ "MetricFactory": "ins_pricing.utils",
53
+ "EPS": "ins_pricing.utils",
54
+ "set_global_seed": "ins_pricing.utils",
55
+ "compute_batch_size": "ins_pricing.utils",
56
+ "tweedie_loss": "ins_pricing.utils",
57
+ "infer_factor_and_cate_list": "ins_pricing.utils",
58
+ "DistributedUtils": "ins_pricing.modelling.bayesopt.utils",
59
+ "TrainingUtils": "ins_pricing.modelling.bayesopt.utils",
60
+ "free_cuda": "ins_pricing.modelling.bayesopt.utils",
61
+ "TorchTrainerMixin": "ins_pricing.modelling.bayesopt.utils",
62
+ }
63
+
24
64
  _LAZY_SUBMODULES = {
25
- "bayesopt": "ins_pricing.modelling.core.bayesopt",
65
+ "bayesopt": "ins_pricing.modelling.bayesopt",
26
66
  "plotting": "ins_pricing.modelling.plotting",
27
67
  "explain": "ins_pricing.modelling.explain",
28
- "BayesOpt": "ins_pricing.modelling.core.BayesOpt",
29
- }
30
-
31
- _PACKAGE_PATHS = {
32
- "bayesopt": Path(__file__).resolve().parent / "modelling" / "core" / "bayesopt",
33
- "plotting": Path(__file__).resolve().parent / "modelling" / "plotting",
34
- "explain": Path(__file__).resolve().parent / "modelling" / "explain",
35
68
  }
36
-
37
- __all__ = sorted(
38
- set(_ROOT_SUBPACKAGES)
39
- | set(_MODELLING_EXPORTS)
40
- | set(_LAZY_SUBMODULES)
41
- )
42
-
43
-
44
- def _lazy_module(name: str, target: str, package_path: Path | None = None) -> types.ModuleType:
45
- proxy = types.ModuleType(name)
46
- if package_path is not None:
47
- proxy.__path__ = [str(package_path)]
48
-
49
- def _load():
50
- module = import_module(target)
51
- sys.modules[name] = module
52
- return module
53
-
54
- def __getattr__(attr: str):
55
- module = _load()
56
- return getattr(module, attr)
57
-
58
- def __dir__() -> list[str]:
59
- module = _load()
60
- return sorted(set(dir(module)))
61
-
62
- proxy.__getattr__ = __getattr__ # type: ignore[attr-defined]
63
- proxy.__dir__ = __dir__ # type: ignore[attr-defined]
64
- return proxy
65
-
66
-
67
- def _install_proxy(alias: str, target: str) -> None:
68
- module_name = f"{__name__}.{alias}"
69
- if module_name in sys.modules:
70
- return
71
- proxy = _lazy_module(module_name, target, _PACKAGE_PATHS.get(alias))
72
- sys.modules[module_name] = proxy
73
- globals()[alias] = proxy
74
-
75
-
76
- for _alias, _target in _LAZY_SUBMODULES.items():
77
- _install_proxy(_alias, _target)
78
-
79
-
80
- def __getattr__(name: str):
81
- if name in _ROOT_SUBPACKAGES:
82
- module = import_module(_ROOT_SUBPACKAGES[name])
83
- globals()[name] = module
84
- return module
85
- if name in _MODELLING_EXPORTS:
86
- module = import_module("ins_pricing.modelling")
87
- value = getattr(module, name)
88
- globals()[name] = value
89
- return value
90
- raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
91
-
92
-
93
- def __dir__() -> list[str]:
94
- return sorted(set(__all__) | set(globals().keys()))
69
+
70
+ _PACKAGE_PATHS = {
71
+ "bayesopt": Path(__file__).resolve().parent / "modelling" / "bayesopt",
72
+ "plotting": Path(__file__).resolve().parent / "modelling" / "plotting",
73
+ "explain": Path(__file__).resolve().parent / "modelling" / "explain",
74
+ }
75
+
76
+ __all__ = sorted(
77
+ set(_ROOT_SUBPACKAGES)
78
+ | set(_MODELLING_EXPORTS)
79
+ | set(_BAYESOPT_EXPORTS)
80
+ | set(_LEGACY_EXPORTS)
81
+ | set(_LAZY_SUBMODULES)
82
+ )
83
+
84
+
85
+ def _lazy_module(name: str, target: str, package_path: Path | None = None) -> types.ModuleType:
86
+ proxy = types.ModuleType(name)
87
+ if package_path is not None:
88
+ proxy.__path__ = [str(package_path)]
89
+
90
+ def _load():
91
+ module = import_module(target)
92
+ sys.modules[name] = module
93
+ return module
94
+
95
+ def __getattr__(attr: str):
96
+ module = _load()
97
+ return getattr(module, attr)
98
+
99
+ def __dir__() -> list[str]:
100
+ module = _load()
101
+ return sorted(set(dir(module)))
102
+
103
+ proxy.__getattr__ = __getattr__ # type: ignore[attr-defined]
104
+ proxy.__dir__ = __dir__ # type: ignore[attr-defined]
105
+ return proxy
106
+
107
+
108
+ def _install_proxy(alias: str, target: str) -> None:
109
+ module_name = f"{__name__}.{alias}"
110
+ if module_name in sys.modules:
111
+ return
112
+ proxy = _lazy_module(module_name, target, _PACKAGE_PATHS.get(alias))
113
+ sys.modules[module_name] = proxy
114
+ globals()[alias] = proxy
115
+
116
+
117
+ for _alias, _target in _LAZY_SUBMODULES.items():
118
+ _install_proxy(_alias, _target)
119
+
120
+
121
+ def __getattr__(name: str):
122
+ if name in _ROOT_SUBPACKAGES:
123
+ module = import_module(_ROOT_SUBPACKAGES[name])
124
+ globals()[name] = module
125
+ return module
126
+ if name in _MODELLING_EXPORTS:
127
+ module = import_module("ins_pricing.modelling")
128
+ value = getattr(module, name)
129
+ globals()[name] = value
130
+ return value
131
+ if name in _BAYESOPT_EXPORTS:
132
+ module = import_module("ins_pricing.modelling.bayesopt")
133
+ value = getattr(module, name)
134
+ globals()[name] = value
135
+ return value
136
+ legacy_module = _LEGACY_EXPORTS.get(name)
137
+ if legacy_module:
138
+ module = import_module(legacy_module)
139
+ value = getattr(module, name)
140
+ globals()[name] = value
141
+ return value
142
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
143
+
144
+
145
+ def __dir__() -> list[str]:
146
+ return sorted(set(__all__) | set(globals().keys()))
@@ -1,56 +1,58 @@
1
- """Thin wrapper for the BayesOpt CLI entry point.
2
-
3
- The main implementation lives in bayesopt_entry_runner.py.
4
- """
5
-
6
- from __future__ import annotations
7
-
1
+ """Thin wrapper for the BayesOpt CLI entry point.
2
+
3
+ The main implementation lives in bayesopt_entry_runner.py.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
8
  from pathlib import Path
9
+ import importlib.util
9
10
  import json
10
11
  import os
11
12
  import sys
12
13
 
13
14
  if __package__ in {None, ""}:
14
- repo_root = Path(__file__).resolve().parents[2]
15
- if str(repo_root) not in sys.path:
16
- sys.path.insert(0, str(repo_root))
17
-
18
- def _apply_env_from_config(argv: list[str]) -> None:
19
- if "--config-json" not in argv:
20
- return
21
- idx = argv.index("--config-json")
22
- if idx + 1 >= len(argv):
23
- return
24
- raw_path = argv[idx + 1]
25
- try:
26
- cfg_path = Path(raw_path).expanduser()
27
- if not cfg_path.is_absolute():
28
- cfg_path = cfg_path.resolve()
29
- if not cfg_path.exists():
30
- script_dir = Path(__file__).resolve().parents[1]
31
- candidate = (script_dir / raw_path).resolve()
32
- if candidate.exists():
33
- cfg_path = candidate
34
- if not cfg_path.exists():
35
- return
36
- cfg = json.loads(cfg_path.read_text(encoding="utf-8", errors="replace"))
37
- env = cfg.get("env", {})
38
- if isinstance(env, dict):
39
- for key, value in env.items():
40
- if key is None:
41
- continue
42
- os.environ.setdefault(str(key), str(value))
43
- except Exception:
44
- return
45
-
46
- _apply_env_from_config(sys.argv)
47
-
48
- try:
49
- from .bayesopt_entry_runner import main
50
- except Exception: # pragma: no cover
51
- from ins_pricing.cli.bayesopt_entry_runner import main
52
-
53
- __all__ = ["main"]
54
-
55
- if __name__ == "__main__":
56
- main()
15
+ if importlib.util.find_spec("ins_pricing") is None:
16
+ repo_root = Path(__file__).resolve().parents[2]
17
+ if str(repo_root) not in sys.path:
18
+ sys.path.insert(0, str(repo_root))
19
+
20
+ def _apply_env_from_config(argv: list[str]) -> None:
21
+ if "--config-json" not in argv:
22
+ return
23
+ idx = argv.index("--config-json")
24
+ if idx + 1 >= len(argv):
25
+ return
26
+ raw_path = argv[idx + 1]
27
+ try:
28
+ cfg_path = Path(raw_path).expanduser()
29
+ if not cfg_path.is_absolute():
30
+ cfg_path = cfg_path.resolve()
31
+ if not cfg_path.exists():
32
+ script_dir = Path(__file__).resolve().parents[1]
33
+ candidate = (script_dir / raw_path).resolve()
34
+ if candidate.exists():
35
+ cfg_path = candidate
36
+ if not cfg_path.exists():
37
+ return
38
+ cfg = json.loads(cfg_path.read_text(encoding="utf-8", errors="replace"))
39
+ env = cfg.get("env", {})
40
+ if isinstance(env, dict):
41
+ for key, value in env.items():
42
+ if key is None:
43
+ continue
44
+ os.environ.setdefault(str(key), str(value))
45
+ except Exception:
46
+ return
47
+
48
+ _apply_env_from_config(sys.argv)
49
+
50
+ try:
51
+ from ins_pricing.cli.bayesopt_entry_runner import main
52
+ except Exception: # pragma: no cover
53
+ from ins_pricing.cli.bayesopt_entry_runner import main
54
+
55
+ __all__ = ["main"]
56
+
57
+ if __name__ == "__main__":
58
+ main()