agi-env 2025.12.19__py3-none-any.whl → 2026.2.6__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.
agi_env/agi_env.py CHANGED
@@ -501,6 +501,7 @@ class AgiEnv(metaclass=_AgiEnvMeta):
501
501
  env_path = self.resources_path / ".env"
502
502
  self.benchmark = self.resources_path / "benchmark.json"
503
503
  self.envars = dotenv_values(dotenv_path=env_path, verbose=verbose)
504
+ logger.debug(f"env path: {env_path}")
504
505
  envars = self.envars
505
506
  repo_agilab_dir = Path(__file__).resolve().parents[4]
506
507
 
@@ -948,8 +949,76 @@ class AgiEnv(metaclass=_AgiEnvMeta):
948
949
  self.uv_worker = self.uv
949
950
  use_freethread = False
950
951
 
951
- self.AGI_LOCAL_SHARE = envars.get("AGI_LOCAL_SHARE", 'localshare')
952
- self.AGI_CLUSTER_SHARE = envars.get("AGI_CLUSTER_SHARE", 'clustershare')
952
+ self.AGI_LOCAL_SHARE = envars.get("AGI_LOCAL_SHARE", "localshare")
953
+ self.AGI_CLUSTER_SHARE = envars.get("AGI_CLUSTER_SHARE", "clustershare")
954
+
955
+ # `AGI_SHARE_DIR` is the user-facing knob (installer + Streamlit UI). Treat it
956
+ # as an override for the cluster share root so updating it is immediately
957
+ # reflected without having to also edit `AGI_CLUSTER_SHARE` manually.
958
+ share_dir_override = envars.get("AGI_SHARE_DIR")
959
+ if share_dir_override is not None:
960
+ share_dir_value = str(share_dir_override).strip()
961
+ if share_dir_value:
962
+ self.AGI_CLUSTER_SHARE = share_dir_value
963
+ try:
964
+ envars["AGI_CLUSTER_SHARE"] = share_dir_value
965
+ except Exception:
966
+ pass
967
+
968
+ def _cluster_enabled_from_settings() -> bool:
969
+ """Best-effort read of the Streamlit 'Enable Cluster' toggle.
970
+
971
+ The toggle is persisted under `[cluster].cluster_enabled` in each app's
972
+ `app_settings.toml`. When the per-app setting is missing, fall back to
973
+ the global `.env` value `AGI_CLUSTER_ENABLED` if present.
974
+ """
975
+
976
+ if self.is_worker_env:
977
+ return True
978
+
979
+ def _parse_bool(value: object) -> bool | None:
980
+ if isinstance(value, bool):
981
+ return value
982
+ if isinstance(value, (int, float)):
983
+ return bool(value)
984
+ if isinstance(value, str):
985
+ normalized = value.strip().lower()
986
+ if normalized in {"1", "true", "yes", "y", "on"}:
987
+ return True
988
+ if normalized in {"0", "false", "no", "n", "off", ""}:
989
+ return False
990
+ return None
991
+
992
+ parsed: bool | None = None
993
+
994
+ try:
995
+ settings_path = self.app_src / "app_settings.toml"
996
+ except Exception:
997
+ settings_path = None
998
+
999
+ try:
1000
+ if (
1001
+ settings_path is not None
1002
+ and settings_path.exists()
1003
+ and settings_path.stat().st_size > 0
1004
+ ):
1005
+ import tomllib
1006
+
1007
+ with settings_path.open("rb") as handle:
1008
+ doc = tomllib.load(handle)
1009
+ cluster_section = doc.get("cluster")
1010
+ if isinstance(cluster_section, dict) and "cluster_enabled" in cluster_section:
1011
+ parsed = _parse_bool(cluster_section.get("cluster_enabled"))
1012
+ except Exception:
1013
+ parsed = None
1014
+
1015
+ if parsed is not None:
1016
+ return parsed
1017
+
1018
+ parsed = _parse_bool(envars.get("AGI_CLUSTER_ENABLED"))
1019
+ return bool(parsed) if parsed is not None else False
1020
+
1021
+ cluster_enabled = _cluster_enabled_from_settings()
953
1022
 
954
1023
  def _abs_path(path_str: str) -> str:
955
1024
  """Absolute path; relative paths are relative to $HOME."""
@@ -1042,24 +1111,28 @@ class AgiEnv(metaclass=_AgiEnvMeta):
1042
1111
 
1043
1112
  # No bind rule found; directory is usable, so accept it.
1044
1113
  return True
1045
-
1046
1114
  candidate = _abs_path(self.AGI_CLUSTER_SHARE)
1047
- if is_mounted(candidate):
1115
+
1116
+ wants_cluster_share = bool(cluster_enabled)
1117
+ mounted = is_mounted(candidate)
1118
+ if mounted and wants_cluster_share:
1048
1119
  self.agi_share_path = self.AGI_CLUSTER_SHARE
1049
1120
  #AgiEnv.logger.info(
1050
1121
  # f"self.agi_share_path = AGI_CLUSTER_SHARE = {candidate}"
1051
1122
  #)
1052
1123
  else:
1053
1124
  self.agi_share_path = self.AGI_LOCAL_SHARE
1054
- fallback = _abs_path(self.AGI_LOCAL_SHARE)
1055
- warning_key = (candidate, fallback)
1056
- if warning_key not in AgiEnv._share_mount_warning_keys:
1057
- AgiEnv._share_mount_warning_keys.add(warning_key)
1058
- AgiEnv.logger.warning(
1059
- "AGI_CLUSTER_SHARE is not mounted at %s; using AGI_LOCAL_SHARE=%s",
1060
- candidate,
1061
- fallback,
1062
- )
1125
+ if wants_cluster_share and not mounted:
1126
+ fallback = _abs_path(self.AGI_LOCAL_SHARE)
1127
+ warning_key = (candidate, fallback)
1128
+ if warning_key not in AgiEnv._share_mount_warning_keys:
1129
+ AgiEnv._share_mount_warning_keys.add(warning_key)
1130
+ AgiEnv.logger.warning(
1131
+ "Cluster is enabled but AGI_CLUSTER_SHARE is not mounted at %s; using AGI_LOCAL_SHARE=%s; using env=%s",
1132
+ candidate,
1133
+ fallback,
1134
+ env_path
1135
+ )
1063
1136
  self._share_root_cache = None
1064
1137
 
1065
1138
  share_root_abs = self.share_root_path()
@@ -1,5 +1,5 @@
1
1
  [project]
2
- version = "2025.12.19"
2
+ version = "2026.02.06"
3
3
  name = "agi-env"
4
4
  description = "AGI Env"
5
5
  requires-python = ">=3.11"
@@ -39,7 +39,7 @@ dependencies = [
39
39
  "ipython",
40
40
  "py7zr",
41
41
  "cmake>=3.29",
42
- "numba",
42
+ "numba>=0.61.0",
43
43
  "streamlit"
44
44
  ]
45
45
  [project.urls]
@@ -92,6 +92,7 @@ Tracker = "https://github.com/ThalesGroup/agilab/issues"
92
92
 
93
93
 
94
94
 
95
+
95
96
 
96
97
 
97
98
  [dependency-groups]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agi-env
3
- Version: 2025.12.19
3
+ Version: 2026.2.6
4
4
  Summary: AGI Env
5
5
  Author-email: Jean-Pierre Morard <focus@thalesgroup.com>
6
6
  Project-URL: Documentation, https://thalesgroup.github.io/agilab
@@ -30,11 +30,11 @@ Requires-Dist: pathspec
30
30
  Requires-Dist: ipython
31
31
  Requires-Dist: py7zr
32
32
  Requires-Dist: cmake>=3.29
33
- Requires-Dist: numba
33
+ Requires-Dist: numba>=0.61.0
34
34
  Requires-Dist: streamlit
35
35
  Dynamic: license-file
36
36
 
