Skip to content

fix: Optional[None] used as default value in tracer + max_separation #674

Closed

Description

@Jammy2211

Overview

Three sites in PyAutoLens use the typing construct Optional[None] as a default value. Optional[None] evaluates to NoneType — a truthy class object — so these defaults silently pass is not None guards. Behavior today is accidentally harmless (details below), but the code is genuinely wrong and misleading. Found by sweeping all four libraries for siblings of the site flagged during autolens_workspace#411.

Plan

  • Replace plane_index_limit: int = Optional[None] with plane_index_limit: Optional[int] = None in autolens/lens/tracer.py and autolens/lens/tracer_util.py.
  • Replace plane_redshift: float = Optional[None] with plane_redshift: Optional[float] = None in autolens/point/max_separation.py.
  • No behavioral change; run the lens + point test suites.
Detailed implementation plan

Affected Repositories

  • PyAutoLens (primary, only — sweep of PyAutoGalaxy/PyAutoArray/PyAutoFit found zero further sites)

Branch Survey

Repository Current Branch Dirty?
./PyAutoLens main clean

In-flight branches (feature/multi-package-rename-multi-dataset, feature/potential-correction-validation) hand-checked: neither touches the three files.

Suggested branch: feature/optional-none-default-typos

Implementation Steps

  1. autolens/lens/tracer.py:250 — plane_index_limit: Optional[int] = None.
  2. autolens/lens/tracer_util.py:178 — same.
  3. autolens/point/max_separation.py:27 — plane_redshift: Optional[float] = None.
  4. python -m pytest test_autolens/lens/ test_autolens/point/.

Why behavior is preserved

  • tracer_util.traced_grid_2d_list_from guards if plane_index_limit is not None:. The NoneType default passes the guard and compares plane_index == NoneType per plane (always False) — the early exit never fires. With None, the guard is skipped entirely: same result, less accidental work.
  • SourceMaxSeparation feeds the default to Tracer.plane_index_via_redshift_from, where np.isclose(NoneType, z) raises TypeError, caught to fall back to plane_index = -1. np.isclose(None, z) raises the same TypeError — identical fallback.

Key Files

  • autolens/lens/tracer.py, autolens/lens/tracer_util.py — multi-plane ray-tracing early-exit parameter.
  • autolens/point/max_separation.py — point-source max-separation plane selection.

Original Prompt

Click to expand starting prompt

Prompt file: PyAutoMind/active/optional_none_default_typos.md. User instruction: "merge and then fix drift", following the multi-plane-guide-units ship report which flagged this library drift. The notebooks/group/start_here.ipynb regeneration drift is explicitly excluded (picked up by the next generation pass).

Activity

  1. Jammy2211 commented on Jul 30, 2026

    @Jammy2211
    CollaboratorAuthor

    Shipped — 2026-07-30

    PRs

    Summary

    Fixed all three Optional[None]-as-default sites (lens/tracer.py, lens/tracer_util.py, point/max_separation.py) to proper Optional[int/float] = None annotations. Behavior-preserving, verified against both callees: the tracer's early-exit guard no longer runs pointlessly on default calls, and SourceMaxSeparation's plane_index = -1 fallback path is unchanged (np.isclose(None, z) raises the same TypeError the NoneType class did). test_autolens/lens/ + point/ 200 passed locally; full CI matrix green.

    Session Notes

    Sweep of PyAutoGalaxy, PyAutoArray and PyAutoFit found zero further sites. Found while re-syncing the pedagogical code copies for autolens_workspace#411/#413.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions