Skip to content

Commit 83016c1

Browse files
Jammy2211claude
authored andcommitted
fix: PYAUTO_DISABLE_JAX has exactly one reader (#181 step 7)
af.Analysis.__init__ is the single resolver of PYAUTO_DISABLE_JAX + jax-availability; AnalysisLens.__init__ now always receives the base-resolved self._use_jax instead of the raw parameter, at all three call sites. Deletes the duplicate env read in AnalysisDataset (design failure mode 8) and FIXES a live bug: AnalysisPoint and the weak analysis silently undid the env downgrade (base set False, AnalysisLens overwrote True), so PYAUTO_DISABLE_JAX=1 was a no-op for them. Construction-level tests: env downgrade respected for AnalysisImaging and AnalysisPoint (the point test fails on pre-fix source), no over-downgrade when the env var is unset. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 38ef6e3 commit 83016c1

6 files changed

Lines changed: 93 additions & 12 deletions

File tree

autolens/analysis/analysis/dataset.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
"""
1515
import logging
1616
import numpy as np
17-
import os
1817
from typing import List, Optional
1918

2019
from autonerves import conf
@@ -84,11 +83,6 @@ def __init__(
8483
anyway.
8584
"""
8685

87-
import os
88-
89-
if os.environ.get("PYAUTO_DISABLE_JAX") == "1":
90-
use_jax = False
91-
9286
super().__init__(
9387
dataset=dataset,
9488
adapt_images=adapt_images,
@@ -99,11 +93,15 @@ def __init__(
9993
**kwargs,
10094
)
10195

96+
# `super().__init__` routes through `af.Analysis.__init__`, the single
97+
# reader of the disable-jax env var and the jax-availability check, which
98+
# resolves `self._use_jax`. Forward that resolved value so `AnalysisLens`
99+
# never overwrites it with the raw parameter.
102100
AnalysisLens.__init__(
103101
self=self,
104102
positions_likelihood_list=positions_likelihood_list,
105103
cosmology=cosmology,
106-
use_jax=use_jax,
104+
use_jax=self._use_jax,
107105
)
108106

109107
self.raise_inversion_positions_likelihood_exception = (

autolens/analysis/analysis/lens.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,11 @@ def __init__(
6161
self.cosmology = cosmology or Planck15()
6262
self.positions_likelihood_list = positions_likelihood_list
6363

64-
# Mirror the autofit Analysis fallback: if jax isn't installed,
65-
# downgrade silently here too (the parent Analysis.__init__ already
66-
# emitted the loud banner — no need to repeat it).
64+
# `use_jax` is expected to already be the base-resolved value
65+
# (`self._use_jax` set by `af.Analysis.__init__`, the single reader of
66+
# the disable-jax env var and the jax-availability check). This guard is
67+
# a defensive, idempotent re-check of jax availability only — it never
68+
# re-reads the env var and does not repeat the parent's loud banner.
6769
import importlib.util
6870
if use_jax and importlib.util.find_spec("jax") is None:
6971
use_jax = False

autolens/point/model/analysis.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,10 @@ def __init__(
8181
"""
8282
super().__init__(cosmology=cosmology, use_jax=use_jax, **kwargs)
8383

84-
AnalysisLens.__init__(self=self, cosmology=cosmology, use_jax=use_jax)
84+
# `super().__init__` (af.Analysis) is the single reader of the
85+
# disable-jax env var + the jax-availability check; forward the
86+
# resolved `self._use_jax` so `AnalysisLens` does not overwrite it.
87+
AnalysisLens.__init__(self=self, cosmology=cosmology, use_jax=self._use_jax)
8588

8689
self.dataset = dataset
8790

autolens/weak/model/analysis.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@ def __init__(
6868
"""
6969
super().__init__(cosmology=cosmology, use_jax=use_jax, **kwargs)
7070

71-
AnalysisLens.__init__(self=self, cosmology=cosmology, use_jax=use_jax)
71+
# `super().__init__` (af.Analysis) is the single reader of the
72+
# disable-jax env var + the jax-availability check; forward the
73+
# resolved `self._use_jax` so `AnalysisLens` does not overwrite it.
74+
AnalysisLens.__init__(self=self, cosmology=cosmology, use_jax=self._use_jax)
7275

7376
self.dataset = dataset
7477

test_autolens/analysis/analysis/test_analysis_dataset.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from pathlib import Path
2+
import importlib.util
23
import os
34
import pytest
45

@@ -12,6 +13,37 @@
1213
directory = Path(__file__).resolve().parent
1314

1415

16+
def _jax_installed() -> bool:
17+
return importlib.util.find_spec("jax") is not None
18+
19+
20+
def test__pyauto_disable_jax_env_downgrades_use_jax__imaging(
21+
monkeypatch, masked_imaging_7x7
22+
):
23+
# Regression cover for the deleted local env read in `AnalysisDataset`:
24+
# the disable-jax env var must still downgrade `use_jax`, now resolved
25+
# solely by `af.Analysis.__init__` (the single reader) and forwarded to
26+
# `AnalysisLens` as `self._use_jax`.
27+
monkeypatch.setenv("PYAUTO_DISABLE_JAX", "1")
28+
29+
analysis = al.AnalysisImaging(dataset=masked_imaging_7x7, use_jax=True)
30+
31+
assert analysis._use_jax is False
32+
33+
34+
@pytest.mark.skipif(not _jax_installed(), reason="jax not installed")
35+
def test__use_jax_true_env_unset__not_downgraded__imaging(
36+
monkeypatch, masked_imaging_7x7
37+
):
38+
# No over-downgrade: with the env var unset and jax installed,
39+
# `use_jax=True` must survive as `self._use_jax is True`.
40+
monkeypatch.delenv("PYAUTO_DISABLE_JAX", raising=False)
41+
42+
analysis = al.AnalysisImaging(dataset=masked_imaging_7x7, use_jax=True)
43+
44+
assert analysis._use_jax is True
45+
46+
1547
def test__modify_before_fit__inversion_no_positions_likelihood__raises_exception(
1648
masked_imaging_7x7,
1749
):

test_autolens/point/model/test_analysis_point.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
from pathlib import Path
2+
import importlib.util
3+
4+
import pytest
25

36
import autofit as af
47
import autolens as al
@@ -8,6 +11,46 @@
811
directory = Path(__file__).resolve().parent
912

1013

14+
def _jax_installed() -> bool:
15+
return importlib.util.find_spec("jax") is not None
16+
17+
18+
def test__pyauto_disable_jax_env_downgrades_use_jax__point(
19+
monkeypatch, point_dataset
20+
):
21+
# THE BUG TEST. Before the one-reader fix `AnalysisPoint` had no local
22+
# env read and `AnalysisLens.__init__` overwrote the base-resolved
23+
# `self._use_jax` with the raw `use_jax` parameter, so the disable-jax
24+
# env var was silently a no-op (base set False, AnalysisLens set True).
25+
# It must now downgrade to False.
26+
monkeypatch.setenv("PYAUTO_DISABLE_JAX", "1")
27+
28+
solver = al.m.MockPointSolver(model_positions=point_dataset.positions)
29+
30+
analysis = al.AnalysisPoint(
31+
dataset=point_dataset, solver=solver, use_jax=True
32+
)
33+
34+
assert analysis._use_jax is False
35+
36+
37+
@pytest.mark.skipif(not _jax_installed(), reason="jax not installed")
38+
def test__use_jax_true_env_unset__not_downgraded__point(
39+
monkeypatch, point_dataset
40+
):
41+
# No over-downgrade: with the env var unset and jax installed,
42+
# `use_jax=True` must survive as `self._use_jax is True`.
43+
monkeypatch.delenv("PYAUTO_DISABLE_JAX", raising=False)
44+
45+
solver = al.m.MockPointSolver(model_positions=point_dataset.positions)
46+
47+
analysis = al.AnalysisPoint(
48+
dataset=point_dataset, solver=solver, use_jax=True
49+
)
50+
51+
assert analysis._use_jax is True
52+
53+
1154
def _test__make_result__result_imaging_is_returned(point_dataset):
1255
model = af.Collection(
1356
galaxies=af.Collection(

0 commit comments

Comments
 (0)