37
- [![PyPI version](https://img.shields.io/badge/PyPI-2025.12.19.post1-informational?logo=pypi)](https://pypi.org/project/agi-env)
37
+ [![PyPI version](https://img.shields.io/badge/PyPI-2025.12.19-informational?logo=pypi)](https://pypi.org/project/agi-env)
38
38
  [![Supported Python Versions](https://img.shields.io/pypi/pyversions/agilab.svg)](https://pypi.org/project/agilab/)
39
39
  [![License: BSD 3-Clause](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
40
40
  [![pypi_dl](https://img.shields.io/pypi/dm/agilab)]()
@@ -1,23 +1,21 @@
1
1
  __init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  agi_env/__init__.py,sha256=-CQAqnhPWSxSF2dDd_qgFT0l5anRSJA2wQHYHXpaTMg,22
3
- agi_env/agi_env.py,sha256=-MvdqGXhnwo2SX1fFxZZDHYgy-w_ulNDVSR5WVfk_rM,136513
3
+ agi_env/agi_env.py,sha256=HRs4aXPAqtMTDDY0yE9npwaIbMo9O5M317zIk-GwwVU,139592
4
4
  agi_env/agi_logger.py,sha256=FS8kPIWvDx5JkK5Rz7krawLjHwK1-YelY36ogXJulIE,6053
5
5
  agi_env/app_args.py,sha256=lVGgbJ3GMxGVPaxKKBNYgbyvJzYNEuTNCKCYAL14V_s,3162
6
6
  agi_env/defaults.py,sha256=6EHHTbHLvHgD-QqQeyV2MpKDtioGCF9B6hrnp12xizE,614
7
7
  agi_env/pagelib.py,sha256=453urFtXQ4kzbgWd00OMSqh8fUHrvT3W35uRT6EvJjk,66787
8
8
  agi_env/streamlit_args.py,sha256=AEVHCvPPQsLbDh8sSXHIAombqrVYuGOwVF3jVDvuV80,7493
9
- agi_env/resources/.DS_Store,sha256=MfZyFCxQM5bjZfnQ6nCP2NJApo8i6kJJg-wAXIyglzs,6148
10
9
  agi_env/resources/.agilab/.env,sha256=wtL5F5R_3XKDqgmzfWHUdRQ0D9qYbxei35NXefYCBz0,629
11
10
  agi_env/resources/.agilab/balancer_df.csv,sha256=vHIgSiO2AzEptpXWoOp-YkCY-RsjEoDUQw7cEHKWh44,20890
12
11
  agi_env/resources/.agilab/balancer_model.pkl,sha256=trKIFnZfYt0XT_Ms_rGs6abDvcm_mc1BuuPBCbwfCD0,1942056
13
- agi_env/resources/mistral_offline/.DS_Store,sha256=6Ft2bE3Gh1hBGWHs9QC6oGxbZ4Y5OPu80HCRIUgxSyw,6148
14
12
  agi_env/resources/mistral_offline/README.md,sha256=H4vtXFQvU_gW9pKpAK1SYf6mRxRyMlPAwSpfIoDh104,698
15
13
  agi_env/resources/mistral_offline/data/.gitignore,sha256=JFSYaZ4qwoaAJN1DCdDDRS9vIyDHfn4X4h87RWRHJ-s,24
16
14
  agi_env/resources/mistral_offline/data/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- agi_env-2025.12.19.data/data/agi_env/pyproject.toml,sha256=Jdq2Os8mD7XHKSInZFU49RgBpzNsJLuUlMjL63pTFiE,2103
18
- agi_env-2025.12.19.data/data/agi_env/uv_config.toml,sha256=-7cu1wTytwNDdNVcnNr-rWyPh7DCa30lR7YDjv5D6Lo,131
19
- agi_env-2025.12.19.dist-info/licenses/LICENSE,sha256=ucK7uAh-6Rbh-GKMACsfmvd899wRIzHtyl7exM1bChY,1564
20
- agi_env-2025.12.19.dist-info/METADATA,sha256=CY2kc7tpBKfgl4lafs5oYx4aLIvnr_R05QMntOpKt-0,3462
21
- agi_env-2025.12.19.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
22
- agi_env-2025.12.19.dist-info/top_level.txt,sha256=3ra3EDD3xb5BQbN419HqFmaO0LqD41YV-QiOozDJ920,17
23
- agi_env-2025.12.19.dist-info/RECORD,,
15
+ agi_env-2026.2.6.data/data/agi_env/pyproject.toml,sha256=JhIWa86Cxfsxar83zSeaYpXCLjzfNWz3xhHFyzi-PX4,2112
16
+ agi_env-2026.2.6.data/data/agi_env/uv_config.toml,sha256=-7cu1wTytwNDdNVcnNr-rWyPh7DCa30lR7YDjv5D6Lo,131
17
+ agi_env-2026.2.6.dist-info/licenses/LICENSE,sha256=ucK7uAh-6Rbh-GKMACsfmvd899wRIzHtyl7exM1bChY,1564
18
+ agi_env-2026.2.6.dist-info/METADATA,sha256=mQ08DnIrNkDYcO5Q5SFvADmyJEDT4lsp-2FhjCBWFpk,3462
19
+ agi_env-2026.2.6.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
20
+ agi_env-2026.2.6.dist-info/top_level.txt,sha256=3ra3EDD3xb5BQbN419HqFmaO0LqD41YV-QiOozDJ920,17
21
+ agi_env-2026.2.6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
Binary file
Binary file