diff --git a/docs/agents/python.md b/docs/agents/python.md
index 4fe9843cf..b8cfaca87 100644
--- a/docs/agents/python.md
+++ b/docs/agents/python.md
@@ -6,12 +6,10 @@ remains configured for editor feedback.
## Required checks
-- **Tool environment:** Run Python checks in this worktree's `.conda-env`:
- `conda run --prefix .conda-env make typecheck` and
- `conda run --prefix .conda-env make lint`. If the environment is activated
- instead, verify that `python`, `mypy`, and `black` all resolve inside the
- same environment before running the Make targets. A `python` path inside
- `.conda-env` alone does not establish which tools Make will invoke.
+- **Tool environment:** Run Python checks from within an active, isolated project
+ environment (e.g., `conda`, `venv`, or an agent sandbox). Verify that `python`,
+ `mypy`, and `black` all resolve to this same environment before running the Make
+ targets.
- **Types:** Annotate functions and methods. Avoid `Any` in signatures. Use
`make typecheck` for type checking; it runs the project's mypy target.
- **Format and lint:** Format modified Python files with `black` from the
@@ -27,15 +25,15 @@ remains configured for editor feedback.
## Testing
-- **Test environment:** Run pytest and Make test targets through `.conda-env`.
- NumCosmo tests write FFTW wisdom under `~/.numcosmo`, and download tests use
- `~/.firecrown`; ensure these directories are writable before running those
- tests in a sandbox. Treat a denied cache write as a sandbox failure, then
+- **Test environment:** Run `pytest` and Make test targets within your active
+ environment. NumCosmo tests write FFTW wisdom under `~/.numcosmo`, and download
+ tests use `~/.firecrown`; ensure these directories are writable before running
+ those tests in a sandbox. Treat a denied cache write as a sandbox failure, then
rerun with scoped access before judging the test result.
-- **Avoid monkeypatching**: Prefer use of fixtures, parameterized tests, and
+- **Avoid monkeypatching:** Prefer use of fixtures, parameterized tests, and
dependency injection to the use of monkeypatching. Use monkeypatching only
- when other techniques would lead to more complicated code. Any use of
- monkeypatching must contain a comment explaining why monkeypatching it the
+ when other techniques would lead to more complicated code. Any use of
+ monkeypatching must contain a comment explaining why monkeypatching is the
best choice for that test.
## Review guidance
diff --git a/pyproject.toml b/pyproject.toml
index 4b99311a7..8059d4a4d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -148,10 +148,6 @@ explicit_package_bases = true
disallow_any_generics = true
disallow_untyped_defs = true
-[[tool.mypy.overrides]]
-module = ["tests", "tests.*"]
-disallow_untyped_defs = false
-
[[tool.mypy.overrides]]
module = "firecrown.connector.cobaya.*"
disallow_subclassing_any = false
diff --git a/tests/_types.py b/tests/_types.py
new file mode 100644
index 000000000..6e3b8eafa
--- /dev/null
+++ b/tests/_types.py
@@ -0,0 +1,36 @@
+"""Shared types for test fixtures."""
+
+from typing import TypeAlias, TypedDict
+
+from numcosmo_py import Nc
+import numpy as np
+import numpy.typing as npt
+import sacc
+
+from firecrown.metadata_types import TracerNames
+
+RedshiftDistribution: TypeAlias = tuple[
+ npt.NDArray[np.float64], npt.NDArray[np.float64]
+]
+"""Sampled redshift distribution as (z, dndz), without a normalization guarantee."""
+
+WindowedAngularPowerSpectrum: TypeAlias = tuple[
+ npt.NDArray[np.int64], npt.NDArray[np.float64], sacc.BandpowerWindow
+]
+"""Window ell grid, measured bandpowers, and their bandpower window."""
+
+SaccGalaxyWindowedFixture: TypeAlias = tuple[
+ sacc.Sacc,
+ dict[str, RedshiftDistribution],
+ dict[tuple[TracerNames, str], WindowedAngularPowerSpectrum],
+]
+"""SACC data, distributions by tracer name, and spectra by tracer pair/data type."""
+
+
+class NumCosmoCosmologyFixture(TypedDict):
+ """Values provided by the NumCosmo cosmology fixtures."""
+
+ cosmo: Nc.HICosmo
+ p_ml: Nc.PowspecML
+ p_mnl: Nc.PowspecMNL
+ dist: Nc.Distance
diff --git a/tests/app/analysis/test_download.py b/tests/app/analysis/test_download.py
index 268a5cd38..13abe76be 100644
--- a/tests/app/analysis/test_download.py
+++ b/tests/app/analysis/test_download.py
@@ -72,7 +72,7 @@ class TestDownloadFromUrl:
@patch("urllib.request.urlretrieve")
def test_download_from_url_uses_cache_when_available(
- self, mock_retrieve, tmp_path: Path
+ self, mock_retrieve: MagicMock, tmp_path: Path
) -> None:
"""Test that cached files are used instead of downloading."""
output_file = tmp_path / "test.txt"
@@ -99,7 +99,7 @@ def test_download_from_url_uses_cache_when_available(
@patch("urllib.request.urlretrieve")
def test_download_from_url_downloads_when_not_cached(
- self, mock_retrieve, tmp_path: Path
+ self, mock_retrieve: MagicMock, tmp_path: Path
) -> None:
"""Test that file is downloaded when not in cache."""
output_file = tmp_path / "test_new.txt"
@@ -113,7 +113,7 @@ def test_download_from_url_downloads_when_not_cached(
try:
# Mock the download to create the cached file
- def mock_download(url, path):
+ def mock_download(url: str, path: Path) -> None:
assert url is not None
Path(path).write_text("downloaded content", encoding="utf-8")
@@ -135,7 +135,7 @@ def mock_download(url, path):
@patch("urllib.request.urlretrieve")
def test_download_from_url_with_description(
- self, mock_retrieve, tmp_path: Path
+ self, mock_retrieve: MagicMock, tmp_path: Path
) -> None:
"""Test download with custom description."""
output_file = tmp_path / "test_desc.txt"
@@ -149,7 +149,7 @@ def test_download_from_url_with_description(
try:
# Mock the download
- def mock_download(url, path):
+ def mock_download(url: str, path: Path) -> None:
assert url is not None
Path(path).write_text("content", encoding="utf-8")
@@ -193,7 +193,7 @@ def test_download_from_url_network_error(self, tmp_path: Path) -> None:
@patch("urllib.request.urlretrieve")
def test_download_from_url_console_parameter(
- self, mock_retrieve, tmp_path: Path
+ self, mock_retrieve: MagicMock, tmp_path: Path
) -> None:
"""Test that console parameter is required."""
output_file = tmp_path / "test_console.txt"
@@ -207,7 +207,7 @@ def test_download_from_url_console_parameter(
try:
# Mock the download
- def mock_download(_, path):
+ def mock_download(_: str, path: Path) -> None:
Path(path).write_text("content", encoding="utf-8")
mock_retrieve.side_effect = mock_download
diff --git a/tests/app/analysis/test_types.py b/tests/app/analysis/test_types.py
index c6ef426b2..6f3a6345e 100644
--- a/tests/app/analysis/test_types.py
+++ b/tests/app/analysis/test_types.py
@@ -3,6 +3,8 @@
Tests type definitions, enums, and data models for framework configuration.
"""
+from pathlib import Path
+
import pyccl
import pytest
from pydantic import ValidationError
@@ -827,7 +829,7 @@ def test_to_ccl_cosmology_all_optional_fields_false(self) -> None:
class TestConfigGeneratorMethods:
"""Tests for ConfigGenerator methods."""
- def test_config_generator_add_sacc(self, tmp_path) -> None:
+ def test_config_generator_add_sacc(self, tmp_path: Path) -> None:
"""Test add_sacc method."""
gen = CobayaConfigGenerator(
output_path=tmp_path,
@@ -841,7 +843,7 @@ def test_config_generator_add_sacc(self, tmp_path) -> None:
gen.add_sacc(sacc_path)
assert gen.sacc_path == sacc_path
- def test_config_generator_add_factory(self, tmp_path) -> None:
+ def test_config_generator_add_factory(self, tmp_path: Path) -> None:
"""Test add_factory method."""
gen = CobayaConfigGenerator(
output_path=tmp_path,
@@ -855,7 +857,7 @@ def test_config_generator_add_factory(self, tmp_path) -> None:
gen.add_factory(factory_path)
assert gen.factory_source == factory_path
- def test_config_generator_add_build_parameters(self, tmp_path) -> None:
+ def test_config_generator_add_build_parameters(self, tmp_path: Path) -> None:
"""Test add_build_parameters method."""
gen = CobayaConfigGenerator(
output_path=tmp_path,
@@ -869,7 +871,7 @@ def test_config_generator_add_build_parameters(self, tmp_path) -> None:
gen.add_build_parameters(params)
assert gen.build_parameters == params
- def test_config_generator_add_models(self, tmp_path) -> None:
+ def test_config_generator_add_models(self, tmp_path: Path) -> None:
"""Test add_models method."""
gen = CobayaConfigGenerator(
output_path=tmp_path,
@@ -908,14 +910,14 @@ def test_get_path_str_with_string(self) -> None:
result = get_path_str("my_string_path", use_absolute=False)
assert result == "my_string_path"
- def test_get_path_str_with_path_absolute(self, tmp_path) -> None:
+ def test_get_path_str_with_path_absolute(self, tmp_path: Path) -> None:
"""Test get_path_str with Path object and absolute flag."""
test_path = tmp_path / "subdir" / "file.txt"
result = get_path_str(test_path, use_absolute=True)
assert result == test_path.absolute().as_posix()
- def test_get_path_str_with_path_relative(self, tmp_path) -> None:
+ def test_get_path_str_with_path_relative(self, tmp_path: Path) -> None:
"""Test get_path_str with Path object and relative flag."""
test_path = tmp_path / "subdir" / "file.txt"
diff --git a/tests/app/examples/test_cluster_counts.py b/tests/app/examples/test_cluster_counts.py
index e97c133ac..3e232283d 100644
--- a/tests/app/examples/test_cluster_counts.py
+++ b/tests/app/examples/test_cluster_counts.py
@@ -6,6 +6,7 @@
import importlib.util
import sys
from pathlib import Path
+from typing import TypedDict, Unpack
from unittest.mock import patch
import pytest
@@ -26,8 +27,25 @@
from firecrown.modeling_tools import ModelingTools
-def make_builder(tmp_path: Path, **kwargs) -> ExampleClusterCounts:
- """Create a builder without running the generation workflow."""
+class _BuilderKwargs(TypedDict, total=False):
+ """Optional constructor arguments exercised by these tests."""
+
+ prefix: str
+ dataset: ClusterDataset
+ use_cluster_counts: bool
+ use_mean_log_mass: bool
+ cosmology_spec: Path
+
+
+def make_builder(
+ tmp_path: Path, **kwargs: Unpack[_BuilderKwargs]
+) -> ExampleClusterCounts:
+ """Create a builder without running the generation workflow.
+
+ :param tmp_path: Output directory for the builder.
+ :param kwargs: Optional builder settings used by the test.
+ :returns: Builder with generation suppressed.
+ """
with patch.object(ExampleClusterCounts, "_proceed_generation"):
return ExampleClusterCounts(
output_path=tmp_path, target_framework=Frameworks.COSMOSIS, **kwargs
diff --git a/tests/app/examples/test_cluster_shear.py b/tests/app/examples/test_cluster_shear.py
index 0ceb40dac..d8cc80e3e 100644
--- a/tests/app/examples/test_cluster_shear.py
+++ b/tests/app/examples/test_cluster_shear.py
@@ -4,6 +4,7 @@
"""
from pathlib import Path
+from typing import TypedDict, Unpack
from unittest.mock import patch
import numpy as np
@@ -22,8 +23,23 @@
from firecrown.modeling_tools import ModelingTools
-def make_builder(tmp_path: Path, **kwargs) -> ExampleClusterShear:
- """Create a builder without running the generation workflow."""
+class _BuilderKwargs(TypedDict, total=False):
+ """Optional constructor arguments exercised by these tests."""
+
+ prefix: str
+ profile: ClusterProfile
+ cosmology_spec: Path
+
+
+def make_builder(
+ tmp_path: Path, **kwargs: Unpack[_BuilderKwargs]
+) -> ExampleClusterShear:
+ """Create a builder without running the generation workflow.
+
+ :param tmp_path: Output directory for the builder.
+ :param kwargs: Optional builder settings used by the test.
+ :returns: Builder with generation suppressed.
+ """
with patch.object(ExampleClusterShear, "_proceed_generation"):
return ExampleClusterShear(
output_path=tmp_path, target_framework=Frameworks.COSMOSIS, **kwargs
diff --git a/tests/app/examples/test_relocation.py b/tests/app/examples/test_relocation.py
index 45be8cd49..85bd80f3f 100644
--- a/tests/app/examples/test_relocation.py
+++ b/tests/app/examples/test_relocation.py
@@ -30,7 +30,9 @@
params=CASES,
ids=[f"{name}-{framework.value}" for name, framework in CASES],
)
-def fixture_generated(request, tmp_path: Path) -> tuple[Path, Frameworks, str]:
+def fixture_generated(
+ request: pytest.FixtureRequest, tmp_path: Path
+) -> tuple[Path, Frameworks, str]:
"""Generate each example for each framework with the default options."""
name, framework = request.param
example_cls, options = EXAMPLES[name]
diff --git a/tests/app/test_experiment.py b/tests/app/test_experiment.py
index 6984b60d8..52115a5cd 100644
--- a/tests/app/test_experiment.py
+++ b/tests/app/test_experiment.py
@@ -140,7 +140,9 @@ def test_load_experiment_invalid_yaml_raises_exception(
with pytest.raises(Exception):
Load(experiment_file=exp_file)
- def test_load_experiment_prints_file_path(self, tmp_path: Path, capsys) -> None:
+ def test_load_experiment_prints_file_path(
+ self, tmp_path: Path, capsys: pytest.CaptureFixture[str]
+ ) -> None:
"""Test that load prints the file path to console."""
exp_file = tmp_path / "exp.yaml"
exp_data = {
@@ -201,7 +203,9 @@ def test_view_calls_print_factories(self, tmp_path: Path) -> None:
class TestViewPrintFactories:
"""Tests for View._print_factories method."""
- def test_print_factories_displays_data_source(self, tmp_path: Path, capsys) -> None:
+ def test_print_factories_displays_data_source(
+ self, tmp_path: Path, capsys: pytest.CaptureFixture[str]
+ ) -> None:
"""Test that _print_factories displays data source information."""
exp_file = tmp_path / "exp.yaml"
exp_data = {
@@ -230,7 +234,9 @@ def test_print_factories_displays_data_source(self, tmp_path: Path, capsys) -> N
assert "Data Source" in captured.out
assert "data.sacc" in captured.out
- def test_print_factories_displays_filters(self, tmp_path: Path, capsys) -> None:
+ def test_print_factories_displays_filters(
+ self, tmp_path: Path, capsys: pytest.CaptureFixture[str]
+ ) -> None:
"""Test that filters are displayed when present."""
exp_file = tmp_path / "exp.yaml"
exp_data = {
@@ -263,7 +269,7 @@ def test_print_factories_displays_filters(self, tmp_path: Path, capsys) -> None:
assert "scale_cuts.yaml" in captured.out
def test_print_factories_displays_weak_lensing(
- self, tmp_path: Path, capsys
+ self, tmp_path: Path, capsys: pytest.CaptureFixture[str]
) -> None:
"""Test that weak lensing factories are displayed."""
exp_file = tmp_path / "exp.yaml"
@@ -300,7 +306,7 @@ def test_print_factories_displays_weak_lensing(
assert "src0" in captured.out
def test_print_factories_displays_number_counts(
- self, tmp_path: Path, capsys
+ self, tmp_path: Path, capsys: pytest.CaptureFixture[str]
) -> None:
"""Test that number counts factories are displayed."""
exp_file = tmp_path / "exp.yaml"
@@ -335,7 +341,9 @@ def test_print_factories_displays_number_counts(
assert "NumberCounts" in captured.out
assert "lens0" in captured.out
- def test_print_factories_displays_cmb(self, tmp_path: Path, capsys) -> None:
+ def test_print_factories_displays_cmb(
+ self, tmp_path: Path, capsys: pytest.CaptureFixture[str]
+ ) -> None:
"""Test that CMB factories are displayed."""
exp_file = tmp_path / "exp.yaml"
exp_data = {
@@ -367,7 +375,9 @@ def test_print_factories_displays_cmb(self, tmp_path: Path, capsys) -> None:
assert "CMBConvergence" in captured.out
assert "cmb_convergence" in captured.out
- def test_print_factories_displays_systematics(self, tmp_path: Path, capsys) -> None:
+ def test_print_factories_displays_systematics(
+ self, tmp_path: Path, capsys: pytest.CaptureFixture[str]
+ ) -> None:
"""Test that systematics are displayed."""
exp_file = tmp_path / "exp.yaml"
exp_data = {
@@ -404,7 +414,7 @@ def test_print_factories_displays_systematics(self, tmp_path: Path, capsys) -> N
assert "multiplicative_bias" in captured.out
def test_print_factories_empty_systematics_shows_dash(
- self, tmp_path: Path, capsys
+ self, tmp_path: Path, capsys: pytest.CaptureFixture[str]
) -> None:
"""Test that empty systematics list displays a dash."""
exp_file = tmp_path / "exp.yaml"
@@ -439,7 +449,9 @@ def test_print_factories_empty_systematics_shows_dash(
# The table should have dash for empty systematics
assert "WeakLensing" in captured.out
- def test_print_factories_multiple_factories(self, tmp_path: Path, capsys) -> None:
+ def test_print_factories_multiple_factories(
+ self, tmp_path: Path, capsys: pytest.CaptureFixture[str]
+ ) -> None:
"""Test displaying multiple factories of different types."""
exp_file = tmp_path / "exp.yaml"
exp_data = {
@@ -491,7 +503,9 @@ def test_print_factories_multiple_factories(self, tmp_path: Path, capsys) -> Non
class TestFormatSysFunction:
"""Tests for the fmt_sys helper function within _print_factories."""
- def test_fmt_sys_with_multiple_systematics(self, tmp_path: Path, capsys) -> None:
+ def test_fmt_sys_with_multiple_systematics(
+ self, tmp_path: Path, capsys: pytest.CaptureFixture[str]
+ ) -> None:
"""Test that multiple systematics are formatted correctly."""
exp_file = tmp_path / "exp.yaml"
exp_data = {
diff --git a/tests/conftest.py b/tests/conftest.py
index 31ea7330d..09ac02881 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -8,7 +8,7 @@
import ast
import sys
from itertools import product
-from typing import assert_never
+from typing import Callable, assert_never
import numpy as np
import numpy.typing as npt
@@ -43,6 +43,11 @@
from firecrown.modeling_tools import ModelingTools
from firecrown.updatable import ParamsMap, get_default_params_map
from firecrown.utils import upper_triangle_indices
+from tests._types import (
+ RedshiftDistribution,
+ SaccGalaxyWindowedFixture,
+ WindowedAngularPowerSpectrum,
+)
# Helper function for creating AST ClassDef nodes across Python versions
if sys.version_info >= (3, 12):
@@ -83,7 +88,7 @@ def _make_class_def(
)
-def pytest_addoption(parser):
+def pytest_addoption(parser: pytest.Parser) -> None:
"""Add handling of firecrown-specific options for the pytest test runner.
--runslow: used to run tests marked as slow, which are otherwise not run.
@@ -100,7 +105,7 @@ def pytest_addoption(parser):
)
-def pytest_configure(config):
+def pytest_configure(config: pytest.Config) -> None:
"""Add new markers that can be set on pytest tests.
Use the marker `slow` for any test that takes more than a second to run.
@@ -110,7 +115,9 @@ def pytest_configure(config):
config.addinivalue_line("markers", "slow: mark test as slow to run")
-def pytest_collection_modifyitems(config, items):
+def pytest_collection_modifyitems(
+ config: pytest.Config, items: list[pytest.Item]
+) -> None:
"""Apply our special markers and option handling for pytest."""
if not config.getoption("--example"):
@@ -120,7 +127,7 @@ def pytest_collection_modifyitems(config, items):
_skip_tests(items, "slow", "need --runslow option to run")
-def _skip_tests(items, keyword, reason):
+def _skip_tests(items: list[pytest.Item], keyword: str, reason: str) -> None:
"""Helper method to skip tests based on a marker name."""
tests_to_skip = pytest.mark.skip(reason=reason)
@@ -228,7 +235,7 @@ def fixture_tools_with_vanilla_cosmology() -> ModelingTools:
@pytest.fixture(name="harmonic_bin_1")
-def fixture_harmonic_bin_1(request) -> TomographicBin:
+def fixture_harmonic_bin_1(request: pytest.FixtureRequest) -> TomographicBin:
"""Generate an TomographicBin object with 5 bins."""
return request.param
@@ -327,7 +334,7 @@ def make_many_harmonic_bins() -> list[TomographicBin]:
],
ids=["counts", "shear_t", "shear_minus", "shear_plus"],
)
-def fixture_real_bin_1(request) -> TomographicBin:
+def fixture_real_bin_1(request: pytest.FixtureRequest) -> TomographicBin:
"""Generate an TomographicBin object with 5 bins."""
x = TomographicBin(
bin_name="bin_1",
@@ -348,7 +355,7 @@ def fixture_real_bin_1(request) -> TomographicBin:
],
ids=["counts", "shear_t", "shear_minus", "shear_plus"],
)
-def fixture_real_bin_2(request) -> TomographicBin:
+def fixture_real_bin_2(request: pytest.FixtureRequest) -> TomographicBin:
"""Generate an TomographicBin object with 3 bins."""
x = TomographicBin(
bin_name="bin_2",
@@ -584,9 +591,7 @@ def fixture_cluster_sacc_data() -> sacc.Sacc:
@pytest.fixture(name="sacc_galaxy_cells_src0_src0", scope="module")
-def fixture_sacc_galaxy_cells_src0_src0() -> (
- tuple[sacc.Sacc, npt.NDArray[np.float64], npt.NDArray[np.float64]]
-):
+def fixture_sacc_galaxy_cells_src0_src0() -> tuple[sacc.Sacc, TomographicBin]:
"""Fixture for a SACC data without window functions."""
sacc_data = sacc.Sacc()
@@ -602,7 +607,13 @@ def fixture_sacc_galaxy_cells_src0_src0() -> (
cov = np.diag(np.ones_like(Cells) * 0.01)
sacc_data.add_covariance(cov)
- return sacc_data, z, dndz
+ expected_bin = TomographicBin(
+ bin_name="src0",
+ z=z.copy(),
+ dndz=dndz.copy(),
+ measurements={Galaxies.SHEAR_E},
+ )
+ return sacc_data, expected_bin
@pytest.fixture(name="sacc_galaxy_cells_src0_src1", scope="module")
@@ -635,9 +646,7 @@ def fixture_sacc_galaxy_cells_src0_src1() -> tuple[
@pytest.fixture(name="sacc_galaxy_cells_lens0_lens0", scope="module")
-def fixture_sacc_galaxy_cells_lens0_lens0() -> (
- tuple[sacc.Sacc, npt.NDArray[np.float64], npt.NDArray[np.float64]]
-):
+def fixture_sacc_galaxy_cells_lens0_lens0() -> tuple[sacc.Sacc, TomographicBin]:
"""Fixture for a SACC data without window functions."""
sacc_data = sacc.Sacc()
@@ -653,7 +662,13 @@ def fixture_sacc_galaxy_cells_lens0_lens0() -> (
cov = np.diag(np.ones_like(Cells) * 0.01)
sacc_data.add_covariance(cov)
- return sacc_data, z, dndz
+ expected_bin = TomographicBin(
+ bin_name="lens0",
+ z=z.copy(),
+ dndz=dndz.copy(),
+ measurements={Galaxies.COUNTS},
+ )
+ return sacc_data, expected_bin
@pytest.fixture(name="sacc_galaxy_cells_lens0_lens1")
@@ -684,9 +699,7 @@ def fixture_sacc_galaxy_cells_lens0_lens1() -> tuple[
@pytest.fixture(name="sacc_galaxy_xis_lens0_lens0")
-def fixture_sacc_galaxy_xis_lens0_lens0() -> (
- tuple[sacc.Sacc, npt.NDArray[np.float64], npt.NDArray[np.float64]]
-):
+def fixture_sacc_galaxy_xis_lens0_lens0() -> tuple[sacc.Sacc, TomographicBin]:
"""Fixture for a SACC data without window functions."""
sacc_data = sacc.Sacc()
@@ -702,7 +715,13 @@ def fixture_sacc_galaxy_xis_lens0_lens0() -> (
cov = np.diag(np.ones_like(xis) * 0.01)
sacc_data.add_covariance(cov)
- return sacc_data, z, dndz
+ expected_bin = TomographicBin(
+ bin_name="lens0",
+ z=z.copy(),
+ dndz=dndz.copy(),
+ measurements={Galaxies.COUNTS},
+ )
+ return sacc_data, expected_bin
@pytest.fixture(name="sacc_galaxy_xis_lens0_lens1")
@@ -866,14 +885,7 @@ def fixture_sacc_galaxy_cells() -> tuple[
@pytest.fixture(name="sacc_galaxy_cwindows", scope="module")
-def fixture_sacc_galaxy_cwindows() -> tuple[
- sacc.Sacc,
- dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
- dict[
- tuple[TracerNames, str],
- tuple[npt.NDArray[np.int64], npt.NDArray[np.float64], sacc.BandpowerWindow],
- ],
-]:
+def fixture_sacc_galaxy_cwindows() -> SaccGalaxyWindowedFixture:
"""Fixture for a SACC data with window functions.
Module-scoped because SACC objects are expensive to create and are
@@ -888,11 +900,8 @@ def fixture_sacc_galaxy_cwindows() -> tuple[
src_bins_centers = np.linspace(0.25, 0.75, 5)
lens_bins_centers = np.linspace(0.1, 0.6, 5)
- tracers: dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]] = {}
- tracer_pairs: dict[
- tuple[TracerNames, str],
- tuple[npt.NDArray[np.int64], npt.NDArray[np.float64], sacc.BandpowerWindow],
- ] = {}
+ tracers: dict[str, RedshiftDistribution] = {}
+ tracer_pairs: dict[tuple[TracerNames, str], WindowedAngularPowerSpectrum] = {}
for i, mn in enumerate(src_bins_centers):
dndz = np.exp(-0.5 * (z - mn) ** 2 / 0.05 / 0.05)
@@ -1176,9 +1185,7 @@ def fixture_sacc_galaxy_cells_order_convention() -> sacc.Sacc:
@pytest.fixture(name="sacc_galaxy_cells_src0_src0_no_data")
-def fixture_sacc_galaxy_cells_src0_src0_no_data() -> (
- tuple[sacc.Sacc, np.ndarray, np.ndarray]
-):
+def fixture_sacc_galaxy_cells_src0_src0_no_data() -> tuple[sacc.Sacc, TomographicBin]:
"""Fixture for a SACC data without window functions."""
sacc_data = sacc.Sacc()
@@ -1187,32 +1194,38 @@ def fixture_sacc_galaxy_cells_src0_src0_no_data() -> (
dndz = np.exp(-0.5 * (z - 0.5) ** 2 / 0.05 / 0.05)
sacc_data.add_tracer("NZ", "src0", z, dndz)
- return sacc_data, z, dndz
+ expected_bin = TomographicBin(
+ bin_name="src0",
+ z=z.copy(),
+ dndz=dndz.copy(),
+ measurements={Galaxies.SHEAR_E},
+ )
+ return sacc_data, expected_bin
-@pytest.fixture(name="sacc_galaxy_xis_lens0_lens0_no_data")
-def fixture_sacc_galaxy_xis_lens0_lens0_no_data() -> (
- tuple[sacc.Sacc, np.ndarray, np.ndarray]
-):
- """Fixture for a SACC data without window functions."""
+@pytest.fixture(name="sacc_galaxy_lens0_no_two_point_data")
+def fixture_sacc_galaxy_lens0_no_two_point_data() -> sacc.Sacc:
+ """Provide lens0 redshift information without measured two-point data.
+
+ No angular separations or correlation measurements are stored.
+
+ :returns: A SACC object containing only the lens0 redshift tracer.
+ """
sacc_data = sacc.Sacc()
z = np.linspace(0, 1.0, 256) + 0.05
- thetas = np.linspace(0.0, 2.0 * np.pi, 20)
dndz = np.exp(-0.5 * (z - 0.5) ** 2 / 0.05 / 0.05)
sacc_data.add_tracer("NZ", "lens0", z, dndz)
- return sacc_data, z, thetas
+ return sacc_data
# Two-point related SACC data fixtures with window functions
@pytest.fixture(name="sacc_galaxy_cells_src0_src0_window")
-def fixture_sacc_galaxy_cells_src0_src0_window() -> (
- tuple[sacc.Sacc, np.ndarray, np.ndarray]
-):
+def fixture_sacc_galaxy_cells_src0_src0_window() -> tuple[sacc.Sacc, TomographicBin]:
"""Fixture for a SACC data with a window function."""
sacc_data = sacc.Sacc()
@@ -1233,13 +1246,17 @@ def fixture_sacc_galaxy_cells_src0_src0_window() -> (
cov = np.diag(np.ones_like(Cells) * 0.01)
sacc_data.add_covariance(cov)
- return sacc_data, z, dndz
+ expected_bin = TomographicBin(
+ bin_name="src0",
+ z=z.copy(),
+ dndz=dndz.copy(),
+ measurements={Galaxies.SHEAR_E},
+ )
+ return sacc_data, expected_bin
@pytest.fixture(name="sacc_galaxy_cells_src0_src0_no_window")
-def fixture_sacc_galaxy_cells_src0_src0_no_window() -> (
- tuple[sacc.Sacc, np.ndarray, np.ndarray]
-):
+def fixture_sacc_galaxy_cells_src0_src0_no_window() -> tuple[sacc.Sacc, TomographicBin]:
"""Fixture for a SACC data without a window function."""
sacc_data = sacc.Sacc()
@@ -1255,7 +1272,13 @@ def fixture_sacc_galaxy_cells_src0_src0_no_window() -> (
cov = np.diag(np.ones_like(Cells) * 0.01)
sacc_data.add_covariance(cov)
- return sacc_data, z, dndz
+ expected_bin = TomographicBin(
+ bin_name="src0",
+ z=z.copy(),
+ dndz=dndz.copy(),
+ measurements={Galaxies.SHEAR_E},
+ )
+ return sacc_data, expected_bin
@pytest.fixture(name="sacc_galaxy_xis_lens0_lens0_real")
@@ -1321,7 +1344,7 @@ def fixture_tp_factory_missing_counts(
# Optimized fixtures that eliminate "incompatible measurements" skips
-def _discover_measurements_by_space():
+def _discover_measurements_by_space() -> tuple[list[Measurement], list[Measurement]]:
"""Automatically discover all measurements that support real/harmonic space.
This function dynamically finds all measurement types from the enums,
@@ -1355,7 +1378,10 @@ def _discover_measurements_by_space():
return real_measurements, harmonic_measurements
-def _generate_compatible_pairs(measurements, compatibility_func):
+def _generate_compatible_pairs(
+ measurements: list[Measurement],
+ compatibility_func: Callable[[Measurement, Measurement], bool],
+) -> list[tuple[Measurement, Measurement]]:
"""Generate all valid measurement pairs for a given compatibility function."""
return [
(m1, m2)
@@ -1376,7 +1402,9 @@ def _generate_compatible_pairs(measurements, compatibility_func):
)
-def _create_measurement_pair_ids(pairs):
+def _create_measurement_pair_ids(
+ pairs: list[tuple[Measurement, Measurement]],
+) -> list[str]:
"""Create human-readable test IDs for measurement pairs."""
return [f"{m1.name.lower()}-{m2.name.lower()}" for m1, m2 in pairs]
@@ -1386,7 +1414,9 @@ def _create_measurement_pair_ids(pairs):
params=_VALID_REAL_MEASUREMENT_PAIRS,
ids=_create_measurement_pair_ids(_VALID_REAL_MEASUREMENT_PAIRS),
)
-def fixture_optimized_real_measurement_pair(request):
+def fixture_optimized_real_measurement_pair(
+ request: pytest.FixtureRequest,
+) -> tuple[Measurement, Measurement]:
"""Generate only valid real-space measurement pairs.
Eliminates all "incompatible measurements" skips by pre-filtering
@@ -1401,7 +1431,9 @@ def fixture_optimized_real_measurement_pair(request):
params=_VALID_HARMONIC_MEASUREMENT_PAIRS,
ids=_create_measurement_pair_ids(_VALID_HARMONIC_MEASUREMENT_PAIRS),
)
-def fixture_optimized_harmonic_measurement_pair(request):
+def fixture_optimized_harmonic_measurement_pair(
+ request: pytest.FixtureRequest,
+) -> tuple[Galaxies | CMB, Galaxies | CMB]:
"""Generate only valid harmonic-space measurement pairs.
Eliminates all "incompatible measurements" skips by pre-filtering
@@ -1412,7 +1444,9 @@ def fixture_optimized_harmonic_measurement_pair(request):
@pytest.fixture(name="optimized_real_two_point_xy")
-def fixture_optimized_real_two_point_xy(optimized_real_measurement_pair) -> TwoPointXY:
+def fixture_optimized_real_two_point_xy(
+ optimized_real_measurement_pair: tuple[Measurement, Measurement],
+) -> TwoPointXY:
"""Generate TwoPointXY for real space with zero skipped tests.
Uses auto-discovered valid measurement pairs, eliminating all
@@ -1440,7 +1474,7 @@ def fixture_optimized_real_two_point_xy(optimized_real_measurement_pair) -> TwoP
@pytest.fixture(name="optimized_harmonic_two_point_xy")
def fixture_optimized_harmonic_two_point_xy(
- optimized_harmonic_measurement_pair,
+ optimized_harmonic_measurement_pair: tuple[Galaxies | CMB, Galaxies | CMB],
) -> TwoPointXY:
"""Generate TwoPointXY for harmonic space with zero skipped tests.
diff --git a/tests/connector/cobaya/test_model_likelihood.py b/tests/connector/cobaya/test_model_likelihood.py
index 663b6dfc7..3afd8e70d 100644
--- a/tests/connector/cobaya/test_model_likelihood.py
+++ b/tests/connector/cobaya/test_model_likelihood.py
@@ -21,8 +21,10 @@
from firecrown.likelihood._likelihood import NamedParameters
from firecrown.modeling_tools import ModelingTools
+type CobayaParamsConfig = dict[str, float | dict[str, bool]]
-def test_cobaya_ccl_initialize():
+
+def test_cobaya_ccl_initialize() -> None:
ccl_connector = LikelihoodConnector(
info={
"firecrownIni": "tests/likelihood/lkdir/lkscript.py",
@@ -35,7 +37,7 @@ def test_cobaya_ccl_initialize():
assert ccl_connector.distance_max_z == 4.0
-def test_cobaya_ccl_initialize_with_distance_max_z():
+def test_cobaya_ccl_initialize_with_distance_max_z() -> None:
ccl_connector = LikelihoodConnector(
info={
"firecrownIni": "tests/likelihood/lkdir/lkscript.py",
@@ -47,7 +49,7 @@ def test_cobaya_ccl_initialize_with_distance_max_z():
assert ccl_connector.distance_max_z == 1210.0
-def test_cobaya_ccl_initialize_with_params():
+def test_cobaya_ccl_initialize_with_params() -> None:
ccl_connector = LikelihoodConnector(
info={
"firecrownIni": "tests/likelihood/lkdir/lkscript.py",
@@ -61,7 +63,7 @@ def test_cobaya_ccl_initialize_with_params():
assert ccl_connector.input_style == "CAMB"
-def test_compute_pyccl_args_options_default_no_extension():
+def test_compute_pyccl_args_options_default_no_extension() -> None:
"""With the default distance_max_z (4.0), no background extension is
needed since it does not exceed the redshift already covered by
spl.A_SPLINE_MIN (z~9)."""
@@ -76,7 +78,7 @@ def test_compute_pyccl_args_options_default_no_extension():
assert z_bg.max() == pytest.approx(1.0 / spl.A_SPLINE_MIN - 1.0)
-def test_compute_pyccl_args_options_extends_for_cmb_lensing():
+def test_compute_pyccl_args_options_extends_for_cmb_lensing() -> None:
"""A distance_max_z beyond spl.A_SPLINE_MIN's implicit z_max extends the
background arrays out to that redshift, without the array's minimum
scale factor landing exactly on spl.A_SPLINE_MINLOG (see the note in
@@ -105,7 +107,7 @@ def test_compute_pyccl_args_options_extends_for_cmb_lensing():
assert z_spline_min == pytest.approx(z_bg_no_ext.max())
-def test_cobaya_likelihood_initialize():
+def test_cobaya_likelihood_initialize() -> None:
lk_connector = LikelihoodConnector(
info={
"firecrownIni": "tests/likelihood/lkdir/lkscript.py",
@@ -117,7 +119,7 @@ def test_cobaya_likelihood_initialize():
assert lk_connector.firecrownIni == "tests/likelihood/lkdir/lkscript.py"
-def test_cobaya_likelihood_initialize_with_params():
+def test_cobaya_likelihood_initialize_with_params() -> None:
lk_connector = LikelihoodConnector(
info={
"firecrownIni": "tests/likelihood/lkdir/lkscript.py",
@@ -132,10 +134,10 @@ def test_cobaya_likelihood_initialize_with_params():
@pytest.fixture(name="fiducial_params")
-def fixture_fiducial_params():
+def fixture_fiducial_params() -> CobayaParamsConfig:
# Fiducial parameters for CAMB
# These are the names expected by Cobaya.
- fiducial_params = {
+ fiducial_params: CobayaParamsConfig = {
"ombh2": 0.022,
"omch2": 0.12,
"H0": 68,
@@ -148,7 +150,9 @@ def fixture_fiducial_params():
return fiducial_params
-def test_cobaya_ccl_likelihood(fiducial_params):
+def test_cobaya_ccl_likelihood(
+ fiducial_params: CobayaParamsConfig,
+) -> None:
info_fiducial = {
"params": fiducial_params,
"likelihood": {
@@ -166,7 +170,9 @@ def test_cobaya_ccl_likelihood(fiducial_params):
assert model_fiducial.logposterior({}).logpost == -3.0
-def test_resetting_after_exception_in_log_likelihood(fiducial_params):
+def test_resetting_after_exception_in_log_likelihood(
+ fiducial_params: CobayaParamsConfig,
+) -> None:
fiducial_params.update({"pantheon_M": -19.0})
info_fiducial = {
"params": fiducial_params,
@@ -204,7 +210,9 @@ def test_resetting_after_exception_in_log_likelihood(fiducial_params):
assert np.isfinite(model_fiducial.logposterior({}).logpost)
-def test_parameterized_likelihood_missing(fiducial_params):
+def test_parameterized_likelihood_missing(
+ fiducial_params: CobayaParamsConfig,
+) -> None:
info_fiducial = {
"params": fiducial_params,
"likelihood": {
@@ -221,7 +229,9 @@ def test_parameterized_likelihood_missing(fiducial_params):
_ = get_model(info_fiducial)
-def test_parameterized_likelihood_wrong_type(fiducial_params):
+def test_parameterized_likelihood_wrong_type(
+ fiducial_params: CobayaParamsConfig,
+) -> None:
info_fiducial = {
"params": fiducial_params,
"likelihood": {
@@ -241,7 +251,9 @@ def test_parameterized_likelihood_wrong_type(fiducial_params):
_ = get_model(info_fiducial)
-def test_parameterized_likelihood_dict(fiducial_params):
+def test_parameterized_likelihood_dict(
+ fiducial_params: CobayaParamsConfig,
+) -> None:
info_fiducial = {
"params": fiducial_params,
"likelihood": {
@@ -260,7 +272,9 @@ def test_parameterized_likelihood_dict(fiducial_params):
assert model_fiducial.logposterior({}).logpost == -1.5
-def test_parameterized_likelihood_namedparameters(fiducial_params):
+def test_parameterized_likelihood_namedparameters(
+ fiducial_params: CobayaParamsConfig,
+) -> None:
info_fiducial = {
"params": fiducial_params,
"likelihood": {
@@ -281,7 +295,9 @@ def test_parameterized_likelihood_namedparameters(fiducial_params):
assert model_fiducial.logposterior({}).logpost == -1.5
-def test_sampler_parameter_likelihood_missing(fiducial_params):
+def test_sampler_parameter_likelihood_missing(
+ fiducial_params: CobayaParamsConfig,
+) -> None:
info_fiducial = {
"params": fiducial_params,
"likelihood": {
@@ -299,7 +315,9 @@ def test_sampler_parameter_likelihood_missing(fiducial_params):
_ = get_model(info_fiducial)
-def test_sampler_parameter_likelihood(fiducial_params):
+def test_sampler_parameter_likelihood(
+ fiducial_params: CobayaParamsConfig,
+) -> None:
fiducial_params.update({"my_prefix_sampler_param0": 1.0})
info_fiducial = {
"params": fiducial_params,
@@ -319,7 +337,9 @@ def test_sampler_parameter_likelihood(fiducial_params):
assert model_fiducial.logposterior({}).logpost == -2.1
-def test_derived_parameter_likelihood(fiducial_params):
+def test_derived_parameter_likelihood(
+ fiducial_params: CobayaParamsConfig,
+) -> None:
fiducial_params.update({"derived_section__derived_param0": {"derived": True}})
info_fiducial = {
"params": fiducial_params,
@@ -341,7 +361,9 @@ def test_derived_parameter_likelihood(fiducial_params):
assert logpost.derived[0] == 1.0
-def _factory_as(_: NamedParameters):
+def _factory_as(
+ _: NamedParameters,
+) -> tuple[ConstGaussian, ModelingTools]:
return ConstGaussian([stat.TrivialStatistic()]), ModelingTools(
ccl_factory=ccl_factory.CCLFactory(
amplitude_parameter=ccl_factory.PoweSpecAmplitudeParameter.AS
@@ -349,7 +371,9 @@ def _factory_as(_: NamedParameters):
)
-def _factory_sigma8(_: NamedParameters):
+def _factory_sigma8(
+ _: NamedParameters,
+) -> tuple[ConstGaussian, ModelingTools]:
return ConstGaussian([stat.TrivialStatistic()]), ModelingTools(
ccl_factory=ccl_factory.CCLFactory(
amplitude_parameter=ccl_factory.PoweSpecAmplitudeParameter.SIGMA8
@@ -357,7 +381,7 @@ def _factory_sigma8(_: NamedParameters):
)
-def test_likelihood_connector_from_module():
+def test_likelihood_connector_from_module() -> None:
name = "my_dummy_likelihood_module"
factory_full = f"{name}.factory"
mod = types.ModuleType(factory_full)
@@ -378,7 +402,7 @@ def test_likelihood_connector_from_module():
assert "sigma8" in lk_connector.get_requirements()
-def test_get_can_support_params_with_map_none():
+def test_get_can_support_params_with_map_none() -> None:
"""Test get_can_support_params when map is None (non-DEFAULT creation mode)."""
# Create a connector that uses PURE_CCL_MODE, which keeps map=None
lk_connector = LikelihoodConnector(
@@ -396,7 +420,7 @@ def test_get_can_support_params_with_map_none():
assert supported_params == []
-def test_logp_with_pure_ccl_mode():
+def test_logp_with_pure_ccl_mode() -> None:
"""Test logp method with PURE_CCL_MODE (non-DEFAULT creation mode)."""
# Pure CCL mode requires different parameters than the CAMB-based DEFAULT mode
pure_ccl_params = {
@@ -431,7 +455,7 @@ def test_logp_with_pure_ccl_mode():
assert logpost.logpost == -3.0
-def test_missing_input_style_assertion():
+def test_missing_input_style_assertion() -> None:
"""Test assertion failure when input_style is None in DEFAULT mode."""
# Create a connector with DEFAULT mode but no input_style
# This should trigger the assertion at line 113: assert self.input_style
@@ -444,7 +468,7 @@ def test_missing_input_style_assertion():
)
-def test_get_requirements_different_modes():
+def test_get_requirements_different_modes() -> None:
"""Test get_requirements with different CCL creation modes."""
# Test with DEFAULT mode (should include external observables)
lk_connector_default = LikelihoodConnector(
@@ -478,7 +502,7 @@ def test_get_requirements_different_modes():
assert "Hubble" not in requirements_pure
-def test_initialize_without_build_parameters_attribute():
+def test_initialize_without_build_parameters_attribute() -> None:
"""Test initialize() when build_parameters attribute doesn't exist.
This covers the case where hasattr(self, 'build_parameters') is False,
diff --git a/tests/connector/cosmosis/test_cosmosis_module.py b/tests/connector/cosmosis/test_cosmosis_module.py
index ef8e84925..7fe2b98cd 100644
--- a/tests/connector/cosmosis/test_cosmosis_module.py
+++ b/tests/connector/cosmosis/test_cosmosis_module.py
@@ -10,9 +10,10 @@
import pytest
import numpy as np
-import pyccl
from cosmosis.datablock import DataBlock, option_section, names as section_names
+import pyccl
+from firecrown.connector.mapping import MappingCosmoSIS
from firecrown.likelihood._likelihood import NamedParameters
from firecrown.connector.cosmosis.likelihood import (
FirecrownLikelihood,
@@ -109,7 +110,7 @@ def fixture_config_with_two_point_real() -> DataBlock:
@pytest.fixture(name="ccl_mode", params=["default", "pure_ccl"])
-def fixture_ccl_mode(request) -> DataBlock:
+def fixture_ccl_mode(request: pytest.FixtureRequest) -> str:
return request.param
@@ -280,7 +281,9 @@ def fixture_sample_without_M(minimal_sample: DataBlock) -> DataBlock:
return minimal_sample
-def test_extract_section_gets_named_parameters(defective_module_config: DataBlock):
+def test_extract_section_gets_named_parameters(
+ defective_module_config: DataBlock,
+) -> None:
params = extract_section(defective_module_config, "module_options")
assert isinstance(params, NamedParameters)
assert params.get_string("likelihood_source") == str(
@@ -288,16 +291,18 @@ def test_extract_section_gets_named_parameters(defective_module_config: DataBloc
)
-def test_extract_section_raises_on_missing_section(defective_module_config: DataBlock):
+def test_extract_section_raises_on_missing_section(
+ defective_module_config: DataBlock,
+) -> None:
with pytest.raises(RuntimeError, match="Datablock section `xxx' does not exist"):
_ = extract_section(defective_module_config, "xxx")
@pytest.mark.parametrize("ccl_mode", ["pure_ccl"], indirect=True)
def test_wrong_use_of_camb_module_with_ccl_not_in_default_mode(
- config_with_two_point_harmonic,
+ config_with_two_point_harmonic: DataBlock,
ccl_mode: str,
-):
+) -> None:
config_with_two_point_harmonic.put_string("camb", "cow", "moo")
assert ccl_mode == "pure_ccl"
with pytest.raises(
@@ -311,27 +316,27 @@ def test_wrong_use_of_camb_module_with_ccl_not_in_default_mode(
_ = FirecrownLikelihood(config_with_two_point_harmonic)
-def test_parameterless_module_construction(minimal_module_config):
+def test_parameterless_module_construction(minimal_module_config: DataBlock) -> None:
"""Make sure we can create a CosmoSIS likelihood modules that does not
introduce any new parameters."""
module = FirecrownLikelihood(minimal_module_config)
assert module.sampling_sections == []
-def test_missing_required_parameter(defective_module_config):
+def test_missing_required_parameter(defective_module_config: DataBlock) -> None:
"""Make sure that a missing required parameter entails the expected
failure."""
with pytest.raises(KeyError):
_ = FirecrownLikelihood(defective_module_config)
-def test_initialize_minimal_module(minimal_firecrown_mod: FirecrownLikelihood):
+def test_initialize_minimal_module(minimal_firecrown_mod: FirecrownLikelihood) -> None:
assert isinstance(minimal_firecrown_mod, FirecrownLikelihood)
def test_execute_missing_cosmological_parameters(
minimal_firecrown_mod: FirecrownLikelihood,
-):
+) -> None:
no_cosmo_params = DataBlock()
with pytest.raises(
RuntimeError,
@@ -343,7 +348,7 @@ def test_execute_missing_cosmological_parameters(
@pytest.mark.parametrize("ccl_mode", ["default"], indirect=True)
def test_execute_with_cosmo(
minimal_firecrown_mod: FirecrownLikelihood, minimal_sample: DataBlock, ccl_mode: str
-):
+) -> None:
assert ccl_mode == "default"
assert minimal_firecrown_mod.execute(minimal_sample) == 0
assert minimal_sample[section_names.likelihoods, "firecrown_like"] == -3.0
@@ -354,7 +359,7 @@ def test_execute_with_derived_parameters(
firecrown_mod_with_derived_parameters: FirecrownLikelihood,
minimal_sample: DataBlock,
ccl_mode: str,
-):
+) -> None:
assert ccl_mode == "default"
assert firecrown_mod_with_derived_parameters.execute(minimal_sample) == 0
assert minimal_sample.get_double("derived_section", "derived_param0") == 1.0
@@ -364,7 +369,7 @@ def test_execute_with_derived_parameters(
def test_module_init_with_missing_sampling_sections(
config_with_const_gaussian_missing_sampling_parameters_sections: DataBlock,
ccl_mode: str,
-):
+) -> None:
assert ccl_mode == "default"
with pytest.raises(RuntimeError, match=r"\['pantheon_M'\]"):
s = config_with_const_gaussian_missing_sampling_parameters_sections.to_string()
@@ -396,7 +401,7 @@ def fixture_working_config_for_const_gaussian(
def test_module_init_with_wrong_sampling_sections(
config_with_wrong_sampling_sections: DataBlock,
-):
+) -> None:
mod = FirecrownLikelihood(config_with_wrong_sampling_sections)
assert isinstance(mod, FirecrownLikelihood)
@@ -406,7 +411,7 @@ def test_module_exec_with_wrong_sampling_sections(
config_with_wrong_sampling_sections: DataBlock,
sample_with_M: DataBlock,
ccl_mode: str,
-):
+) -> None:
assert ccl_mode == "default"
mod = FirecrownLikelihood(config_with_wrong_sampling_sections)
with pytest.raises(
@@ -420,7 +425,7 @@ def test_module_exec_missing_parameter_in_sampling_sections(
firecrown_mod_with_const_gaussian: FirecrownLikelihood,
sample_without_M: DataBlock,
ccl_mode: str,
-):
+) -> None:
assert ccl_mode == "default"
with pytest.raises(RuntimeError, match="`supernova_parameters`") as exc:
_ = firecrown_mod_with_const_gaussian.execute(sample_without_M)
@@ -435,7 +440,7 @@ def test_module_exec_working(
firecrown_mod_with_const_gaussian: FirecrownLikelihood,
sample_with_M: DataBlock,
ccl_mode: str,
-):
+) -> None:
assert ccl_mode == "default"
assert firecrown_mod_with_const_gaussian.execute(sample_with_M) == 0
assert sample_with_M.get_double("likelihoods", "firecrown_like") < 0.0
@@ -446,7 +451,7 @@ def test_execute_function(
firecrown_mod_with_const_gaussian: FirecrownLikelihood,
sample_with_M: DataBlock,
ccl_mode: str,
-):
+) -> None:
assert ccl_mode == "default"
assert execute(sample_with_M, firecrown_mod_with_const_gaussian) == 0
assert sample_with_M.get_double("likelihoods", "firecrown_like") < 0.0
@@ -457,7 +462,7 @@ def test_module_exec_with_two_point_real(
firecrown_mod_with_two_point_real: FirecrownLikelihood,
sample_with_lens0_bias: DataBlock,
ccl_mode: str,
-):
+) -> None:
assert ccl_mode == "default"
assert firecrown_mod_with_two_point_real.execute(sample_with_lens0_bias) == 0
@@ -513,7 +518,7 @@ def test_module_exec_with_two_point_real(
def test_module_exec_with_two_point_harmonic(
firecrown_mod_with_two_point_harmonic: FirecrownLikelihood,
sample_with_lens0_bias: DataBlock,
-):
+) -> None:
assert firecrown_mod_with_two_point_harmonic.execute(sample_with_lens0_bias) == 0
# CosmoSIS always writes the output to the same section, so we can
@@ -565,7 +570,7 @@ def test_module_exec_with_two_point_harmonic(
)
-def test_mapping_cosmosis_background(mapping_cosmosis):
+def test_mapping_cosmosis_background(mapping_cosmosis: MappingCosmoSIS) -> None:
block = DataBlock()
background_d_m = np.geomspace(0.1, 10.0, 100)
@@ -593,7 +598,7 @@ def test_mapping_cosmosis_background(mapping_cosmosis):
assert "pk_nonlin" not in ccl_args
-def test_mapping_cosmosis_pk_linear(mapping_cosmosis):
+def test_mapping_cosmosis_pk_linear(mapping_cosmosis: MappingCosmoSIS) -> None:
block = DataBlock()
block.put_double_array_1d("distances", "d_m", np.geomspace(0.1, 10.0, 100))
@@ -630,7 +635,7 @@ def test_mapping_cosmosis_pk_linear(mapping_cosmosis):
)
-def test_mapping_cosmosis_pk_nonlin(mapping_cosmosis):
+def test_mapping_cosmosis_pk_nonlin(mapping_cosmosis: MappingCosmoSIS) -> None:
block = DataBlock()
block.put_double_array_1d("distances", "d_m", np.geomspace(0.1, 10.0, 100))
@@ -668,7 +673,7 @@ def test_mapping_cosmosis_pk_nonlin(mapping_cosmosis):
)
-def test_form_error_message_with_sampling_sections():
+def test_form_error_message_with_sampling_sections() -> None:
sampling_sections = ["section1", "section2"]
exc = MissingSamplerParameterError("missing_param")
expected_msg = (
@@ -680,7 +685,7 @@ def test_form_error_message_with_sampling_sections():
assert form_error_message(sampling_sections, exc) == expected_msg
-def test_form_error_message_with_empty_sampling_sections():
+def test_form_error_message_with_empty_sampling_sections() -> None:
sampling_sections: list[str] = []
exc = MissingSamplerParameterError("missing_param")
# flake8: noqa
@@ -693,7 +698,7 @@ def test_form_error_message_with_empty_sampling_sections():
assert form_error_message(sampling_sections, exc) == expected_msg
-def test_form_error_message_with_single_sampling_section():
+def test_form_error_message_with_single_sampling_section() -> None:
sampling_sections = ["section1"]
exc = MissingSamplerParameterError("missing_param")
# flake8: noqa
@@ -706,13 +711,15 @@ def test_form_error_message_with_single_sampling_section():
assert form_error_message(sampling_sections, exc) == expected_msg
-def test_form_error_message_with_missing_sampler_parameter_error():
+def test_form_error_message_with_missing_sampler_parameter_error() -> None:
sampling_sections = ["section1", "section2"]
exc = MissingSamplerParameterError("missing_param")
assert "missing_param" in form_error_message(sampling_sections, exc)
-def test_same_param_names_in_different_sections_failure(sample_with_M: DataBlock):
+def test_same_param_names_in_different_sections_failure(
+ sample_with_M: DataBlock,
+) -> None:
sample_with_M.put_double("section1", "a", 1.0)
sample_with_M.put_double("section2", "a", 10.0)
with pytest.raises(
@@ -730,7 +737,7 @@ def test_resetting_after_exception_in_log_likelihood(
firecrown_mod_with_const_gaussian: FirecrownLikelihood,
sample_with_M: DataBlock,
ccl_mode: str,
-):
+) -> None:
assert ccl_mode == "default"
msg = "Test exception in log-likelihood"
warn_msg = (
@@ -760,7 +767,7 @@ def test_gaussfamily_special_case(
firecrown_mod_with_const_gaussian: FirecrownLikelihood,
sample_with_M: DataBlock,
ccl_mode: str,
-):
+) -> None:
assert ccl_mode == "default"
msg = "Error CCL_ERROR_SPLINE: fake_ccl_.c:119;"
warn_msg = f"CCL error:.*\n.*{msg}"
diff --git a/tests/connector/numcosmo/conftest.py b/tests/connector/numcosmo/conftest.py
index 7c6c6d63e..d36b73ae2 100644
--- a/tests/connector/numcosmo/conftest.py
+++ b/tests/connector/numcosmo/conftest.py
@@ -6,16 +6,21 @@
import pytest
from numcosmo_py import GObject, Nc, Ncm
+from tests._types import NumCosmoCosmologyFixture
+
+# NumCosmo's introspected static constructors and enum members confuse Pylint.
+# Keep the corresponding suppressions local to the affected calls below.
+
@pytest.fixture(name="numcosmo_cosmo_xcdm")
-def fixture_numcosmo_cosmo_xcdm():
+def fixture_numcosmo_cosmo_xcdm() -> NumCosmoCosmologyFixture:
"""Create a NumCosmo cosmology instance of XCDM."""
- prim = Nc.HIPrimPowerLaw.new()
+ prim = Nc.HIPrimPowerLaw.new() # pylint: disable=no-value-for-parameter
prim.param_set_by_name( # pylint: disable=no-member
"ln10e10ASA", math.log(1.0e10 * 2.0e-09)
)
prim.param_set_by_name("n_SA", 0.971) # pylint: disable=no-member
- reion = Nc.HIReionCamb.new()
+ reion = Nc.HIReionCamb.new() # pylint: disable=no-value-for-parameter
bbn = Nc.BBNParametrized.new()
bbn.param_set_by_name("Yp", 0.2454) # pylint: disable=no-member
@@ -31,7 +36,9 @@ def fixture_numcosmo_cosmo_xcdm():
reion.set_z_from_tau(0.0561) # pylint: disable=no-member
- p_ml = Nc.PowspecMLTransfer.new(Nc.TransferFuncEH.new())
+ p_ml = Nc.PowspecMLTransfer.new(
+ Nc.TransferFuncEH.new() # pylint: disable=no-value-for-parameter
+ )
p_mnl = Nc.PowspecMNLHaloFit.new(p_ml, 3.0, 1.0e-5)
dist = Nc.Distance.new(6.0)
dist.comoving_distance_spline.set_reltol(1.0e-5) # pylint: disable=no-member
@@ -40,14 +47,14 @@ def fixture_numcosmo_cosmo_xcdm():
@pytest.fixture(name="numcosmo_cosmo_xcdm_no_nu")
-def fixture_numcosmo_cosmo_xcdm_no_nu():
+def fixture_numcosmo_cosmo_xcdm_no_nu() -> NumCosmoCosmologyFixture:
"""Create a NumCosmo cosmology instance of XCDM without neutrinos."""
- prim = Nc.HIPrimPowerLaw.new()
+ prim = Nc.HIPrimPowerLaw.new() # pylint: disable=no-value-for-parameter
prim.param_set_by_name( # pylint: disable=no-member
"ln10e10ASA", math.log(1.0e10 * 2.0e-09)
)
prim.param_set_by_name("n_SA", 0.971) # pylint: disable=no-member
- reion = Nc.HIReionCamb.new()
+ reion = Nc.HIReionCamb.new() # pylint: disable=no-value-for-parameter
bbn = Nc.BBNParametrized.new()
bbn.param_set_by_name("Yp", 0.2454) # pylint: disable=no-member
@@ -62,7 +69,9 @@ def fixture_numcosmo_cosmo_xcdm_no_nu():
reion.set_z_from_tau(0.0561) # pylint: disable=no-member
- p_ml = Nc.PowspecMLTransfer.new(Nc.TransferFuncEH.new())
+ p_ml = Nc.PowspecMLTransfer.new(
+ Nc.TransferFuncEH.new() # pylint: disable=no-value-for-parameter
+ )
p_mnl = Nc.PowspecMNLHaloFit.new(p_ml, 3.0, 1.0e-5)
dist = Nc.Distance.new(6.0)
dist.comoving_distance_spline.set_reltol(1.0e-5) # pylint: disable=no-member
@@ -71,16 +80,16 @@ def fixture_numcosmo_cosmo_xcdm_no_nu():
@pytest.fixture(name="numcosmo_cosmo_cpl")
-def fixture_numcosmo_cosmo_cpl():
+def fixture_numcosmo_cosmo_cpl() -> NumCosmoCosmologyFixture:
"""Create a NumCosmo cosmology instance using CPL parametrization for the dark
energy equation of state."""
- prim = Nc.HIPrimPowerLaw.new()
+ prim = Nc.HIPrimPowerLaw.new() # pylint: disable=no-value-for-parameter
prim.param_set_by_name( # pylint: disable=no-member
"ln10e10ASA", math.log(1.0e10 * 2.0e-09)
)
prim.param_set_by_name("n_SA", 0.971) # pylint: disable=no-member
- reion = Nc.HIReionCamb.new()
+ reion = Nc.HIReionCamb.new() # pylint: disable=no-value-for-parameter
bbn = Nc.BBNParametrized.new()
bbn.param_set_by_name("Yp", 0.2454) # pylint: disable=no-member
@@ -96,7 +105,9 @@ def fixture_numcosmo_cosmo_cpl():
reion.set_z_from_tau(0.0561) # pylint: disable=no-member
- p_ml = Nc.PowspecMLTransfer.new(Nc.TransferFuncEH.new())
+ p_ml = Nc.PowspecMLTransfer.new(
+ Nc.TransferFuncEH.new() # pylint: disable=no-value-for-parameter
+ )
p_mnl = Nc.PowspecMNLHaloFit.new(p_ml, 3.0, 1.0e-5)
dist = Nc.Distance.new(6.0)
dist.comoving_distance_spline.set_reltol(1.0e-5) # pylint: disable=no-member
@@ -105,7 +116,7 @@ def fixture_numcosmo_cosmo_cpl():
@pytest.fixture(name="nc_model_trivial", scope="session")
-def fixture_nc_model_trivial():
+def fixture_nc_model_trivial() -> type[Ncm.Model]:
"""Create a NumCosmoModel instance."""
my_model_trivial_yaml = r"""
NcmModelBuilder:
@@ -123,7 +134,7 @@ def fixture_nc_model_trivial():
default-value: 0.1
fit-type: 0
"""
- ser = Ncm.Serialize.new(Ncm.SerializeOpt.NONE)
+ ser = Ncm.Serialize.new(Ncm.SerializeOpt.NONE) # pylint: disable=no-member
mb_model: Ncm.ModelBuilder = cast(
Ncm.ModelBuilder,
ser.from_yaml(my_model_trivial_yaml), # pylint: disable=no-member
diff --git a/tests/connector/numcosmo/test_numcosmo_connector.py b/tests/connector/numcosmo/test_numcosmo_connector.py
index c032e2b7d..bc9f2117c 100644
--- a/tests/connector/numcosmo/test_numcosmo_connector.py
+++ b/tests/connector/numcosmo/test_numcosmo_connector.py
@@ -3,22 +3,28 @@
import pytest
from numcosmo_py import GObject, Nc, Ncm
+from firecrown.connector.mapping import Mapping
from firecrown.connector.numcosmo import (
MappingNumCosmo,
NumCosmoData,
NumCosmoFactory,
NumCosmoGaussCov,
+ create_params_map,
)
from firecrown.likelihood._likelihood import (
Likelihood,
NamedParameters,
)
+from firecrown.modeling_tools import CCLCreationMode
+from firecrown.updatable import ParamsMap
-Ncm.cfg_init()
+# Pylint mistakes NumCosmo's introspected static functions for instance methods.
+# Keep no-value-for-parameter suppressions local to the affected calls below.
+Ncm.cfg_init() # pylint: disable=no-value-for-parameter
@pytest.fixture(name="factory_plain")
-def fixture_factory_plain():
+def fixture_factory_plain() -> NumCosmoFactory:
"""Create a NumCosmoFactory instance."""
map_cosmo = MappingNumCosmo(dist=Nc.Distance.new(6.0))
build_parameters = NamedParameters()
@@ -31,7 +37,7 @@ def fixture_factory_plain():
@pytest.fixture(name="factory_const_gauss")
-def fixture_factory_const_gauss():
+def fixture_factory_const_gauss() -> NumCosmoFactory:
"""Create a NumCosmoFactory instance."""
map_cosmo = MappingNumCosmo(dist=Nc.Distance.new(6.0))
build_parameters = NamedParameters()
@@ -43,12 +49,18 @@ def fixture_factory_const_gauss():
)
-def test_wrong_use_of_power_spectra_with_ccl_not_in_default_mode():
+def test_wrong_use_of_power_spectra_with_ccl_not_in_default_mode() -> None:
map_cosmo = MappingNumCosmo(
dist=Nc.Distance.new(6.0),
- p_ml=Nc.PowspecMLTransfer.new(Nc.TransferFuncEH.new()),
+ p_ml=Nc.PowspecMLTransfer.new(
+ Nc.TransferFuncEH.new() # pylint: disable=no-value-for-parameter
+ ),
p_mnl=Nc.PowspecMNLHaloFit.new(
- Nc.PowspecMLTransfer.new(Nc.TransferFuncEH.new()), 3.0, 1.0e-4
+ Nc.PowspecMLTransfer.new(
+ Nc.TransferFuncEH.new() # pylint: disable=no-value-for-parameter
+ ),
+ 3.0,
+ 1.0e-4,
),
)
build_parameters = NamedParameters({"projection": "harmonic"})
@@ -61,21 +73,23 @@ def test_wrong_use_of_power_spectra_with_ccl_not_in_default_mode():
)
-def test_numcosmo_connector_plain(factory_plain):
+def test_numcosmo_connector_plain(factory_plain: NumCosmoFactory) -> None:
"""Test the NumCosmo connector."""
assert factory_plain.get_data() is not None
assert factory_plain.get_mapping() is not None
-def test_numcosmo_connector_const_gauss(factory_const_gauss):
+def test_numcosmo_connector_const_gauss(factory_const_gauss: NumCosmoFactory) -> None:
"""Test the NumCosmo connector."""
assert factory_const_gauss.get_data() is not None
assert factory_const_gauss.get_mapping() is not None
-def test_numcosmo_factory_plain_get_firecrown_likelihood(factory_plain):
+def test_numcosmo_factory_plain_get_firecrown_likelihood(
+ factory_plain: NumCosmoFactory,
+) -> None:
"""Test the NumCosmo connector."""
assert factory_plain.get_data() is not None
@@ -86,7 +100,9 @@ def test_numcosmo_factory_plain_get_firecrown_likelihood(factory_plain):
assert isinstance(fc_likelihood, Likelihood)
-def test_numcosmo_factory_const_gauss_get_firecrown_likelihood(factory_const_gauss):
+def test_numcosmo_factory_const_gauss_get_firecrown_likelihood(
+ factory_const_gauss: NumCosmoFactory,
+) -> None:
"""Test the NumCosmo connector."""
assert factory_const_gauss.get_data() is not None
@@ -97,7 +113,7 @@ def test_numcosmo_factory_const_gauss_get_firecrown_likelihood(factory_const_gau
assert isinstance(fc_likelihood, Likelihood)
-def test_numcosmo_factory_plain_get_properties(factory_plain):
+def test_numcosmo_factory_plain_get_properties(factory_plain: NumCosmoFactory) -> None:
"""Test the NumCosmo connector."""
nc_data = factory_plain.get_data()
@@ -110,7 +126,9 @@ def test_numcosmo_factory_plain_get_properties(factory_plain):
assert isinstance(nc_data.likelihood_build_parameters, Ncm.VarDict)
-def test_numcosmo_factory_const_gauss_get_properties(factory_const_gauss):
+def test_numcosmo_factory_const_gauss_get_properties(
+ factory_const_gauss: NumCosmoFactory,
+) -> None:
"""Test the NumCosmo connector."""
nc_data = factory_const_gauss.get_data()
@@ -126,7 +144,9 @@ def test_numcosmo_factory_const_gauss_get_properties(factory_const_gauss):
assert isinstance(nc_data.likelihood_build_parameters, Ncm.VarDict)
-def test_numcosmo_factory_plain_set_properties_order1(factory_plain):
+def test_numcosmo_factory_plain_set_properties_order1(
+ factory_plain: NumCosmoFactory,
+) -> None:
"""Test the NumCosmo connector."""
nc_data = factory_plain.get_data()
@@ -140,7 +160,9 @@ def test_numcosmo_factory_plain_set_properties_order1(factory_plain):
assert isinstance(old_fc_likelihood, Likelihood)
nc_data.likelihood_source = "tests/likelihood/lkdir/lkscript.py"
- nc_data.likelihood_build_parameters = Ncm.VarDict.new()
+ nc_data.likelihood_build_parameters = (
+ Ncm.VarDict.new() # pylint: disable=no-value-for-parameter
+ )
fc_likelihood = nc_data.likelihood
assert fc_likelihood is not None
@@ -148,7 +170,9 @@ def test_numcosmo_factory_plain_set_properties_order1(factory_plain):
assert fc_likelihood != old_fc_likelihood
-def test_numcosmo_factory_plain_set_properties_order2(factory_plain):
+def test_numcosmo_factory_plain_set_properties_order2(
+ factory_plain: NumCosmoFactory,
+) -> None:
"""Test the NumCosmo connector."""
nc_data = factory_plain.get_data()
@@ -161,7 +185,9 @@ def test_numcosmo_factory_plain_set_properties_order2(factory_plain):
assert old_fc_likelihood is not None
assert isinstance(old_fc_likelihood, Likelihood)
- nc_data.likelihood_build_parameters = Ncm.VarDict.new()
+ nc_data.likelihood_build_parameters = (
+ Ncm.VarDict.new() # pylint: disable=no-value-for-parameter
+ )
nc_data.likelihood_source = "tests/likelihood/lkdir/lkscript.py"
fc_likelihood = nc_data.likelihood
@@ -170,7 +196,9 @@ def test_numcosmo_factory_plain_set_properties_order2(factory_plain):
assert fc_likelihood != old_fc_likelihood
-def test_numcosmo_factory_plain_set_properties_empty_build_parameters(factory_plain):
+def test_numcosmo_factory_plain_set_properties_empty_build_parameters(
+ factory_plain: NumCosmoFactory,
+) -> None:
"""Test the NumCosmo connector."""
nc_data = factory_plain.get_data()
@@ -192,7 +220,9 @@ def test_numcosmo_factory_plain_set_properties_empty_build_parameters(factory_pl
assert fc_likelihood != old_fc_likelihood
-def test_numcosmo_factory_const_gauss_set_properties_order1(factory_const_gauss):
+def test_numcosmo_factory_const_gauss_set_properties_order1(
+ factory_const_gauss: NumCosmoFactory,
+) -> None:
"""Test the NumCosmo connector."""
nc_data = factory_const_gauss.get_data()
@@ -208,7 +238,9 @@ def test_numcosmo_factory_const_gauss_set_properties_order1(factory_const_gauss)
nc_data.likelihood_source = (
"tests/likelihood/gauss_family/lkscript_const_gaussian.py"
)
- nc_data.likelihood_build_parameters = Ncm.VarDict.new()
+ nc_data.likelihood_build_parameters = (
+ Ncm.VarDict.new() # pylint: disable=no-value-for-parameter
+ )
fc_likelihood = nc_data.likelihood
assert fc_likelihood is not None
@@ -216,7 +248,9 @@ def test_numcosmo_factory_const_gauss_set_properties_order1(factory_const_gauss)
assert fc_likelihood != old_fc_likelihood
-def test_numcosmo_factory_const_gauss_set_properties_order2(factory_const_gauss):
+def test_numcosmo_factory_const_gauss_set_properties_order2(
+ factory_const_gauss: NumCosmoFactory,
+) -> None:
"""Test the NumCosmo connector."""
nc_data = factory_const_gauss.get_data()
@@ -229,7 +263,9 @@ def test_numcosmo_factory_const_gauss_set_properties_order2(factory_const_gauss)
assert old_fc_likelihood is not None
assert isinstance(old_fc_likelihood, Likelihood)
- nc_data.likelihood_build_parameters = Ncm.VarDict.new()
+ nc_data.likelihood_build_parameters = (
+ Ncm.VarDict.new() # pylint: disable=no-value-for-parameter
+ )
nc_data.likelihood_source = (
"tests/likelihood/gauss_family/lkscript_const_gaussian.py"
)
@@ -241,8 +277,8 @@ def test_numcosmo_factory_const_gauss_set_properties_order2(factory_const_gauss)
def test_numcosmo_factory_const_gauss_set_properties_empty_build_parameters(
- factory_const_gauss,
-):
+ factory_const_gauss: NumCosmoFactory,
+) -> None:
"""Test the NumCosmo connector."""
nc_data = factory_const_gauss.get_data()
@@ -266,7 +302,7 @@ def test_numcosmo_factory_const_gauss_set_properties_empty_build_parameters(
assert fc_likelihood != old_fc_likelihood
-def test_empty_plain_data():
+def test_empty_plain_data() -> None:
"""Test the NumCosmo connector."""
nc_data = NumCosmoData()
@@ -274,7 +310,7 @@ def test_empty_plain_data():
assert nc_data.likelihood_build_parameters is None
-def test_empty_gauss_cov_data():
+def test_empty_gauss_cov_data() -> None:
"""Test the NumCosmo connector."""
nc_data = NumCosmoGaussCov()
@@ -282,12 +318,8 @@ def test_empty_gauss_cov_data():
assert nc_data.likelihood_build_parameters is None
-def test_create_params_map_with_mapping():
+def test_create_params_map_with_mapping() -> None:
"""Test create_params_map function when mapping is provided."""
- from firecrown.connector.mapping import Mapping
- from firecrown.connector.numcosmo import create_params_map
- from firecrown.updatable import ParamsMap
-
# Create a simple mock model and mset
model_name = "test_model"
model_builder = Ncm.ModelBuilder.new(
@@ -347,11 +379,8 @@ def test_create_params_map_with_mapping():
assert params_map["h"] == 0.7
-def test_create_params_map_without_mapping():
+def test_create_params_map_without_mapping() -> None:
"""Test create_params_map function when mapping is None."""
- from firecrown.connector.numcosmo import create_params_map
- from firecrown.updatable import ParamsMap
-
# Create a simple mock model and mset
model_name = "test_model2"
model_builder = Ncm.ModelBuilder.new(
@@ -393,7 +422,7 @@ def test_create_params_map_without_mapping():
assert "h" not in params_map
-def test_numcosmo_data_pure_ccl_mode():
+def test_numcosmo_data_pure_ccl_mode() -> None:
"""Test NumCosmoData.do_prepare with PURE_CCL_MODE (non-DEFAULT creation mode)."""
# This test covers lines 574-577 (the 'else' branch in do_prepare)
build_parameters = NamedParameters()
@@ -408,8 +437,6 @@ def test_numcosmo_data_pure_ccl_mode():
assert isinstance(nc_data, NumCosmoData)
# Verify that the CCL factory is in PURE_CCL_MODE
- from firecrown.modeling_tools import CCLCreationMode
-
assert nc_data.tools.ccl_factory.creation_mode == CCLCreationMode.PURE_CCL_MODE
# Create a simple model for testing
@@ -455,7 +482,10 @@ def test_numcosmo_data_pure_ccl_mode():
model.params_set_default_ftype()
# Create a basic cosmology model as well
- cosmo = Nc.HICosmoDEXcdm(prim=Nc.HIPrimPowerLaw.new(), reion=Nc.HIReionCamb.new())
+ cosmo = Nc.HICosmoDEXcdm(
+ prim=Nc.HIPrimPowerLaw.new(), # pylint: disable=no-value-for-parameter
+ reion=Nc.HIReionCamb.new(), # pylint: disable=no-value-for-parameter
+ )
mset = Ncm.MSet()
mset.set(cosmo)
@@ -470,7 +500,7 @@ def test_numcosmo_data_pure_ccl_mode():
assert nc_data.dof == nc_data.len - mset.fparams_len()
-def test_numcosmo_gauss_cov_none_mapping():
+def test_numcosmo_gauss_cov_none_mapping() -> None:
"""Test NumCosmoGaussCov._will_calculate_power_spectra with None mapping."""
# This test covers line 677 where _nc_mapping is None and returns False
build_parameters = NamedParameters()
@@ -484,20 +514,21 @@ def test_numcosmo_gauss_cov_none_mapping():
nc_data = factory.get_data()
assert isinstance(nc_data, NumCosmoGaussCov)
- # Verify that _nc_mapping is None
- assert nc_data._nc_mapping is None
+ # These assertions intentionally exercise the internal no-mapping path.
+ assert nc_data._nc_mapping is None # pylint: disable=protected-access
- # Test _will_calculate_power_spectra method indirectly
- # When _nc_mapping is None, _will_calculate_power_spectra should return False
- # This is tested through the _configure_object method which calls it
- assert nc_data._will_calculate_power_spectra() is False
+ # With no mapping, this internal method must not request power spectra.
+ assert (
+ nc_data._will_calculate_power_spectra() # pylint: disable=protected-access
+ is False
+ )
# Verify the object was configured correctly
assert nc_data.len > 0
assert nc_data.dof > 0
-def test_numcosmo_gauss_cov_pure_ccl_mode():
+def test_numcosmo_gauss_cov_pure_ccl_mode() -> None:
"""Test do_prepare with PURE_CCL_MODE (non-DEFAULT creation mode)."""
# This test covers lines 887-891 (the 'else' branch in do_prepare)
build_parameters = NamedParameters({"projection": "harmonic"})
@@ -512,13 +543,11 @@ def test_numcosmo_gauss_cov_pure_ccl_mode():
assert isinstance(nc_data, NumCosmoGaussCov)
# Verify that the CCL factory is in PURE_CCL_MODE
- from firecrown.modeling_tools import CCLCreationMode
-
assert nc_data.tools.ccl_factory.creation_mode == CCLCreationMode.PURE_CCL_MODE
# Verify that _nc_mapping is None (this triggers assert _nc_mapping is None
# in line 888)
- assert nc_data._nc_mapping is None
+ assert nc_data._nc_mapping is None # pylint: disable=protected-access
# Create a simple model for testing
model_name = "test_model_gauss_pure_ccl"
@@ -567,7 +596,10 @@ def test_numcosmo_gauss_cov_pure_ccl_mode():
model.params_set_default_ftype()
# Create a basic cosmology model as well
- cosmo = Nc.HICosmoDEXcdm(prim=Nc.HIPrimPowerLaw.new(), reion=Nc.HIReionCamb.new())
+ cosmo = Nc.HICosmoDEXcdm(
+ prim=Nc.HIPrimPowerLaw.new(), # pylint: disable=no-value-for-parameter
+ reion=Nc.HIReionCamb.new(), # pylint: disable=no-value-for-parameter
+ )
mset = Ncm.MSet()
mset.set(cosmo)
diff --git a/tests/connector/numcosmo/test_numcosmo_mapping.py b/tests/connector/numcosmo/test_numcosmo_mapping.py
index 0098df044..9e436e942 100644
--- a/tests/connector/numcosmo/test_numcosmo_mapping.py
+++ b/tests/connector/numcosmo/test_numcosmo_mapping.py
@@ -1,10 +1,11 @@
"""Unit tests for the numcosmo Mapping connector."""
-import unittest.mock as mock
from typing import cast
+from unittest import mock
import pyccl as ccl
import pytest
+import sacc
from numcosmo_py import GObject, Nc, Ncm
from firecrown.connector.numcosmo import (
@@ -17,9 +18,13 @@
)
from firecrown.likelihood._gaussian import ConstGaussian
from firecrown.likelihood._likelihood import Likelihood, NamedParameters
+from firecrown.likelihood._statistic import TrivialStatistic
from firecrown.modeling_tools import ModelingTools, PoweSpecAmplitudeParameter
+from tests._types import NumCosmoCosmologyFixture
-Ncm.cfg_init()
+# NumCosmo's introspected static functions and enum members confuse Pylint.
+# Keep the corresponding suppressions local to the affected calls below.
+Ncm.cfg_init() # pylint: disable=no-value-for-parameter
@pytest.fixture(name="map_cosmo_dist")
@@ -28,19 +33,9 @@ def fixture_map_cosmo_dist() -> MappingNumCosmo:
return MappingNumCosmo(dist=Nc.Distance.new(6.0))
-@pytest.fixture(name="map_cosmo_spec_nl")
-def fixture_map_cosmo_spec_nl(numcosmo_cosmo) -> MappingNumCosmo:
- """Return a MappingNumCosmo instance with the specified p_ml, p_mnl, and dist."""
- return MappingNumCosmo(
- p_ml=numcosmo_cosmo["p_ml"],
- p_mnl=numcosmo_cosmo["p_mnl"],
- dist=numcosmo_cosmo["dist"],
- )
-
-
def test_create_params_map_non_existing_model(
map_cosmo_dist: MappingNumCosmo,
-):
+) -> None:
"""Test the NumCosmo mapping connector create_params_map
with an non existing type."""
@@ -58,7 +53,7 @@ def test_create_params_map_non_existing_model(
def test_numcosmo_mapping_create_params_map_absent_model(
map_cosmo_dist: MappingNumCosmo,
-):
+) -> None:
"""Test the NumCosmo mapping connector create_params_map
with an existing type but not present in the model set."""
@@ -76,7 +71,7 @@ def test_numcosmo_mapping_create_params_map_absent_model(
def test_numcosmo_mapping_create_params_map_two_models_sharing_parameters(
map_cosmo_dist: MappingNumCosmo,
-):
+) -> None:
"""Test the NumCosmo mapping connector create_params_map
with an existing type but not present in the model set."""
@@ -128,7 +123,7 @@ def test_numcosmo_mapping_create_params_map_two_models_sharing_parameters(
fit-type: 0
"""
- ser = Ncm.Serialize.new(Ncm.SerializeOpt.NONE)
+ ser = Ncm.Serialize.new(Ncm.SerializeOpt.NONE) # pylint: disable=no-member
mb_model1: Ncm.ModelBuilder = cast(
Ncm.ModelBuilder, ser.from_yaml(my_model1_dc_yaml) # pylint: disable=no-member
)
@@ -159,7 +154,7 @@ def test_numcosmo_mapping_create_params_map_two_models_sharing_parameters(
create_params_map(["MyModel1", "MyModel2"], mset, map_cosmo_dist.mapping)
-def test_numcosmo_mapping_unsupported(map_cosmo_dist: MappingNumCosmo):
+def test_numcosmo_mapping_unsupported(map_cosmo_dist: MappingNumCosmo) -> None:
"""Test the NumCosmo mapping connector with an unsupported model."""
cosmo = Nc.HICosmoDEJbp()
@@ -171,7 +166,7 @@ def test_numcosmo_mapping_unsupported(map_cosmo_dist: MappingNumCosmo):
map_cosmo_dist.set_params_from_numcosmo(mset, PoweSpecAmplitudeParameter.SIGMA8)
-def test_numcosmo_mapping_missing_hiprim(map_cosmo_dist: MappingNumCosmo):
+def test_numcosmo_mapping_missing_hiprim(map_cosmo_dist: MappingNumCosmo) -> None:
"""Test the NumCosmo mapping connector with a model missing hiprim."""
cosmo = Nc.HICosmoDECpl()
@@ -185,7 +180,7 @@ def test_numcosmo_mapping_missing_hiprim(map_cosmo_dist: MappingNumCosmo):
map_cosmo_dist.set_params_from_numcosmo(mset, PoweSpecAmplitudeParameter.AS)
-def test_numcosmo_mapping_invalid_hiprim(map_cosmo_dist: MappingNumCosmo):
+def test_numcosmo_mapping_invalid_hiprim(map_cosmo_dist: MappingNumCosmo) -> None:
"""Test the NumCosmo mapping connector with a model an invalid hiprim."""
prim = Nc.HIPrimAtan()
@@ -204,9 +199,15 @@ def test_numcosmo_mapping_invalid_hiprim(map_cosmo_dist: MappingNumCosmo):
"numcosmo_cosmo_fixture",
["numcosmo_cosmo_xcdm", "numcosmo_cosmo_xcdm_no_nu", "numcosmo_cosmo_cpl"],
)
-def test_numcosmo_mapping(numcosmo_cosmo_fixture, request):
+def test_numcosmo_mapping(
+ numcosmo_cosmo_fixture: str,
+ request: pytest.FixtureRequest,
+) -> None:
"""Test the NumCosmo mapping connector consistence."""
- numcosmo_cosmo = request.getfixturevalue(numcosmo_cosmo_fixture)
+ # Cast: parametrization selects only cosmology fixtures with this shared shape.
+ numcosmo_cosmo = cast(
+ NumCosmoCosmologyFixture, request.getfixturevalue(numcosmo_cosmo_fixture)
+ )
cosmo = numcosmo_cosmo["cosmo"]
map_cosmo = MappingNumCosmo(
@@ -231,9 +232,15 @@ def test_numcosmo_mapping(numcosmo_cosmo_fixture, request):
"numcosmo_cosmo_fixture",
["numcosmo_cosmo_xcdm", "numcosmo_cosmo_xcdm_no_nu", "numcosmo_cosmo_cpl"],
)
-def test_numcosmo_serialize_mapping(numcosmo_cosmo_fixture, request):
+def test_numcosmo_serialize_mapping(
+ numcosmo_cosmo_fixture: str,
+ request: pytest.FixtureRequest,
+) -> None:
"""Test the NumCosmo mapping connector consistence."""
- numcosmo_cosmo = request.getfixturevalue(numcosmo_cosmo_fixture)
+ # Cast: parametrization selects only cosmology fixtures with this shared shape.
+ numcosmo_cosmo = cast(
+ NumCosmoCosmologyFixture, request.getfixturevalue(numcosmo_cosmo_fixture)
+ )
cosmo = numcosmo_cosmo["cosmo"]
map_cosmo = MappingNumCosmo(
@@ -244,7 +251,7 @@ def test_numcosmo_serialize_mapping(numcosmo_cosmo_fixture, request):
assert map_cosmo.mapping_name == "default"
- ser = Ncm.Serialize.new(Ncm.SerializeOpt.NONE)
+ ser = Ncm.Serialize.new(Ncm.SerializeOpt.NONE) # pylint: disable=no-member
map_cosmo_dup = ser.dup_obj(map_cosmo) # pylint: disable=no-member
assert isinstance(map_cosmo_dup, MappingNumCosmo)
@@ -277,15 +284,18 @@ def test_numcosmo_serialize_mapping(numcosmo_cosmo_fixture, request):
["numcosmo_cosmo_xcdm", "numcosmo_cosmo_xcdm_no_nu", "numcosmo_cosmo_cpl"],
)
def test_numcosmo_data(
- numcosmo_cosmo_fixture,
- trivial_stats,
- sacc_data_for_trivial_stat,
- nc_model_trivial,
- request,
-):
+ numcosmo_cosmo_fixture: str,
+ trivial_stats: list[TrivialStatistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ nc_model_trivial: type[Ncm.Model],
+ request: pytest.FixtureRequest,
+) -> None:
"""Test the NumCosmo data connector for NcmData."""
- numcosmo_cosmo = request.getfixturevalue(numcosmo_cosmo_fixture)
+ # Cast: parametrization selects only cosmology fixtures with this shared shape.
+ numcosmo_cosmo = cast(
+ NumCosmoCosmologyFixture, request.getfixturevalue(numcosmo_cosmo_fixture)
+ )
cosmo = numcosmo_cosmo["cosmo"]
map_cosmo = MappingNumCosmo(
@@ -328,15 +338,18 @@ def test_numcosmo_data(
["numcosmo_cosmo_xcdm", "numcosmo_cosmo_xcdm_no_nu", "numcosmo_cosmo_cpl"],
)
def test_numcosmo_gauss_cov(
- numcosmo_cosmo_fixture,
- trivial_stats,
- sacc_data_for_trivial_stat,
- nc_model_trivial,
- request,
-):
+ numcosmo_cosmo_fixture: str,
+ trivial_stats: list[TrivialStatistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ nc_model_trivial: type[Ncm.Model],
+ request: pytest.FixtureRequest,
+) -> None:
"""Test the NumCosmo data connector for NcmDataGaussCov."""
- numcosmo_cosmo = request.getfixturevalue(numcosmo_cosmo_fixture)
+ # Cast: parametrization selects only cosmology fixtures with this shared shape.
+ numcosmo_cosmo = cast(
+ NumCosmoCosmologyFixture, request.getfixturevalue(numcosmo_cosmo_fixture)
+ )
cosmo = numcosmo_cosmo["cosmo"]
map_cosmo = MappingNumCosmo(
@@ -386,13 +399,16 @@ def test_numcosmo_gauss_cov(
],
)
def test_numcosmo_serialize_likelihood(
- numcosmo_cosmo_fixture,
- likelihood_file,
- request,
-):
+ numcosmo_cosmo_fixture: str,
+ likelihood_file: str,
+ request: pytest.FixtureRequest,
+) -> None:
"""Test the NumCosmo data connector for NcmData with serialization."""
- numcosmo_cosmo = request.getfixturevalue(numcosmo_cosmo_fixture)
+ # Cast: parametrization selects only cosmology fixtures with this shared shape.
+ numcosmo_cosmo = cast(
+ NumCosmoCosmologyFixture, request.getfixturevalue(numcosmo_cosmo_fixture)
+ )
map_cosmo = MappingNumCosmo(
p_ml=numcosmo_cosmo["p_ml"],
@@ -413,7 +429,7 @@ def test_numcosmo_serialize_likelihood(
assert fc_data.get_length() > 0
assert fc_data.get_dof() > 0
- ser = Ncm.Serialize.new(Ncm.SerializeOpt.NONE)
+ ser = Ncm.Serialize.new(Ncm.SerializeOpt.NONE) # pylint: disable=no-member
fc_data_dup = ser.dup_obj(fc_data) # pylint: disable=no-member
assert isinstance(fc_data_dup, (NumCosmoData, NumCosmoGaussCov))
@@ -435,14 +451,16 @@ def test_numcosmo_serialize_likelihood(
assert fc_data_dup.model_list == fc_data.model_list
-def test_numcosmo_mapping_deprecated_require_nonlinear_pk():
+def test_numcosmo_mapping_deprecated_require_nonlinear_pk() -> None:
"""Test the MappingNumCosmo deprecated require_nonlinear_pk."""
with pytest.deprecated_call():
_ = MappingNumCosmo(require_nonlinear_pk=True)
-def test_numcosmo_mapping_sigma8_missing_pk(map_cosmo_dist: MappingNumCosmo):
+def test_numcosmo_mapping_sigma8_missing_pk(
+ map_cosmo_dist: MappingNumCosmo,
+) -> None:
"""Test the MappingNumCosmo with sigma8 as a parameter but missing pk."""
cosmo = Nc.HICosmoDEXcdm()
@@ -457,12 +475,14 @@ def test_numcosmo_mapping_sigma8_missing_pk(map_cosmo_dist: MappingNumCosmo):
@pytest.fixture(name="numcosmo_cosmo")
-def fixture_numcosmo_cosmo():
+def fixture_numcosmo_cosmo() -> mock.Mock:
"""Create a mock NumCosmo cosmology instance."""
return mock.Mock(spec=Nc.HICosmo)
-def test_get_amplitude_parameters_sigma8_no_powerspectrum(numcosmo_cosmo):
+def test_get_amplitude_parameters_sigma8_no_powerspectrum(
+ numcosmo_cosmo: mock.Mock,
+) -> None:
"""Test the get_amplitude_parameters function with sigma8 as a parameter but
without a power spectrum."""
@@ -474,7 +494,7 @@ def test_get_amplitude_parameters_sigma8_no_powerspectrum(numcosmo_cosmo):
)
-def test_accessors_with_no_powerspectrum():
+def test_accessors_with_no_powerspectrum() -> None:
mapping = MappingNumCosmo()
assert mapping.p_ml is None
assert mapping.p_mnl is None
@@ -483,21 +503,27 @@ def test_accessors_with_no_powerspectrum():
mapping.p_mnl = None
assert mapping.p_mnl is None
- linear = Nc.PowspecMLTransfer.new(Nc.TransferFuncEH.new())
+ linear = Nc.PowspecMLTransfer.new(
+ Nc.TransferFuncEH.new() # pylint: disable=no-value-for-parameter
+ )
nonlinear = Nc.PowspecMNLHaloFit.new(linear, 3.0, 1.0e-5)
mapping.p_mnl = nonlinear
assert mapping._p is None # pylint: disable=protected-access
-def test_accessors_with_only_linear_powerspectrum():
- linear = Nc.PowspecMLTransfer.new(Nc.TransferFuncEH.new())
+def test_accessors_with_only_linear_powerspectrum() -> None:
+ linear = Nc.PowspecMLTransfer.new(
+ Nc.TransferFuncEH.new() # pylint: disable=no-value-for-parameter
+ )
mapping = MappingNumCosmo(p_ml=linear)
assert mapping._p is not None # pylint: disable=protected-access
mapping.p_ml = linear
assert mapping.p_mnl is None
# Change to a different linear power spectrum
- other_linear = Nc.PowspecMLTransfer.new(Nc.TransferFuncBBKS.new())
+ other_linear = Nc.PowspecMLTransfer.new(
+ Nc.TransferFuncBBKS.new() # pylint: disable=no-value-for-parameter
+ )
mapping.p_ml = other_linear
assert mapping._p is not None # pylint: disable=protected-access
assert mapping.p_ml == other_linear
@@ -511,13 +537,16 @@ def test_accessors_with_only_linear_powerspectrum():
assert mapping.p_mnl == nonlinear
-def test_mapping_ccl_args_bg_only():
+def test_mapping_ccl_args_bg_only() -> None:
"""Test the MappingNumCosmo class with background only."""
mapping = MappingNumCosmo(dist=Nc.Distance.new(6.0))
assert mapping.p_ml is None
assert mapping.p_mnl is None
- cosmo = Nc.HICosmoDEXcdm(prim=Nc.HIPrimPowerLaw.new(), reion=Nc.HIReionCamb.new())
+ cosmo = Nc.HICosmoDEXcdm(
+ prim=Nc.HIPrimPowerLaw.new(), # pylint: disable=no-value-for-parameter
+ reion=Nc.HIReionCamb.new(), # pylint: disable=no-value-for-parameter
+ )
mset = Ncm.MSet.new_array([cosmo])
mset.prepare_fparam_map()
@@ -529,15 +558,20 @@ def test_mapping_ccl_args_bg_only():
assert "pk_nonlin" not in ccl_args
-def test_mapping_ccl_args_bg_pk_ml():
+def test_mapping_ccl_args_bg_pk_ml() -> None:
"""Test the MappingNumCosmo class with background and pk_ml."""
mapping = MappingNumCosmo(
dist=Nc.Distance.new(6.0),
- p_ml=Nc.PowspecMLTransfer.new(Nc.TransferFuncEH.new()),
+ p_ml=Nc.PowspecMLTransfer.new(
+ Nc.TransferFuncEH.new() # pylint: disable=no-value-for-parameter
+ ),
)
assert mapping.p_mnl is None
- cosmo = Nc.HICosmoDEXcdm(prim=Nc.HIPrimPowerLaw.new(), reion=Nc.HIReionCamb.new())
+ cosmo = Nc.HICosmoDEXcdm(
+ prim=Nc.HIPrimPowerLaw.new(), # pylint: disable=no-value-for-parameter
+ reion=Nc.HIReionCamb.new(), # pylint: disable=no-value-for-parameter
+ )
mset = Ncm.MSet.new_array([cosmo])
mset.prepare_fparam_map()
@@ -549,9 +583,11 @@ def test_mapping_ccl_args_bg_pk_ml():
assert "pk_nonlin" not in ccl_args
-def test_mapping_ccl_args_bg_pk_ml_pk_mnl():
+def test_mapping_ccl_args_bg_pk_ml_pk_mnl() -> None:
"""Test the MappingNumCosmo class with background, pk_ml and pk_mnl."""
- p_ml = Nc.PowspecMLTransfer.new(Nc.TransferFuncEH.new())
+ p_ml = Nc.PowspecMLTransfer.new(
+ Nc.TransferFuncEH.new() # pylint: disable=no-value-for-parameter
+ )
mapping = MappingNumCosmo(
dist=Nc.Distance.new(6.0),
p_ml=p_ml,
@@ -560,7 +596,10 @@ def test_mapping_ccl_args_bg_pk_ml_pk_mnl():
assert mapping.p_ml is not None
assert mapping.p_mnl is not None
- cosmo = Nc.HICosmoDEXcdm(prim=Nc.HIPrimPowerLaw.new(), reion=Nc.HIReionCamb.new())
+ cosmo = Nc.HICosmoDEXcdm(
+ prim=Nc.HIPrimPowerLaw.new(), # pylint: disable=no-value-for-parameter
+ reion=Nc.HIReionCamb.new(), # pylint: disable=no-value-for-parameter
+ )
mset = Ncm.MSet.new_array([cosmo])
mset.prepare_fparam_map()
@@ -572,9 +611,11 @@ def test_mapping_ccl_args_bg_pk_ml_pk_mnl():
assert "pk_nonlin" in ccl_args
-def test_mapping_ccl_args_bg_pk_mnl():
+def test_mapping_ccl_args_bg_pk_mnl() -> None:
"""Test the MappingNumCosmo class with background, pk_ml and pk_mnl."""
- p_ml = Nc.PowspecMLTransfer.new(Nc.TransferFuncEH.new())
+ p_ml = Nc.PowspecMLTransfer.new(
+ Nc.TransferFuncEH.new() # pylint: disable=no-value-for-parameter
+ )
with pytest.raises(
AssertionError, match="PowspecML object must be provided when using PowspecMNL"
):
diff --git a/tests/connector/test_mapping.py b/tests/connector/test_mapping.py
index fb94790bb..ce8a05478 100644
--- a/tests/connector/test_mapping.py
+++ b/tests/connector/test_mapping.py
@@ -20,7 +20,7 @@
# TODO: Refactor these test functions to use a sensible fixture.
-def test_conversion_from_cosmosis_camb_as():
+def test_conversion_from_cosmosis_camb_as() -> None:
cosmosis_params = {
"a_s": 2.1e-09,
"baryon_fraction": 0.13333333333333333,
@@ -65,7 +65,7 @@ def test_conversion_from_cosmosis_camb_as():
assert p.T_CMB == 2.7255 # currently hard-wired
-def test_conversion_from_cosmosis_camb_sigma8():
+def test_conversion_from_cosmosis_camb_sigma8() -> None:
cosmosis_params = {
"a_s": 2.1e-09,
"baryon_fraction": 0.13333333333333333,
@@ -111,7 +111,7 @@ def test_conversion_from_cosmosis_camb_sigma8():
assert p.T_CMB == 2.7255 # currently hard-wired
-def test_conversion_from_cosmosis_camb_using_delta_neff():
+def test_conversion_from_cosmosis_camb_using_delta_neff() -> None:
cosmosis_params = {
"a_s": 2.1e-09,
"baryon_fraction": 0.13333333333333333,
@@ -147,7 +147,7 @@ def test_conversion_from_cosmosis_camb_using_delta_neff():
assert p.Neff == pytest.approx(3.171)
-def test_get_params_names():
+def test_get_params_names() -> None:
fc_map = Mapping()
with pytest.deprecated_call():
@@ -155,7 +155,7 @@ def test_get_params_names():
assert not params_names
-def test_transform_k_h_to_k():
+def test_transform_k_h_to_k() -> None:
fc_map = Mapping()
with pytest.deprecated_call():
@@ -163,7 +163,7 @@ def test_transform_k_h_to_k():
fc_map.transform_k_h_to_k(np.array([], dtype=np.float64))
-def test_transform_p_k_h3_to_p_k():
+def test_transform_p_k_h3_to_p_k() -> None:
fc_map = Mapping()
with pytest.deprecated_call():
@@ -171,7 +171,7 @@ def test_transform_p_k_h3_to_p_k():
fc_map.transform_p_k_h3_to_p_k(np.array([], dtype=np.float64))
-def test_transform_h_to_h_over_h0():
+def test_transform_h_to_h_over_h0() -> None:
fc_map = Mapping()
with pytest.deprecated_call():
@@ -179,7 +179,7 @@ def test_transform_h_to_h_over_h0():
fc_map.transform_h_to_h_over_h0(np.array([], dtype=np.float64))
-def test_sigma8_and_A_s():
+def test_sigma8_and_A_s() -> None:
fc_map = Mapping()
params_dict: dict[str, Any] = {
@@ -210,14 +210,14 @@ def test_sigma8_and_A_s():
fc_map.set_params(**params_dict)
-def test_mappping_builder():
+def test_mappping_builder() -> None:
with pytest.raises(
ValueError, match="input_style must be .* not invalid_input_style"
):
mapping_builder(input_style="invalid_input_style")
-def test_mapping_cosmosis():
+def test_mapping_cosmosis() -> None:
mapping_cosmosis = mapping_builder(input_style="CosmoSIS")
assert isinstance(mapping_cosmosis, Mapping)
@@ -268,21 +268,21 @@ def test_mapping_cosmosis():
assert d["m_nu"] == 0.0
-def test_mapping_cosmosis_k_h_to_h(mapping_cosmosis):
+def test_mapping_cosmosis_k_h_to_h(mapping_cosmosis: MappingCosmoSIS) -> None:
k_h_array = np.geomspace(0.1, 10.0, 10)
k_array = mapping_cosmosis.transform_k_h_to_k(k_h_array)
assert np.allclose(k_h_array * mapping_cosmosis.h, k_array)
-def test_mapping_cosmosis_p_k_h3_to_p_k(mapping_cosmosis):
+def test_mapping_cosmosis_p_k_h3_to_p_k(mapping_cosmosis: MappingCosmoSIS) -> None:
p_k_h3_array = np.geomspace(0.1, 10.0, 10)
p_k_array = mapping_cosmosis.transform_p_k_h3_to_p_k(p_k_h3_array)
assert np.allclose(p_k_h3_array / mapping_cosmosis.h**3, p_k_array)
-def test_mapping_camb():
+def test_mapping_camb() -> None:
mapping_camb = mapping_builder(input_style="CAMB")
assert isinstance(mapping_camb, MappingCAMB)
@@ -333,7 +333,7 @@ def test_mapping_camb():
assert d["m_nu"] == 0.0
-def test_mapping_camb_setting_both_A_s_and_sigma8():
+def test_mapping_camb_setting_both_A_s_and_sigma8() -> None:
mapping_camb = mapping_builder(input_style="CAMB")
assert isinstance(mapping_camb, MappingCAMB)
with pytest.raises(
@@ -358,7 +358,7 @@ def test_mapping_camb_setting_both_A_s_and_sigma8():
)
-def test_mapping_camb_setting_neither_A_s_and_sigma8():
+def test_mapping_camb_setting_neither_A_s_and_sigma8() -> None:
mapping_camb = mapping_builder(input_style="CAMB")
assert isinstance(mapping_camb, MappingCAMB)
with pytest.raises(
@@ -381,7 +381,7 @@ def test_mapping_camb_setting_neither_A_s_and_sigma8():
)
-def test_mapping_camb_setting_A_s():
+def test_mapping_camb_setting_A_s() -> None:
mapping_camb = mapping_builder(input_style="CAMB")
assert isinstance(mapping_camb, MappingCAMB)
mapping_camb.set_params_from_camb(
@@ -403,7 +403,7 @@ def test_mapping_camb_setting_A_s():
assert mapping_camb.A_s == 2.1e-9
-def test_mapping_camb_setting_sigma8():
+def test_mapping_camb_setting_sigma8() -> None:
mapping_camb = mapping_builder(input_style="CAMB")
assert isinstance(mapping_camb, MappingCAMB)
mapping_camb.set_params_from_camb(
@@ -425,7 +425,7 @@ def test_mapping_camb_setting_sigma8():
assert mapping_camb.sigma8 == 0.8
-def test_mapping_m_nu_list_asdict():
+def test_mapping_m_nu_list_asdict() -> None:
mapping0 = Mapping()
mapping0.Omega_c = 0.26
mapping0.Omega_b = 0.04
diff --git a/tests/example/test_cluster_number_counts.py b/tests/example/test_cluster_number_counts.py
index f6a62d7ad..8c6caa99e 100644
--- a/tests/example/test_cluster_number_counts.py
+++ b/tests/example/test_cluster_number_counts.py
@@ -28,14 +28,14 @@
@pytest.fixture(name="target_framework", params=Frameworks)
-def fixture_target_framework(request) -> Frameworks:
+def fixture_target_framework(request: pytest.FixtureRequest) -> Frameworks:
"""Generate a target framework for all frameworks."""
return request.param
@pytest.fixture(name="cluster_example", params=CLUSTER_CASES)
def fixture_cluster_example(
- request, target_framework: Frameworks, tmp_path: Path
+ request: pytest.FixtureRequest, target_framework: Frameworks, tmp_path: Path
) -> tuple[Path, Frameworks]:
"""Generate each cluster example for all frameworks."""
example_cls, options = CLUSTER_CASES[request.param]
diff --git a/tests/example/test_cmb_cross.py b/tests/example/test_cmb_cross.py
index 07b86a9bc..f90fb58f3 100644
--- a/tests/example/test_cmb_cross.py
+++ b/tests/example/test_cmb_cross.py
@@ -10,7 +10,7 @@
@pytest.fixture(name="target_framework", params=Frameworks)
-def fixture_target_framework(request) -> Frameworks:
+def fixture_target_framework(request: pytest.FixtureRequest) -> Frameworks:
"""Generate a target framework for all frameworks."""
return request.param
@@ -33,7 +33,7 @@ def fixture_cmb_cross_example(
@pytest.mark.example
-def test_cmb_cross_run(cmb_cross_example):
+def test_cmb_cross_run(cmb_cross_example: tuple[Path, Frameworks]) -> None:
"""Run each framework's generated configuration end-to-end.
This is what actually exercises the background/distance splines out to
diff --git a/tests/example/test_cosmic_shear.py b/tests/example/test_cosmic_shear.py
index 089ee96ad..43f9f6106 100644
--- a/tests/example/test_cosmic_shear.py
+++ b/tests/example/test_cosmic_shear.py
@@ -10,13 +10,13 @@
@pytest.fixture(name="target_framework", params=Frameworks)
-def fixture_target_framework(request) -> Frameworks:
+def fixture_target_framework(request: pytest.FixtureRequest) -> Frameworks:
"""Generate a target framework for all frameworks."""
return request.param
@pytest.fixture(name="use_absolute_path", params=[True, False])
-def fixture_use_absolute_path(request) -> bool:
+def fixture_use_absolute_path(request: pytest.FixtureRequest) -> bool:
"""Generate a use_absolute_path for all path types."""
return request.param
@@ -37,7 +37,7 @@ def fixture_cosmic_shear_example(
@pytest.mark.example
-def test_cosmic_shear_run(cosmic_shear_example):
+def test_cosmic_shear_run(cosmic_shear_example: tuple[Path, Frameworks]) -> None:
output_path, framework = cosmic_shear_example
match framework:
case Frameworks.COSMOSIS:
diff --git a/tests/example/test_des_y1_3x2pt.py b/tests/example/test_des_y1_3x2pt.py
index b72e5b311..decc953e2 100644
--- a/tests/example/test_des_y1_3x2pt.py
+++ b/tests/example/test_des_y1_3x2pt.py
@@ -10,19 +10,19 @@
@pytest.fixture(name="target_framework", params=Frameworks)
-def fixture_target_framework(request) -> Frameworks:
+def fixture_target_framework(request: pytest.FixtureRequest) -> Frameworks:
"""Generate a target framework for all frameworks."""
return request.param
@pytest.fixture(name="use_absolute_path", params=[True, False])
-def fixture_use_absolute_path(request) -> bool:
+def fixture_use_absolute_path(request: pytest.FixtureRequest) -> bool:
"""Generate a use_absolute_path for all path types."""
return request.param
@pytest.fixture(name="factory_type", params=DESY1FactoryType)
-def fixture_factory_type(request) -> DESY1FactoryType:
+def fixture_factory_type(request: pytest.FixtureRequest) -> DESY1FactoryType:
"""Generate a factory type for all factory types."""
return request.param
@@ -51,7 +51,7 @@ def fixture_des_y1_3x2pt_example(
@pytest.mark.example
-def test_des_y1_3x2pt_run(des_y1_3x2pt_example):
+def test_des_y1_3x2pt_run(des_y1_3x2pt_example: tuple[Path, Frameworks]) -> None:
output_path, framework = des_y1_3x2pt_example
match framework:
case Frameworks.COSMOSIS:
diff --git a/tests/example/test_srd_sn.py b/tests/example/test_srd_sn.py
index 28cd36f81..756e7831e 100644
--- a/tests/example/test_srd_sn.py
+++ b/tests/example/test_srd_sn.py
@@ -10,13 +10,13 @@
@pytest.fixture(name="target_framework", params=Frameworks)
-def fixture_target_framework(request) -> Frameworks:
+def fixture_target_framework(request: pytest.FixtureRequest) -> Frameworks:
"""Generate a target framework for all frameworks."""
return request.param
@pytest.fixture(name="use_absolute_path", params=[True, False])
-def fixture_use_absolute_path(request) -> bool:
+def fixture_use_absolute_path(request: pytest.FixtureRequest) -> bool:
"""Generate a use_absolute_path for all path types."""
return request.param
@@ -37,7 +37,7 @@ def fixture_sn_srd_example(
@pytest.mark.example
-def test_srd_sn_run(sn_srd_example):
+def test_srd_sn_run(sn_srd_example: tuple[Path, Frameworks]) -> None:
output_path, framework = sn_srd_example
match framework:
case Frameworks.COSMOSIS:
diff --git a/tests/fctools/test_ast_utils.py b/tests/fctools/test_ast_utils.py
index 41bab6415..f01dcfea9 100644
--- a/tests/fctools/test_ast_utils.py
+++ b/tests/fctools/test_ast_utils.py
@@ -4,6 +4,7 @@
"""
import ast
+from pathlib import Path
import pytest
@@ -22,7 +23,7 @@
class TestGetModuleDocstring:
"""Tests for get_module_docstring function."""
- def test_get_simple_docstring(self, tmp_path):
+ def test_get_simple_docstring(self, tmp_path: Path) -> None:
"""Test extracting a simple module docstring."""
py_file = tmp_path / "test_module.py"
py_file.write_text('"""This is a module docstring."""\n\ndef func():\n pass')
@@ -31,7 +32,7 @@ def test_get_simple_docstring(self, tmp_path):
assert result == "This is a module docstring."
- def test_get_multiline_docstring(self, tmp_path):
+ def test_get_multiline_docstring(self, tmp_path: Path) -> None:
"""Test extracting a multi-line module docstring."""
py_file = tmp_path / "test_module.py"
content = '''"""This is the first line.
@@ -50,7 +51,7 @@ def func():
assert "This is the first line." in result
assert "This is the second paragraph." in result
- def test_get_no_docstring(self, tmp_path):
+ def test_get_no_docstring(self, tmp_path: Path) -> None:
"""Test file with no module docstring."""
py_file = tmp_path / "test_module.py"
py_file.write_text("def func():\n pass")
@@ -59,7 +60,7 @@ def test_get_no_docstring(self, tmp_path):
assert result is None
- def test_get_single_quote_docstring(self, tmp_path):
+ def test_get_single_quote_docstring(self, tmp_path: Path) -> None:
"""Test extracting docstring with single quotes."""
py_file = tmp_path / "test_module.py"
py_file.write_text("'''Single quote docstring'''\n\ndef func():\n pass")
@@ -68,14 +69,14 @@ def test_get_single_quote_docstring(self, tmp_path):
assert result == "Single quote docstring"
- def test_nonexistent_file(self, tmp_path):
+ def test_nonexistent_file(self, tmp_path: Path) -> None:
"""Test reading from a nonexistent file."""
py_file = tmp_path / "nonexistent.py"
with pytest.raises(OSError):
get_module_docstring(py_file)
- def test_invalid_python_syntax(self, tmp_path):
+ def test_invalid_python_syntax(self, tmp_path: Path) -> None:
"""Test file with invalid Python syntax."""
py_file = tmp_path / "invalid.py"
py_file.write_text("def broken(\n # missing closing paren")
@@ -87,7 +88,7 @@ def test_invalid_python_syntax(self, tmp_path):
class TestGetClassDefinition:
"""Tests for get_class_definition function."""
- def test_find_simple_class(self):
+ def test_find_simple_class(self) -> None:
"""Test finding a simple class definition."""
source = """
class MyClass:
@@ -99,7 +100,7 @@ class MyClass:
assert isinstance(result, ast.ClassDef)
assert result.name == "MyClass"
- def test_find_class_with_docstring(self):
+ def test_find_class_with_docstring(self) -> None:
"""Test finding a class with a docstring."""
source = '''
class DocumentedClass:
@@ -113,7 +114,7 @@ class DocumentedClass:
docstring = ast.get_docstring(result)
assert docstring == "This is a documented class."
- def test_find_nested_class(self):
+ def test_find_nested_class(self) -> None:
"""Test finding a nested class."""
source = """
class OuterClass:
@@ -125,7 +126,7 @@ class InnerClass:
assert result is not None
assert result.name == "InnerClass"
- def test_class_not_found(self):
+ def test_class_not_found(self) -> None:
"""Test searching for a nonexistent class."""
source = """
class MyClass:
@@ -135,7 +136,7 @@ class MyClass:
assert result is None
- def test_multiple_classes(self):
+ def test_multiple_classes(self) -> None:
"""Test finding the correct class among multiple classes."""
source = """
class FirstClass:
@@ -152,7 +153,7 @@ class ThirdClass:
assert result is not None
assert result.name == "SecondClass"
- def test_invalid_syntax(self):
+ def test_invalid_syntax(self) -> None:
"""Test parsing source with invalid syntax."""
source = "class BrokenClass"
@@ -163,13 +164,13 @@ def test_invalid_syntax(self):
class TestFormatDocstringSummary:
"""Tests for format_docstring_summary function."""
- def test_format_simple_docstring(self):
+ def test_format_simple_docstring(self) -> None:
"""Test formatting a simple one-line docstring."""
result = format_docstring_summary("This is a simple docstring.")
assert result == "This is a simple docstring."
- def test_format_multiline_docstring(self):
+ def test_format_multiline_docstring(self) -> None:
"""Test formatting a multi-line docstring (returns first line)."""
docstring = """This is the first line.
@@ -180,25 +181,25 @@ def test_format_multiline_docstring(self):
assert result == "This is the first line."
- def test_format_none_docstring(self):
+ def test_format_none_docstring(self) -> None:
"""Test formatting None docstring."""
result = format_docstring_summary(None)
assert result == "No description available"
- def test_format_empty_docstring(self):
+ def test_format_empty_docstring(self) -> None:
"""Test formatting an empty docstring."""
result = format_docstring_summary("")
assert result == "No description available"
- def test_format_whitespace_only_docstring(self):
+ def test_format_whitespace_only_docstring(self) -> None:
"""Test formatting a docstring with only whitespace."""
result = format_docstring_summary(" \n\n ")
assert result == "No description available"
- def test_format_long_docstring_truncation(self):
+ def test_format_long_docstring_truncation(self) -> None:
"""Test truncation of long docstrings."""
long_text = "a" * 100
result = format_docstring_summary(long_text, max_length=80)
@@ -207,7 +208,7 @@ def test_format_long_docstring_truncation(self):
assert result.endswith("...")
assert result.startswith("aaa")
- def test_format_docstring_with_triple_quotes(self):
+ def test_format_docstring_with_triple_quotes(self) -> None:
"""Test docstring that includes triple quotes gets filtered correctly."""
# The function filters out lines starting with triple quotes
result = format_docstring_summary('"""This is a docstring."""')
@@ -215,7 +216,7 @@ def test_format_docstring_with_triple_quotes(self):
# Since the only line starts with triple quotes, it's filtered
assert result == "No description available"
- def test_format_docstring_preserves_short_text(self):
+ def test_format_docstring_preserves_short_text(self) -> None:
"""Test that short docstrings are not truncated."""
short_text = "Short description"
result = format_docstring_summary(short_text, max_length=80)
@@ -223,7 +224,7 @@ def test_format_docstring_preserves_short_text(self):
assert result == short_text
assert not result.endswith("...")
- def test_format_custom_max_length(self):
+ def test_format_custom_max_length(self) -> None:
"""Test custom maximum length parameter."""
text = "This is a moderately long description"
result = format_docstring_summary(text, max_length=20)
@@ -235,7 +236,7 @@ def test_format_custom_max_length(self):
class TestExtractClassAttributes:
"""Tests for extract_class_attributes function."""
- def test_extract_simple_attributes(self):
+ def test_extract_simple_attributes(self) -> None:
"""Test extracting simple class attributes."""
source = """
class MyClass:
@@ -251,7 +252,7 @@ class MyClass:
assert "attr2" in result
assert "attr3" in result
- def test_extract_annotated_attributes(self):
+ def test_extract_annotated_attributes(self) -> None:
"""Test extracting type-annotated attributes."""
source = """
class MyClass:
@@ -267,7 +268,7 @@ class MyClass:
assert "age" in result
assert "value" in result
- def test_extract_no_attributes(self):
+ def test_extract_no_attributes(self) -> None:
"""Test class with no attributes."""
source = """
class MyClass:
@@ -280,7 +281,7 @@ def method(self):
assert not result
- def test_extract_mixed_attributes(self):
+ def test_extract_mixed_attributes(self) -> None:
"""Test class with both annotated and simple attributes."""
source = """
class MyClass:
@@ -296,7 +297,7 @@ class MyClass:
assert "annotated" in result
assert "no_value" in result
- def test_ignores_instance_attributes(self):
+ def test_ignores_instance_attributes(self) -> None:
"""Test that instance attributes in __init__ are not extracted."""
source = """
class MyClass:
@@ -312,7 +313,7 @@ def __init__(self):
assert "class_attr" in result
assert "instance_attr" not in result
- def test_extract_non_name_targets(self):
+ def test_extract_non_name_targets(self) -> None:
"""Test handling of assignments to non-Name targets."""
source = """
class MyClass:
@@ -334,7 +335,7 @@ class MyClass:
class TestFormatClassDocstring:
"""Tests for format_class_docstring function."""
- def test_format_simple_docstring(self):
+ def test_format_simple_docstring(self) -> None:
"""Test formatting a simple class docstring."""
source = '''
class MyClass:
@@ -348,7 +349,7 @@ class MyClass:
assert len(result) > 0
assert any("Simple docstring." in line for line in result)
- def test_format_multiline_docstring(self):
+ def test_format_multiline_docstring(self) -> None:
"""Test formatting a multi-line class docstring."""
source = '''
class MyClass:
@@ -366,7 +367,7 @@ class MyClass:
joined = " ".join(result)
assert "First line." in joined
- def test_format_no_docstring(self):
+ def test_format_no_docstring(self) -> None:
"""Test formatting when class has no docstring."""
source = """
class MyClass:
@@ -378,7 +379,7 @@ class MyClass:
assert not result
- def test_format_preserves_structure(self):
+ def test_format_preserves_structure(self) -> None:
"""Test that docstring formatting preserves basic structure."""
source = '''
class MyClass:
@@ -400,7 +401,7 @@ class MyClass:
assert "Args:" in joined
assert "Returns:" in joined
- def test_format_empty_string_docstring(self):
+ def test_format_empty_string_docstring(self) -> None:
"""Test formatting when docstring is an empty string."""
# Create a ClassDef node with empty docstring manually
# This is an edge case that's hard to create via parsing
@@ -420,7 +421,7 @@ def test_format_empty_string_docstring(self):
class TestGetFunctionNames:
"""Tests for get_function_names function."""
- def test_get_simple_methods(self):
+ def test_get_simple_methods(self) -> None:
"""Test extracting method names from a simple class."""
source = """
class MyClass:
@@ -438,7 +439,7 @@ def method2(self):
assert "method2" in result
assert len(result) == 2
- def test_get_no_methods(self):
+ def test_get_no_methods(self) -> None:
"""Test class with no methods."""
source = """
class MyClass:
@@ -450,7 +451,7 @@ class MyClass:
assert not result
- def test_get_special_methods(self):
+ def test_get_special_methods(self) -> None:
"""Test extracting special methods like __init__."""
source = """
class MyClass:
@@ -471,7 +472,7 @@ def regular_method(self):
assert "__str__" in result
assert "regular_method" in result
- def test_get_static_and_class_methods(self):
+ def test_get_static_and_class_methods(self) -> None:
"""Test extracting static and class methods."""
source = """
class MyClass:
@@ -494,7 +495,7 @@ def instance_method(self):
assert "class_method" in result
assert "instance_method" in result
- def test_ignores_nested_functions(self):
+ def test_ignores_nested_functions(self) -> None:
"""Test that nested functions are not included."""
source = """
class MyClass:
diff --git a/tests/fctools/test_code_block_checker.py b/tests/fctools/test_code_block_checker.py
index 44c1b187b..29374fd4d 100644
--- a/tests/fctools/test_code_block_checker.py
+++ b/tests/fctools/test_code_block_checker.py
@@ -33,7 +33,7 @@ def create_temp_qmd_file(content: str) -> Path:
# Tests for check_qmd_file()
-def test_check_qmd_file_no_code_blocks():
+def test_check_qmd_file_no_code_blocks() -> None:
"""Test with a QMD file containing no code blocks."""
content = """# Tutorial Title
@@ -49,7 +49,7 @@ def test_check_qmd_file_no_code_blocks():
qmd_file.unlink()
-def test_check_qmd_file_valid_python_block():
+def test_check_qmd_file_valid_python_block() -> None:
"""Test with valid Python code block."""
content = """# Tutorial
@@ -71,7 +71,7 @@ def test_check_qmd_file_valid_python_block():
qmd_file.unlink()
-def test_check_qmd_file_invalid_python_block():
+def test_check_qmd_file_invalid_python_block() -> None:
"""Test with invalid Python code block."""
content = """# Tutorial
@@ -93,7 +93,7 @@ def test_check_qmd_file_invalid_python_block():
qmd_file.unlink()
-def test_check_qmd_file_multiple_valid_blocks():
+def test_check_qmd_file_multiple_valid_blocks() -> None:
"""Test with multiple valid Python blocks."""
content = """# Tutorial
@@ -125,7 +125,7 @@ def foo():
qmd_file.unlink()
-def test_check_qmd_file_multiple_blocks_with_errors():
+def test_check_qmd_file_multiple_blocks_with_errors() -> None:
"""Test with multiple Python blocks where some have errors."""
content = """# Tutorial
@@ -164,7 +164,7 @@ def foo(
qmd_file.unlink()
-def test_check_qmd_file_non_python_code_blocks():
+def test_check_qmd_file_non_python_code_blocks() -> None:
"""Test that non-Python code blocks are ignored."""
content = """# Tutorial
@@ -197,7 +197,7 @@ def test_check_qmd_file_non_python_code_blocks():
qmd_file.unlink()
-def test_check_qmd_file_python_block_with_options():
+def test_check_qmd_file_python_block_with_options() -> None:
"""Test Python block with execution options."""
content = """# Tutorial
@@ -222,7 +222,7 @@ def test_check_qmd_file_python_block_with_options():
qmd_file.unlink()
-def test_check_qmd_file_empty_python_block():
+def test_check_qmd_file_empty_python_block() -> None:
"""Test with empty Python code block."""
content = """# Tutorial
@@ -241,7 +241,7 @@ def test_check_qmd_file_empty_python_block():
qmd_file.unlink()
-def test_check_qmd_file_python_block_with_comments():
+def test_check_qmd_file_python_block_with_comments() -> None:
"""Test Python block with comments."""
content = """# Tutorial
@@ -260,7 +260,7 @@ def test_check_qmd_file_python_block_with_comments():
qmd_file.unlink()
-def test_check_qmd_file_display_only_python_block():
+def test_check_qmd_file_display_only_python_block() -> None:
"""Test display-only Python block with .python format."""
content = """# Tutorial
@@ -279,7 +279,7 @@ def test_check_qmd_file_display_only_python_block():
qmd_file.unlink()
-def test_check_qmd_file_display_only_with_syntax_error():
+def test_check_qmd_file_display_only_with_syntax_error() -> None:
"""Test display-only Python block with syntax error."""
content = """# Tutorial
@@ -301,7 +301,7 @@ def test_check_qmd_file_display_only_with_syntax_error():
qmd_file.unlink()
-def test_check_qmd_file_mixed_executable_and_display():
+def test_check_qmd_file_mixed_executable_and_display() -> None:
"""Test mix of executable and display-only blocks."""
content = """# Tutorial
@@ -332,7 +332,7 @@ def test_check_qmd_file_mixed_executable_and_display():
qmd_file.unlink()
-def test_check_qmd_file_syntax_error_details():
+def test_check_qmd_file_syntax_error_details() -> None:
"""Test that syntax error details are captured correctly."""
content = """# Tutorial
@@ -353,7 +353,7 @@ def test_check_qmd_file_syntax_error_details():
qmd_file.unlink()
-def test_check_qmd_file_multiline_statements():
+def test_check_qmd_file_multiline_statements() -> None:
"""Test Python block with multiline statements."""
content = """# Tutorial
@@ -382,7 +382,7 @@ def long_function(
# Tests for main()
-def test_main_with_valid_directory():
+def test_main_with_valid_directory() -> None:
"""Test main function with a directory containing valid QMD files."""
# Create temporary directory with valid QMD file
with tempfile.TemporaryDirectory() as temp_dir:
@@ -403,14 +403,14 @@ def test_main_with_valid_directory():
assert "No syntax errors" in result.stderr
-def test_main_with_invalid_directory():
+def test_main_with_invalid_directory() -> None:
"""Test main function with non-existent directory."""
result = runner.invoke(app, ["/nonexistent/directory"])
assert result.exit_code != 0
-def test_main_with_syntax_errors():
+def test_main_with_syntax_errors() -> None:
"""Test main function with QMD files containing syntax errors."""
with tempfile.TemporaryDirectory() as temp_dir:
qmd_path = Path(temp_dir) / "test.qmd"
@@ -430,7 +430,7 @@ def test_main_with_syntax_errors():
assert "Block 1" in result.stderr
-def test_main_with_multiple_files():
+def test_main_with_multiple_files() -> None:
"""Test main function with multiple QMD files."""
with tempfile.TemporaryDirectory() as temp_dir:
# Valid file
@@ -456,7 +456,7 @@ def test_main_with_multiple_files():
assert "Total syntax errors" in result.stderr
-def test_main_with_empty_directory():
+def test_main_with_empty_directory() -> None:
"""Test main function with empty directory."""
with tempfile.TemporaryDirectory() as temp_dir:
result = runner.invoke(app, [temp_dir])
@@ -466,7 +466,7 @@ def test_main_with_empty_directory():
assert "No syntax errors" in result.stderr
-def test_main_quiet_mode_no_errors():
+def test_main_quiet_mode_no_errors() -> None:
"""Test --quiet flag suppresses success messages."""
with tempfile.TemporaryDirectory() as temp_dir:
qmd_path = Path(temp_dir) / "valid.qmd"
@@ -484,7 +484,7 @@ def test_main_quiet_mode_no_errors():
assert result.stderr.strip() == ""
-def test_main_quiet_mode_with_errors():
+def test_main_quiet_mode_with_errors() -> None:
"""Test --quiet flag still reports errors."""
with tempfile.TemporaryDirectory() as temp_dir:
qmd_path = Path(temp_dir) / "error.qmd"
diff --git a/tests/fctools/test_common.py b/tests/fctools/test_common.py
index d0be99c72..4b0c7676b 100644
--- a/tests/fctools/test_common.py
+++ b/tests/fctools/test_common.py
@@ -23,7 +23,7 @@
@pytest.fixture
-def console():
+def console() -> Console:
"""Return a rich console object for testing."""
return Console()
@@ -31,7 +31,7 @@ def console():
class TestLoadJsonFile:
"""Tests for load_json_file function."""
- def test_load_valid_json(self, tmp_path, console):
+ def test_load_valid_json(self, tmp_path: Path, console: Console) -> None:
"""Test loading a valid JSON file."""
json_file = tmp_path / "test.json"
test_data = {"key": "value", "number": 42, "list": [1, 2, 3]}
@@ -41,7 +41,9 @@ def test_load_valid_json(self, tmp_path, console):
assert result == test_data
- def test_load_json_with_custom_context(self, tmp_path, console):
+ def test_load_json_with_custom_context(
+ self, tmp_path: Path, console: Console
+ ) -> None:
"""Test that custom error context is used in error messages."""
json_file = tmp_path / "test.json"
json_file.write_text("{invalid json}")
@@ -51,7 +53,7 @@ def test_load_json_with_custom_context(self, tmp_path, console):
assert exc_info.value.code == 1
- def test_load_nonexistent_file(self, tmp_path, console):
+ def test_load_nonexistent_file(self, tmp_path: Path, console: Console) -> None:
"""Test loading a file that doesn't exist."""
json_file = tmp_path / "nonexistent.json"
@@ -60,7 +62,7 @@ def test_load_nonexistent_file(self, tmp_path, console):
assert exc_info.value.code == 1
- def test_load_invalid_json(self, tmp_path, console):
+ def test_load_invalid_json(self, tmp_path: Path, console: Console) -> None:
"""Test loading a file with invalid JSON."""
json_file = tmp_path / "invalid.json"
json_file.write_text("{this is not valid JSON}")
@@ -70,7 +72,7 @@ def test_load_invalid_json(self, tmp_path, console):
assert exc_info.value.code == 1
- def test_load_empty_file(self, tmp_path, console):
+ def test_load_empty_file(self, tmp_path: Path, console: Console) -> None:
"""Test loading an empty file."""
json_file = tmp_path / "empty.json"
json_file.write_text("")
@@ -80,7 +82,7 @@ def test_load_empty_file(self, tmp_path, console):
assert exc_info.value.code == 1
- def test_load_complex_json(self, tmp_path, console):
+ def test_load_complex_json(self, tmp_path: Path, console: Console) -> None:
"""Test loading JSON with nested structures."""
json_file = tmp_path / "complex.json"
test_data = {
@@ -98,14 +100,14 @@ def test_load_complex_json(self, tmp_path, console):
class TestImportClassFromPath:
"""Tests for import_class_from_path function."""
- def test_import_builtin_class(self, console):
+ def test_import_builtin_class(self, console: Console) -> None:
"""Test importing a built-in Python class."""
result = import_class_from_path(console, "pathlib.Path")
assert result == Path
assert isinstance(Path(), result)
- def test_import_nested_class(self, console):
+ def test_import_nested_class(self, console: Console) -> None:
"""Test importing a class from a nested module."""
result = import_class_from_path(console, "collections.abc.Mapping")
@@ -113,28 +115,28 @@ def test_import_nested_class(self, console):
assert result == Mapping
- def test_import_invalid_module(self, console):
+ def test_import_invalid_module(self, console: Console) -> None:
"""Test importing from a nonexistent module."""
with pytest.raises(SystemExit) as exc_info:
import_class_from_path(console, "nonexistent.module.Class")
assert exc_info.value.code == 1
- def test_import_invalid_class(self, console):
+ def test_import_invalid_class(self, console: Console) -> None:
"""Test importing a nonexistent class from a valid module."""
with pytest.raises(SystemExit) as exc_info:
import_class_from_path(console, "pathlib.NonexistentClass")
assert exc_info.value.code == 1
- def test_import_invalid_path_format(self, console):
+ def test_import_invalid_path_format(self, console: Console) -> None:
"""Test importing with an invalid path format (no dots)."""
with pytest.raises(SystemExit) as exc_info:
import_class_from_path(console, "InvalidPath")
assert exc_info.value.code == 1
- def test_import_firecrown_class(self, console):
+ def test_import_firecrown_class(self, console: Console) -> None:
"""Test importing a class from firecrown."""
result = import_class_from_path(console, "firecrown.updatable.Updatable")
@@ -147,7 +149,7 @@ def test_import_firecrown_class(self, console):
class TestImportModuleFromFile:
"""Tests for import_module_from_file function."""
- def test_import_valid_module(self, tmp_path, console):
+ def test_import_valid_module(self, tmp_path: Path, console: Console) -> None:
"""Test importing a valid Python module from a file."""
module_file = tmp_path / "test_module.py"
module_file.write_text("""
@@ -163,7 +165,9 @@ def test_function():
assert module.test_function() == 42
assert module.TEST_CONSTANT == "hello"
- def test_import_module_with_custom_name(self, tmp_path, console):
+ def test_import_module_with_custom_name(
+ self, tmp_path: Path, console: Console
+ ) -> None:
"""Test importing a module with a custom name."""
module_file = tmp_path / "custom.py"
module_file.write_text("VALUE = 123")
@@ -172,7 +176,7 @@ def test_import_module_with_custom_name(self, tmp_path, console):
assert module.VALUE == 123
- def test_import_nonexistent_file(self, tmp_path, console):
+ def test_import_nonexistent_file(self, tmp_path: Path, console: Console) -> None:
"""Test importing from a nonexistent file."""
module_file = tmp_path / "nonexistent.py"
@@ -181,7 +185,9 @@ def test_import_nonexistent_file(self, tmp_path, console):
assert exc_info.value.code == 1
- def test_import_file_with_syntax_error(self, tmp_path, console):
+ def test_import_file_with_syntax_error(
+ self, tmp_path: Path, console: Console
+ ) -> None:
"""Test importing a file with syntax errors."""
module_file = tmp_path / "syntax_error.py"
module_file.write_text("def broken_function(\n # missing closing paren")
@@ -191,7 +197,9 @@ def test_import_file_with_syntax_error(self, tmp_path, console):
assert exc_info.value.code == 1
- def test_import_file_with_import_error(self, tmp_path, console):
+ def test_import_file_with_import_error(
+ self, tmp_path: Path, console: Console
+ ) -> None:
"""Test importing a file that imports a nonexistent module."""
module_file = tmp_path / "import_error.py"
module_file.write_text("import nonexistent_module")
@@ -201,7 +209,7 @@ def test_import_file_with_import_error(self, tmp_path, console):
assert exc_info.value.code == 1
- def test_import_module_none_spec(self, tmp_path, console):
+ def test_import_module_none_spec(self, tmp_path: Path, console: Console) -> None:
"""Test case where spec_from_file_location returns None."""
# This is extremely rare, but can happen with certain file paths or conditions
# Testing with a directory instead of a file might trigger this
@@ -217,21 +225,23 @@ def test_import_module_none_spec(self, tmp_path, console):
class TestCliError:
"""Tests for cli_error function."""
- def test_cli_error_exits(self, console):
+ def test_cli_error_exits(self, console: Console) -> None:
"""Test that cli_error exits the program."""
with pytest.raises(SystemExit) as exc_info:
cli_error(console, "Test error message")
assert exc_info.value.code == 1
- def test_cli_error_custom_exit_code(self, console):
+ def test_cli_error_custom_exit_code(self, console: Console) -> None:
"""Test cli_error with a custom exit code."""
with pytest.raises(SystemExit) as exc_info:
cli_error(console, "Test error message", exit_code=2)
assert exc_info.value.code == 2
- def test_cli_error_adds_prefix(self, capsys, console):
+ def test_cli_error_adds_prefix(
+ self, capsys: pytest.CaptureFixture[str], console: Console
+ ) -> None:
"""Test that ERROR: prefix is added if not present."""
with pytest.raises(SystemExit):
cli_error(console, "Test message")
@@ -239,7 +249,9 @@ def test_cli_error_adds_prefix(self, capsys, console):
captured = capsys.readouterr()
assert "ERROR: Test message" in captured.err
- def test_cli_error_preserves_prefix(self, capsys, console):
+ def test_cli_error_preserves_prefix(
+ self, capsys: pytest.CaptureFixture[str], console: Console
+ ) -> None:
"""Test that existing ERROR: prefix is not duplicated."""
with pytest.raises(SystemExit):
cli_error(console, "ERROR: Already has prefix")
@@ -252,19 +264,23 @@ def test_cli_error_preserves_prefix(self, capsys, console):
class TestCliWarning:
"""Tests for cli_warning function."""
- def test_cli_warning_does_not_exit(self, console):
+ def test_cli_warning_does_not_exit(self, console: Console) -> None:
"""Test that cli_warning does not exit the program."""
# Should not raise SystemExit
cli_warning(console, "Test warning message")
- def test_cli_warning_adds_prefix(self, capsys, console):
+ def test_cli_warning_adds_prefix(
+ self, capsys: pytest.CaptureFixture[str], console: Console
+ ) -> None:
"""Test that Warning: prefix is added if not present."""
cli_warning(console, "Test message")
captured = capsys.readouterr()
assert "Warning: Test message" in captured.err
- def test_cli_warning_preserves_prefix(self, capsys, console):
+ def test_cli_warning_preserves_prefix(
+ self, capsys: pytest.CaptureFixture[str], console: Console
+ ) -> None:
"""Test that existing Warning: prefix is not duplicated."""
cli_warning(console, "Warning: Already has prefix")
@@ -272,7 +288,9 @@ def test_cli_warning_preserves_prefix(self, capsys, console):
assert "Warning: Warning:" not in captured.err
assert "Warning: Already has prefix" in captured.err
- def test_multiple_warnings(self, capsys, console):
+ def test_multiple_warnings(
+ self, capsys: pytest.CaptureFixture[str], console: Console
+ ) -> None:
"""Test that multiple warnings can be issued."""
cli_warning(console, "First warning")
cli_warning(console, "Second warning")
@@ -285,7 +303,7 @@ def test_multiple_warnings(self, capsys, console):
class TestValidateInputFile:
"""Tests for validate_input_file function."""
- def test_validate_existing_file(self, tmp_path, console):
+ def test_validate_existing_file(self, tmp_path: Path, console: Console) -> None:
"""Test validating an existing readable file."""
test_file = tmp_path / "test.txt"
test_file.write_text("content")
@@ -293,7 +311,7 @@ def test_validate_existing_file(self, tmp_path, console):
# Should not raise
validate_input_file(console, test_file)
- def test_validate_nonexistent_file(self, tmp_path, console):
+ def test_validate_nonexistent_file(self, tmp_path: Path, console: Console) -> None:
"""Test validating a nonexistent file."""
test_file = tmp_path / "nonexistent.txt"
@@ -302,14 +320,18 @@ def test_validate_nonexistent_file(self, tmp_path, console):
assert exc_info.value.code == 1
- def test_validate_directory_not_file(self, tmp_path, console):
+ def test_validate_directory_not_file(
+ self, tmp_path: Path, console: Console
+ ) -> None:
"""Test validating a directory instead of a file."""
with pytest.raises(SystemExit) as exc_info:
validate_input_file(console, tmp_path)
assert exc_info.value.code == 1
- def test_validate_custom_description(self, tmp_path, console):
+ def test_validate_custom_description(
+ self, tmp_path: Path, console: Console
+ ) -> None:
"""Test validate_input_file with custom file description."""
test_file = tmp_path / "nonexistent.txt"
@@ -320,7 +342,7 @@ def test_validate_custom_description(self, tmp_path, console):
# Error message should contain custom description
- def test_validate_unreadable_file(self, tmp_path, console):
+ def test_validate_unreadable_file(self, tmp_path: Path, console: Console) -> None:
"""Test validating a file without read permissions."""
if sys.platform == "win32":
pytest.skip("File permission tests unreliable on Windows")
@@ -344,14 +366,16 @@ def test_validate_unreadable_file(self, tmp_path, console):
class TestValidateOutputPath:
"""Tests for validate_output_path function."""
- def test_validate_new_output_path(self, tmp_path, console):
+ def test_validate_new_output_path(self, tmp_path: Path, console: Console) -> None:
"""Test validating a new output path (file doesn't exist)."""
output_file = tmp_path / "output.txt"
# Should not raise
validate_output_path(console, output_file, overwrite=False)
- def test_validate_existing_path_without_overwrite(self, tmp_path, console):
+ def test_validate_existing_path_without_overwrite(
+ self, tmp_path: Path, console: Console
+ ) -> None:
"""Test validating existing file without overwrite permission."""
output_file = tmp_path / "existing.txt"
output_file.write_text("existing content")
@@ -361,7 +385,9 @@ def test_validate_existing_path_without_overwrite(self, tmp_path, console):
assert exc_info.value.code == 1
- def test_validate_existing_path_with_overwrite(self, tmp_path, console):
+ def test_validate_existing_path_with_overwrite(
+ self, tmp_path: Path, console: Console
+ ) -> None:
"""Test validating existing file with overwrite permission."""
output_file = tmp_path / "existing.txt"
output_file.write_text("existing content")
@@ -373,37 +399,37 @@ def test_validate_existing_path_with_overwrite(self, tmp_path, console):
class TestFormatLineRanges:
"""Tests for format_line_ranges function."""
- def test_format_empty_list(self):
+ def test_format_empty_list(self) -> None:
"""Test formatting an empty list."""
result = format_line_ranges([])
assert not result
- def test_format_single_line(self):
+ def test_format_single_line(self) -> None:
"""Test formatting a single line number."""
result = format_line_ranges([42])
assert result == ["42"]
- def test_format_consecutive_lines(self):
+ def test_format_consecutive_lines(self) -> None:
"""Test formatting consecutive line numbers."""
result = format_line_ranges([1, 2, 3, 4, 5])
assert result == ["1-5"]
- def test_format_mixed_ranges(self):
+ def test_format_mixed_ranges(self) -> None:
"""Test formatting mixed consecutive and individual lines."""
result = format_line_ranges([1, 2, 3, 5, 6, 8, 10, 11, 12])
assert result == ["1-3", "5-6", "8", "10-12"]
- def test_format_unsorted_lines(self):
+ def test_format_unsorted_lines(self) -> None:
"""Test formatting unsorted line numbers."""
result = format_line_ranges([5, 1, 3, 2, 8])
assert result == ["1-3", "5", "8"]
- def test_format_duplicate_lines(self):
+ def test_format_duplicate_lines(self) -> None:
"""Test formatting with duplicate line numbers."""
result = format_line_ranges([1, 2, 2, 3, 5, 5, 6])
@@ -411,19 +437,19 @@ def test_format_duplicate_lines(self):
assert len(result) == 4 # ['1-2', '2-3', '5', '5-6']
assert "1-2" in result or "2-3" in result
- def test_format_large_range(self):
+ def test_format_large_range(self) -> None:
"""Test formatting a large range of consecutive lines."""
result = format_line_ranges(list(range(100, 200)))
assert result == ["100-199"]
- def test_format_all_individual_lines(self):
+ def test_format_all_individual_lines(self) -> None:
"""Test formatting non-consecutive lines."""
result = format_line_ranges([1, 5, 10, 15, 20])
assert result == ["1", "5", "10", "15", "20"]
- def test_format_two_consecutive_lines(self):
+ def test_format_two_consecutive_lines(self) -> None:
"""Test formatting exactly two consecutive lines."""
result = format_line_ranges([5, 6])
diff --git a/tests/fctools/test_coverage_summary.py b/tests/fctools/test_coverage_summary.py
index 3606fd100..c98930f1e 100644
--- a/tests/fctools/test_coverage_summary.py
+++ b/tests/fctools/test_coverage_summary.py
@@ -3,9 +3,14 @@
Tests the coverage analysis and reporting functionality.
"""
+# pylint: disable=too-many-lines
+
import json
+from pathlib import Path
+from typing import Any
import pytest
+from pytest import CaptureFixture
from rich.console import Console
from typer.testing import CliRunner
@@ -29,7 +34,7 @@
@pytest.fixture
-def console():
+def console() -> Console:
"""Return a rich console object for testing."""
return Console()
@@ -37,7 +42,7 @@ def console():
class TestCoverageSummary:
"""Tests for CoverageSummary dataclass."""
- def test_default_values(self):
+ def test_default_values(self) -> None:
"""Test that CoverageSummary has correct default values."""
summary = CoverageSummary()
@@ -54,7 +59,7 @@ def test_default_values(self):
assert summary.total_branches == 0
assert summary.total_missing_branches == 0
- def test_custom_values(self):
+ def test_custom_values(self) -> None:
"""Test creating CoverageSummary with custom values."""
summary = CoverageSummary(
total_files=10,
@@ -70,7 +75,7 @@ def test_custom_values(self):
class TestFileIssue:
"""Tests for FileIssue dataclass."""
- def test_file_issue_creation(self):
+ def test_file_issue_creation(self) -> None:
"""Test creating a FileIssue object."""
issue = FileIssue(
file_path="test.py",
@@ -97,7 +102,7 @@ def test_file_issue_creation(self):
class TestCalculateBranchCoverageSummary:
"""Tests for _calculate_branch_coverage_summary function."""
- def test_with_branches(self):
+ def test_with_branches(self) -> None:
"""Test branch coverage calculation with branches present."""
totals = {"num_branches": 100, "missing_branches": 20}
@@ -107,7 +112,7 @@ def test_with_branches(self):
assert missing == 20
assert coverage == 80.0
- def test_with_no_branches(self):
+ def test_with_no_branches(self) -> None:
"""Test branch coverage when no branches exist."""
totals = {"num_branches": 0, "missing_branches": 0}
@@ -117,7 +122,7 @@ def test_with_no_branches(self):
assert missing == 0
assert coverage == 100.0
- def test_missing_keys(self):
+ def test_missing_keys(self) -> None:
"""Test with missing dictionary keys."""
totals: dict[str, int] = {}
@@ -127,7 +132,7 @@ def test_missing_keys(self):
assert missing == 0
assert coverage == 100.0
- def test_perfect_branch_coverage(self):
+ def test_perfect_branch_coverage(self) -> None:
"""Test with 100% branch coverage."""
totals = {"num_branches": 50, "missing_branches": 0}
@@ -141,7 +146,7 @@ def test_perfect_branch_coverage(self):
class TestCalculateFileBranchCoverage:
"""Tests for _calculate_file_branch_coverage function."""
- def test_with_branches(self):
+ def test_with_branches(self) -> None:
"""Test file branch coverage with branches present."""
file_summary = {"num_branches": 10, "covered_branches": 8}
@@ -149,7 +154,7 @@ def test_with_branches(self):
assert coverage == 80.0
- def test_no_branches_with_statements(self):
+ def test_no_branches_with_statements(self) -> None:
"""Test file with no branches but has statements."""
file_summary = {"num_branches": 0}
@@ -157,7 +162,7 @@ def test_no_branches_with_statements(self):
assert coverage == 100.0
- def test_no_branches_no_statements(self):
+ def test_no_branches_no_statements(self) -> None:
"""Test file with no branches and no statements."""
file_summary = {"num_branches": 0}
@@ -165,7 +170,7 @@ def test_no_branches_no_statements(self):
assert coverage == 0.0
- def test_perfect_branch_coverage(self):
+ def test_perfect_branch_coverage(self) -> None:
"""Test file with 100% branch coverage."""
file_summary = {"num_branches": 20, "covered_branches": 20}
@@ -173,7 +178,7 @@ def test_perfect_branch_coverage(self):
assert coverage == 100.0
- def test_missing_keys(self):
+ def test_missing_keys(self) -> None:
"""Test with missing dictionary keys."""
file_summary: dict[str, int] = {}
@@ -185,7 +190,7 @@ def test_missing_keys(self):
class TestCreateFileIssue:
"""Tests for _create_file_issue function."""
- def test_create_file_issue(self):
+ def test_create_file_issue(self) -> None:
"""Test creating a FileIssue from coverage data."""
file_summary = {"num_statements": 100, "num_branches": 20}
missing_lines = [10, 20, 30]
@@ -218,7 +223,7 @@ def test_create_file_issue(self):
class TestAnalyzeSingleFile:
"""Tests for _analyze_single_file function."""
- def test_perfect_coverage_file(self):
+ def test_perfect_coverage_file(self) -> None:
"""Test analyzing a file with perfect coverage."""
summary = CoverageSummary()
file_data = {
@@ -242,7 +247,7 @@ def test_perfect_coverage_file(self):
assert summary.files_with_missing_branches == 0
assert summary.files_with_excluded_lines == 0
- def test_file_with_missing_lines(self):
+ def test_file_with_missing_lines(self) -> None:
"""Test analyzing a file with missing lines."""
summary = CoverageSummary()
file_data = {
@@ -265,7 +270,7 @@ def test_file_with_missing_lines(self):
assert summary.files_with_perfect_coverage == 0
assert summary.files_with_missing_lines == 1
- def test_file_with_missing_branches(self):
+ def test_file_with_missing_branches(self) -> None:
"""Test analyzing a file with missing branches."""
summary = CoverageSummary()
file_data = {
@@ -286,7 +291,7 @@ def test_file_with_missing_branches(self):
assert result.missing_branches_count == 2
assert summary.files_with_missing_branches == 1
- def test_file_with_excluded_lines_only(self):
+ def test_file_with_excluded_lines_only(self) -> None:
"""Test analyzing a file with only excluded lines (no missing coverage)."""
summary = CoverageSummary()
file_data = {
@@ -307,7 +312,7 @@ def test_file_with_excluded_lines_only(self):
assert summary.files_with_excluded_lines == 1
assert summary.files_with_perfect_coverage == 1 # Still perfect coverage
- def test_file_with_all_issues(self):
+ def test_file_with_all_issues(self) -> None:
"""Test file with missing lines, branches, and excluded lines."""
summary = CoverageSummary()
file_data = {
@@ -334,7 +339,7 @@ def test_file_with_all_issues(self):
class TestAnalyzeCoverageJson:
"""Tests for analyze_coverage_json function."""
- def test_analyze_simple_coverage(self, tmp_path, console):
+ def test_analyze_simple_coverage(self, tmp_path: Path, console: Console) -> None:
"""Test analyzing a simple coverage JSON file."""
coverage_data = {
"files": {
@@ -382,7 +387,9 @@ def test_analyze_simple_coverage(self, tmp_path, console):
assert len(file_issues) == 1
assert file_issues[0].file_path == "file1.py"
- def test_file_issues_sorted_by_coverage(self, tmp_path, console):
+ def test_file_issues_sorted_by_coverage(
+ self, tmp_path: Path, console: Console
+ ) -> None:
"""Test that file issues are sorted by coverage (worst first)."""
coverage_data = {
"files": {
@@ -437,7 +444,7 @@ def test_file_issues_sorted_by_coverage(self, tmp_path, console):
assert file_issues[1].file_path == "file3.py" # Middle: 75%
assert file_issues[2].file_path == "file1.py" # Best: 90%
- def test_empty_coverage_file(self, tmp_path, console):
+ def test_empty_coverage_file(self, tmp_path: Path, console: Console) -> None:
"""Test analyzing an empty coverage file."""
coverage_data: dict[str, dict[str, object]] = {"files": {}, "totals": {}}
@@ -453,7 +460,7 @@ def test_empty_coverage_file(self, tmp_path, console):
class TestPrintCoverageSummary:
"""Tests for print_coverage_summary function."""
- def test_print_summary(self, capsys, console):
+ def test_print_summary(self, capsys: CaptureFixture[str], console: Console) -> None:
"""Test printing coverage summary."""
summary = CoverageSummary(
total_files=10,
@@ -485,7 +492,9 @@ def test_print_summary(self, capsys, console):
class TestPrintSourceCodeForMissingLines:
"""Tests for _print_source_code_for_missing_lines function."""
- def test_print_source_existing_file(self, tmp_path, capsys, console):
+ def test_print_source_existing_file(
+ self, tmp_path: Path, capsys: CaptureFixture[str], console: Console
+ ) -> None:
"""Test printing source code for existing file."""
source_file = tmp_path / "test.py"
source_file.write_text("line 1\nline 2\nline 3\nline 4\nline 5\n")
@@ -511,7 +520,9 @@ def test_print_source_existing_file(self, tmp_path, capsys, console):
assert "2: line 2" in captured.out
assert "4: line 4" in captured.out
- def test_print_source_nonexistent_file(self, capsys, console):
+ def test_print_source_nonexistent_file(
+ self, capsys: CaptureFixture[str], console: Console
+ ) -> None:
"""Test handling of nonexistent source file."""
issue = FileIssue(
file_path="/nonexistent/file.py",
@@ -532,7 +543,9 @@ def test_print_source_nonexistent_file(self, capsys, console):
captured = capsys.readouterr()
assert "(Source file not found for line details)" in captured.out
- def test_print_source_with_unicode_error(self, tmp_path, capsys, console):
+ def test_print_source_with_unicode_error(
+ self, tmp_path: Path, capsys: CaptureFixture[str], console: Console
+ ) -> None:
"""Test handling of files with encoding errors."""
source_file = tmp_path / "test.py"
# Write binary data that's not valid UTF-8
@@ -557,7 +570,9 @@ def test_print_source_with_unicode_error(self, tmp_path, capsys, console):
captured = capsys.readouterr()
assert "(Error reading source file:" in captured.out
- def test_print_source_line_out_of_range(self, tmp_path, capsys, console):
+ def test_print_source_line_out_of_range(
+ self, tmp_path: Path, capsys: CaptureFixture[str], console: Console
+ ) -> None:
"""Test handling of line numbers outside file range."""
source_file = tmp_path / "test.py"
source_file.write_text("line 1\nline 2\n")
@@ -586,7 +601,9 @@ def test_print_source_line_out_of_range(self, tmp_path, capsys, console):
class TestPrintFileIssueDetails:
"""Tests for _print_file_issue_details function."""
- def test_print_with_missing_lines_and_branches(self, tmp_path, capsys, console):
+ def test_print_with_missing_lines_and_branches(
+ self, tmp_path: Path, capsys: CaptureFixture[str], console: Console
+ ) -> None:
"""Test printing file issue with missing lines and branches."""
source_file = tmp_path / "test.py"
source_file.write_text("line 1\nline 2\nline 3\n")
@@ -616,7 +633,9 @@ def test_print_with_missing_lines_and_branches(self, tmp_path, capsys, console):
assert "Missing Branches (1):" in captured.out
assert "[10, 11]" in captured.out
- def test_print_without_showing_source(self, capsys, console):
+ def test_print_without_showing_source(
+ self, capsys: CaptureFixture[str], console: Console
+ ) -> None:
"""Test printing without showing source code."""
issue = FileIssue(
file_path="test.py",
@@ -639,7 +658,9 @@ def test_print_without_showing_source(self, capsys, console):
assert "Missing Lines (1):" in captured.out
assert "Source code for missing lines:" not in captured.out
- def test_print_with_no_branches(self, capsys, console):
+ def test_print_with_no_branches(
+ self, capsys: CaptureFixture[str], console: Console
+ ) -> None:
"""Test printing for file with no branches."""
issue = FileIssue(
file_path="test.py",
@@ -662,7 +683,9 @@ def test_print_with_no_branches(self, capsys, console):
assert "Branch Coverage:" not in captured.out # Should not show for 0 branches
assert "Excluded Lines (1):" in captured.out
- def test_print_with_excluded_lines(self, capsys, console):
+ def test_print_with_excluded_lines(
+ self, capsys: CaptureFixture[str], console: Console
+ ) -> None:
"""Test printing with excluded lines."""
issue = FileIssue(
file_path="test.py",
@@ -688,14 +711,18 @@ def test_print_with_excluded_lines(self, capsys, console):
class TestPrintFileIssues:
"""Tests for print_file_issues function."""
- def test_print_no_issues(self, capsys, console):
+ def test_print_no_issues(
+ self, capsys: CaptureFixture[str], console: Console
+ ) -> None:
"""Test printing when no issues exist."""
print_file_issues(console, [])
captured = capsys.readouterr()
assert "ALL FILES HAVE PERFECT COVERAGE!" in captured.out
- def test_print_multiple_issues(self, capsys, console):
+ def test_print_multiple_issues(
+ self, capsys: CaptureFixture[str], console: Console
+ ) -> None:
"""Test printing multiple file issues."""
issues = [
FileIssue(
@@ -737,7 +764,9 @@ def test_print_multiple_issues(self, capsys, console):
class TestPrintPerfectCoverageFiles:
"""Tests for print_perfect_coverage_files function."""
- def test_print_perfect_files(self, capsys, console):
+ def test_print_perfect_files(
+ self, capsys: CaptureFixture[str], console: Console
+ ) -> None:
"""Test printing files with perfect coverage."""
file_issues = [
FileIssue(
@@ -764,7 +793,9 @@ def test_print_perfect_files(self, capsys, console):
assert "✅ good2.py" in captured.out
assert "bad.py" not in captured.out
- def test_no_perfect_files(self, capsys, console):
+ def test_no_perfect_files(
+ self, capsys: CaptureFixture[str], console: Console
+ ) -> None:
"""Test when no files have perfect coverage."""
file_issues = [
FileIssue(
@@ -793,7 +824,7 @@ def test_no_perfect_files(self, capsys, console):
class TestMainFunction: # pylint: disable=import-outside-toplevel
"""Tests for main CLI function."""
- def test_main_basic_usage(self, tmp_path):
+ def test_main_basic_usage(self, tmp_path: Path) -> None:
"""Test main function with basic coverage file."""
coverage_data = {
"files": {
@@ -829,7 +860,7 @@ def test_main_basic_usage(self, tmp_path):
assert match_wrapped(result.stdout, "COVERAGE ANALYSIS SUMMARY")
assert match_wrapped(result.stdout, "Total files analyzed: 1")
- def test_main_with_show_source(self, tmp_path):
+ def test_main_with_show_source(self, tmp_path: Path) -> None:
"""Test main function with --show-source flag."""
source_file = tmp_path / "test.py"
source_file.write_text("line 1\nline 2\n")
@@ -867,7 +898,7 @@ def test_main_with_show_source(self, tmp_path):
assert match_wrapped(result.stdout, "Source code for missing lines:")
- def test_main_with_show_perfect(self, tmp_path):
+ def test_main_with_show_perfect(self, tmp_path: Path) -> None:
"""Test main function with --show-perfect flag."""
coverage_data = {
"files": {
@@ -913,20 +944,24 @@ def test_main_with_show_perfect(self, tmp_path):
assert match_wrapped(result.stdout, "FILES WITH PERFECT COVERAGE:")
assert match_wrapped(result.stdout, "perfect.py")
- def test_main_with_nonexistent_file(self, tmp_path):
+ def test_main_with_nonexistent_file(self, tmp_path: Path) -> None:
"""Test main function with nonexistent coverage file."""
runner = CliRunner()
result = runner.invoke(app, [str(tmp_path / "nonexistent.json")])
assert result.exit_code != 0
- def test_main_with_os_error(self, tmp_path, monkeypatch):
+ def test_main_with_os_error(
+ self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
+ ) -> None:
"""Test main function handling of OSError."""
coverage_file = tmp_path / "coverage.json"
coverage_file.write_text('{"files": {}, "totals": {}}')
# Mock load_json_file to raise OSError
- def mock_load_json_file(*args, **kwargs):
+ def mock_load_json_file(
+ console: Console, file_path: Path, error_context: str = "reading file"
+ ) -> dict[str, Any]:
raise OSError("Simulated OS error")
from firecrown.fctools import coverage_summary
@@ -940,7 +975,7 @@ def mock_load_json_file(*args, **kwargs):
assert match_wrapped(result.stdout, "Error analyzing coverage file:")
- def test_main_block_with_subprocess(self, tmp_path):
+ def test_main_block_with_subprocess(self, tmp_path: Path) -> None:
"""Test that the script can be executed directly via subprocess.
This test verifies that the __main__ block and ImportError fallback
diff --git a/tests/fctools/test_coverage_to_tsv_cli.py b/tests/fctools/test_coverage_to_tsv_cli.py
index 5342042d8..832224173 100644
--- a/tests/fctools/test_coverage_to_tsv_cli.py
+++ b/tests/fctools/test_coverage_to_tsv_cli.py
@@ -13,7 +13,7 @@
from . import match_wrapped
-def test_main_basic(tmp_path):
+def test_main_basic(tmp_path: Path) -> None:
coverage_file = tmp_path / "coverage.json"
output_file = tmp_path / "output.tsv"
@@ -70,7 +70,7 @@ def test_main_basic(tmp_path):
assert "src/example.py" in lines[1]
-def test_main_with_timing(tmp_path):
+def test_main_with_timing(tmp_path: Path) -> None:
coverage_file = tmp_path / "coverage.json"
timing_file = tmp_path / "timing.json"
output_file = tmp_path / "output.tsv"
@@ -132,7 +132,7 @@ def test_main_with_timing(tmp_path):
assert match_wrapped(result.stdout, "Records with timing data:")
-def test_main_default_output_filename(tmp_path):
+def test_main_default_output_filename(tmp_path: Path) -> None:
coverage_file = tmp_path / "coverage.json"
coverage_data = {
@@ -183,7 +183,7 @@ def test_main_default_output_filename(tmp_path):
assert default_output.exists()
-def test_main_nonexistent_input(tmp_path):
+def test_main_nonexistent_input(tmp_path: Path) -> None:
nonexistent_file = tmp_path / "does_not_exist.json"
output_file = tmp_path / "output.tsv"
@@ -203,7 +203,7 @@ def test_main_nonexistent_input(tmp_path):
assert match_wrapped(result.stderr.lower(), "does not exist")
-def test_main_invalid_json(tmp_path):
+def test_main_invalid_json(tmp_path: Path) -> None:
coverage_file = tmp_path / "invalid.json"
output_file = tmp_path / "output.tsv"
@@ -225,7 +225,7 @@ def test_main_invalid_json(tmp_path):
assert "json" in result.stderr.lower()
-def test_main_missing_expected_key(tmp_path):
+def test_main_missing_expected_key(tmp_path: Path) -> None:
coverage_file = tmp_path / "missing_key.json"
output_file = tmp_path / "output.tsv"
@@ -257,7 +257,7 @@ def test_main_missing_expected_key(tmp_path):
assert len(lines) == 1
-def test_main_write_error(tmp_path):
+def test_main_write_error(tmp_path: Path) -> None:
coverage_file = tmp_path / "coverage.json"
coverage_data = {
@@ -310,7 +310,7 @@ def test_main_write_error(tmp_path):
assert match_wrapped(result.stdout, "Error: File operation failed")
-def test_main_timing_file_not_found(tmp_path):
+def test_main_timing_file_not_found(tmp_path: Path) -> None:
coverage_file = tmp_path / "coverage.json"
output_file = tmp_path / "output.tsv"
nonexistent_timing = tmp_path / "timing_does_not_exist.txt"
diff --git a/tests/fctools/test_coverage_to_tsv_data.py b/tests/fctools/test_coverage_to_tsv_data.py
index 55f46c2b7..3aa82ef8d 100644
--- a/tests/fctools/test_coverage_to_tsv_data.py
+++ b/tests/fctools/test_coverage_to_tsv_data.py
@@ -6,6 +6,8 @@
# pylint: disable=missing-function-docstring
+from pathlib import Path
+
import pytest
from firecrown.fctools.coverage_to_tsv import (
@@ -18,7 +20,7 @@
# Tests for match_test_to_function()
-def test_match_test_to_function_exact_name_match():
+def test_match_test_to_function_exact_name_match() -> None:
test_name = "tests/test_module.py::test_my_function"
function_name = "my_function"
file_path = "src/module.py"
@@ -29,7 +31,7 @@ def test_match_test_to_function_exact_name_match():
assert score >= 0.5
-def test_match_test_to_function_file_match():
+def test_match_test_to_function_file_match() -> None:
test_name = "tests/test_example.py::test_something"
function_name = "other_function"
file_path = "src/example.py"
@@ -40,7 +42,7 @@ def test_match_test_to_function_file_match():
assert score == pytest.approx(0.3)
-def test_match_test_to_function_full_match():
+def test_match_test_to_function_full_match() -> None:
test_name = "tests/test_utils.py::test_format_string"
function_name = "format_string"
file_path = "src/utils.py"
@@ -54,7 +56,7 @@ def test_match_test_to_function_full_match():
assert score == 1.0
-def test_match_test_to_function_no_match():
+def test_match_test_to_function_no_match() -> None:
test_name = "tests/test_other.py::test_something"
function_name = "unrelated_function"
file_path = "src/different.py"
@@ -64,7 +66,7 @@ def test_match_test_to_function_no_match():
assert score == 0.0
-def test_match_test_to_function_test_name_no_separator():
+def test_match_test_to_function_test_name_no_separator() -> None:
test_name = "tests/test_module.py"
function_name = "some_function"
file_path = "src/module.py"
@@ -79,7 +81,7 @@ def test_match_test_to_function_test_name_no_separator():
assert score >= 0.3
-def test_match_test_to_function_case_insensitive():
+def test_match_test_to_function_case_insensitive() -> None:
test_name = "tests/test_module.py::test_MyFunction"
function_name = "myfunction"
file_path = "src/other.py"
@@ -93,7 +95,7 @@ def test_match_test_to_function_case_insensitive():
# Tests for extract_coverage_data()
-def test_extract_coverage_data_basic():
+def test_extract_coverage_data_basic() -> None:
coverage_data = {
"files": {
"src/example.py": {
@@ -144,7 +146,7 @@ def test_extract_coverage_data_basic():
assert record.test_duration is None
-def test_extract_coverage_data_with_timing():
+def test_extract_coverage_data_with_timing() -> None:
coverage_data = {
"files": {
"src/utils.py": {
@@ -186,7 +188,7 @@ def test_extract_coverage_data_with_timing():
assert record.test_duration == 0.25
-def test_extract_coverage_data_timing_below_threshold():
+def test_extract_coverage_data_timing_below_threshold() -> None:
coverage_data = {
"files": {
"src/module.py": {
@@ -227,7 +229,7 @@ def test_extract_coverage_data_timing_below_threshold():
assert record.test_duration is None
-def test_extract_coverage_data_multiple_functions():
+def test_extract_coverage_data_multiple_functions() -> None:
coverage_data = {
"files": {
"src/module.py": {
@@ -277,7 +279,7 @@ def test_extract_coverage_data_multiple_functions():
assert func_names == {"func_a", "func_b"}
-def test_extract_coverage_data_no_functions():
+def test_extract_coverage_data_no_functions() -> None:
coverage_data = {
"files": {
"src/empty.py": {
@@ -295,7 +297,7 @@ def test_extract_coverage_data_no_functions():
assert len(result) == 0
-def test_extract_coverage_data_empty_files():
+def test_extract_coverage_data_empty_files() -> None:
coverage_data: dict[str, dict[str, object]] = {"files": {}}
result = extract_coverage_data(coverage_data)
@@ -303,7 +305,7 @@ def test_extract_coverage_data_empty_files():
assert len(result) == 0
-def test_extract_coverage_data_missing_summary_fields():
+def test_extract_coverage_data_missing_summary_fields() -> None:
coverage_data: dict[str, dict[str, object]] = {
"files": {
"src/partial.py": {
@@ -326,7 +328,7 @@ def test_extract_coverage_data_missing_summary_fields():
# Tests for write_tsv_file()
-def test_write_tsv_file(tmp_path):
+def test_write_tsv_file(tmp_path: Path) -> None:
output_file = tmp_path / "output.tsv"
data = [
CoverageRecord(
@@ -368,7 +370,7 @@ def test_write_tsv_file(tmp_path):
assert data_row[-1] == "0.25"
-def test_write_tsv_file_no_timing(tmp_path):
+def test_write_tsv_file_no_timing(tmp_path: Path) -> None:
output_file = tmp_path / "output.tsv"
data = [
CoverageRecord(
@@ -411,7 +413,7 @@ def test_write_tsv_file_no_timing(tmp_path):
assert data_row[-2] == "100.0"
-def test_write_tsv_file_multiple_records(tmp_path):
+def test_write_tsv_file_multiple_records(tmp_path: Path) -> None:
output_file = tmp_path / "output.tsv"
data = [
CoverageRecord(
diff --git a/tests/fctools/test_coverage_to_tsv_output.py b/tests/fctools/test_coverage_to_tsv_output.py
index 6e30fbbfb..7e5101358 100644
--- a/tests/fctools/test_coverage_to_tsv_output.py
+++ b/tests/fctools/test_coverage_to_tsv_output.py
@@ -10,6 +10,8 @@
import sys
from pathlib import Path
+import pytest
+
from firecrown.fctools.coverage_to_tsv import CoverageRecord, main, write_tsv_file
from . import match_wrapped
@@ -17,7 +19,7 @@
# Tests for write_tsv_file()
-def test_write_tsv_file(tmp_path):
+def test_write_tsv_file(tmp_path: Path) -> None:
output_file = tmp_path / "output.tsv"
data = [
CoverageRecord(
@@ -59,7 +61,7 @@ def test_write_tsv_file(tmp_path):
assert data_row[-1] == "0.25"
-def test_write_tsv_file_no_timing(tmp_path):
+def test_write_tsv_file_no_timing(tmp_path: Path) -> None:
output_file = tmp_path / "output.tsv"
data = [
CoverageRecord(
@@ -102,7 +104,7 @@ def test_write_tsv_file_no_timing(tmp_path):
assert data_row[-2] == "100.0"
-def test_write_tsv_file_multiple_records(tmp_path):
+def test_write_tsv_file_multiple_records(tmp_path: Path) -> None:
output_file = tmp_path / "output.tsv"
data = [
CoverageRecord(
@@ -154,7 +156,7 @@ def test_write_tsv_file_multiple_records(tmp_path):
# Tests for main()
-def test_main_basic(tmp_path):
+def test_main_basic(tmp_path: Path) -> None:
# Create input file
input_file = tmp_path / "coverage.json"
coverage_data = {
@@ -204,7 +206,7 @@ def test_main_basic(tmp_path):
assert match_wrapped(result.stdout, "Records written: 1")
-def test_main_with_timing(tmp_path):
+def test_main_with_timing(tmp_path: Path) -> None:
# Create input file
input_file = tmp_path / "coverage.json"
coverage_data = {
@@ -268,7 +270,9 @@ def test_main_with_timing(tmp_path):
assert match_wrapped(result.stdout, "Records with timing data:")
-def test_main_default_output_filename(tmp_path, monkeypatch):
+def test_main_default_output_filename(
+ tmp_path: Path, monkeypatch: pytest.MonkeyPatch
+) -> None:
# Get absolute path to script before changing directory
script_path = Path("firecrown/fctools/coverage_to_tsv.py").absolute()
@@ -317,7 +321,7 @@ def test_main_default_output_filename(tmp_path, monkeypatch):
assert Path("coverage_data.tsv").exists()
-def test_main_nonexistent_input(tmp_path):
+def test_main_nonexistent_input(tmp_path: Path) -> None:
input_file = tmp_path / "nonexistent.json"
output_file = tmp_path / "output.tsv"
@@ -334,7 +338,7 @@ def test_main_nonexistent_input(tmp_path):
assert match_wrapped(result.stderr.lower(), "does not exist")
-def test_main_invalid_json(tmp_path):
+def test_main_invalid_json(tmp_path: Path) -> None:
input_file = tmp_path / "invalid.json"
input_file.write_text("This is not valid JSON")
@@ -352,7 +356,7 @@ def test_main_invalid_json(tmp_path):
assert "ERROR" in result.stderr
-def test_main_missing_expected_key(tmp_path):
+def test_main_missing_expected_key(tmp_path: Path) -> None:
input_file = tmp_path / "bad_structure.json"
# Missing 'files' key that code expects
input_file.write_text('{"other_key": "value"}')
@@ -372,7 +376,7 @@ def test_main_missing_expected_key(tmp_path):
assert match_wrapped(result.stdout, "Records written: 0")
-def test_main_write_error(tmp_path):
+def test_main_write_error(tmp_path: Path) -> None:
input_file = tmp_path / "coverage.json"
coverage_data = {
"files": {
@@ -420,7 +424,7 @@ def test_main_write_error(tmp_path):
assert match_wrapped(result.stdout, "Error: File operation failed")
-def test_main_timing_file_not_found(tmp_path):
+def test_main_timing_file_not_found(tmp_path: Path) -> None:
input_file = tmp_path / "coverage.json"
coverage_data = {
"files": {
@@ -476,7 +480,7 @@ def test_main_timing_file_not_found(tmp_path):
# Tests for main() function called directly (for coverage of console output)
-def test_main_direct_basic(tmp_path, capsys):
+def test_main_direct_basic(tmp_path: Path, capsys: pytest.CaptureFixture[str]) -> None:
"""Test main function called directly for coverage of success path console output.
This test calls main() directly (not via subprocess) to ensure coverage
@@ -538,7 +542,9 @@ def test_main_direct_basic(tmp_path, capsys):
assert match_wrapped(captured.out, "Records written: 1")
-def test_main_direct_with_timing(tmp_path, capsys):
+def test_main_direct_with_timing(
+ tmp_path: Path, capsys: pytest.CaptureFixture[str]
+) -> None:
"""Test main function with timing data for coverage of timing-related output.
Tests the branch where timing_data is not None (lines 367-370).
diff --git a/tests/fctools/test_coverage_to_tsv_parsing.py b/tests/fctools/test_coverage_to_tsv_parsing.py
index 853980715..fef319717 100644
--- a/tests/fctools/test_coverage_to_tsv_parsing.py
+++ b/tests/fctools/test_coverage_to_tsv_parsing.py
@@ -6,6 +6,7 @@
# pylint: disable=missing-function-docstring
import json
+from pathlib import Path
import pytest
from rich.console import Console
@@ -20,7 +21,7 @@
# Tests for _parse_duration_line()
-def test_parse_duration_line_valid():
+def test_parse_duration_line_valid() -> None:
line = "0.12s call tests/test_example.py::test_function"
result = _parse_duration_line(line)
assert result is not None
@@ -29,7 +30,7 @@ def test_parse_duration_line_valid():
assert duration == 0.12
-def test_parse_duration_line_with_setup():
+def test_parse_duration_line_with_setup() -> None:
line = "0.05s setup tests/test_example.py::test_function"
result = _parse_duration_line(line)
assert result is not None
@@ -38,7 +39,7 @@ def test_parse_duration_line_with_setup():
assert duration == 0.05
-def test_parse_duration_line_with_teardown():
+def test_parse_duration_line_with_teardown() -> None:
line = "0.03s teardown tests/test_example.py::test_function"
result = _parse_duration_line(line)
assert result is not None
@@ -47,7 +48,7 @@ def test_parse_duration_line_with_teardown():
assert duration == 0.03
-def test_parse_duration_line_integer_duration():
+def test_parse_duration_line_integer_duration() -> None:
line = "1s call tests/test_example.py::test_function"
result = _parse_duration_line(line)
assert result is not None
@@ -56,7 +57,7 @@ def test_parse_duration_line_integer_duration():
assert duration == 1.0
-def test_parse_duration_line_no_phase():
+def test_parse_duration_line_no_phase() -> None:
line = "0.25s tests/test_example.py::test_function"
result = _parse_duration_line(line)
assert result is not None
@@ -65,19 +66,19 @@ def test_parse_duration_line_no_phase():
assert duration == 0.25
-def test_parse_duration_line_invalid():
+def test_parse_duration_line_invalid() -> None:
line = "This is not a valid duration line"
result = _parse_duration_line(line)
assert result is None
-def test_parse_duration_line_no_duration():
+def test_parse_duration_line_no_duration() -> None:
line = "tests/test_example.py::test_function"
result = _parse_duration_line(line)
assert result is None
-def test_parse_duration_line_invalid_duration_format():
+def test_parse_duration_line_invalid_duration_format() -> None:
line = "abc call tests/test_example.py::test_function"
result = _parse_duration_line(line)
assert result is None
@@ -86,7 +87,7 @@ def test_parse_duration_line_invalid_duration_format():
# Tests for _load_text_durations()
-def test_load_text_durations(tmp_path):
+def test_load_text_durations(tmp_path: Path) -> None:
timing_file = tmp_path / "durations.txt"
timing_file.write_text(
"0.12s call tests/test_example.py::test_func1\n"
@@ -106,7 +107,7 @@ def test_load_text_durations(tmp_path):
assert result["tests/test_example.py::test_func2"] == pytest.approx(0.08)
-def test_load_text_durations_empty_file(tmp_path):
+def test_load_text_durations_empty_file(tmp_path: Path) -> None:
timing_file = tmp_path / "empty.txt"
timing_file.write_text("")
@@ -114,7 +115,7 @@ def test_load_text_durations_empty_file(tmp_path):
assert not result
-def test_load_text_durations_all_invalid(tmp_path):
+def test_load_text_durations_all_invalid(tmp_path: Path) -> None:
timing_file = tmp_path / "invalid.txt"
timing_file.write_text("Invalid line 1\nInvalid line 2\nInvalid line 3\n")
@@ -125,7 +126,7 @@ def test_load_text_durations_all_invalid(tmp_path):
# Tests for _load_json_timing()
-def test_load_json_timing(tmp_path):
+def test_load_json_timing(tmp_path: Path) -> None:
timing_file = tmp_path / "timing.json"
data = {
"tests": [
@@ -143,7 +144,7 @@ def test_load_json_timing(tmp_path):
assert result["tests/test_b.py::test_three"] == 0.3
-def test_load_json_timing_missing_fields(tmp_path):
+def test_load_json_timing_missing_fields(tmp_path: Path) -> None:
timing_file = tmp_path / "timing.json"
data = {
"tests": [
@@ -161,7 +162,7 @@ def test_load_json_timing_missing_fields(tmp_path):
assert result["tests/test_b.py::test_two"] == 0.0
-def test_load_json_timing_invalid_duration(tmp_path):
+def test_load_json_timing_invalid_duration(tmp_path: Path) -> None:
timing_file = tmp_path / "timing.json"
data = {
"tests": [
@@ -175,7 +176,7 @@ def test_load_json_timing_invalid_duration(tmp_path):
assert result["tests/test_a.py::test_one"] == 0.0
-def test_load_json_timing_no_tests_key(tmp_path):
+def test_load_json_timing_no_tests_key(tmp_path: Path) -> None:
timing_file = tmp_path / "timing.json"
data = {"summary": "some data", "other_field": []}
timing_file.write_text(json.dumps(data))
@@ -188,7 +189,7 @@ def test_load_json_timing_no_tests_key(tmp_path):
# Tests for parse_timing_data()
-def test_parse_timing_data_json_format(tmp_path):
+def test_parse_timing_data_json_format(tmp_path: Path) -> None:
console = Console()
timing_file = tmp_path / "timing.json"
data = {
@@ -203,7 +204,7 @@ def test_parse_timing_data_json_format(tmp_path):
assert result["tests/test_a.py::test_one"] == 0.5
-def test_parse_timing_data_text_format(tmp_path):
+def test_parse_timing_data_text_format(tmp_path: Path) -> None:
console = Console()
timing_file = tmp_path / "durations.txt"
timing_file.write_text("0.12s call tests/test_example.py::test_func\n")
@@ -213,20 +214,20 @@ def test_parse_timing_data_text_format(tmp_path):
assert result["tests/test_example.py::test_func"] == pytest.approx(0.12)
-def test_parse_timing_data_none():
+def test_parse_timing_data_none() -> None:
console = Console()
result = parse_timing_data(console, None)
assert not result
-def test_parse_timing_data_nonexistent_file(tmp_path):
+def test_parse_timing_data_nonexistent_file(tmp_path: Path) -> None:
console = Console()
timing_file = tmp_path / "nonexistent.json"
result = parse_timing_data(console, timing_file)
assert not result
-def test_parse_timing_data_json_decode_error_fallback(tmp_path):
+def test_parse_timing_data_json_decode_error_fallback(tmp_path: Path) -> None:
console = Console()
# File that's not valid JSON but has valid text durations
timing_file = tmp_path / "mixed.txt"
@@ -238,14 +239,18 @@ def test_parse_timing_data_json_decode_error_fallback(tmp_path):
assert result["tests/test_example.py::test_func"] == pytest.approx(0.15)
-def test_parse_timing_data_oserror_during_text_read(tmp_path, capsys, monkeypatch):
+def test_parse_timing_data_oserror_during_text_read(
+ tmp_path: Path,
+ capsys: pytest.CaptureFixture[str],
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
console = Console()
# Create a file that will cause JSON parse error
timing_file = tmp_path / "bad.txt"
timing_file.write_text("not json")
# Mock _load_text_durations to raise OSError
- def mock_load_text(*args, **kwargs):
+ def mock_load_text(path: Path) -> dict[str, float]:
raise OSError("Mocked error")
monkeypatch.setattr(
@@ -259,13 +264,17 @@ def mock_load_text(*args, **kwargs):
assert "Warning: Could not parse timing data" in captured.out
-def test_parse_timing_data_oserror_initial_read(tmp_path, capsys, monkeypatch):
+def test_parse_timing_data_oserror_initial_read(
+ tmp_path: Path,
+ capsys: pytest.CaptureFixture[str],
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
console = Console()
timing_file = tmp_path / "test.json"
timing_file.write_text("{}")
# Mock _load_json_timing to raise OSError
- def mock_load_json(*args, **kwargs):
+ def mock_load_json(path: Path) -> dict[str, float]:
raise OSError("Cannot read file")
monkeypatch.setattr(
diff --git a/tests/fctools/test_coverage_to_tsv_processing.py b/tests/fctools/test_coverage_to_tsv_processing.py
index 2edb17479..8095a9f2d 100644
--- a/tests/fctools/test_coverage_to_tsv_processing.py
+++ b/tests/fctools/test_coverage_to_tsv_processing.py
@@ -5,6 +5,8 @@
# pylint: disable=missing-function-docstring
+from typing import Any
+
import pytest
from firecrown.fctools.coverage_to_tsv import (
@@ -15,7 +17,7 @@
# Tests for match_test_to_function()
-def test_match_test_to_function_exact_name_match():
+def test_match_test_to_function_exact_name_match() -> None:
test_name = "tests/test_module.py::test_my_function"
function_name = "my_function"
file_path = "src/module.py"
@@ -26,7 +28,7 @@ def test_match_test_to_function_exact_name_match():
assert score >= 0.5
-def test_match_test_to_function_file_match():
+def test_match_test_to_function_file_match() -> None:
test_name = "tests/test_example.py::test_something"
function_name = "other_function"
file_path = "src/example.py"
@@ -37,7 +39,7 @@ def test_match_test_to_function_file_match():
assert score == pytest.approx(0.3)
-def test_match_test_to_function_full_match():
+def test_match_test_to_function_full_match() -> None:
test_name = "tests/test_utils.py::test_format_string"
function_name = "format_string"
file_path = "src/utils.py"
@@ -51,7 +53,7 @@ def test_match_test_to_function_full_match():
assert score == 1.0
-def test_match_test_to_function_no_match():
+def test_match_test_to_function_no_match() -> None:
test_name = "tests/test_other.py::test_something"
function_name = "unrelated_function"
file_path = "src/different.py"
@@ -61,7 +63,7 @@ def test_match_test_to_function_no_match():
assert score == 0.0
-def test_match_test_to_function_test_name_no_separator():
+def test_match_test_to_function_test_name_no_separator() -> None:
test_name = "tests/test_module.py"
function_name = "some_function"
file_path = "src/module.py"
@@ -76,7 +78,7 @@ def test_match_test_to_function_test_name_no_separator():
assert score >= 0.3
-def test_match_test_to_function_case_insensitive():
+def test_match_test_to_function_case_insensitive() -> None:
test_name = "tests/test_module.py::test_MyFunction"
function_name = "myfunction"
file_path = "src/other.py"
@@ -90,8 +92,8 @@ def test_match_test_to_function_case_insensitive():
# Tests for extract_coverage_data()
-def test_extract_coverage_data_basic():
- coverage_data = {
+def test_extract_coverage_data_basic() -> None:
+ coverage_data: dict[str, Any] = {
"files": {
"src/example.py": {
"summary": {
@@ -141,8 +143,8 @@ def test_extract_coverage_data_basic():
assert record.test_duration is None
-def test_extract_coverage_data_with_timing():
- coverage_data = {
+def test_extract_coverage_data_with_timing() -> None:
+ coverage_data: dict[str, Any] = {
"files": {
"src/utils.py": {
"summary": {
@@ -183,8 +185,8 @@ def test_extract_coverage_data_with_timing():
assert record.test_duration == 0.25
-def test_extract_coverage_data_timing_below_threshold():
- coverage_data = {
+def test_extract_coverage_data_timing_below_threshold() -> None:
+ coverage_data: dict[str, Any] = {
"files": {
"src/module.py": {
"summary": {
@@ -224,8 +226,8 @@ def test_extract_coverage_data_timing_below_threshold():
assert record.test_duration is None
-def test_extract_coverage_data_multiple_functions():
- coverage_data = {
+def test_extract_coverage_data_multiple_functions() -> None:
+ coverage_data: dict[str, Any] = {
"files": {
"src/module.py": {
"summary": {
@@ -274,8 +276,8 @@ def test_extract_coverage_data_multiple_functions():
assert func_names == {"func_a", "func_b"}
-def test_extract_coverage_data_no_functions():
- coverage_data = {
+def test_extract_coverage_data_no_functions() -> None:
+ coverage_data: dict[str, Any] = {
"files": {
"src/empty.py": {
"summary": {
@@ -292,16 +294,16 @@ def test_extract_coverage_data_no_functions():
assert len(result) == 0
-def test_extract_coverage_data_empty_files():
- coverage_data: dict[str, dict[str, object]] = {"files": {}}
+def test_extract_coverage_data_empty_files() -> None:
+ coverage_data: dict[str, Any] = {"files": {}}
result = extract_coverage_data(coverage_data)
assert len(result) == 0
-def test_extract_coverage_data_missing_summary_fields():
- coverage_data: dict[str, dict[str, object]] = {
+def test_extract_coverage_data_missing_summary_fields() -> None:
+ coverage_data: dict[str, Any] = {
"files": {
"src/partial.py": {
"summary": {}, # Missing all fields
diff --git a/tests/fctools/test_coverage_to_tsv_timing.py b/tests/fctools/test_coverage_to_tsv_timing.py
index c1002e44b..95b6703da 100644
--- a/tests/fctools/test_coverage_to_tsv_timing.py
+++ b/tests/fctools/test_coverage_to_tsv_timing.py
@@ -7,6 +7,7 @@
# pylint: disable=missing-function-docstring
import json
+from pathlib import Path
import pytest
from rich.console import Console
@@ -21,7 +22,7 @@
# Tests for _parse_duration_line()
-def test_parse_duration_line_valid():
+def test_parse_duration_line_valid() -> None:
line = "0.12s call tests/test_example.py::test_function"
result = _parse_duration_line(line)
assert result is not None
@@ -30,7 +31,7 @@ def test_parse_duration_line_valid():
assert duration == 0.12
-def test_parse_duration_line_with_setup():
+def test_parse_duration_line_with_setup() -> None:
line = "0.05s setup tests/test_example.py::test_function"
result = _parse_duration_line(line)
assert result is not None
@@ -39,7 +40,7 @@ def test_parse_duration_line_with_setup():
assert duration == 0.05
-def test_parse_duration_line_with_teardown():
+def test_parse_duration_line_with_teardown() -> None:
line = "0.03s teardown tests/test_example.py::test_function"
result = _parse_duration_line(line)
assert result is not None
@@ -48,7 +49,7 @@ def test_parse_duration_line_with_teardown():
assert duration == 0.03
-def test_parse_duration_line_integer_duration():
+def test_parse_duration_line_integer_duration() -> None:
line = "1s call tests/test_example.py::test_function"
result = _parse_duration_line(line)
assert result is not None
@@ -57,7 +58,7 @@ def test_parse_duration_line_integer_duration():
assert duration == 1.0
-def test_parse_duration_line_no_phase():
+def test_parse_duration_line_no_phase() -> None:
line = "0.25s tests/test_example.py::test_function"
result = _parse_duration_line(line)
assert result is not None
@@ -66,19 +67,19 @@ def test_parse_duration_line_no_phase():
assert duration == 0.25
-def test_parse_duration_line_invalid():
+def test_parse_duration_line_invalid() -> None:
line = "This is not a valid duration line"
result = _parse_duration_line(line)
assert result is None
-def test_parse_duration_line_no_duration():
+def test_parse_duration_line_no_duration() -> None:
line = "tests/test_example.py::test_function"
result = _parse_duration_line(line)
assert result is None
-def test_parse_duration_line_invalid_duration_format():
+def test_parse_duration_line_invalid_duration_format() -> None:
line = "abc call tests/test_example.py::test_function"
result = _parse_duration_line(line)
assert result is None
@@ -87,7 +88,7 @@ def test_parse_duration_line_invalid_duration_format():
# Tests for _load_text_durations()
-def test_load_text_durations(tmp_path):
+def test_load_text_durations(tmp_path: Path) -> None:
timing_file = tmp_path / "durations.txt"
timing_file.write_text(
"0.12s call tests/test_example.py::test_func1\n"
@@ -107,7 +108,7 @@ def test_load_text_durations(tmp_path):
assert result["tests/test_example.py::test_func2"] == pytest.approx(0.08)
-def test_load_text_durations_empty_file(tmp_path):
+def test_load_text_durations_empty_file(tmp_path: Path) -> None:
timing_file = tmp_path / "empty.txt"
timing_file.write_text("")
@@ -115,7 +116,7 @@ def test_load_text_durations_empty_file(tmp_path):
assert not result
-def test_load_text_durations_all_invalid(tmp_path):
+def test_load_text_durations_all_invalid(tmp_path: Path) -> None:
timing_file = tmp_path / "invalid.txt"
timing_file.write_text("Invalid line 1\nInvalid line 2\nInvalid line 3\n")
@@ -126,7 +127,7 @@ def test_load_text_durations_all_invalid(tmp_path):
# Tests for _load_json_timing()
-def test_load_json_timing(tmp_path):
+def test_load_json_timing(tmp_path: Path) -> None:
timing_file = tmp_path / "timing.json"
data = {
"tests": [
@@ -144,7 +145,7 @@ def test_load_json_timing(tmp_path):
assert result["tests/test_b.py::test_three"] == 0.3
-def test_load_json_timing_missing_fields(tmp_path):
+def test_load_json_timing_missing_fields(tmp_path: Path) -> None:
timing_file = tmp_path / "timing.json"
data = {
"tests": [
@@ -162,7 +163,7 @@ def test_load_json_timing_missing_fields(tmp_path):
assert result["tests/test_b.py::test_two"] == 0.0
-def test_load_json_timing_invalid_duration(tmp_path):
+def test_load_json_timing_invalid_duration(tmp_path: Path) -> None:
timing_file = tmp_path / "timing.json"
data = {
"tests": [
@@ -176,7 +177,7 @@ def test_load_json_timing_invalid_duration(tmp_path):
assert result["tests/test_a.py::test_one"] == 0.0
-def test_load_json_timing_no_tests_key(tmp_path):
+def test_load_json_timing_no_tests_key(tmp_path: Path) -> None:
timing_file = tmp_path / "timing.json"
data = {"summary": "some data", "other_field": []}
timing_file.write_text(json.dumps(data))
@@ -189,7 +190,7 @@ def test_load_json_timing_no_tests_key(tmp_path):
# Tests for parse_timing_data()
-def test_parse_timing_data_json_format(tmp_path):
+def test_parse_timing_data_json_format(tmp_path: Path) -> None:
console = Console()
timing_file = tmp_path / "timing.json"
data = {
@@ -204,7 +205,7 @@ def test_parse_timing_data_json_format(tmp_path):
assert result["tests/test_a.py::test_one"] == 0.5
-def test_parse_timing_data_text_format(tmp_path):
+def test_parse_timing_data_text_format(tmp_path: Path) -> None:
console = Console()
timing_file = tmp_path / "durations.txt"
timing_file.write_text("0.12s call tests/test_example.py::test_func\n")
@@ -214,20 +215,20 @@ def test_parse_timing_data_text_format(tmp_path):
assert result["tests/test_example.py::test_func"] == pytest.approx(0.12)
-def test_parse_timing_data_none():
+def test_parse_timing_data_none() -> None:
console = Console()
result = parse_timing_data(console, None)
assert not result
-def test_parse_timing_data_nonexistent_file(tmp_path):
+def test_parse_timing_data_nonexistent_file(tmp_path: Path) -> None:
console = Console()
timing_file = tmp_path / "nonexistent.json"
result = parse_timing_data(console, timing_file)
assert not result
-def test_parse_timing_data_json_decode_error_fallback(tmp_path):
+def test_parse_timing_data_json_decode_error_fallback(tmp_path: Path) -> None:
console = Console()
# File that's not valid JSON but has valid text durations
timing_file = tmp_path / "mixed.txt"
@@ -239,14 +240,18 @@ def test_parse_timing_data_json_decode_error_fallback(tmp_path):
assert result["tests/test_example.py::test_func"] == pytest.approx(0.15)
-def test_parse_timing_data_oserror_during_text_read(tmp_path, capsys, monkeypatch):
+def test_parse_timing_data_oserror_during_text_read(
+ tmp_path: Path,
+ capsys: pytest.CaptureFixture[str],
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
console = Console()
# Create a file that will cause JSON parse error
timing_file = tmp_path / "bad.txt"
timing_file.write_text("not json")
# Mock _load_text_durations to raise OSError
- def mock_load_text(*args, **kwargs):
+ def mock_load_text(path: Path) -> dict[str, float]:
raise OSError("Mocked error")
monkeypatch.setattr(
diff --git a/tests/fctools/test_generate_symbol_map.py b/tests/fctools/test_generate_symbol_map.py
index f8575bbda..09792b0a8 100644
--- a/tests/fctools/test_generate_symbol_map.py
+++ b/tests/fctools/test_generate_symbol_map.py
@@ -5,6 +5,7 @@
"""
import json
+from pathlib import Path
from types import ModuleType
import pytest
@@ -36,14 +37,14 @@ class MockExternalClass:
__module__ = "external.package"
-def mock_function():
+def mock_function() -> None:
"""Mock function for testing."""
mock_function.__module__ = "firecrown.mock.module"
-def test_is_private_name():
+def test_is_private_name() -> None:
"""Test that private names are detected."""
assert _is_private_name("_private")
assert _is_private_name("__dunder__")
@@ -51,23 +52,23 @@ def test_is_private_name():
assert not _is_private_name("MY_CONSTANT")
-def test_is_excluded_type_class():
+def test_is_excluded_type_class() -> None:
"""Test that classes are identified as excluded types."""
assert _is_excluded_type(MockFirecrownClass)
-def test_is_excluded_type_function():
+def test_is_excluded_type_function() -> None:
"""Test that functions are identified as excluded types."""
assert _is_excluded_type(mock_function)
-def test_is_excluded_type_module():
+def test_is_excluded_type_module() -> None:
"""Test that modules are identified as excluded types."""
mock_module = ModuleType("mock")
assert _is_excluded_type(mock_module)
-def test_is_excluded_type_instance():
+def test_is_excluded_type_instance() -> None:
"""Test that instances are not excluded types."""
instance = MockFirecrownClass()
assert not _is_excluded_type(instance)
@@ -75,7 +76,7 @@ def test_is_excluded_type_instance():
assert not _is_excluded_type("value")
-def test_has_constant_name_uppercase():
+def test_has_constant_name_uppercase() -> None:
"""Test that UPPER_CASE names are recognized."""
assert _has_constant_name("CONSTANT")
assert _has_constant_name("MY_CONSTANT")
@@ -84,7 +85,7 @@ def test_has_constant_name_uppercase():
assert _has_constant_name("FOUND4HELP")
-def test_has_constant_name_mixed_case():
+def test_has_constant_name_mixed_case() -> None:
"""Test that Mixed_Case names are NOT recognized.
The regex pattern requires all-uppercase constant names.
@@ -93,26 +94,26 @@ def test_has_constant_name_mixed_case():
assert not _has_constant_name("Some_Constant")
-def test_has_constant_name_lowercase():
+def test_has_constant_name_lowercase() -> None:
"""Test that lowercase names are not recognized."""
assert not _has_constant_name("lowercase")
assert not _has_constant_name("my_var")
assert not _has_constant_name("some_variable")
-def test_is_firecrown_instance_with_firecrown_class():
+def test_is_firecrown_instance_with_firecrown_class() -> None:
"""Test that instances of Firecrown classes are identified."""
instance = MockFirecrownClass()
assert _is_firecrown_instance(instance)
-def test_is_firecrown_instance_with_external_class():
+def test_is_firecrown_instance_with_external_class() -> None:
"""Test that instances of external classes are not identified."""
instance = MockExternalClass()
assert not _is_firecrown_instance(instance)
-def test_is_firecrown_instance_with_builtin():
+def test_is_firecrown_instance_with_builtin() -> None:
"""Test that builtin instances are not identified as Firecrown."""
assert not _is_firecrown_instance(42)
assert not _is_firecrown_instance("value")
@@ -120,36 +121,36 @@ def test_is_firecrown_instance_with_builtin():
assert not _is_firecrown_instance({"key": "value"})
-def test_is_api_constant_private_name():
+def test_is_api_constant_private_name() -> None:
"""Test that private names are rejected."""
assert not _is_api_constant("_private", "anything")
assert not _is_api_constant("__dunder__", "anything")
-def test_is_api_constant_class():
+def test_is_api_constant_class() -> None:
"""Test that classes are rejected (handled separately)."""
assert not _is_api_constant("SomeClass", MockFirecrownClass)
-def test_is_api_constant_function():
+def test_is_api_constant_function() -> None:
"""Test that functions are rejected (handled separately)."""
assert not _is_api_constant("some_function", mock_function)
-def test_is_api_constant_module():
+def test_is_api_constant_module() -> None:
"""Test that modules are rejected."""
mock_module = ModuleType("mock")
assert not _is_api_constant("some_module", mock_module)
-def test_is_api_constant_uppercase():
+def test_is_api_constant_uppercase() -> None:
"""Test that UPPER_CASE names are accepted."""
assert _is_api_constant("CONSTANT", 42)
assert _is_api_constant("MY_CONSTANT", "value")
assert _is_api_constant("API_KEY", [1, 2, 3])
-def test_is_api_constant_mixed_case_with_underscore():
+def test_is_api_constant_mixed_case_with_underscore() -> None:
"""Test that Mixed_Case_With_Underscores names are NOT accepted.
The regex pattern requires all-uppercase constant names.
@@ -161,25 +162,25 @@ def test_is_api_constant_mixed_case_with_underscore():
assert _is_api_constant("Y1_LENS_BINS", {"bin1": 0.1})
-def test_is_api_constant_lowercase():
+def test_is_api_constant_lowercase() -> None:
"""Test that lowercase names are rejected."""
assert not _is_api_constant("lowercase", "value")
assert not _is_api_constant("my_var", 123)
-def test_is_api_constant_firecrown_instance():
+def test_is_api_constant_firecrown_instance() -> None:
"""Test that instances of Firecrown classes are accepted."""
instance = MockFirecrownClass()
assert _is_api_constant("SomeInstance", instance)
-def test_is_api_constant_external_instance():
+def test_is_api_constant_external_instance() -> None:
"""Test that instances of external classes are rejected."""
instance = MockExternalClass()
assert not _is_api_constant("ExternalInstance", instance)
-def test_add_symbol_to_map_class():
+def test_add_symbol_to_map_class() -> None:
"""Test adding a class to the symbol map."""
symbols: dict[str, str] = {}
_add_symbol_to_map(
@@ -193,7 +194,7 @@ def test_add_symbol_to_map_class():
)
-def test_add_symbol_to_map_function():
+def test_add_symbol_to_map_function() -> None:
"""Test adding a function to the symbol map."""
symbols: dict[str, str] = {}
_add_symbol_to_map(symbols, "test.module", "test_func", mock_function, "firecrown")
@@ -205,7 +206,7 @@ def test_add_symbol_to_map_function():
)
-def test_add_symbol_to_map_re_exported_class():
+def test_add_symbol_to_map_re_exported_class() -> None:
"""Test that re-exported classes get both public and private paths."""
symbols: dict[str, str] = {}
@@ -221,7 +222,7 @@ def test_add_symbol_to_map_re_exported_class():
assert "firecrown.mock.module.MyClass" in symbols
-def test_add_symbol_to_map_external_class():
+def test_add_symbol_to_map_external_class() -> None:
"""Test that external classes are not added."""
symbols: dict[str, str] = {}
_add_symbol_to_map(
@@ -231,7 +232,7 @@ def test_add_symbol_to_map_external_class():
assert len(symbols) == 0
-def test_add_symbol_to_map_constant():
+def test_add_symbol_to_map_constant() -> None:
"""Test adding a constant to the symbol map."""
symbols: dict[str, str] = {}
my_constant = {"key": "value"}
@@ -243,7 +244,7 @@ def test_add_symbol_to_map_constant():
assert symbols["test.module.MY_CONSTANT"] == expected_url
-def test_add_symbol_to_map_mixed_case_constant():
+def test_add_symbol_to_map_mixed_case_constant() -> None:
"""Test adding a Mixed_Case constant to the symbol map."""
symbols: dict[str, str] = {}
bins = {"bin1": 0.1, "bin2": 0.2}
@@ -253,7 +254,7 @@ def test_add_symbol_to_map_mixed_case_constant():
assert "test.module.Y1_LENS_BINS" in symbols
-def test_add_symbol_to_map_firecrown_instance():
+def test_add_symbol_to_map_firecrown_instance() -> None:
"""Test adding a Firecrown class instance to the symbol map."""
symbols: dict[str, str] = {}
instance = MockFirecrownClass()
@@ -263,7 +264,7 @@ def test_add_symbol_to_map_firecrown_instance():
assert "test.module.INSTANCE" in symbols
-def test_add_symbol_to_map_lowercase_variable():
+def test_add_symbol_to_map_lowercase_variable() -> None:
"""Test that lowercase variables are not added."""
symbols: dict[str, str] = {}
_add_symbol_to_map(symbols, "test.module", "lowercase_var", 42, "firecrown")
@@ -271,7 +272,7 @@ def test_add_symbol_to_map_lowercase_variable():
assert len(symbols) == 0
-def test_add_symbol_to_map_private_constant():
+def test_add_symbol_to_map_private_constant() -> None:
"""Test that private constants are not added."""
symbols: dict[str, str] = {}
_add_symbol_to_map(symbols, "test.module", "_PRIVATE_CONST", 42, "firecrown")
@@ -279,7 +280,7 @@ def test_add_symbol_to_map_private_constant():
assert len(symbols) == 0
-def test_get_all_symbols_with_mock_package():
+def test_get_all_symbols_with_mock_package() -> None:
"""Test get_all_symbols with a mock package structure."""
# Create a minimal mock package
mock_package = ModuleType("mock_package")
@@ -290,20 +291,20 @@ def test_get_all_symbols_with_mock_package():
original_walk = pkgutil.walk_packages
- def mock_walk(*_args, **_kwargs):
+ def mock_walk(*_args: object, **_kwargs: object) -> list[tuple[object, str, bool]]:
return []
- pkgutil.walk_packages = mock_walk
+ setattr(pkgutil, "walk_packages", mock_walk)
try:
symbols = get_all_symbols(mock_package)
# Should at least handle the empty case without crashing
assert isinstance(symbols, dict)
finally:
- pkgutil.walk_packages = original_walk
+ setattr(pkgutil, "walk_packages", original_walk)
-def test_get_all_symbols_real_firecrown_subset():
+def test_get_all_symbols_real_firecrown_subset() -> None:
"""Test get_all_symbols with real firecrown.updatable module."""
import firecrown.updatable # pylint: disable=import-outside-toplevel
@@ -318,7 +319,7 @@ def test_get_all_symbols_real_firecrown_subset():
assert len(param_symbols) > 0
-def test_get_all_symbols_captures_classes():
+def test_get_all_symbols_captures_classes() -> None:
"""Test that get_all_symbols captures class definitions."""
import firecrown.updatable # pylint: disable=import-outside-toplevel
@@ -333,7 +334,7 @@ def test_get_all_symbols_captures_classes():
assert len(classes) > 0
-def test_get_all_symbols_captures_functions():
+def test_get_all_symbols_captures_functions() -> None:
"""Test that get_all_symbols captures function definitions."""
import firecrown.updatable # pylint: disable=import-outside-toplevel
@@ -343,7 +344,7 @@ def test_get_all_symbols_captures_functions():
assert len(symbols) > 0
-def test_get_all_symbols_excludes_private():
+def test_get_all_symbols_excludes_private() -> None:
"""Test that get_all_symbols excludes private members.
The function excludes members with names starting with underscore,
@@ -365,7 +366,7 @@ def test_get_all_symbols_excludes_private():
assert not after_derived.startswith("_"), f"Found private member: {sym}"
-def test_get_all_symbols_with_generators():
+def test_get_all_symbols_with_generators() -> None:
"""Test get_all_symbols captures constants from generators."""
import firecrown.generators # pylint: disable=import-outside-toplevel
@@ -397,7 +398,7 @@ def test_get_all_symbols_with_generators():
@pytest.mark.filterwarnings(
r"ignore:.*firecrown\.parameters module is deprecated.*:DeprecationWarning"
)
-def test_main_outputs_valid_json():
+def test_main_outputs_valid_json() -> None:
"""Test that main command outputs valid JSON to stdout."""
result = runner.invoke(app, [])
assert result.exit_code == 0
@@ -413,7 +414,7 @@ def test_main_outputs_valid_json():
assert any("firecrown" in key for key in data)
-def test_main_with_output_file(tmp_path):
+def test_main_with_output_file(tmp_path: Path) -> None:
"""Test main command with --output option writes to file."""
output_file = tmp_path / "symbols.json"
@@ -430,7 +431,7 @@ def test_main_with_output_file(tmp_path):
assert len(data) > 0
-def test_main_with_compact_format(tmp_path):
+def test_main_with_compact_format(tmp_path: Path) -> None:
"""Test --compact flag produces single-line JSON."""
output_file = tmp_path / "compact.json"
@@ -448,7 +449,7 @@ def test_main_with_compact_format(tmp_path):
assert len(data) > 0
-def test_main_default_is_pretty(tmp_path):
+def test_main_default_is_pretty(tmp_path: Path) -> None:
"""Test that default formatting is pretty (multi-line)."""
output_file = tmp_path / "pretty.json"
@@ -462,7 +463,7 @@ def test_main_default_is_pretty(tmp_path):
assert content.count("\n") > 10
-def test_main_symbol_count():
+def test_main_symbol_count() -> None:
"""Test that main command reports symbol count."""
result = runner.invoke(app, [])
assert result.exit_code == 0
@@ -475,7 +476,7 @@ def test_main_symbol_count():
assert symbol_count > 50
-def test_main_output_with_status_message(tmp_path):
+def test_main_output_with_status_message(tmp_path: Path) -> None:
"""Test that main command shows status message when writing to file."""
output_file = tmp_path / "symbols.json"
@@ -487,7 +488,7 @@ def test_main_output_with_status_message(tmp_path):
assert "symbols" in result.stderr
-def test_is_api_constant_with_non_firecrown_class():
+def test_is_api_constant_with_non_firecrown_class() -> None:
"""Test _is_api_constant with object that has class with non-firecrown module."""
# Create an object with a class that has __module__ but not from firecrown
obj = object() # object's __class__.__module__ is 'builtins'
@@ -498,7 +499,7 @@ def test_is_api_constant_with_non_firecrown_class():
assert result is False
-def test_is_api_constant_mixed_case_only_second_condition():
+def test_is_api_constant_mixed_case_only_second_condition() -> None:
"""Test _is_api_constant with various naming patterns.
The regex pattern now requires proper UPPER_CASE constant naming.
diff --git a/tests/fctools/test_link_checker.py b/tests/fctools/test_link_checker.py
index d3b64ad54..44d276bbf 100644
--- a/tests/fctools/test_link_checker.py
+++ b/tests/fctools/test_link_checker.py
@@ -10,7 +10,7 @@
import io
from contextlib import redirect_stdout
from pathlib import Path
-from typing import cast
+from typing import Callable, NoReturn, Protocol, cast
import pytest
import requests
@@ -21,6 +21,17 @@
from firecrown.fctools import link_checker
+class RateLimitedResponse(Protocol):
+ """Response members read by the link checker's HTTP 429 handling."""
+
+ status_code: int
+ reason: str
+
+ def raise_for_status(self) -> None:
+ """Raise for an unsuccessful response."""
+ ... # pylint: disable=unnecessary-ellipsis
+
+
@pytest.fixture(name="site_dir")
def fixture_site_dir(tmp_path: Path) -> Path:
"""Provide a temporary directory to be used as the site root for tests.
@@ -53,7 +64,9 @@ def fixture_sample_site(site_dir: Path) -> Path:
@pytest.fixture(name="mock_requests_ok")
-def fixture_mock_requests_ok(monkeypatch):
+def fixture_mock_requests_ok(
+ monkeypatch: pytest.MonkeyPatch,
+) -> Callable[..., object]:
"""Mock ``requests.Session.get``.
Mock to return a simple HTML page containing id 'extid'.
@@ -62,15 +75,20 @@ def fixture_mock_requests_ok(monkeypatch):
class FakeResp:
"""Fake response object for requests.get()."""
- def __init__(self, content: str):
+ def __init__(self, content: str) -> None:
"""Initialize with given content string."""
self.content = content.encode("utf-8")
- def raise_for_status(self):
+ def raise_for_status(self) -> None:
"""Simulate a successful response."""
return None
- def _fake_get(_self, _url, timeout=None, **_kwargs):
+ def _fake_get(
+ _self: requests.Session,
+ _url: str,
+ timeout: int | None = None,
+ **_kwargs: object,
+ ) -> FakeResp:
assert timeout is not None
return FakeResp('
')
@@ -78,18 +96,18 @@ def _fake_get(_self, _url, timeout=None, **_kwargs):
return _fake_get
-def make_429_response(_: str):
+def make_429_response(_: str) -> RateLimitedResponse:
"""Factory to create a mock response that raises HTTPError for 429."""
class Fake429Resp:
"""Fake response object for requests.get() that returns 429."""
- def __init__(self):
+ def __init__(self) -> None:
"""Create fake response."""
self.status_code = 429
self.reason = "Too Many Requests"
- def raise_for_status(self):
+ def raise_for_status(self) -> None:
"""Simulate HTTP 429 error."""
http_error = requests.HTTPError("429 Client Error: Too Many Requests")
# Test double: only status_code is read by the code under test.
@@ -99,7 +117,7 @@ def raise_for_status(self):
return Fake429Resp()
-def test_extract_ids_basic(site_dir: Path):
+def test_extract_ids_basic(site_dir: Path) -> None:
"""Test extraction of ids from a simple HTML file."""
html = site_dir / "page.html"
html.write_text(
@@ -115,7 +133,7 @@ def test_extract_ids_basic(site_dir: Path):
assert ids == {"one", "two"}
-def test_check_anchors_local_ok(site_dir: Path):
+def test_check_anchors_local_ok(site_dir: Path) -> None:
# target page with an id
b = site_dir / "b.html"
b.write_text("Section
")
@@ -140,7 +158,9 @@ def test_check_anchors_local_ok(site_dir: Path):
assert sc.invalid_anchors == 0
-def test_check_anchors_missing_anchor_returns_failure_and_main_exit(site_dir: Path):
+def test_check_anchors_missing_anchor_returns_failure_and_main_exit(
+ site_dir: Path,
+) -> None:
# target without the requested id
b = site_dir / "b.html"
b.write_text("Section
")
@@ -155,7 +175,11 @@ def test_check_anchors_missing_anchor_returns_failure_and_main_exit(site_dir: Pa
assert code != 0
-def test_main_uses_full_broken_link_output_in_ci(site_dir: Path, monkeypatch, capsys):
+def test_main_uses_full_broken_link_output_in_ci(
+ site_dir: Path,
+ monkeypatch: pytest.MonkeyPatch,
+ capsys: pytest.CaptureFixture[str],
+) -> None:
"""CI output should include complete source and target values."""
monkeypatch.setenv("CI", "true")
source = site_dir / "a-very-long-source-file-name.html"
@@ -174,7 +198,11 @@ def test_main_uses_full_broken_link_output_in_ci(site_dir: Path, monkeypatch, ca
assert "Reason: file missing" in captured.out
-def test_main_can_use_table_output_in_ci(site_dir: Path, monkeypatch, capsys):
+def test_main_can_use_table_output_in_ci(
+ site_dir: Path,
+ monkeypatch: pytest.MonkeyPatch,
+ capsys: pytest.CaptureFixture[str],
+) -> None:
"""The table output remains available when explicitly requested."""
monkeypatch.setenv("CI", "true")
(site_dir / "source.html").write_text('broken')
@@ -194,14 +222,16 @@ def test_main_can_use_table_output_in_ci(site_dir: Path, monkeypatch, capsys):
def test_skip_external_prevents_download_and_allows_success(
- site_dir: Path, monkeypatch
-):
+ site_dir: Path, monkeypatch: pytest.MonkeyPatch
+) -> None:
# source linking to an external URL with fragment
a = site_dir / "a.html"
a.write_text('ext')
# Simulate requests raising if called (network would fail)
- def _raise_get(self, url, timeout=None):
+ def _raise_get(
+ self: requests.Session, url: str, timeout: object = None
+ ) -> NoReturn:
raise requests.RequestException("no network in tests")
monkeypatch.setattr(requests.Session, "get", _raise_get)
@@ -242,7 +272,7 @@ def _raise_get(self, url, timeout=None):
)
def test_parametrized_link_scenarios(
sample_site: Path, fname: str, content: str, expected: int
-):
+) -> None:
(sample_site / fname).write_text(content)
code = link_checker.main(
sample_site, download_timeout=1, verbose=False, skip_external=True
@@ -250,7 +280,9 @@ def test_parametrized_link_scenarios(
assert code == expected
-def test_external_download_with_mock(sample_site: Path, mock_requests_ok):
+def test_external_download_with_mock(
+ sample_site: Path, mock_requests_ok: Callable[..., object]
+) -> None:
# external link to page with id extid; mocked response supplies that id
assert mock_requests_ok is not None # to avoid unused variable warning
(sample_site / "ext.html").write_text(
@@ -262,12 +294,14 @@ def test_external_download_with_mock(sample_site: Path, mock_requests_ok):
assert code == 0
-def test_external_download_fails_when_get_raises(sample_site: Path, monkeypatch):
+def test_external_download_fails_when_get_raises(
+ sample_site: Path, monkeypatch: pytest.MonkeyPatch
+) -> None:
(sample_site / "ext2.html").write_text(
'ext'
)
- def _raise(self, url, timeout=None):
+ def _raise(self: requests.Session, url: str, timeout: object = None) -> NoReturn:
raise requests.RequestException("simulated network error")
monkeypatch.setattr(requests.Session, "get", _raise)
@@ -277,7 +311,9 @@ def _raise(self, url, timeout=None):
assert code != 0
-def test_download_url_writes_file_when_ok(sample_site: Path, mock_requests_ok):
+def test_download_url_writes_file_when_ok(
+ sample_site: Path, mock_requests_ok: Callable[..., object]
+) -> None:
assert mock_requests_ok is not None # to avoid unused variable warning
console = Console(record=True)
sc = link_checker.SiteChecker(
@@ -306,14 +342,26 @@ def test_download_url_writes_file_when_ok(sample_site: Path, mock_requests_ok):
],
)
def test_download_url_handles_failure_and_returns_path(
- sample_site: Path, monkeypatch, exc_type, exc_msg, status_code
-):
+ sample_site: Path,
+ monkeypatch: pytest.MonkeyPatch,
+ exc_type: type[requests.RequestException],
+ exc_msg: str,
+ status_code: int | None,
+) -> None:
console = Console(record=True)
- def _raise(_self, _url, _timeout=None, **_kwargs):
+ def _raise(
+ _self: requests.Session,
+ _url: str,
+ _timeout: object = None,
+ **_kwargs: object,
+ ) -> NoReturn:
if status_code is not None:
exc = exc_type(exc_msg)
- exc.response = type("FakeResp", (), {"status_code": status_code})()
+ # Only status_code is read from this deliberately minimal response.
+ exc.response = cast(
+ Response, type("FakeResp", (), {"status_code": status_code})()
+ )
else:
exc = exc_type(exc_msg)
raise exc
@@ -339,11 +387,15 @@ def _raise(_self, _url, _timeout=None, **_kwargs):
sc.close()
-def test_download_url_records_429_error(sample_site: Path, monkeypatch):
+def test_download_url_records_429_error(
+ sample_site: Path, monkeypatch: pytest.MonkeyPatch
+) -> None:
"""Test that _download_url records 429 errors in rate_limited_urls dict."""
console = Console(record=True)
- def _raise_429(self, url, _=None, **_kwargs):
+ def _raise_429(
+ self: requests.Session, url: str, _: object = None, **_kwargs: object
+ ) -> RateLimitedResponse:
assert self is not None # to silence pylint
resp = make_429_response(url)
return resp
@@ -376,13 +428,17 @@ def _raise_429(self, url, _=None, **_kwargs):
sc.close()
-def test_rate_limited_links_dont_count_as_invalid(sample_site: Path, monkeypatch):
+def test_rate_limited_links_dont_count_as_invalid(
+ sample_site: Path, monkeypatch: pytest.MonkeyPatch
+) -> None:
"""Test that 429 rate-limited links don't increment invalid_links counter."""
(sample_site / "link.html").write_text(
'wiki'
)
- def _raise_429(self, url, _=None, **_kwargs):
+ def _raise_429(
+ self: requests.Session, url: str, _: object = None, **_kwargs: object
+ ) -> RateLimitedResponse:
assert self is not None # to silence pylint
resp = make_429_response(url)
return resp
@@ -410,13 +466,17 @@ def _raise_429(self, url, _=None, **_kwargs):
assert any("en.wikipedia.org" in u for u in sc.rate_limited_urls)
-def test_main_returns_zero_for_429_failures_only(site_dir: Path, monkeypatch):
+def test_main_returns_zero_for_429_failures_only(
+ site_dir: Path, monkeypatch: pytest.MonkeyPatch
+) -> None:
"""Test that main() returns 0 when only 429 failures occur (not broken links)."""
(site_dir / "link.html").write_text(
'wiki'
)
- def _raise_429(self, url, _=None, **_kwargs):
+ def _raise_429(
+ self: requests.Session, url: str, _: object = None, **_kwargs: object
+ ) -> RateLimitedResponse:
assert self is not None # to silence pylint
resp = make_429_response(url)
return resp
@@ -430,7 +490,9 @@ def _raise_429(self, url, _=None, **_kwargs):
assert code == 0
-def test_mixed_429_and_real_failure_uses_404_exit_code(site_dir: Path, monkeypatch):
+def test_mixed_429_and_real_failure_uses_404_exit_code(
+ site_dir: Path, monkeypatch: pytest.MonkeyPatch
+) -> None:
"""Test that a mix of 429 and real failures uses the real failure exit code."""
# Create a real broken link (missing file)
(site_dir / "link.html").write_text('broken')
@@ -439,7 +501,9 @@ def test_mixed_429_and_real_failure_uses_404_exit_code(site_dir: Path, monkeypat
'wiki'
)
- def _raise_or_404(self, url, _=None, **_kwargs):
+ def _raise_or_404(
+ self: requests.Session, url: str, _: object = None, **_kwargs: object
+ ) -> RateLimitedResponse | None:
assert self is not None # to silence pylint
if "en.wikipedia.org" in url:
resp = make_429_response(url)
@@ -456,13 +520,17 @@ def _raise_or_404(self, url, _=None, **_kwargs):
assert code != 0
-def test_rate_limited_urls_appear_in_report(sample_site: Path, monkeypatch):
+def test_rate_limited_urls_appear_in_report(
+ sample_site: Path, monkeypatch: pytest.MonkeyPatch
+) -> None:
"""Test that rate-limited URLs appear in verbose output."""
(sample_site / "link.html").write_text(
'wiki'
)
- def _raise_429(self, url, _=None, **_kwargs):
+ def _raise_429(
+ self: requests.Session, url: str, _: object = None, **_kwargs: object
+ ) -> RateLimitedResponse:
assert self is not None # to silence pylint
resp = make_429_response(url)
return resp
@@ -486,7 +554,9 @@ def _raise_429(self, url, _=None, **_kwargs):
assert "wikipedia" in out.lower()
-def test_429_responses_are_cached_like_other_failures(sample_site: Path, monkeypatch):
+def test_429_responses_are_cached_like_other_failures(
+ sample_site: Path, monkeypatch: pytest.MonkeyPatch
+) -> None:
"""Test that 429 responses get cached like other failed downloads."""
(sample_site / "link.html").write_text(
'wiki'
@@ -494,7 +564,9 @@ def test_429_responses_are_cached_like_other_failures(sample_site: Path, monkeyp
call_count = 0
- def _raise_429_count(self, url, _=None, **_kwargs):
+ def _raise_429_count(
+ self: requests.Session, url: str, _: object = None, **_kwargs: object
+ ) -> RateLimitedResponse:
assert self is not None # to silence pylint
nonlocal call_count
call_count += 1
@@ -528,7 +600,7 @@ def _raise_429_count(self, url, _=None, **_kwargs):
assert "http://en.wikipedia.org/wiki/Abstract_type" in sc.downloaded_files
-def test_normalize_fragment_only(sample_site: Path):
+def test_normalize_fragment_only(sample_site: Path) -> None:
console = Console()
sc = link_checker.SiteChecker(
sample_site,
@@ -549,7 +621,7 @@ def test_normalize_fragment_only(sample_site: Path):
sc.close()
-def test_missing_file_reports_file_missing(sample_site: Path):
+def test_missing_file_reports_file_missing(sample_site: Path) -> None:
# source linking to a missing file
(sample_site / "src.html").write_text('bad')
console = Console()
@@ -569,13 +641,17 @@ def test_missing_file_reports_file_missing(sample_site: Path):
assert any(r == "file missing" for _, _, r in missing)
-def test_unreachable_external_is_reported(sample_site: Path, monkeypatch):
+def test_unreachable_external_is_reported(
+ sample_site: Path, monkeypatch: pytest.MonkeyPatch
+) -> None:
# external link with download failing
(sample_site / "ext3.html").write_text(
'ext'
)
- def _raise(self, url, timeout=None, **_kwargs):
+ def _raise(
+ self: requests.Session, url: str, timeout: object = None, **_kwargs: object
+ ) -> NoReturn:
raise requests.RequestException("boom")
monkeypatch.setattr(requests.Session, "get", _raise)
@@ -598,7 +674,7 @@ def _raise(self, url, timeout=None, **_kwargs):
assert any(r == "unreachable link" for _, _, r in missing)
-def test_ignore_non_html_files(sample_site: Path):
+def test_ignore_non_html_files(sample_site: Path) -> None:
# create a non-HTML file with a link
(sample_site / "file.txt").write_text('ok')
@@ -624,8 +700,8 @@ def test_ignore_non_html_files(sample_site: Path):
def test_downloading_same_url_multiple_times_uses_cache(
- sample_site: Path, mock_requests_ok
-):
+ sample_site: Path, mock_requests_ok: Callable[..., object]
+) -> None:
assert mock_requests_ok is not None # to avoid unused variable warning
console = Console(record=True)
sc = link_checker.SiteChecker(
@@ -654,8 +730,8 @@ def test_downloading_same_url_multiple_times_uses_cache(
def test_normalize_href_with_url_multiple_times_uses_cache(
- sample_site: Path, mock_requests_ok
-):
+ sample_site: Path, mock_requests_ok: Callable[..., object]
+) -> None:
assert mock_requests_ok is not None # to avoid unused variable warning
console = Console(record=True)
sc = link_checker.SiteChecker(
@@ -685,7 +761,9 @@ def test_normalize_href_with_url_multiple_times_uses_cache(
sc.close()
-def test_page_with_id_with_no_value(sample_site: Path, mock_requests_ok):
+def test_page_with_id_with_no_value(
+ sample_site: Path, mock_requests_ok: Callable[..., object]
+) -> None:
assert mock_requests_ok is not None # to avoid unused variable warning
# Create a page with an element that has an id attribute with no value
(sample_site / "idless.html").write_text("")
@@ -711,7 +789,9 @@ def test_page_with_id_with_no_value(sample_site: Path, mock_requests_ok):
assert sc.invalid_anchors == 0
-def test_page_with_name_with_no_value(sample_site: Path, mock_requests_ok):
+def test_page_with_name_with_no_value(
+ sample_site: Path, mock_requests_ok: Callable[..., object]
+) -> None:
assert mock_requests_ok is not None # to avoid unused variable warning
# Create a page with an element that has a name attribute with no value
(sample_site / "nameless.html").write_text("")
@@ -737,7 +817,9 @@ def test_page_with_name_with_no_value(sample_site: Path, mock_requests_ok):
assert sc.invalid_anchors == 0
-def test_page_with_href_with_no_value(sample_site: Path, mock_requests_ok):
+def test_page_with_href_with_no_value(
+ sample_site: Path, mock_requests_ok: Callable[..., object]
+) -> None:
assert mock_requests_ok is not None # to avoid unused variable warning
# Create a page with a link that has an href attribute with no value
(sample_site / "hrefless.html").write_text("")
@@ -763,7 +845,9 @@ def test_page_with_href_with_no_value(sample_site: Path, mock_requests_ok):
assert sc.invalid_anchors == 0
-def test_skipping_external_links_verbose_output(sample_site: Path, mock_requests_ok):
+def test_skipping_external_links_verbose_output(
+ sample_site: Path, mock_requests_ok: Callable[..., object]
+) -> None:
assert mock_requests_ok is not None # to avoid unused variable warning
# Create a page with an external link
(sample_site / "external.html").write_text(
@@ -790,7 +874,9 @@ def test_skipping_external_links_verbose_output(sample_site: Path, mock_requests
assert "Skipping external link" in out
-def test_page_with_multiple_ids(sample_site: Path, mock_requests_ok):
+def test_page_with_multiple_ids(
+ sample_site: Path, mock_requests_ok: Callable[..., object]
+) -> None:
assert mock_requests_ok is not None # to avoid unused variable warning
# Create a page with multiple elements having ids
(sample_site / "multiid.html").write_text(
@@ -824,8 +910,8 @@ def test_page_with_multiple_ids(sample_site: Path, mock_requests_ok):
def test_page_with_links_with_same_url_and_different_fragments(
- sample_site: Path, mock_requests_ok
-):
+ sample_site: Path, mock_requests_ok: Callable[..., object]
+) -> None:
assert mock_requests_ok is not None # to avoid unused variable warning
# Create a page with multiple links to the same URL but different fragments
(sample_site / "links.html").write_text(
@@ -861,8 +947,8 @@ def test_page_with_links_with_same_url_and_different_fragments(
def test_link_without_fragment_is_handled_correctly(
- sample_site: Path, mock_requests_ok
-):
+ sample_site: Path, mock_requests_ok: Callable[..., object]
+) -> None:
assert mock_requests_ok is not None # to avoid unused variable warning
# Create a page with a link without a fragment
(sample_site / "nolinkfrag.html").write_text(
@@ -890,7 +976,9 @@ def test_link_without_fragment_is_handled_correctly(
assert sc.invalid_anchors == 0
-def test_cli_runner_exit_codes(sample_site: Path, mock_requests_ok):
+def test_cli_runner_exit_codes(
+ sample_site: Path, mock_requests_ok: Callable[..., object]
+) -> None:
assert mock_requests_ok is not None # to avoid unused variable warning
runner = CliRunner()
diff --git a/tests/fctools/test_list_tools.py b/tests/fctools/test_list_tools.py
index 937dca51d..3134d5057 100644
--- a/tests/fctools/test_list_tools.py
+++ b/tests/fctools/test_list_tools.py
@@ -6,7 +6,9 @@
import subprocess
import sys
from pathlib import Path
+from typing import NoReturn
+import pytest
from typer.testing import CliRunner
from firecrown.fctools.list_tools import (
@@ -22,7 +24,7 @@
class TestExtractDescriptionFromDocstring:
"""Tests for _extract_description_from_docstring function."""
- def test_extract_from_simple_docstring(self):
+ def test_extract_from_simple_docstring(self) -> None:
"""Test extracting description from a simple docstring."""
docstring = "This is a simple tool."
@@ -30,7 +32,7 @@ def test_extract_from_simple_docstring(self):
assert result == "This is a simple tool."
- def test_extract_from_multiline_docstring(self):
+ def test_extract_from_multiline_docstring(self) -> None:
"""Test extracting first line from multiline docstring."""
docstring = """This is the first line.
@@ -41,7 +43,7 @@ def test_extract_from_multiline_docstring(self):
assert result == "This is the first line."
- def test_extract_with_triple_quotes(self):
+ def test_extract_with_triple_quotes(self) -> None:
"""Test handling docstring with triple quotes in text.
The function filters out lines that start with triple quotes,
@@ -54,7 +56,7 @@ def test_extract_with_triple_quotes(self):
# Lines starting with """ are filtered out
assert result == "Tool description not available"
- def test_extract_from_empty_docstring(self):
+ def test_extract_from_empty_docstring(self) -> None:
"""Test handling empty docstring."""
docstring = ""
@@ -62,7 +64,7 @@ def test_extract_from_empty_docstring(self):
assert result == "Tool description not available"
- def test_extract_from_whitespace_only(self):
+ def test_extract_from_whitespace_only(self) -> None:
"""Test handling whitespace-only docstring."""
docstring = " \n \n "
@@ -70,7 +72,7 @@ def test_extract_from_whitespace_only(self):
assert result == "Tool description not available"
- def test_extract_skips_empty_lines(self):
+ def test_extract_skips_empty_lines(self) -> None:
"""Test that empty lines are skipped."""
docstring = """
@@ -81,7 +83,7 @@ def test_extract_skips_empty_lines(self):
assert result == "This is the description."
- def test_extract_with_single_quotes(self):
+ def test_extract_with_single_quotes(self) -> None:
"""Test handling docstring with single triple quotes in text.
The function filters out lines that start with triple quotes,
@@ -98,7 +100,7 @@ def test_extract_with_single_quotes(self):
class TestExtractDescriptionFromFile: # pylint: disable=import-outside-toplevel
"""Tests for _extract_description_from_file function."""
- def test_extract_from_valid_python_file(self, tmp_path):
+ def test_extract_from_valid_python_file(self, tmp_path: Path) -> None:
"""Test extracting description from a valid Python file."""
test_file = tmp_path / "test_tool.py"
test_file.write_text(
@@ -109,7 +111,7 @@ def test_extract_from_valid_python_file(self, tmp_path):
assert "test tool" in result.lower()
- def test_extract_from_file_with_multiline_docstring(self, tmp_path):
+ def test_extract_from_file_with_multiline_docstring(self, tmp_path: Path) -> None:
"""Test extracting from file with multiline docstring."""
test_file = tmp_path / "tool.py"
test_file.write_text(
@@ -120,7 +122,7 @@ def test_extract_from_file_with_multiline_docstring(self, tmp_path):
assert "First line is important" in result
- def test_extract_from_file_without_docstring(self, tmp_path):
+ def test_extract_from_file_without_docstring(self, tmp_path: Path) -> None:
"""Test handling file without module docstring."""
test_file = tmp_path / "no_doc.py"
test_file.write_text("def main():\n pass\n")
@@ -129,7 +131,7 @@ def test_extract_from_file_without_docstring(self, tmp_path):
assert result == "Tool description not available"
- def test_extract_from_nonexistent_file(self, tmp_path):
+ def test_extract_from_nonexistent_file(self, tmp_path: Path) -> None:
"""Test handling nonexistent file."""
fake_file = tmp_path / "nonexistent_tool.py"
# Don't create the file, just use the path
@@ -138,7 +140,7 @@ def test_extract_from_nonexistent_file(self, tmp_path):
assert result == "Tool description not available"
- def test_extract_from_file_with_syntax_error(self, tmp_path):
+ def test_extract_from_file_with_syntax_error(self, tmp_path: Path) -> None:
"""Test handling file with syntax errors.
AST parsing will fail on syntax errors, falling back to the
@@ -152,7 +154,7 @@ def test_extract_from_file_with_syntax_error(self, tmp_path):
# Syntax error in the code causes AST parsing to fail
assert result == "Tool description not available"
- def test_extract_from_file_with_invalid_unicode(self, tmp_path):
+ def test_extract_from_file_with_invalid_unicode(self, tmp_path: Path) -> None:
"""Test handling file with encoding errors."""
test_file = tmp_path / "bad_encoding.py"
test_file.write_bytes(b"\xff\xfe\x00\x00")
@@ -161,7 +163,7 @@ def test_extract_from_file_with_invalid_unicode(self, tmp_path):
assert result == "Tool description not available"
- def test_extract_with_long_docstring(self, tmp_path):
+ def test_extract_with_long_docstring(self, tmp_path: Path) -> None:
"""Test that long docstrings are truncated."""
long_desc = "A" * 200 # Longer than 80 chars
test_file = tmp_path / "long_doc.py"
@@ -172,14 +174,16 @@ def test_extract_with_long_docstring(self, tmp_path):
# Should be truncated to around 80 chars
assert len(result) <= 85 # Allow some margin for ellipsis
- def test_extract_fallback_to_import(self, tmp_path, monkeypatch):
+ def test_extract_fallback_to_import(
+ self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
+ ) -> None:
"""Test fallback to importlib when AST fails."""
# Create a file with a valid docstring
test_file = tmp_path / "import_test.py"
test_file.write_text('"""Fallback test tool."""\nx = 1\n')
# Mock get_module_docstring to raise OSError to trigger fallback
- def mock_get_module_docstring(path):
+ def mock_get_module_docstring(path: Path) -> NoReturn:
raise OSError("Simulated error")
import firecrown.fctools.list_tools as list_tools_module
@@ -193,14 +197,16 @@ def mock_get_module_docstring(path):
# Should get description via importlib fallback
assert "Fallback test tool" in result
- def test_extract_fallback_with_no_spec_loader(self, tmp_path, monkeypatch):
+ def test_extract_fallback_with_no_spec_loader(
+ self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
+ ) -> None:
"""Test fallback when spec.loader is None."""
test_file = tmp_path / "no_loader.py"
test_file.write_text('"""Test."""\n')
# Mock to return a spec without loader
# pylint: disable=unused-argument
- def mock_spec_from_file_location(name, location):
+ def mock_spec_from_file_location(name: str, location: str) -> object:
class FakeSpec:
"""Mock spec without loader."""
@@ -215,7 +221,7 @@ class FakeSpec:
)
# Also mock get_module_docstring to fail
- def mock_get_module_docstring(path):
+ def mock_get_module_docstring(path: Path) -> NoReturn:
raise OSError("Simulated error")
import firecrown.fctools.list_tools as list_tools_module
@@ -229,14 +235,16 @@ def mock_get_module_docstring(path):
# Should return fallback since spec.loader is None
assert result == "Tool description not available"
- def test_extract_fallback_with_empty_docstring(self, tmp_path, monkeypatch):
+ def test_extract_fallback_with_empty_docstring(
+ self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
+ ) -> None:
"""Test fallback when module has no docstring."""
# Create a file without a docstring
test_file = tmp_path / "no_doc_fallback.py"
test_file.write_text("x = 1\n")
# Mock get_module_docstring to raise OSError to trigger fallback
- def mock_get_module_docstring(path):
+ def mock_get_module_docstring(path: Path) -> NoReturn:
raise OSError("Simulated error")
import firecrown.fctools.list_tools as list_tools_module
@@ -254,7 +262,7 @@ def mock_get_module_docstring(path):
class TestDiscoverTools: # pylint: disable=import-outside-toplevel
"""Tests for _discover_tools function."""
- def test_discover_finds_tools(self):
+ def test_discover_finds_tools(self) -> None:
"""Test that tool discovery finds real fctools."""
tools = _discover_tools()
@@ -265,19 +273,21 @@ def test_discover_finds_tools(self):
assert all(isinstance(k, str) for k in tools)
assert all(isinstance(v, str) for v in tools.values())
- def test_discover_excludes_init(self):
+ def test_discover_excludes_init(self) -> None:
"""Test that __init__.py is excluded from tools."""
tools = _discover_tools()
assert "__init__.py" not in tools
- def test_discover_excludes_list_tools(self):
+ def test_discover_excludes_list_tools(self) -> None:
"""Test that list_tools.py excludes itself."""
tools = _discover_tools()
assert "list_tools.py" not in tools
- def test_discover_excludes_private_files(self, tmp_path, monkeypatch):
+ def test_discover_excludes_private_files(
+ self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
+ ) -> None:
"""Test that files starting with _ are excluded."""
# First check the real discover_tools
tools = _discover_tools()
@@ -314,7 +324,7 @@ def test_discover_excludes_private_files(self, tmp_path, monkeypatch):
# Restore original
monkeypatch.setattr(list_tools_module, "__file__", original_file)
- def test_discover_returns_descriptions(self):
+ def test_discover_returns_descriptions(self) -> None:
"""Test that discovered tools have descriptions."""
tools = _discover_tools()
@@ -323,7 +333,7 @@ def test_discover_returns_descriptions(self):
assert description
assert len(description) > 0
- def test_discover_finds_specific_tools(self):
+ def test_discover_finds_specific_tools(self) -> None:
"""Test that known tools are discovered."""
tools = _discover_tools()
@@ -337,7 +347,7 @@ def test_discover_finds_specific_tools(self):
class TestMainFunction: # pylint: disable=import-outside-toplevel
"""Tests for main CLI function."""
- def test_main_basic_output(self):
+ def test_main_basic_output(self) -> None:
"""Test main function produces output."""
runner = CliRunner()
result = runner.invoke(app, [])
@@ -345,7 +355,7 @@ def test_main_basic_output(self):
assert result.exit_code == 0
assert match_wrapped(result.stdout, "Available fctools:")
- def test_main_lists_tools(self):
+ def test_main_lists_tools(self) -> None:
"""Test that main lists actual tools."""
runner = CliRunner()
result = runner.invoke(app, [])
@@ -355,7 +365,7 @@ def test_main_lists_tools(self):
assert match_wrapped(result.stdout, "common.py")
assert match_wrapped(result.stdout, "ast_utils.py")
- def test_main_verbose_flag(self):
+ def test_main_verbose_flag(self) -> None:
"""Test main with --verbose flag."""
runner = CliRunner()
result = runner.invoke(app, ["--verbose"])
@@ -364,7 +374,7 @@ def test_main_verbose_flag(self):
assert match_wrapped(result.stdout, "Available fctools:")
assert match_wrapped(result.stdout, "Usage: python -m firecrown.fctools.")
- def test_main_short_verbose_flag(self):
+ def test_main_short_verbose_flag(self) -> None:
"""Test main with -v flag."""
runner = CliRunner()
result = runner.invoke(app, ["-v"])
@@ -372,7 +382,7 @@ def test_main_short_verbose_flag(self):
assert result.exit_code == 0
assert match_wrapped(result.stdout, "Usage: python -m firecrown.fctools.")
- def test_main_non_verbose_has_help_text(self):
+ def test_main_non_verbose_has_help_text(self) -> None:
"""Test that non-verbose mode shows help text."""
runner = CliRunner()
result = runner.invoke(app, [])
@@ -383,7 +393,7 @@ def test_main_non_verbose_has_help_text(self):
result.stdout, "Use 'python -m firecrown.fctools.TOOL --help'"
)
- def test_main_verbose_shows_tool_details(self):
+ def test_main_verbose_shows_tool_details(self) -> None:
"""Test that verbose mode shows more details."""
runner = CliRunner()
result = runner.invoke(app, ["--verbose"])
@@ -395,7 +405,7 @@ def test_main_verbose_shows_tool_details(self):
has_usage_line = any("Usage: python -m" in line for line in lines)
assert has_usage_line
- def test_main_tools_are_sorted(self):
+ def test_main_tools_are_sorted(self) -> None:
"""Test that tools are listed in alphabetical order."""
runner = CliRunner()
result = runner.invoke(app, [])
@@ -419,7 +429,7 @@ def test_main_tools_are_sorted(self):
if len(tool_names) > 1:
assert tool_names == sorted(tool_names)
- def test_main_with_subprocess(self):
+ def test_main_with_subprocess(self) -> None:
"""Test that the script can be executed directly via subprocess.
This test verifies that the __main__ block and ImportError fallback
@@ -438,7 +448,7 @@ def test_main_with_subprocess(self):
assert match_wrapped(result.stdout, "Available fctools:")
assert "common.py" in result.stdout
- def test_main_subprocess_with_verbose(self):
+ def test_main_subprocess_with_verbose(self) -> None:
"""Test script execution with verbose flag via subprocess."""
script_path = "firecrown/fctools/list_tools.py"
result = subprocess.run(
@@ -456,7 +466,7 @@ def test_main_subprocess_with_verbose(self):
class TestIntegration: # pylint: disable=import-outside-toplevel
"""Integration tests for list_tools functionality."""
- def test_full_workflow(self):
+ def test_full_workflow(self) -> None:
"""Test the complete workflow of discovering and listing tools."""
# Discover tools
tools = _discover_tools()
@@ -475,7 +485,7 @@ def test_full_workflow(self):
tool_path.suffix == ".py"
), f"Tool {tool_name} should be a Python file"
- def test_all_tools_have_valid_descriptions(self):
+ def test_all_tools_have_valid_descriptions(self) -> None:
"""Test that all discovered tools have meaningful descriptions."""
tools = _discover_tools()
@@ -485,7 +495,7 @@ def test_all_tools_have_valid_descriptions(self):
assert isinstance(description, str)
assert len(description) > 0
- def test_cli_output_matches_discovery(self):
+ def test_cli_output_matches_discovery(self) -> None:
"""Test that CLI output matches tool discovery results."""
tools = _discover_tools()
diff --git a/tests/fctools/test_match_wrapped.py b/tests/fctools/test_match_wrapped.py
index dab0e4f66..9666acd1f 100644
--- a/tests/fctools/test_match_wrapped.py
+++ b/tests/fctools/test_match_wrapped.py
@@ -3,7 +3,7 @@
from . import match_wrapped
-def test_match_wrapped():
+def test_match_wrapped() -> None:
text = (
"Reading coverage data from \n"
"/tmp/pytest-of-runner/pytest-0/popen-gw0/"
diff --git a/tests/fctools/test_measurement_compatibility.py b/tests/fctools/test_measurement_compatibility.py
index b6ed8d237..63d5fb5f3 100644
--- a/tests/fctools/test_measurement_compatibility.py
+++ b/tests/fctools/test_measurement_compatibility.py
@@ -6,6 +6,7 @@
import subprocess
import sys
+import pytest
from rich.console import Console
from firecrown.fctools.measurement_compatibility import (
@@ -31,7 +32,7 @@
class TestDiscoverMeasurementsBySpace:
"""Tests for discover_measurements_by_space function."""
- def test_discovers_measurements(self):
+ def test_discovers_measurements(self) -> None:
"""Test that measurements are discovered correctly."""
real_measurements, harmonic_measurements = discover_measurements_by_space()
@@ -43,7 +44,7 @@ def test_discovers_measurements(self):
assert all(isinstance(m, Measurement) for m in real_measurements)
assert all(isinstance(m, Measurement) for m in harmonic_measurements)
- def test_real_measurements_support_real_space(self):
+ def test_real_measurements_support_real_space(self) -> None:
"""Test that all real measurements support real space."""
real_measurements, _ = discover_measurements_by_space()
@@ -51,7 +52,7 @@ def test_real_measurements_support_real_space(self):
for m in real_measurements:
assert measurement_supports_real(m), f"{m} should support real space"
- def test_harmonic_measurements_support_harmonic_space(self):
+ def test_harmonic_measurements_support_harmonic_space(self) -> None:
"""Test that all harmonic measurements support harmonic space."""
_, harmonic_measurements = discover_measurements_by_space()
@@ -61,7 +62,7 @@ def test_harmonic_measurements_support_harmonic_space(self):
m
), f"{m} should support harmonic space"
- def test_measurements_are_subset_of_all(self):
+ def test_measurements_are_subset_of_all(self) -> None:
"""Test that discovered measurements are subsets of ALL_MEASUREMENTS."""
real_measurements, harmonic_measurements = discover_measurements_by_space()
@@ -69,7 +70,7 @@ def test_measurements_are_subset_of_all(self):
assert set(real_measurements).issubset(set(ALL_MEASUREMENTS))
assert set(harmonic_measurements).issubset(set(ALL_MEASUREMENTS))
- def test_discovers_nonempty_lists(self):
+ def test_discovers_nonempty_lists(self) -> None:
"""Test that at least some measurements are discovered."""
real_measurements, harmonic_measurements = discover_measurements_by_space()
@@ -81,7 +82,7 @@ def test_discovers_nonempty_lists(self):
class TestGenerateCompatiblePairs:
"""Tests for generate_compatible_pairs function."""
- def test_generates_pairs_for_real_space(self):
+ def test_generates_pairs_for_real_space(self) -> None:
"""Test generating compatible pairs for real space."""
real_measurements, _ = discover_measurements_by_space()
@@ -94,7 +95,7 @@ def test_generates_pairs_for_real_space(self):
assert all(isinstance(p, tuple) for p in pairs)
assert all(len(p) == 2 for p in pairs)
- def test_generates_pairs_for_harmonic_space(self):
+ def test_generates_pairs_for_harmonic_space(self) -> None:
"""Test generating compatible pairs for harmonic space."""
_, harmonic_measurements = discover_measurements_by_space()
@@ -107,7 +108,7 @@ def test_generates_pairs_for_harmonic_space(self):
assert all(isinstance(p, tuple) for p in pairs)
assert all(len(p) == 2 for p in pairs)
- def test_all_pairs_are_compatible(self):
+ def test_all_pairs_are_compatible(self) -> None:
"""Test that all generated pairs are actually compatible."""
real_measurements, _ = discover_measurements_by_space()
@@ -121,7 +122,7 @@ def test_all_pairs_are_compatible(self):
m1, m2
), f"{m1} and {m2} should be compatible"
- def test_pairs_are_from_input_measurements(self):
+ def test_pairs_are_from_input_measurements(self) -> None:
"""Test that pairs contain only measurements from input list."""
real_measurements, _ = discover_measurements_by_space()
@@ -134,13 +135,13 @@ def test_pairs_are_from_input_measurements(self):
assert m1 in real_measurements
assert m2 in real_measurements
- def test_empty_input_returns_empty_pairs(self):
+ def test_empty_input_returns_empty_pairs(self) -> None:
"""Test that empty measurement list returns empty pairs."""
pairs = generate_compatible_pairs([], measurement_is_compatible_real)
assert pairs == []
- def test_single_measurement_returns_compatible_pairs(self):
+ def test_single_measurement_returns_compatible_pairs(self) -> None:
"""Test behavior with a single measurement."""
# Get one measurement
real_measurements, _ = discover_measurements_by_space()
@@ -160,7 +161,9 @@ def test_single_measurement_returns_compatible_pairs(self):
class TestPrintMeasurementsBySpace:
"""Tests for print_measurements_by_space function."""
- def test_prints_counts_non_verbose(self, capsys):
+ def test_prints_counts_non_verbose(
+ self, capsys: pytest.CaptureFixture[str]
+ ) -> None:
"""Test printing measurement counts in non-verbose mode."""
console = Console()
real_measurements, harmonic_measurements = discover_measurements_by_space()
@@ -175,7 +178,7 @@ def test_prints_counts_non_verbose(self, capsys):
assert match_wrapped(captured.out, str(len(real_measurements)))
assert match_wrapped(captured.out, str(len(harmonic_measurements)))
- def test_prints_details_verbose(self, capsys):
+ def test_prints_details_verbose(self, capsys: pytest.CaptureFixture[str]) -> None:
"""Test printing measurement details in verbose mode."""
console = Console()
real_measurements, harmonic_measurements = discover_measurements_by_space()
@@ -197,7 +200,9 @@ def test_prints_details_verbose(self, capsys):
class TestPrintCompatiblePairs:
"""Tests for print_compatible_pairs function."""
- def test_prints_pair_count_non_verbose(self, capsys):
+ def test_prints_pair_count_non_verbose(
+ self, capsys: pytest.CaptureFixture[str]
+ ) -> None:
"""Test printing pair counts in non-verbose mode."""
console = Console()
real_measurements, _ = discover_measurements_by_space()
@@ -211,7 +216,9 @@ def test_prints_pair_count_non_verbose(self, capsys):
assert match_wrapped(captured.out, "Valid real-space pairs:")
assert match_wrapped(captured.out, str(len(pairs)))
- def test_prints_pair_details_verbose(self, capsys):
+ def test_prints_pair_details_verbose(
+ self, capsys: pytest.CaptureFixture[str]
+ ) -> None:
"""Test printing pair details in verbose mode."""
console = Console()
real_measurements, _ = discover_measurements_by_space()
@@ -230,7 +237,7 @@ def test_prints_pair_details_verbose(self, capsys):
# Should show measurement names
assert "+" in captured.out
- def test_handles_empty_pairs(self, capsys):
+ def test_handles_empty_pairs(self, capsys: pytest.CaptureFixture[str]) -> None:
"""Test handling empty pairs list."""
console = Console()
print_compatible_pairs(console, "test-space", [], False)
@@ -242,7 +249,7 @@ def test_handles_empty_pairs(self, capsys):
class TestPrintEfficiencyGains:
"""Tests for print_efficiency_gains function."""
- def test_prints_efficiency_stats(self, capsys):
+ def test_prints_efficiency_stats(self, capsys: pytest.CaptureFixture[str]) -> None:
"""Test printing efficiency statistics."""
console = Console()
real_measurements, harmonic_measurements = discover_measurements_by_space()
@@ -268,7 +275,9 @@ def test_prints_efficiency_stats(self, capsys):
assert match_wrapped(captured.out, "Total:")
assert match_wrapped(captured.out, "skipped tests eliminated")
- def test_calculates_correct_reduction(self, capsys):
+ def test_calculates_correct_reduction(
+ self, capsys: pytest.CaptureFixture[str]
+ ) -> None:
"""Test that reduction calculations are correct."""
console = Console()
real_measurements, harmonic_measurements = discover_measurements_by_space()
@@ -299,7 +308,9 @@ def test_calculates_correct_reduction(self, capsys):
class TestPrintSummaryStats:
"""Tests for print_summary_stats function."""
- def test_prints_summary_statistics(self, capsys):
+ def test_prints_summary_statistics(
+ self, capsys: pytest.CaptureFixture[str]
+ ) -> None:
"""Test printing summary statistics."""
console = Console()
real_measurements, harmonic_measurements = discover_measurements_by_space()
@@ -326,7 +337,7 @@ def test_prints_summary_statistics(self, capsys):
assert match_wrapped(captured.out, "Real-space compatibility:")
assert match_wrapped(captured.out, "Harmonic-space compatibility:")
- def test_shows_percentages(self, capsys):
+ def test_shows_percentages(self, capsys: pytest.CaptureFixture[str]) -> None:
"""Test that percentages are shown."""
console = Console()
real_measurements, harmonic_measurements = discover_measurements_by_space()
@@ -353,7 +364,7 @@ def test_shows_percentages(self, capsys):
class TestMainFunction: # pylint: disable=import-outside-toplevel
"""Tests for main CLI function."""
- def test_main_default_options(self, capsys):
+ def test_main_default_options(self, capsys: pytest.CaptureFixture[str]) -> None:
"""Test main with default options (space=BOTH, verbose=False)."""
from firecrown.fctools.measurement_compatibility import Space, main
@@ -367,7 +378,7 @@ def test_main_default_options(self, capsys):
assert "Efficiency Improvements:" in captured.out
assert "Summary Statistics:" in captured.out
- def test_main_verbose_flag(self, capsys):
+ def test_main_verbose_flag(self, capsys: pytest.CaptureFixture[str]) -> None:
"""Test main with verbose=True."""
from firecrown.fctools.measurement_compatibility import Space, main
@@ -378,7 +389,9 @@ def test_main_verbose_flag(self, capsys):
# In verbose mode, should show individual measurements
assert "•" in captured.out
- def test_main_verbose_with_space_harmonic(self, capsys):
+ def test_main_verbose_with_space_harmonic(
+ self, capsys: pytest.CaptureFixture[str]
+ ) -> None:
"""Test main with verbose=True and space=HARMONIC."""
from firecrown.fctools.measurement_compatibility import Space, main
@@ -388,7 +401,7 @@ def test_main_verbose_with_space_harmonic(self, capsys):
assert "•" in captured.out
assert "harmonic-space" in captured.out
- def test_main_space_real(self, capsys):
+ def test_main_space_real(self, capsys: pytest.CaptureFixture[str]) -> None:
"""Test main with space=REAL."""
from firecrown.fctools.measurement_compatibility import Space, main
@@ -401,7 +414,7 @@ def test_main_space_real(self, capsys):
# Should not show harmonic-space pairs
assert "harmonic-space" not in captured.out
- def test_main_space_harmonic(self, capsys):
+ def test_main_space_harmonic(self, capsys: pytest.CaptureFixture[str]) -> None:
"""Test main with space=HARMONIC."""
from firecrown.fctools.measurement_compatibility import Space, main
@@ -412,7 +425,7 @@ def test_main_space_harmonic(self, capsys):
# Should show efficiency for harmonic space
assert "Harmonic-space efficiency:" in captured.out
- def test_main_space_both(self, capsys):
+ def test_main_space_both(self, capsys: pytest.CaptureFixture[str]) -> None:
"""Test main with space=BOTH."""
from firecrown.fctools.measurement_compatibility import Space, main
@@ -423,7 +436,7 @@ def test_main_space_both(self, capsys):
assert "harmonic-space" in captured.out
assert "Summary Statistics:" in captured.out
- def test_main_stats_only(self, capsys):
+ def test_main_stats_only(self, capsys: pytest.CaptureFixture[str]) -> None:
"""Test main with stats_only=True."""
from firecrown.fctools.measurement_compatibility import Space, main
@@ -436,7 +449,9 @@ def test_main_stats_only(self, capsys):
# Should not show efficiency improvements
assert "Efficiency Improvements:" not in captured.out
- def test_main_stats_only_with_space_real(self, capsys):
+ def test_main_stats_only_with_space_real(
+ self, capsys: pytest.CaptureFixture[str]
+ ) -> None:
"""Test main with stats_only=True and space=REAL."""
from firecrown.fctools.measurement_compatibility import Space, main
@@ -448,7 +463,9 @@ def test_main_stats_only_with_space_real(self, capsys):
assert "Valid real-space pairs:" not in captured.out
assert "Real-space efficiency:" not in captured.out
- def test_main_stats_only_with_space_harmonic(self, capsys):
+ def test_main_stats_only_with_space_harmonic(
+ self, capsys: pytest.CaptureFixture[str]
+ ) -> None:
"""Test main with stats_only=True and space=HARMONIC."""
from firecrown.fctools.measurement_compatibility import Space, main
@@ -460,7 +477,7 @@ def test_main_stats_only_with_space_harmonic(self, capsys):
assert "Valid harmonic-space pairs:" not in captured.out
assert "Harmonic-space efficiency:" not in captured.out
- def test_main_combined_flags(self, capsys):
+ def test_main_combined_flags(self, capsys: pytest.CaptureFixture[str]) -> None:
"""Test main with verbose=True and space=REAL."""
from firecrown.fctools.measurement_compatibility import Space, main
@@ -472,7 +489,9 @@ def test_main_combined_flags(self, capsys):
# Should show Real-space efficiency
assert "Real-space efficiency:" in captured.out
- def test_main_space_real_without_verbose(self, capsys):
+ def test_main_space_real_without_verbose(
+ self, capsys: pytest.CaptureFixture[str]
+ ) -> None:
"""Test main with space=REAL and verbose=False."""
from firecrown.fctools.measurement_compatibility import Space, main
@@ -484,7 +503,9 @@ def test_main_space_real_without_verbose(self, capsys):
# Should show Real-space efficiency
assert "Real-space efficiency:" in captured.out
- def test_main_space_harmonic_without_verbose(self, capsys):
+ def test_main_space_harmonic_without_verbose(
+ self, capsys: pytest.CaptureFixture[str]
+ ) -> None:
"""Test main with space=HARMONIC and verbose=False."""
from firecrown.fctools.measurement_compatibility import Space, main
@@ -496,7 +517,9 @@ def test_main_space_harmonic_without_verbose(self, capsys):
# Should not show real-space details when space=harmonic
assert "Valid real-space pairs:" not in captured.out
- def test_main_space_both_shows_all_sections(self, capsys):
+ def test_main_space_both_shows_all_sections(
+ self, capsys: pytest.CaptureFixture[str]
+ ) -> None:
"""Test main with space=BOTH shows all sections."""
from firecrown.fctools.measurement_compatibility import Space, main
@@ -514,7 +537,7 @@ def test_main_space_both_shows_all_sections(self, capsys):
# Should show summary statistics
assert "Summary Statistics:" in captured.out
- def test_main_with_subprocess(self):
+ def test_main_with_subprocess(self) -> None:
"""Test that the script can be executed directly via subprocess.
This test verifies that the __main__ block works correctly.
@@ -530,7 +553,7 @@ def test_main_with_subprocess(self):
assert result.returncode == 0
assert "Firecrown Measurement Compatibility Analysis" in result.stdout
- def test_main_subprocess_with_stats_only(self):
+ def test_main_subprocess_with_stats_only(self) -> None:
"""Test script execution with --stats-only flag."""
script_path = "firecrown/fctools/measurement_compatibility.py"
result = subprocess.run(
@@ -547,7 +570,7 @@ def test_main_subprocess_with_stats_only(self):
class TestIntegration:
"""Integration tests for measurement compatibility functionality."""
- def test_full_workflow_real_space(self):
+ def test_full_workflow_real_space(self) -> None:
"""Test complete workflow for real space."""
# Discover measurements
real_measurements, _ = discover_measurements_by_space()
@@ -565,7 +588,7 @@ def test_full_workflow_real_space(self):
for m1, m2 in pairs:
assert measurement_is_compatible_real(m1, m2)
- def test_full_workflow_harmonic_space(self):
+ def test_full_workflow_harmonic_space(self) -> None:
"""Test complete workflow for harmonic space."""
# Discover measurements
_, harmonic_measurements = discover_measurements_by_space()
@@ -583,7 +606,7 @@ def test_full_workflow_harmonic_space(self):
for m1, m2 in pairs:
assert measurement_is_compatible_harmonic(m1, m2)
- def test_compatibility_is_subset_of_all_combinations(self):
+ def test_compatibility_is_subset_of_all_combinations(self) -> None:
"""Test that compatible pairs are a subset of all possible combinations."""
real_measurements, harmonic_measurements = discover_measurements_by_space()
@@ -598,7 +621,7 @@ def test_compatibility_is_subset_of_all_combinations(self):
assert len(real_pairs) <= len(real_measurements) ** 2
assert len(harmonic_pairs) <= len(harmonic_measurements) ** 2
- def test_cli_produces_consistent_output(self):
+ def test_cli_produces_consistent_output(self) -> None:
"""Test that CLI produces consistent output across runs."""
script_path = "firecrown/fctools/measurement_compatibility.py"
@@ -621,7 +644,7 @@ def test_cli_produces_consistent_output(self):
assert result2.returncode == 0
assert result1.stdout == result2.stdout
- def test_all_measurements_categorized(self):
+ def test_all_measurements_categorized(self) -> None:
"""Test that measurements are properly categorized."""
real_measurements, harmonic_measurements = discover_measurements_by_space()
diff --git a/tests/fctools/test_print_code.py b/tests/fctools/test_print_code.py
index 5da48cf15..e4294e72e 100644
--- a/tests/fctools/test_print_code.py
+++ b/tests/fctools/test_print_code.py
@@ -27,7 +27,7 @@
# pylint: disable=missing-function-docstring,missing-class-docstring
-def _get_subprocess_env():
+def _get_subprocess_env() -> dict[str, str]:
"""Get environment with PYTHONPATH set to include the current directory."""
env = os.environ.copy()
# Add current directory to PYTHONPATH so subprocess can import tests module
@@ -70,7 +70,7 @@ class ClassNoDocstring:
# Tests for _render_attributes
-def test_render_attributes_simple():
+def test_render_attributes_simple() -> None:
"""Test _render_attributes with simple attributes."""
# Create a simple ClassDef with attributes
class_def = _make_class_def(
@@ -98,7 +98,7 @@ def test_render_attributes_simple():
assert any("attr2: str = 'default'" in line for line in result)
-def test_render_attributes_empty():
+def test_render_attributes_empty() -> None:
"""Test _render_attributes with empty class body."""
class_def = _make_class_def(
name="EmptyClass",
@@ -111,7 +111,7 @@ def test_render_attributes_empty():
assert not result
-def test_render_attributes_no_annotation():
+def test_render_attributes_no_annotation() -> None:
"""Test _render_attributes with attribute without annotation."""
assign_node = ast.Assign(
targets=[ast.Name(id="attr")], value=ast.Constant(value=42)
@@ -129,7 +129,7 @@ def test_render_attributes_no_annotation():
assert any("attr = 42" in line for line in result)
-def test_render_attributes_complex_value():
+def test_render_attributes_complex_value() -> None:
"""Test _render_attributes with complex attribute value."""
class_def = _make_class_def(
name="TestClass",
@@ -152,7 +152,7 @@ def test_render_attributes_complex_value():
# Tests for _build_class_code
-def test_build_class_code_simple_class():
+def test_build_class_code_simple_class() -> None:
"""Test _build_class_code with a simple class."""
code = _build_class_code(SimpleClass)
assert "class SimpleClass():" in code
@@ -161,7 +161,7 @@ def test_build_class_code_simple_class():
assert "attr2: str = 'default'" in code
-def test_build_class_code_decorated_class():
+def test_build_class_code_decorated_class() -> None:
"""Test _build_class_code with a decorated class."""
code = _build_class_code(DecoratedClass)
assert "@dataclass" in code
@@ -169,7 +169,7 @@ def test_build_class_code_decorated_class():
assert "value: int" in code
-def test_build_class_code_class_with_bases():
+def test_build_class_code_class_with_bases() -> None:
"""Test _build_class_code with a class that has base classes."""
code = _build_class_code(ClassWithBases)
# This should include the base class - exact format depends on AST
@@ -177,21 +177,21 @@ def test_build_class_code_class_with_bases():
assert "attr3: float = 1.0" in code
-def test_build_class_code_no_docstring():
+def test_build_class_code_no_docstring() -> None:
"""Test _build_class_code with a class without docstring."""
code = _build_class_code(ClassNoDocstring)
assert "class ClassNoDocstring():" in code
assert "attr: int" in code
-def test_build_class_code_builtin_class():
+def test_build_class_code_builtin_class() -> None:
"""Test _build_class_code with a built-in class."""
# Built-in classes should raise TypeError (no source file)
with pytest.raises(TypeError):
_build_class_code(int)
-def test_build_class_code_no_attributes():
+def test_build_class_code_no_attributes() -> None:
"""Test _build_class_code with a class that has no attributes."""
# Use a class defined at module level to avoid indentation issues
code = _build_class_code(ClassNoDocstring)
@@ -202,7 +202,7 @@ def test_build_class_code_no_attributes():
# Tests for display_class_attributes
-def test_display_class_attributes_simple(capsys):
+def test_display_class_attributes_simple(capsys: pytest.CaptureFixture[str]) -> None:
"""Test display_class_attributes with a simple class."""
display_class_attributes(SimpleClass)
captured = capsys.readouterr()
@@ -212,14 +212,14 @@ def test_display_class_attributes_simple(capsys):
assert "```" in captured.out
-def test_display_class_attributes_builtin_class():
+def test_display_class_attributes_builtin_class() -> None:
"""Test display_class_attributes with a built-in class."""
# Built-in classes raise TypeError, not OSError, so it will propagate
with pytest.raises(TypeError, match="built-in class"):
display_class_attributes(int)
-def test_display_class_attributes_decorated(capsys):
+def test_display_class_attributes_decorated(capsys: pytest.CaptureFixture[str]) -> None:
"""Test display_class_attributes with a decorated class."""
display_class_attributes(DecoratedClass)
captured = capsys.readouterr()
@@ -227,7 +227,9 @@ def test_display_class_attributes_decorated(capsys):
assert "class DecoratedClass():" in captured.out
-def test_display_class_attributes_no_markdown_simple(capsys):
+def test_display_class_attributes_no_markdown_simple(
+ capsys: pytest.CaptureFixture[str],
+) -> None:
"""Test display_class_attributes with markdown disabled."""
# This should just call display_class_without_markdown
display_class_attributes(SimpleClass)
@@ -238,7 +240,9 @@ def test_display_class_attributes_no_markdown_simple(capsys):
# Tests for display_class_without_markdown
-def test_display_class_without_markdown_simple(capsys):
+def test_display_class_without_markdown_simple(
+ capsys: pytest.CaptureFixture[str],
+) -> None:
"""Test display_class_without_markdown with a simple class."""
display_class_without_markdown(SimpleClass)
captured = capsys.readouterr()
@@ -249,14 +253,16 @@ def test_display_class_without_markdown_simple(capsys):
assert "```" not in captured.out
-def test_display_class_without_markdown_builtin_class():
+def test_display_class_without_markdown_builtin_class() -> None:
"""Test display_class_without_markdown with a built-in class."""
# Built-in classes raise TypeError, not OSError, so it will propagate
with pytest.raises(TypeError, match="built-in class"):
display_class_without_markdown(int)
-def test_display_class_without_markdown_decorated(capsys):
+def test_display_class_without_markdown_decorated(
+ capsys: pytest.CaptureFixture[str],
+) -> None:
"""Test display_class_without_markdown with a decorated class."""
display_class_without_markdown(DecoratedClass)
captured = capsys.readouterr()
@@ -267,7 +273,7 @@ def test_display_class_without_markdown_decorated(capsys):
# Tests for main CLI
-def test_main_simple_class():
+def test_main_simple_class() -> None:
"""Test main CLI with a simple class path."""
script_path = "firecrown/fctools/print_code.py"
result = subprocess.run(
@@ -282,7 +288,7 @@ def test_main_simple_class():
assert match_wrapped(result.stdout, "attr1: int")
-def test_main_no_markdown():
+def test_main_no_markdown() -> None:
"""Test main CLI with --no-markdown flag."""
script_path = "firecrown/fctools/print_code.py"
result = subprocess.run(
@@ -302,7 +308,7 @@ def test_main_no_markdown():
assert "```python" not in result.stdout
-def test_main_decorated_class():
+def test_main_decorated_class() -> None:
"""Test main CLI with a decorated class."""
script_path = "firecrown/fctools/print_code.py"
result = subprocess.run(
@@ -317,7 +323,7 @@ def test_main_decorated_class():
assert match_wrapped(result.stdout, "class DecoratedClass():")
-def test_main_class_with_bases():
+def test_main_class_with_bases() -> None:
"""Test main CLI with a class that has base classes."""
script_path = "firecrown/fctools/print_code.py"
result = subprocess.run(
@@ -332,7 +338,7 @@ def test_main_class_with_bases():
assert "attr3: float = 1.0" in result.stdout
-def test_main_invalid_class_path():
+def test_main_invalid_class_path() -> None:
"""Test main CLI with invalid class path."""
script_path = "firecrown/fctools/print_code.py"
result = subprocess.run(
@@ -345,7 +351,7 @@ def test_main_invalid_class_path():
assert result.returncode != 0
-def test_main_builtin_class():
+def test_main_builtin_class() -> None:
"""Test main CLI with built-in class."""
script_path = "firecrown/fctools/print_code.py"
result = subprocess.run(
@@ -358,7 +364,7 @@ def test_main_builtin_class():
assert result.returncode != 0
-def test_main_missing_argument():
+def test_main_missing_argument() -> None:
"""Test main CLI with missing argument."""
script_path = "firecrown/fctools/print_code.py"
result = subprocess.run(
@@ -371,7 +377,7 @@ def test_main_missing_argument():
assert "Missing argument" in result.stderr
-def test_main_help():
+def test_main_help() -> None:
"""Test main CLI with --help flag."""
script_path = "firecrown/fctools/print_code.py"
result = subprocess.run(
@@ -386,7 +392,7 @@ def test_main_help():
assert match_wrapped(strip_rich_markup(result.stdout), "--no-markdown")
-def test_main_multiple_classes():
+def test_main_multiple_classes() -> None:
"""Test main CLI with multiple class names."""
script_path = "firecrown/fctools/print_code.py"
result = subprocess.run(
@@ -415,7 +421,7 @@ def test_main_multiple_classes():
assert "class DecoratedClass()" in result.stdout
-def test_main_multiple_classes_with_invalid():
+def test_main_multiple_classes_with_invalid() -> None:
"""Test main CLI with multiple classes where one is invalid."""
script_path = "firecrown/fctools/print_code.py"
# Test with invalid module
@@ -440,7 +446,7 @@ def test_main_multiple_classes_with_invalid():
)
-def test_build_class_code_with_none_class_def():
+def test_build_class_code_with_none_class_def() -> None:
"""Test _build_class_code when get_class_definition returns None."""
# This tests the error path when class definition can't be found
# The ValueError is raised when class_def is None
@@ -461,7 +467,7 @@ class TestClass:
# Integration tests
-def test_integration_full_workflow():
+def test_integration_full_workflow() -> None:
"""Test full workflow from CLI to output."""
script_path = "firecrown/fctools/print_code.py"
result = subprocess.run(
@@ -479,7 +485,7 @@ def test_integration_full_workflow():
assert "attr2: str = 'default'" in result.stdout
-def test_integration_multiple_runs():
+def test_integration_multiple_runs() -> None:
"""Test that multiple runs work correctly."""
script_path = "firecrown/fctools/print_code.py"
# Run twice with same class
@@ -502,7 +508,7 @@ def test_integration_multiple_runs():
assert result1.stdout == result2.stdout
-def test_integration_error_handling():
+def test_integration_error_handling() -> None:
"""Test error handling in full workflow."""
script_path = "firecrown/fctools/print_code.py"
# Test with invalid path
@@ -518,7 +524,7 @@ def test_integration_error_handling():
# Direct main() function tests for coverage
-def test_main_function_single_class(capsys):
+def test_main_function_single_class(capsys: pytest.CaptureFixture[str]) -> None:
"""Test main function directly with single class."""
# Call main with a single class
main(class_names=["tests.fctools.test_print_code.SimpleClass"], no_markdown=False)
@@ -529,7 +535,9 @@ def test_main_function_single_class(capsys):
assert "A simple test class." in captured.out
-def test_main_function_no_markdown_flag(capsys):
+def test_main_function_no_markdown_flag(
+ capsys: pytest.CaptureFixture[str],
+) -> None:
"""Test main function with no_markdown=True."""
# Call main with no_markdown flag
main(class_names=["tests.fctools.test_print_code.SimpleClass"], no_markdown=True)
@@ -540,7 +548,7 @@ def test_main_function_no_markdown_flag(capsys):
assert "```python" not in captured.out
-def test_main_function_multiple_classes(capsys):
+def test_main_function_multiple_classes(capsys: pytest.CaptureFixture[str]) -> None:
"""Test main function with multiple classes."""
# Call main with multiple classes
main(
@@ -561,7 +569,9 @@ def test_main_function_multiple_classes(capsys):
assert "Class: tests.fctools.test_print_code.DecoratedClass" in captured.out
-def test_main_function_multiple_classes_no_markdown(capsys):
+def test_main_function_multiple_classes_no_markdown(
+ capsys: pytest.CaptureFixture[str],
+) -> None:
"""Test main function with multiple classes and no_markdown=True."""
# Call main with multiple classes and no_markdown
main(
diff --git a/tests/fctools/test_print_hierarchy.py b/tests/fctools/test_print_hierarchy.py
index 8195b1aae..16fa80c6d 100644
--- a/tests/fctools/test_print_hierarchy.py
+++ b/tests/fctools/test_print_hierarchy.py
@@ -9,6 +9,8 @@
import subprocess
import sys
+import pytest
+
from firecrown.fctools.print_hierarchy import (
full_type_name,
get_defined_methods,
@@ -22,13 +24,13 @@
# Tests for full_type_name()
-def test_builtin_type():
+def test_builtin_type() -> None:
"""Test getting full name for built-in type."""
result = full_type_name(int)
assert result == "builtins.int"
-def test_standard_library_type():
+def test_standard_library_type() -> None:
"""Test getting full name for standard library type."""
from collections import OrderedDict # pylint: disable=import-outside-toplevel
@@ -36,7 +38,7 @@ def test_standard_library_type():
assert result == "collections.OrderedDict"
-def test_custom_class():
+def test_custom_class() -> None:
"""Test getting full name for a custom class."""
class MyClass:
@@ -50,7 +52,7 @@ class MyClass:
# Tests for get_defined_methods()
-def test_class_with_no_methods():
+def test_class_with_no_methods() -> None:
"""Test getting methods from a class with no methods."""
class EmptyClass:
@@ -61,28 +63,28 @@ class EmptyClass:
assert len(methods) == 0
-def test_class_with_simple_method():
+def test_class_with_simple_method() -> None:
"""Test getting methods from a class with one method."""
class SimpleClass:
- def my_method(self):
+ def my_method(self) -> None:
pass
methods = get_defined_methods(SimpleClass)
assert "my_method" in methods
-def test_class_with_multiple_methods():
+def test_class_with_multiple_methods() -> None:
"""Test getting methods from a class with multiple methods."""
class MultiMethodClass:
- def method_one(self):
+ def method_one(self) -> None:
pass
- def method_two(self):
+ def method_two(self) -> None:
pass
- def method_three(self):
+ def method_three(self) -> None:
pass
methods = get_defined_methods(MultiMethodClass)
@@ -92,15 +94,15 @@ def method_three(self):
assert "method_three" in methods
-def test_inherited_method_not_included():
+def test_inherited_method_not_included() -> None:
"""Test that inherited methods are not included."""
class BaseClass:
- def base_method(self):
+ def base_method(self) -> None:
pass
class DerivedClass(BaseClass):
- def derived_method(self):
+ def derived_method(self) -> None:
pass
methods = get_defined_methods(DerivedClass)
@@ -108,29 +110,29 @@ def derived_method(self):
assert "base_method" not in methods
-def test_overridden_method_included():
+def test_overridden_method_included() -> None:
"""Test that overridden methods are included."""
class BaseClass:
- def my_method(self):
+ def my_method(self) -> str:
return "base"
class DerivedClass(BaseClass):
- def my_method(self):
+ def my_method(self) -> str:
return "derived"
methods = get_defined_methods(DerivedClass)
assert "my_method" in methods
-def test_special_methods_included():
+def test_special_methods_included() -> None:
"""Test that special methods are included."""
class WithInit:
- def __init__(self):
+ def __init__(self) -> None:
pass
- def __str__(self):
+ def __str__(self) -> str:
return "test"
methods = get_defined_methods(WithInit)
@@ -138,19 +140,19 @@ def __str__(self):
assert "__str__" in methods
-def test_class_with_static_and_class_methods():
+def test_class_with_static_and_class_methods() -> None:
"""Test that static and class methods are not included."""
class WithSpecialMethods:
- def regular_method(self):
+ def regular_method(self) -> None:
pass
@staticmethod
- def static_method():
+ def static_method() -> None:
pass
@classmethod
- def class_method(cls):
+ def class_method(cls) -> None:
pass
methods = get_defined_methods(WithSpecialMethods)
@@ -163,11 +165,11 @@ def class_method(cls):
# Tests for print_one_type()
-def test_prints_type_info(capsys):
+def test_prints_type_info(capsys: pytest.CaptureFixture[str]) -> None:
"""Test printing basic type information."""
class SimpleClass:
- def my_method(self):
+ def my_method(self) -> None:
pass
print_one_type(0, SimpleClass)
@@ -179,14 +181,14 @@ def my_method(self):
assert "my_method" in captured.out
-def test_prints_multiple_methods(capsys):
+def test_prints_multiple_methods(capsys: pytest.CaptureFixture[str]) -> None:
"""Test printing type with multiple methods."""
class MultiMethodClass:
- def method_a(self):
+ def method_a(self) -> None:
pass
- def method_b(self):
+ def method_b(self) -> None:
pass
print_one_type(1, MultiMethodClass)
@@ -198,7 +200,7 @@ def method_b(self):
assert "method_b" in captured.out
-def test_prints_with_different_indices(capsys):
+def test_prints_with_different_indices(capsys: pytest.CaptureFixture[str]) -> None:
"""Test printing with different index values."""
class TestClass:
@@ -214,7 +216,7 @@ class TestClass:
# Tests for print_type_hierarchy()
-def test_prints_simple_class(capsys):
+def test_prints_simple_class(capsys: pytest.CaptureFixture[str]) -> None:
"""Test printing hierarchy for a simple class."""
class SimpleClass:
@@ -229,19 +231,19 @@ class SimpleClass:
assert "builtins.object" in captured.out
-def test_prints_inheritance_chain(capsys):
+def test_prints_inheritance_chain(capsys: pytest.CaptureFixture[str]) -> None:
"""Test printing hierarchy with inheritance."""
class Base:
- def base_method(self):
+ def base_method(self) -> None:
pass
class Middle(Base):
- def middle_method(self):
+ def middle_method(self) -> None:
pass
class Derived(Middle):
- def derived_method(self):
+ def derived_method(self) -> None:
pass
print_type_hierarchy(Derived)
@@ -259,7 +261,9 @@ def derived_method(self):
assert "base_method" in captured.out
-def test_prints_builtin_type_hierarchy(capsys):
+def test_prints_builtin_type_hierarchy(
+ capsys: pytest.CaptureFixture[str],
+) -> None:
"""Test printing hierarchy for built-in types."""
from collections import OrderedDict # pylint: disable=import-outside-toplevel
@@ -275,7 +279,7 @@ def test_prints_builtin_type_hierarchy(capsys):
# Tests for main()
-def test_main_direct_single_typename(capsys):
+def test_main_direct_single_typename(capsys: pytest.CaptureFixture[str]) -> None:
"""Test main function directly with single typename for coverage.
This test calls the main() function directly (not via subprocess)
@@ -291,7 +295,7 @@ def test_main_direct_single_typename(capsys):
assert "=" not in captured.out or captured.out.count("=") < 10
-def test_main_direct_multiple_typenames(capsys):
+def test_main_direct_multiple_typenames(capsys: pytest.CaptureFixture[str]) -> None:
"""Test main function directly with multiple typenames for coverage.
This test calls the main() function directly (not via subprocess)
@@ -311,7 +315,7 @@ def test_main_direct_multiple_typenames(capsys):
assert "=" * 60 in captured.out
-def test_main_with_single_typename():
+def test_main_with_single_typename() -> None:
"""Test main with a single type name."""
script_path = "firecrown/fctools/print_hierarchy.py"
result = subprocess.run(
@@ -326,7 +330,7 @@ def test_main_with_single_typename():
assert match_wrapped(result.stdout, "OrderedDict")
-def test_main_with_multiple_typenames():
+def test_main_with_multiple_typenames() -> None:
"""Test main with multiple type names."""
script_path = "firecrown/fctools/print_hierarchy.py"
result = subprocess.run(
@@ -343,7 +347,7 @@ def test_main_with_multiple_typenames():
assert "=" in result.stdout
-def test_main_with_no_arguments():
+def test_main_with_no_arguments() -> None:
"""Test main with no arguments (should fail)."""
script_path = "firecrown/fctools/print_hierarchy.py"
result = subprocess.run(
@@ -357,7 +361,7 @@ def test_main_with_no_arguments():
# Should show error about missing argument
-def test_main_with_invalid_typename():
+def test_main_with_invalid_typename() -> None:
"""Test main with invalid type name."""
script_path = "firecrown/fctools/print_hierarchy.py"
result = subprocess.run(
@@ -373,7 +377,7 @@ def test_main_with_invalid_typename():
assert "nonexistent" in result.stderr
-def test_main_with_mixed_valid_invalid():
+def test_main_with_mixed_valid_invalid() -> None:
"""Test main with mix of valid and invalid type names."""
script_path = "firecrown/fctools/print_hierarchy.py"
result = subprocess.run(
@@ -397,7 +401,7 @@ def test_main_with_mixed_valid_invalid():
assert "Could not import module" in result.stderr
-def test_main_with_builtin_type():
+def test_main_with_builtin_type() -> None:
"""Test main with built-in type."""
script_path = "firecrown/fctools/print_hierarchy.py"
result = subprocess.run(
@@ -411,7 +415,7 @@ def test_main_with_builtin_type():
assert "int" in result.stdout
-def test_main_with_subprocess():
+def test_main_with_subprocess() -> None:
"""Test that the script can be executed directly via subprocess.
This test verifies that the __main__ block works correctly.
@@ -429,7 +433,7 @@ def test_main_with_subprocess():
assert "Path" in result.stdout
-def test_main_subprocess_with_multiple_types():
+def test_main_subprocess_with_multiple_types() -> None:
"""Test script execution with multiple type arguments."""
script_path = "firecrown/fctools/print_hierarchy.py"
result = subprocess.run(
@@ -445,7 +449,7 @@ def test_main_subprocess_with_multiple_types():
assert match_wrapped(result.stdout, "=")
-def test_main_subprocess_with_invalid_type():
+def test_main_subprocess_with_invalid_type() -> None:
"""Test script execution with invalid type name."""
script_path = "firecrown/fctools/print_hierarchy.py"
result = subprocess.run(
@@ -465,7 +469,9 @@ def test_main_subprocess_with_invalid_type():
# Integration tests
-def test_full_workflow_with_standard_type(capsys):
+def test_full_workflow_with_standard_type(
+ capsys: pytest.CaptureFixture[str],
+) -> None:
"""Test complete workflow with a standard library type."""
from collections import OrderedDict # pylint: disable=import-outside-toplevel
@@ -484,19 +490,21 @@ def test_full_workflow_with_standard_type(capsys):
assert "dict" in captured.out
-def test_full_workflow_with_custom_hierarchy(capsys):
+def test_full_workflow_with_custom_hierarchy(
+ capsys: pytest.CaptureFixture[str],
+) -> None:
"""Test complete workflow with custom class hierarchy."""
class GrandParent:
- def grandparent_method(self):
+ def grandparent_method(self) -> None:
pass
class Parent(GrandParent):
- def parent_method(self):
+ def parent_method(self) -> None:
pass
class Child(Parent):
- def child_method(self):
+ def child_method(self) -> None:
pass
# Test each function
@@ -515,7 +523,7 @@ def child_method(self):
assert "grandparent_method" in captured.out
-def test_cli_produces_consistent_output():
+def test_cli_produces_consistent_output() -> None:
"""Test that CLI produces consistent output across runs."""
script_path = "firecrown/fctools/print_hierarchy.py"
@@ -539,7 +547,7 @@ def test_cli_produces_consistent_output():
assert result1.stdout == result2.stdout
-def test_handles_complex_inheritance():
+def test_handles_complex_inheritance() -> None:
"""Test handling complex inheritance patterns."""
script_path = "firecrown/fctools/print_hierarchy.py"
# OrderedDict has complex MRO
@@ -558,21 +566,21 @@ def test_handles_complex_inheritance():
assert len(hierarchy_lines) > 2 # At least OrderedDict, dict, object
-def test_method_detection_accuracy():
+def test_method_detection_accuracy() -> None:
"""Test that method detection is accurate."""
class Base:
- def base_only(self):
+ def base_only(self) -> None:
pass
- def to_override(self):
+ def to_override(self) -> None:
pass
class Derived(Base):
- def derived_only(self):
+ def derived_only(self) -> None:
pass
- def to_override(self):
+ def to_override(self) -> None:
pass # Override
base_methods = get_defined_methods(Base)
diff --git a/tests/fctools/test_symbol_reference_checker.py b/tests/fctools/test_symbol_reference_checker.py
index 08578851a..28a5a71e3 100644
--- a/tests/fctools/test_symbol_reference_checker.py
+++ b/tests/fctools/test_symbol_reference_checker.py
@@ -1,6 +1,7 @@
"""Tests for the symbol_reference_checker module."""
import json
+from pathlib import Path
import pytest
from typer.testing import CliRunner
@@ -16,7 +17,7 @@
runner = CliRunner()
-def test_extract_code_spans_simple():
+def test_extract_code_spans_simple() -> None:
"""Test extracting code spans from simple markdown."""
content = "This is `code1` and `code2` in text."
spans = extract_code_spans(content)
@@ -25,7 +26,7 @@ def test_extract_code_spans_simple():
assert spans[1] == (1, "code2")
-def test_extract_code_spans_multiline():
+def test_extract_code_spans_multiline() -> None:
"""Test extracting code spans from multiple lines."""
content = """Line 1 with `span1`
Line 2 with `span2` and `span3`
@@ -39,14 +40,14 @@ def test_extract_code_spans_multiline():
assert spans[3] == (4, "span4")
-def test_extract_code_spans_empty():
+def test_extract_code_spans_empty() -> None:
"""Test extracting code spans from text without any."""
content = "No code spans here at all."
spans = extract_code_spans(content)
assert len(spans) == 0
-def test_check_qmd_file_valid_symbols(tmp_path):
+def test_check_qmd_file_valid_symbols(tmp_path: Path) -> None:
"""Test checking a file with valid symbol references."""
# Create a test .qmd file
qmd_file = tmp_path / "test.qmd"
@@ -66,7 +67,7 @@ def test_check_qmd_file_valid_symbols(tmp_path):
assert len(errors) == 0
-def test_check_qmd_file_invalid_fully_qualified(tmp_path):
+def test_check_qmd_file_invalid_fully_qualified(tmp_path: Path) -> None:
"""Test checking a file with invalid fully-qualified symbol."""
qmd_file = tmp_path / "test.qmd"
qmd_file.write_text("""
@@ -83,7 +84,7 @@ def test_check_qmd_file_invalid_fully_qualified(tmp_path):
assert "Line 2" in errors[0]
-def test_check_qmd_file_invalid_unqualified(tmp_path):
+def test_check_qmd_file_invalid_unqualified(tmp_path: Path) -> None:
"""Test checking a file with invalid unqualified symbol."""
qmd_file = tmp_path / "test.qmd"
qmd_file.write_text("""
@@ -99,7 +100,7 @@ def test_check_qmd_file_invalid_unqualified(tmp_path):
assert "Updateable" in errors[0]
-def test_check_qmd_file_multiple_errors(tmp_path):
+def test_check_qmd_file_multiple_errors(tmp_path: Path) -> None:
"""Test that all errors are reported, not just the first."""
qmd_file = tmp_path / "test.qmd"
qmd_file.write_text("""
@@ -119,7 +120,7 @@ def test_check_qmd_file_multiple_errors(tmp_path):
assert any("InvalidClass3" in e for e in errors)
-def test_check_qmd_file_with_exclude_pattern(tmp_path):
+def test_check_qmd_file_with_exclude_pattern(tmp_path: Path) -> None:
"""Test that exclude pattern works."""
qmd_file = tmp_path / "test.qmd"
qmd_file.write_text("""
@@ -141,7 +142,7 @@ def test_check_qmd_file_with_exclude_pattern(tmp_path):
assert len(errors_with_exclude) == 0
-def test_check_qmd_file_lowercase_code_not_checked(tmp_path):
+def test_check_qmd_file_lowercase_code_not_checked(tmp_path: Path) -> None:
"""Test that lowercase code spans are not checked as symbols."""
qmd_file = tmp_path / "test.qmd"
qmd_file.write_text("""
@@ -155,7 +156,7 @@ def test_check_qmd_file_lowercase_code_not_checked(tmp_path):
assert len(errors) == 0
-def test_check_qmd_file_partial_module_path(tmp_path):
+def test_check_qmd_file_partial_module_path(tmp_path: Path) -> None:
"""Test validation of partial module paths."""
qmd_file = tmp_path / "test.qmd"
qmd_file.write_text("""
@@ -171,7 +172,7 @@ def test_check_qmd_file_partial_module_path(tmp_path):
assert len(errors) == 0
-def test_main_success(tmp_path):
+def test_main_success(tmp_path: Path) -> None:
"""Test main function with valid symbols."""
# Create test files
qmd_file = tmp_path / "test.qmd"
@@ -189,7 +190,7 @@ def test_main_success(tmp_path):
assert "No invalid symbol references" in result.stdout
-def test_main_with_errors(tmp_path):
+def test_main_with_errors(tmp_path: Path) -> None:
"""Test main function with invalid symbols."""
# Create test files
qmd_file = tmp_path / "test.qmd"
@@ -207,21 +208,22 @@ def test_main_with_errors(tmp_path):
assert "firecrown.invalid.Symbol" in result.stderr
-def test_main_missing_symbol_map(tmp_path):
+def test_main_missing_symbol_map(tmp_path: Path) -> None:
"""Test main function with missing symbol map file."""
result = runner.invoke(app, [str(tmp_path), str(tmp_path / "nonexistent.json")])
assert result.exit_code != 0
-def test_validate_symbol_map_rejects_non_string_value():
+def test_validate_symbol_map_rejects_non_string_value() -> None:
+ symbol_map: dict[str, object] = {"symbol": 123}
with pytest.raises(SystemExit) as exc_info:
- _validate_symbol_map({"symbol": 123})
+ _validate_symbol_map(symbol_map)
assert exc_info.value.code == 1
-def test_main_with_exclude_pattern(tmp_path):
+def test_main_with_exclude_pattern(tmp_path: Path) -> None:
"""Test main function with exclude pattern."""
qmd_file = tmp_path / "test.qmd"
qmd_file.write_text("Example: `firecrown.example.ExampleClass`")
@@ -241,7 +243,9 @@ def test_main_with_exclude_pattern(tmp_path):
assert result.exit_code == 0
-def test_load_external_symbols_read_error(tmp_path, capsys):
+def test_load_external_symbols_read_error(
+ tmp_path: Path, capsys: pytest.CaptureFixture[str]
+) -> None:
"""Test _load_external_symbols handles OSError gracefully."""
# pylint: disable=import-outside-toplevel
from firecrown.fctools.symbol_reference_checker import (
@@ -263,7 +267,9 @@ def test_load_external_symbols_read_error(tmp_path, capsys):
assert "Warning" in captured.err or captured.err == ""
-def test_load_external_symbols_unicode_error(tmp_path, capsys):
+def test_load_external_symbols_unicode_error(
+ tmp_path: Path, capsys: pytest.CaptureFixture[str]
+) -> None:
"""Test _load_external_symbols handles UnicodeDecodeError gracefully."""
# pylint: disable=import-outside-toplevel
from firecrown.fctools.symbol_reference_checker import (
@@ -284,7 +290,7 @@ def test_load_external_symbols_unicode_error(tmp_path, capsys):
assert "Warning" in captured.err or captured.err == ""
-def test_load_external_symbols_with_comments_and_empty_lines(tmp_path):
+def test_load_external_symbols_with_comments_and_empty_lines(tmp_path: Path) -> None:
"""Test _load_external_symbols filters comments and empty lines."""
# pylint: disable=import-outside-toplevel
from firecrown.fctools.symbol_reference_checker import (
@@ -309,7 +315,9 @@ def test_load_external_symbols_with_comments_and_empty_lines(tmp_path):
assert result == {"ValidSymbol1", "ValidSymbol2", "ValidSymbol3"}
-def test_compile_exclude_pattern_invalid_regex(capsys):
+def test_compile_exclude_pattern_invalid_regex(
+ capsys: pytest.CaptureFixture[str],
+) -> None:
"""Test _compile_exclude_pattern handles invalid regex."""
# pylint: disable=import-outside-toplevel
from firecrown.fctools.symbol_reference_checker import (
@@ -327,7 +335,9 @@ def test_compile_exclude_pattern_invalid_regex(capsys):
assert "Warning" in captured.err
-def test_check_qmd_file_unqualified_symbol_also_fully_qualified(tmp_path):
+def test_check_qmd_file_unqualified_symbol_also_fully_qualified(
+ tmp_path: Path,
+) -> None:
"""Test unqualified symbol that exists in symbol map without dots.
This tests the case where a symbol like `CustomClass` is in the symbol
@@ -350,7 +360,7 @@ def test_check_qmd_file_unqualified_symbol_also_fully_qualified(tmp_path):
assert len(errors) == 0
-def test_main_with_external_symbols_file(tmp_path):
+def test_main_with_external_symbols_file(tmp_path: Path) -> None:
"""Test main function with external symbols file."""
# Create test files
qmd_file = tmp_path / "test.qmd"
@@ -378,7 +388,9 @@ def test_main_with_external_symbols_file(tmp_path):
assert "No invalid symbol references" in result.stdout
-def test_check_qmd_file_with_invalid_exclude_pattern(tmp_path, capsys):
+def test_check_qmd_file_with_invalid_exclude_pattern(
+ tmp_path: Path, capsys: pytest.CaptureFixture[str]
+) -> None:
"""Test check_qmd_file handles invalid exclude pattern gracefully."""
qmd_file = tmp_path / "test.qmd"
qmd_file.write_text("Reference: `firecrown.invalid.Symbol`")
@@ -396,10 +408,8 @@ def test_check_qmd_file_with_invalid_exclude_pattern(tmp_path, capsys):
assert "Warning" in captured.err
-def test_check_qmd_file_unqualified_not_in_fully_qualified():
+def test_check_qmd_file_unqualified_not_in_fully_qualified() -> None:
"""Test check_qmd_file with unqualified symbol not in fully_qualified set."""
- from pathlib import Path # pylint: disable=import-outside-toplevel
-
qmd_file = Path("test.qmd")
# Use an uppercase unqualified symbol that doesn't exist
content = "Reference to `UnknownSymbol` in text."
diff --git a/tests/fctools/test_tracer.py b/tests/fctools/test_tracer.py
index e4c495377..945089d75 100644
--- a/tests/fctools/test_tracer.py
+++ b/tests/fctools/test_tracer.py
@@ -12,7 +12,7 @@
import types
from pathlib import Path
from types import FrameType
-from typing import cast
+from typing import Generator, cast
import pytest
@@ -47,7 +47,7 @@ def _make_frame(
@pytest.fixture(autouse=True)
-def cleanup_tracing():
+def cleanup_tracing() -> Generator[None, None, None]:
"""Ensure sys.settrace is always cleaned up after each test.
This fixture runs automatically for all tests and ensures that tracing
@@ -66,7 +66,7 @@ def cleanup_tracing():
# Tests for TracerState.__init__()
-def test_tracer_state_init_creates_file(tmp_path):
+def test_tracer_state_init_creates_file(tmp_path: Path) -> None:
"""Test that TracerState creates a trace file."""
trace_file = tmp_path / "test.tsv"
tracer = TracerState(str(trace_file))
@@ -79,7 +79,7 @@ def test_tracer_state_init_creates_file(tmp_path):
tracer.close()
-def test_tracer_state_init_writes_header(tmp_path):
+def test_tracer_state_init_writes_header(tmp_path: Path) -> None:
"""Test that TracerState writes header line."""
trace_file = tmp_path / "test.tsv"
tracer = TracerState(str(trace_file))
@@ -92,7 +92,9 @@ def test_tracer_state_init_writes_header(tmp_path):
tracer.close()
-def test_tracer_state_default_filename(tmp_path, monkeypatch):
+def test_tracer_state_default_filename(
+ tmp_path: Path, monkeypatch: pytest.MonkeyPatch
+) -> None:
"""Test that TracerState uses default filename."""
monkeypatch.chdir(tmp_path)
tracer = TracerState()
@@ -107,7 +109,7 @@ def test_tracer_state_default_filename(tmp_path, monkeypatch):
# Tests for TracerState.trace_call() - call events
-def test_trace_call_event(tmp_path):
+def test_trace_call_event(tmp_path: Path) -> None:
"""Test tracing a function call event."""
trace_file = tmp_path / "test.tsv"
tracer = TracerState(str(trace_file))
@@ -130,13 +132,13 @@ def test_trace_call_event(tmp_path):
tracer.close()
-def test_trace_call_with_self_argument(tmp_path):
+def test_trace_call_with_self_argument(tmp_path: Path) -> None:
"""Test tracing a method call with self argument."""
trace_file = tmp_path / "test.tsv"
tracer = TracerState(str(trace_file))
class TestClass:
- def method(self):
+ def method(self) -> None:
pass
obj = TestClass()
@@ -156,7 +158,7 @@ def method(self):
tracer.close()
-def test_trace_call_no_arguments(tmp_path):
+def test_trace_call_no_arguments(tmp_path: Path) -> None:
"""Test tracing a function with no arguments."""
trace_file = tmp_path / "test.tsv"
tracer = TracerState(str(trace_file))
@@ -177,7 +179,7 @@ def test_trace_call_no_arguments(tmp_path):
# Tests for TracerState.trace_call() - return events
-def test_trace_return_event(tmp_path):
+def test_trace_return_event(tmp_path: Path) -> None:
"""Test tracing a function return event."""
trace_file = tmp_path / "test.tsv"
tracer = TracerState(str(trace_file))
@@ -198,7 +200,7 @@ def test_trace_return_event(tmp_path):
tracer.close()
-def test_trace_return_with_none(tmp_path):
+def test_trace_return_with_none(tmp_path: Path) -> None:
"""Test tracing a return with None value."""
trace_file = tmp_path / "test.tsv"
tracer = TracerState(str(trace_file))
@@ -218,14 +220,14 @@ def test_trace_return_with_none(tmp_path):
tracer.close()
-def test_trace_return_with_unprintable_object(tmp_path):
+def test_trace_return_with_unprintable_object(tmp_path: Path) -> None:
"""Test tracing a return with object that can't be converted to str."""
trace_file = tmp_path / "test.tsv"
tracer = TracerState(str(trace_file))
tracer.level = 1
class UnprintableObject:
- def __str__(self):
+ def __str__(self) -> str:
raise AttributeError("Cannot convert to string")
obj = UnprintableObject()
@@ -243,14 +245,14 @@ def __str__(self):
tracer.close()
-def test_trace_return_with_recursion_error(tmp_path):
+def test_trace_return_with_recursion_error(tmp_path: Path) -> None:
"""Test tracing a return with object that causes RecursionError on str()."""
trace_file = tmp_path / "test.tsv"
tracer = TracerState(str(trace_file))
tracer.level = 1
class RecursiveObject:
- def __str__(self):
+ def __str__(self) -> str:
raise RecursionError("Maximum recursion depth exceeded")
obj = RecursiveObject()
@@ -268,14 +270,14 @@ def __str__(self):
tracer.close()
-def test_trace_return_with_type_error(tmp_path):
+def test_trace_return_with_type_error(tmp_path: Path) -> None:
"""Test tracing a return with object that causes TypeError on str()."""
trace_file = tmp_path / "test.tsv"
tracer = TracerState(str(trace_file))
tracer.level = 1
class TypeErrorObject:
- def __str__(self):
+ def __str__(self) -> str:
raise TypeError("Cannot convert to string")
obj = TypeErrorObject()
@@ -296,7 +298,7 @@ def __str__(self):
# Tests for TracerState.trace_call() - exception events
-def test_trace_exception_event(tmp_path):
+def test_trace_exception_event(tmp_path: Path) -> None:
"""Test tracing an exception event."""
trace_file = tmp_path / "test.tsv"
tracer = TracerState(str(trace_file))
@@ -316,7 +318,7 @@ def test_trace_exception_event(tmp_path):
tracer.close()
-def test_trace_call_returns_itself(tmp_path):
+def test_trace_call_returns_itself(tmp_path: Path) -> None:
"""Test that trace_call returns itself for continued tracing."""
trace_file = tmp_path / "test.tsv"
tracer = TracerState(str(trace_file))
@@ -334,7 +336,7 @@ def test_trace_call_returns_itself(tmp_path):
# Tests for TracerState.close()
-def test_tracer_state_close(tmp_path):
+def test_tracer_state_close(tmp_path: Path) -> None:
"""Test that close() closes the trace file."""
trace_file = tmp_path / "test.tsv"
tracer = TracerState(str(trace_file))
@@ -348,7 +350,7 @@ def test_tracer_state_close(tmp_path):
# Tests for settrace()
-def test_settrace_creates_tracer(tmp_path):
+def test_settrace_creates_tracer(tmp_path: Path) -> None:
"""Test that settrace creates and returns a TracerState."""
trace_file = tmp_path / "test.tsv"
tracer = settrace(str(trace_file))
@@ -361,7 +363,7 @@ def test_settrace_creates_tracer(tmp_path):
tracer.close()
-def test_settrace_enables_tracing(tmp_path):
+def test_settrace_enables_tracing(tmp_path: Path) -> None:
"""Test that settrace enables sys.settrace."""
trace_file = tmp_path / "test.tsv"
tracer = settrace(str(trace_file))
@@ -374,7 +376,9 @@ def test_settrace_enables_tracing(tmp_path):
tracer.close()
-def test_settrace_default_filename(tmp_path, monkeypatch):
+def test_settrace_default_filename(
+ tmp_path: Path, monkeypatch: pytest.MonkeyPatch
+) -> None:
"""Test that settrace uses default filename."""
monkeypatch.chdir(tmp_path)
tracer = settrace()
@@ -390,7 +394,7 @@ def test_settrace_default_filename(tmp_path, monkeypatch):
# Tests for untrace()
-def test_untrace_disables_tracing(tmp_path):
+def test_untrace_disables_tracing(tmp_path: Path) -> None:
"""Test that untrace disables sys.settrace."""
trace_file = tmp_path / "test.tsv"
tracer = settrace(str(trace_file))
@@ -401,7 +405,7 @@ def test_untrace_disables_tracing(tmp_path):
assert sys.gettrace() is None
-def test_untrace_closes_file(tmp_path):
+def test_untrace_closes_file(tmp_path: Path) -> None:
"""Test that untrace closes the trace file."""
trace_file = tmp_path / "test.tsv"
tracer = settrace(str(trace_file))
@@ -414,7 +418,7 @@ def test_untrace_closes_file(tmp_path):
# Tests for main() - script execution
-def test_main_traces_script(tmp_path):
+def test_main_traces_script(tmp_path: Path) -> None:
"""Test main traces a Python script."""
# Create a simple test script
script_file = tmp_path / "test_script.py"
@@ -450,7 +454,7 @@ def simple_function():
assert "entry\tevent\tlevel\tfunction\tvalue\textra" in content
-def test_main_with_nonexistent_script(tmp_path):
+def test_main_with_nonexistent_script(tmp_path: Path) -> None:
"""Test the main CLI with a nonexistent script."""
trace_file = tmp_path / "trace_output.txt"
@@ -472,7 +476,7 @@ def test_main_with_nonexistent_script(tmp_path):
assert match_wrapped(result.stdout, "not found")
-def test_main_module_mode_with_cli_runner(tmp_path):
+def test_main_module_mode_with_cli_runner(tmp_path: Path) -> None:
"""Test the main CLI in module mode with subprocess."""
trace_file = tmp_path / "trace_output.txt"
@@ -495,7 +499,7 @@ def test_main_module_mode_with_cli_runner(tmp_path):
assert trace_file.stat().st_size > 0
-def test_main_module_tracing(tmp_path):
+def test_main_module_tracing(tmp_path: Path) -> None:
"""Test main with module tracing (all module-related scenarios).
Uses subprocess to avoid Click CliRunner I/O conflicts with sys.settrace()
@@ -571,7 +575,9 @@ def test_main_module_tracing(tmp_path):
assert trace_file3.exists()
-def test_main_default_output_filename(tmp_path, monkeypatch):
+def test_main_default_output_filename(
+ tmp_path: Path, monkeypatch: pytest.MonkeyPatch
+) -> None:
"""Test main uses default output filename."""
monkeypatch.chdir(tmp_path)
@@ -593,7 +599,7 @@ def test_main_default_output_filename(tmp_path, monkeypatch):
assert Path("trace.tsv").exists()
-def test_main_short_output_option(tmp_path):
+def test_main_short_output_option(tmp_path: Path) -> None:
"""Test main with -o short option."""
script_file = tmp_path / "test_script.py"
script_file.write_text("x = 1\n")
@@ -616,7 +622,7 @@ def test_main_short_output_option(tmp_path):
assert trace_file.exists()
-def test_main_handles_script_with_system_exit(tmp_path):
+def test_main_handles_script_with_system_exit(tmp_path: Path) -> None:
"""Test main handles scripts that call sys.exit()."""
script_file = tmp_path / "exit_script.py"
script_file.write_text("import sys\nsys.exit(0)\n")
@@ -640,7 +646,7 @@ def test_main_handles_script_with_system_exit(tmp_path):
assert trace_file.exists()
-def test_main_with_subprocess(tmp_path):
+def test_main_with_subprocess(tmp_path: Path) -> None:
"""Test that the script can be executed directly via subprocess.
This test verifies that the __main__ block works correctly.
@@ -663,7 +669,7 @@ def test_main_with_subprocess(tmp_path):
assert trace_file.exists()
-def test_main_with_oserror_in_script(tmp_path):
+def test_main_with_oserror_in_script(tmp_path: Path) -> None:
"""Test main handles OSError during script execution."""
script_file = tmp_path / "error_script.py"
script_file.write_text("raise OSError('Test error')\n")
@@ -687,7 +693,7 @@ def test_main_with_oserror_in_script(tmp_path):
assert trace_file.exists()
-def test_main_with_runtime_error_in_script(tmp_path):
+def test_main_with_runtime_error_in_script(tmp_path: Path) -> None:
"""Test main handles RuntimeError during script execution."""
script_file = tmp_path / "error_script.py"
script_file.write_text("raise RuntimeError('Test error')\n")
@@ -711,7 +717,7 @@ def test_main_with_runtime_error_in_script(tmp_path):
assert trace_file.exists()
-def test_main_with_value_error_in_script(tmp_path):
+def test_main_with_value_error_in_script(tmp_path: Path) -> None:
"""Test main handles ValueError during script execution."""
script_file = tmp_path / "error_script.py"
script_file.write_text("raise ValueError('Test error')\n")
@@ -738,7 +744,7 @@ def test_main_with_value_error_in_script(tmp_path):
# Integration tests
-def test_full_tracing_workflow(tmp_path):
+def test_full_tracing_workflow(tmp_path: Path) -> None:
"""Test complete tracing workflow with actual function execution."""
trace_file = tmp_path / "trace.tsv"
@@ -747,10 +753,10 @@ def test_full_tracing_workflow(tmp_path):
try:
# Execute some code to trace
- def add(a, b):
+ def add(a: int, b: int) -> int:
return a + b
- def multiply(x, y):
+ def multiply(x: int, y: int) -> int:
return x * y
result1 = add(2, 3)
@@ -775,15 +781,15 @@ def multiply(x, y):
assert len(lines) > 1 # Header + at least some trace entries
-def test_tracing_with_nested_calls(tmp_path):
+def test_tracing_with_nested_calls(tmp_path: Path) -> None:
"""Test tracing with nested function calls."""
trace_file = tmp_path / "trace.tsv"
tracer = settrace(str(trace_file))
try:
- def outer():
- def inner():
+ def outer() -> str:
+ def inner() -> str:
return "inner"
return inner()
@@ -800,7 +806,7 @@ def inner():
assert "outer" in content or "inner" in content
-def test_cli_produces_valid_tsv(tmp_path):
+def test_cli_produces_valid_tsv(tmp_path: Path) -> None:
"""Test that CLI produces valid TSV file."""
script_file = tmp_path / "test_script.py"
script_file.write_text("""
@@ -844,7 +850,9 @@ def func():
# Direct main() function tests for coverage
-def test_main_function_with_script(tmp_path, capsys):
+def test_main_function_with_script(
+ tmp_path: Path, capsys: pytest.CaptureFixture[str]
+) -> None:
"""Test main function directly with a script file."""
from firecrown.fctools.tracer import main # pylint: disable=import-outside-toplevel
@@ -863,7 +871,9 @@ def test_main_function_with_script(tmp_path, capsys):
assert "Trace complete" in captured.out
-def test_main_function_with_nonexistent_script(tmp_path, capsys):
+def test_main_function_with_nonexistent_script(
+ tmp_path: Path, capsys: pytest.CaptureFixture[str]
+) -> None:
"""Test main function with nonexistent script."""
from firecrown.fctools.tracer import main # pylint: disable=import-outside-toplevel
@@ -880,7 +890,9 @@ def test_main_function_with_nonexistent_script(tmp_path, capsys):
assert "not found" in captured.out
-def test_main_function_with_module(tmp_path, capsys):
+def test_main_function_with_module(
+ tmp_path: Path, capsys: pytest.CaptureFixture[str]
+) -> None:
"""Test main function in module mode."""
from firecrown.fctools.tracer import main # pylint: disable=import-outside-toplevel
@@ -896,7 +908,9 @@ def test_main_function_with_module(tmp_path, capsys):
assert "Trace complete" in captured.out
-def test_main_function_with_invalid_module(tmp_path, capsys):
+def test_main_function_with_invalid_module(
+ tmp_path: Path, capsys: pytest.CaptureFixture[str]
+) -> None:
"""Test main function with invalid module name."""
from firecrown.fctools.tracer import main # pylint: disable=import-outside-toplevel
@@ -912,7 +926,9 @@ def test_main_function_with_invalid_module(tmp_path, capsys):
assert trace_file.exists()
-def test_main_function_with_script_system_exit(tmp_path, capsys):
+def test_main_function_with_script_system_exit(
+ tmp_path: Path, capsys: pytest.CaptureFixture[str]
+) -> None:
"""Test main function with script that calls sys.exit()."""
from firecrown.fctools.tracer import main # pylint: disable=import-outside-toplevel
@@ -928,7 +944,9 @@ def test_main_function_with_script_system_exit(tmp_path, capsys):
assert trace_file.exists()
-def test_main_function_with_script_import_error(tmp_path, capsys):
+def test_main_function_with_script_import_error(
+ tmp_path: Path, capsys: pytest.CaptureFixture[str]
+) -> None:
"""Test main function with script that has import error."""
from firecrown.fctools.tracer import main # pylint: disable=import-outside-toplevel
@@ -945,7 +963,9 @@ def test_main_function_with_script_import_error(tmp_path, capsys):
assert trace_file.exists()
-def test_main_function_with_script_value_error(tmp_path, capsys):
+def test_main_function_with_script_value_error(
+ tmp_path: Path, capsys: pytest.CaptureFixture[str]
+) -> None:
"""Test main function with script that raises ValueError."""
from firecrown.fctools.tracer import main # pylint: disable=import-outside-toplevel
diff --git a/tests/generators/test_inferred_galaxy_zdist.py b/tests/generators/test_inferred_galaxy_zdist.py
index 6c524b58f..2b213ba68 100644
--- a/tests/generators/test_inferred_galaxy_zdist.py
+++ b/tests/generators/test_inferred_galaxy_zdist.py
@@ -3,7 +3,6 @@
import copy
import re
from itertools import pairwise, product
-from typing import Any
import numpy as np
import numpy.typing as npt
@@ -14,6 +13,7 @@
from scipy.integrate import simpson
from firecrown.generators._inferred_galaxy_zdist import (
+ BinsType,
LSST_Y1_LENS_HARMONIC_BIN_COLLECTION,
LSST_Y1_SOURCE_HARMONIC_BIN_COLLECTION,
LSST_Y10_LENS_HARMONIC_BIN_COLLECTION,
@@ -60,7 +60,7 @@
)
],
)
-def fixture_zdist_y1(request):
+def fixture_zdist_y1(request: pytest.FixtureRequest) -> ZDistLSSTSRD:
"""Fixture for the ZDistLSSTSRD class."""
return request.param[0](
use_autoknot=request.param[1], autoknots_reltol=request.param[2]
@@ -68,7 +68,7 @@ def fixture_zdist_y1(request):
@pytest.fixture(name="z_array", params=[100, 600, 1000])
-def fixture_z_array(request):
+def fixture_z_array(request: pytest.FixtureRequest) -> npt.NDArray[np.float64]:
"""Fixture for the z array."""
return np.linspace(0, 3.0, request.param)
@@ -76,13 +76,13 @@ def fixture_z_array(request):
@pytest.fixture(
name="bins", params=[Y1_LENS_BINS, Y10_LENS_BINS, Y1_SOURCE_BINS, Y10_SOURCE_BINS]
)
-def fixture_bins(request) -> dict[str, Any]:
+def fixture_bins(request: pytest.FixtureRequest) -> BinsType:
"""Fixture for the bins."""
return request.param
@pytest.fixture(name="reltol", params=[1e-4, 1e-5])
-def fixture_reltol(request):
+def fixture_reltol(request: pytest.FixtureRequest) -> float:
"""Fixture for the relative tolerance."""
return request.param
@@ -109,7 +109,9 @@ def fixture_reltol(request):
),
ids=[f"{b[0]}_autoknots_{b[1]}" for b in product(BINS_LIST, [True, False])],
)
-def fixture_zdist_bins(request) -> list[ZDistLSSTSRDBin]:
+def fixture_zdist_bins(
+ request: pytest.FixtureRequest,
+) -> list[ZDistLSSTSRDBin]:
"""Fixture for the ZDistLSSTSRD class."""
match request.param[0]:
case "one_lens_y1":
@@ -140,7 +142,7 @@ def fixture_zdist_bins(request) -> list[ZDistLSSTSRDBin]:
return bins
-def test_zdist(zdist: ZDistLSSTSRD, z_array: npt.NDArray[np.float64]):
+def test_zdist(zdist: ZDistLSSTSRD, z_array: npt.NDArray[np.float64]) -> None:
"""Test the ZDistLSSTSRD class."""
Pz = zdist.distribution(z_array)
assert Pz.shape == z_array.shape
@@ -149,8 +151,8 @@ def test_zdist(zdist: ZDistLSSTSRD, z_array: npt.NDArray[np.float64]):
def test_compute_one_bin_dist(
zdist: ZDistLSSTSRD,
z_array: npt.NDArray[np.float64],
- bins: dict[str, Any],
-):
+ bins: BinsType,
+) -> None:
"""Test the compute_binned_dist method."""
Pz = zdist.binned_distribution(
@@ -170,8 +172,8 @@ def test_compute_one_bin_dist(
def test_compute_all_bins_dist(
zdist: ZDistLSSTSRD,
z_array: npt.NDArray[np.float64],
- bins: dict[str, Any],
-):
+ bins: BinsType,
+) -> None:
"""Test the compute_binned_dist method."""
for zpl, zpu in pairwise(bins["edges"]):
@@ -188,7 +190,7 @@ def test_compute_all_bins_dist(
assert_allclose(simpson(y=Pz.dndz, x=Pz.z), 1.0, atol=1e-3)
-def test_zdist_bin():
+def test_zdist_bin() -> None:
"""Test the ZDistLSSTSRDBin class."""
zpl = 0.1
zpu = 0.2
@@ -214,7 +216,7 @@ def test_zdist_bin():
assert zbin.measurements == measurements
-def test_zdist_bin_generate(zdist: ZDistLSSTSRD):
+def test_zdist_bin_generate(zdist: ZDistLSSTSRD) -> None:
"""Test the ZDistLSSTSRDBin generate method."""
zpl = 0.1
zpu = 0.2
@@ -240,7 +242,7 @@ def test_zdist_bin_generate(zdist: ZDistLSSTSRD):
assert Pz.measurements == measurements
-def test_zdist_bin_from_bad_yaml():
+def test_zdist_bin_from_bad_yaml() -> None:
"""Test that the right exception is thrown if the yaml is malformed."""
bin_yaml = """
zpl: 0.1
@@ -260,7 +262,7 @@ def test_zdist_bin_from_bad_yaml():
_ = base_model_from_yaml(ZDistLSSTSRDBin, bin_yaml)
-def test_zdist_bin_from_yaml():
+def test_zdist_bin_from_yaml() -> None:
"""Test the ZDistLSSTSRDBin class from_json method."""
zpl = 0.1
zpu = 0.2
@@ -291,7 +293,7 @@ def test_zdist_bin_from_yaml():
assert zbin.measurements == measurements
-def test_zdist_bin_to_yaml():
+def test_zdist_bin_to_yaml() -> None:
"""Test the ZDistLSSTSRDBin class to_yaml method."""
zbin = ZDistLSSTSRDBin(
zpl=0.1,
@@ -317,7 +319,7 @@ def test_zdist_bin_to_yaml():
}
-def test_zdist_bin_collection(zdist_bins):
+def test_zdist_bin_collection(zdist_bins: list[ZDistLSSTSRDBin]) -> None:
"""Test the ZDistLSSTSRDBinCollection class."""
alpha = 0.9
beta = 2.0
@@ -333,7 +335,9 @@ def test_zdist_bin_collection(zdist_bins):
assert zbin_collection.bins == zdist_bins
-def test_zdist_bin_collection_generate(zdist_bins):
+def test_zdist_bin_collection_generate(
+ zdist_bins: list[ZDistLSSTSRDBin],
+) -> None:
"""Test the ZDistLSSTSRDBinCollection generate method."""
alpha = 0.9
beta = 2.0
@@ -361,7 +365,9 @@ def test_zdist_bin_collection_generate(zdist_bins):
assert Pz.measurements == zbin.measurements
-def test_zdist_bin_collection_to_yaml(zdist_bins):
+def test_zdist_bin_collection_to_yaml(
+ zdist_bins: list[ZDistLSSTSRDBin],
+) -> None:
"""Test the ZDistLSSTSRDBinCollection to_yaml method."""
alpha = 0.9
beta = 2.0
@@ -398,7 +404,9 @@ def test_zdist_bin_collection_to_yaml(zdist_bins):
}
-def test_zdist_bin_collection_from_yaml(zdist_bins):
+def test_zdist_bin_collection_from_yaml(
+ zdist_bins: list[ZDistLSSTSRDBin],
+) -> None:
"""Test the ZDistLSSTSRDBinCollection from_yaml method."""
alpha = 0.9
beta = 2.0
@@ -437,7 +445,7 @@ def test_zdist_bin_collection_from_yaml(zdist_bins):
assert zbin.measurements == zbin_from_yaml.measurements
-def test_make_measurement_from_measurement():
+def test_make_measurement_from_measurement() -> None:
cluster_meas: set[Measurement] = {Clusters.COUNTS}
galaxy_meas: set[Measurement] = {Galaxies.SHEAR_E}
cmb_meas: set[Measurement] = {CMB.CONVERGENCE}
@@ -446,7 +454,7 @@ def test_make_measurement_from_measurement():
assert make_measurements(cmb_meas) == cmb_meas
-def test_make_measurement_from_dictionary():
+def test_make_measurement_from_dictionary() -> None:
cluster_info = [{"subject": "Clusters", "property": "COUNTS"}]
galaxy_info = [{"subject": "Galaxies", "property": "SHEAR_E"}]
cmb_info = [{"subject": "CMB", "property": "CONVERGENCE"}]
@@ -471,7 +479,7 @@ def test_make_measurement_from_dictionary():
_ = make_measurements({3}) # type: ignore
-def test_distribution(zdist: ZDistLSSTSRD):
+def test_distribution(zdist: ZDistLSSTSRD) -> None:
"""Test the distribution method."""
stats = zdist.compute_distribution(0.03)
@@ -484,7 +492,7 @@ def test_distribution(zdist: ZDistLSSTSRD):
assert_allclose([0.0, middle_z, zdist.max_z], bins)
-def test_true_distribution(zdist: ZDistLSSTSRD):
+def test_true_distribution(zdist: ZDistLSSTSRD) -> None:
"""Test the true_distribution method."""
stats = zdist.compute_true_distribution()
assert isinstance(stats, Ncm.StatsDist1d)
diff --git a/tests/integration/models/two_point/test_theory.py b/tests/integration/models/two_point/test_theory.py
index ab09cb273..80e0e9529 100644
--- a/tests/integration/models/two_point/test_theory.py
+++ b/tests/integration/models/two_point/test_theory.py
@@ -1,8 +1,10 @@
"""Integration tests for the TwoPointTheory class using real Source instances."""
import pytest
+import sacc
-from firecrown.likelihood import Source
+from firecrown.likelihood import Source, Tracer
+from firecrown.modeling_tools import ModelingTools
from firecrown.models.two_point import TwoPointTheory
from firecrown.updatable import ParamsMap
@@ -10,24 +12,24 @@
class FakeSource(Source):
"""A minimal concrete Source implementation for testing."""
- def read_systematics(self, sacc_data) -> None:
+ def read_systematics(self, sacc_data: sacc.Sacc) -> None:
pass
- def _read(self, sacc_data) -> None:
+ def _read(self, sacc_data: sacc.Sacc) -> None:
pass
- def _update_source(self, params) -> None:
+ def _update_source(self, params: ParamsMap) -> None:
pass
def get_scale(self) -> float:
return 1.0
- def create_tracers(self, tools):
- return []
+ def create_tracers(self, tools: ModelingTools) -> tuple[list[Tracer], object]:
+ raise NotImplementedError("FakeSource only supports update and reset tests.")
@pytest.mark.integration
-def test_two_point_theory_update_integration():
+def test_two_point_theory_update_integration() -> None:
"""Integration test: update method updates real sources."""
source1 = FakeSource("tracer_1")
source2 = FakeSource("tracer_2")
@@ -46,7 +48,7 @@ def test_two_point_theory_update_integration():
@pytest.mark.integration
-def test_two_point_theory_reset_integration():
+def test_two_point_theory_reset_integration() -> None:
"""Integration test: reset method resets real sources."""
source1 = FakeSource("tracer_1")
source2 = FakeSource("tracer_2")
diff --git a/tests/likelihood/gauss_family/lkscript_const_gaussian.py b/tests/likelihood/gauss_family/lkscript_const_gaussian.py
index 5c9c3a2f2..cdc57b337 100644
--- a/tests/likelihood/gauss_family/lkscript_const_gaussian.py
+++ b/tests/likelihood/gauss_family/lkscript_const_gaussian.py
@@ -6,6 +6,7 @@
import sacc
from firecrown.likelihood._gaussian import ConstGaussian
+from firecrown.likelihood._likelihood import NamedParameters
from firecrown.likelihood.supernova._supernova import Supernova
from firecrown.modeling_tools import (
CCLFactory,
@@ -14,7 +15,7 @@
)
-def build_likelihood(_):
+def build_likelihood(_: NamedParameters) -> tuple[ConstGaussian, ModelingTools]:
"""Return a ConstGaussian (likelihood) object."""
statistic = Supernova(sacc_tracer="pantheon")
likelihood = ConstGaussian(statistics=[statistic])
diff --git a/tests/likelihood/gauss_family/lkscript_two_point.py b/tests/likelihood/gauss_family/lkscript_two_point.py
index 6aa898d2c..f53dacfd1 100644
--- a/tests/likelihood/gauss_family/lkscript_two_point.py
+++ b/tests/likelihood/gauss_family/lkscript_two_point.py
@@ -19,7 +19,7 @@
)
-def build_likelihood(params: NamedParameters):
+def build_likelihood(params: NamedParameters) -> tuple[ConstGaussian, ModelingTools]:
"""Return a ConstGaussian (likelihood) object."""
sacc_data = sacc.Sacc()
diff --git a/tests/likelihood/gauss_family/lkscript_two_point_pure_ccl.py b/tests/likelihood/gauss_family/lkscript_two_point_pure_ccl.py
index d54d8ca87..3c3352c7d 100644
--- a/tests/likelihood/gauss_family/lkscript_two_point_pure_ccl.py
+++ b/tests/likelihood/gauss_family/lkscript_two_point_pure_ccl.py
@@ -20,7 +20,7 @@
)
-def build_likelihood(params: NamedParameters):
+def build_likelihood(params: NamedParameters) -> tuple[ConstGaussian, ModelingTools]:
"""Return a ConstGaussian (likelihood) object."""
sacc_data = sacc.Sacc()
diff --git a/tests/likelihood/gauss_family/statistic/source/test_source.py b/tests/likelihood/gauss_family/statistic/source/test_source.py
index 5cb6dcf0d..624f5b64b 100644
--- a/tests/likelihood/gauss_family/statistic/source/test_source.py
+++ b/tests/likelihood/gauss_family/statistic/source/test_source.py
@@ -5,7 +5,7 @@
# pylint: disable=too-many-locals
import itertools as it
-from typing import Callable, List
+from typing import Callable, List, Sequence
import numpy as np
import numpy.typing as npt
@@ -30,6 +30,7 @@
from firecrown.likelihood.number_counts._args import NumberCountsArgs
from firecrown.likelihood.weak_lensing import WeakLensingArgs
from firecrown.metadata_functions import extract_all_tracers_tomographic_bins
+from firecrown.metadata_types import TomographicBin
from firecrown.modeling_tools import ModelingTools
from firecrown.updatable import ParamsMap, get_default_params
@@ -53,7 +54,9 @@
"ConstantMagnificationBiasSystematicFactory",
],
)
-def fixture_nc_sys_factory(request) -> nc_factories.NumberCountsSystematicFactory:
+def fixture_nc_sys_factory(
+ request: pytest.FixtureRequest,
+) -> nc_factories.NumberCountsSystematicFactory:
"""Fixture for the NumberCountsSystematicFactory class."""
return request.param
@@ -77,7 +80,9 @@ def fixture_nc_sys_factory(request) -> nc_factories.NumberCountsSystematicFactor
"PhotoZShiftandStretchFactory",
],
)
-def fixture_wl_sys_factory(request):
+def fixture_wl_sys_factory(
+ request: pytest.FixtureRequest,
+) -> wl.WeakLensingSystematicFactory:
"""Fixture for the WeakLensingSystematicFactory class."""
return request.param
@@ -89,16 +94,16 @@ class TrivialSourceGalaxyArgs(SourceGalaxyArgs):
class TrivialSourceGalaxy(SourceGalaxy[TrivialSourceGalaxyArgs]):
"""This is the most trivial possible subclass of SourceGalaxy."""
- def create_tracers(self, tools: ModelingTools):
- return Tracer(pyccl.Tracer()), TrivialSourceGalaxyArgs(
- z=np.array([]), dndz=np.array([])
+ def create_tracers(self, tools: ModelingTools) -> tuple[Sequence[Tracer], object]:
+ raise NotImplementedError(
+ "TrivialSourceGalaxy only supports source argument tests."
)
def get_scale(self) -> float:
return 1.0
-def test_trivial_tracer_construction(empty_pyccl_tracer):
+def test_trivial_tracer_construction(empty_pyccl_tracer: pyccl.Tracer) -> None:
trivial = Tracer(empty_pyccl_tracer)
assert trivial.ccl_tracer is empty_pyccl_tracer
# If we have not assigned a name through the initializer, the name of the resulting
@@ -112,7 +117,7 @@ def test_trivial_tracer_construction(empty_pyccl_tracer):
assert not trivial.has_pt
-def test_tracer_construction_with_name(empty_pyccl_tracer):
+def test_tracer_construction_with_name(empty_pyccl_tracer: pyccl.Tracer) -> None:
named = Tracer(empty_pyccl_tracer, tracer_name="Fred")
assert named.ccl_tracer is empty_pyccl_tracer
assert named.tracer_name == "Fred"
@@ -121,7 +126,7 @@ def test_tracer_construction_with_name(empty_pyccl_tracer):
assert not named.has_pt
-def test_nc_linear_bias_systematic():
+def test_nc_linear_bias_systematic() -> None:
a = nc_sys.LinearBiasSystematic("xxx")
assert isinstance(a, nc_sys.LinearBiasSystematic)
assert a.parameter_prefix == "xxx"
@@ -146,7 +151,7 @@ def test_nc_linear_bias_systematic():
def test_nc_nonlinear_bias_systematic_tracer_args_missing(
tools_with_vanilla_cosmology: ModelingTools,
-):
+) -> None:
a = nc_sys.LinearBiasSystematic("xxx")
# The values in the ParamsMap and the tracer_args are set to allow easy verification
# that a tracer_args of None is handled correctly.
@@ -157,7 +162,7 @@ def test_nc_nonlinear_bias_systematic_tracer_args_missing(
assert np.allclose(new_tracer_args.bias, np.array([1.0]))
-def test_trivial_source_galaxy_construction():
+def test_trivial_source_galaxy_construction() -> None:
trivial = TrivialSourceGalaxy(sacc_tracer="no-sacc-tracer")
with pytest.raises(
@@ -167,7 +172,7 @@ def test_trivial_source_galaxy_construction():
trivial.read(sacc.Sacc())
-def test_trivial_source_select_field():
+def test_trivial_source_select_field() -> None:
tools = ModelingTools()
trivial = TrivialSourceGalaxy(sacc_tracer="no-sacc-tracer")
select_field: SourceGalaxySelectField[SourceGalaxyArgs] = SourceGalaxySelectField(
@@ -183,15 +188,16 @@ def test_trivial_source_select_field():
def test_weak_lensing_source_init(
- sacc_galaxy_cells_src0_src0, tools_with_vanilla_cosmology: ModelingTools
-):
- sacc_data, z, dndz = sacc_galaxy_cells_src0_src0
+ sacc_galaxy_cells_src0_src0: tuple[sacc.Sacc, TomographicBin],
+ tools_with_vanilla_cosmology: ModelingTools,
+) -> None:
+ sacc_data, expected_bin = sacc_galaxy_cells_src0_src0
source = wl.WeakLensing(sacc_tracer="src0")
source.read(sacc_data)
- assert_allclose(source.tracer_args.z, z)
- assert_allclose(source.tracer_args.dndz, dndz)
+ assert_allclose(source.tracer_args.z, expected_bin.z)
+ assert_allclose(source.tracer_args.dndz, expected_bin.dndz)
source.update(ParamsMap())
ts = source.get_tracers(tools_with_vanilla_cosmology)
assert len(ts) == 1
@@ -200,8 +206,10 @@ def test_weak_lensing_source_init(
assert len(dp) == 0
-def test_weak_lensing_source_create_ready(sacc_galaxy_cells_src0_src0):
- sacc_data, _, _ = sacc_galaxy_cells_src0_src0
+def test_weak_lensing_source_create_ready(
+ sacc_galaxy_cells_src0_src0: tuple[sacc.Sacc, TomographicBin],
+) -> None:
+ sacc_data, _ = sacc_galaxy_cells_src0_src0
all_tracers = extract_all_tracers_tomographic_bins(sacc_data)
src0 = next((obj for obj in all_tracers if obj.bin_name == "src0"), None)
@@ -216,8 +224,10 @@ def test_weak_lensing_source_create_ready(sacc_galaxy_cells_src0_src0):
assert_allclose(source_ready.tracer_args.dndz, source_read.tracer_args.dndz)
-def test_weak_lensing_source_factory(sacc_galaxy_cells_src0_src0):
- sacc_data, _, _ = sacc_galaxy_cells_src0_src0
+def test_weak_lensing_source_factory(
+ sacc_galaxy_cells_src0_src0: tuple[sacc.Sacc, TomographicBin],
+) -> None:
+ sacc_data, _ = sacc_galaxy_cells_src0_src0
all_tracers = extract_all_tracers_tomographic_bins(sacc_data)
src0 = next((obj for obj in all_tracers if obj.bin_name == "src0"), None)
@@ -233,8 +243,10 @@ def test_weak_lensing_source_factory(sacc_galaxy_cells_src0_src0):
assert_allclose(source_ready.tracer_args.dndz, source_read.tracer_args.dndz)
-def test_weak_lensing_source_factory_cache(sacc_galaxy_cells_src0_src0):
- sacc_data, _, _ = sacc_galaxy_cells_src0_src0
+def test_weak_lensing_source_factory_cache(
+ sacc_galaxy_cells_src0_src0: tuple[sacc.Sacc, TomographicBin],
+) -> None:
+ sacc_data, _ = sacc_galaxy_cells_src0_src0
all_tracers = extract_all_tracers_tomographic_bins(sacc_data)
src0 = next((obj for obj in all_tracers if obj.bin_name == "src0"), None)
@@ -248,9 +260,10 @@ def test_weak_lensing_source_factory_cache(sacc_galaxy_cells_src0_src0):
@pytest.mark.parametrize("include_z_dependence", [True, False])
def test_weak_lensing_source_factory_global_systematics(
- sacc_galaxy_cells_src0_src0, include_z_dependence
-):
- sacc_data, _, _ = sacc_galaxy_cells_src0_src0
+ sacc_galaxy_cells_src0_src0: tuple[sacc.Sacc, TomographicBin],
+ include_z_dependence: bool,
+) -> None:
+ sacc_data, _ = sacc_galaxy_cells_src0_src0
all_tracers = extract_all_tracers_tomographic_bins(sacc_data)
src0 = next((obj for obj in all_tracers if obj.bin_name == "src0"), None)
@@ -279,8 +292,10 @@ def test_weak_lensing_source_factory_global_systematics(
assert source_ready.systematics == source_read.systematics
-def test_weak_lensing_source_init_wrong_name(sacc_galaxy_cells_src0_src0):
- sacc_data, _, _ = sacc_galaxy_cells_src0_src0
+def test_weak_lensing_source_init_wrong_name(
+ sacc_galaxy_cells_src0_src0: tuple[sacc.Sacc, TomographicBin],
+) -> None:
+ sacc_data, _ = sacc_galaxy_cells_src0_src0
source = wl.WeakLensing(sacc_tracer="src10")
with pytest.raises(KeyError, match="src10"):
@@ -288,16 +303,17 @@ def test_weak_lensing_source_init_wrong_name(sacc_galaxy_cells_src0_src0):
def test_number_counts_source_init(
- sacc_galaxy_cells_lens0_lens0, tools_with_vanilla_cosmology: ModelingTools
-):
+ sacc_galaxy_cells_lens0_lens0: tuple[sacc.Sacc, TomographicBin],
+ tools_with_vanilla_cosmology: ModelingTools,
+) -> None:
- sacc_data, z, dndz = sacc_galaxy_cells_lens0_lens0
+ sacc_data, expected_bin = sacc_galaxy_cells_lens0_lens0
source = nc.NumberCounts(sacc_tracer="lens0")
source.read(sacc_data)
- assert_allclose(source.tracer_args.z, z)
- assert_allclose(source.tracer_args.dndz, dndz)
+ assert_allclose(source.tracer_args.z, expected_bin.z)
+ assert_allclose(source.tracer_args.dndz, expected_bin.dndz)
source.update(ParamsMap(lens0_bias=1.1))
dp = source.get_derived_parameters()
assert dp is not None
@@ -306,8 +322,10 @@ def test_number_counts_source_init(
assert len(ts) == 1
-def test_number_counts_source_create_ready(sacc_galaxy_cells_lens0_lens0):
- sacc_data, _, _ = sacc_galaxy_cells_lens0_lens0
+def test_number_counts_source_create_ready(
+ sacc_galaxy_cells_lens0_lens0: tuple[sacc.Sacc, TomographicBin],
+) -> None:
+ sacc_data, _ = sacc_galaxy_cells_lens0_lens0
all_tracers = extract_all_tracers_tomographic_bins(sacc_data)
lens0 = next((obj for obj in all_tracers if obj.bin_name == "lens0"), None)
@@ -322,8 +340,10 @@ def test_number_counts_source_create_ready(sacc_galaxy_cells_lens0_lens0):
assert_allclose(source_ready.tracer_args.dndz, source_read.tracer_args.dndz)
-def test_number_counts_source_factory(sacc_galaxy_cells_lens0_lens0):
- sacc_data, _, _ = sacc_galaxy_cells_lens0_lens0
+def test_number_counts_source_factory(
+ sacc_galaxy_cells_lens0_lens0: tuple[sacc.Sacc, TomographicBin],
+) -> None:
+ sacc_data, _ = sacc_galaxy_cells_lens0_lens0
all_tracers = extract_all_tracers_tomographic_bins(sacc_data)
lens0 = next((obj for obj in all_tracers if obj.bin_name == "lens0"), None)
@@ -339,8 +359,10 @@ def test_number_counts_source_factory(sacc_galaxy_cells_lens0_lens0):
assert_allclose(source_ready.tracer_args.dndz, source_read.tracer_args.dndz)
-def test_number_counts_source_factory_cache(sacc_galaxy_cells_lens0_lens0):
- sacc_data, _, _ = sacc_galaxy_cells_lens0_lens0
+def test_number_counts_source_factory_cache(
+ sacc_galaxy_cells_lens0_lens0: tuple[sacc.Sacc, TomographicBin],
+) -> None:
+ sacc_data, _ = sacc_galaxy_cells_lens0_lens0
all_tracers = extract_all_tracers_tomographic_bins(sacc_data)
lens0 = next((obj for obj in all_tracers if obj.bin_name == "lens0"), None)
@@ -352,8 +374,10 @@ def test_number_counts_source_factory_cache(sacc_galaxy_cells_lens0_lens0):
assert source_ready is nc_factory.create(tomographic_bin=lens0)
-def test_number_counts_source_factory_global_systematics(sacc_galaxy_cells_lens0_lens0):
- sacc_data, _, _ = sacc_galaxy_cells_lens0_lens0
+def test_number_counts_source_factory_global_systematics(
+ sacc_galaxy_cells_lens0_lens0: tuple[sacc.Sacc, TomographicBin],
+) -> None:
+ sacc_data, _ = sacc_galaxy_cells_lens0_lens0
all_tracers = extract_all_tracers_tomographic_bins(sacc_data)
lens0 = next((obj for obj in all_tracers if obj.bin_name == "lens0"), None)
@@ -378,8 +402,10 @@ def test_number_counts_source_factory_global_systematics(sacc_galaxy_cells_lens0
assert source_ready.systematics == source_read.systematics
-def test_number_counts_source_init_wrong_name(sacc_galaxy_cells_lens0_lens0):
- sacc_data, _, _ = sacc_galaxy_cells_lens0_lens0
+def test_number_counts_source_init_wrong_name(
+ sacc_galaxy_cells_lens0_lens0: tuple[sacc.Sacc, TomographicBin],
+) -> None:
+ sacc_data, _ = sacc_galaxy_cells_lens0_lens0
source = nc.NumberCounts(sacc_tracer="lens10")
with pytest.raises(KeyError, match="lens10"):
@@ -388,48 +414,48 @@ def test_number_counts_source_init_wrong_name(sacc_galaxy_cells_lens0_lens0):
def test_number_counts_systematic_factory(
nc_sys_factory: nc_factories.NumberCountsSystematicFactory,
-):
+) -> None:
sys_pz_shift = nc_sys_factory.create("bin_1")
assert sys_pz_shift.parameter_prefix == "bin_1"
-def test_wl_photozshiftfactory_no_globals():
+def test_wl_photozshiftfactory_no_globals() -> None:
factory = wl.PhotoZShiftFactory()
with pytest.raises(ValueError, match="PhotoZShift cannot be global"):
_ = factory.create_global()
-def test_wl_photozshiftandstretchfactory_no_globals():
+def test_wl_photozshiftandstretchfactory_no_globals() -> None:
factory = wl.PhotoZShiftandStretchFactory()
with pytest.raises(ValueError, match="PhotoZShiftandStretch cannot be global"):
_ = factory.create_global()
-def test_wl_multiplicativeshearbiasfactory_no_globals():
+def test_wl_multiplicativeshearbiasfactory_no_globals() -> None:
factory = wl.MultiplicativeShearBiasFactory()
with pytest.raises(ValueError, match="MultiplicativeShearBias cannot be global"):
_ = factory.create_global()
-def test_nc_photozshiftfactory_no_globals():
+def test_nc_photozshiftfactory_no_globals() -> None:
factory = nc_factories.PhotoZShiftFactory()
with pytest.raises(ValueError, match="PhotoZShift cannot be global"):
_ = factory.create_global()
-def test_nc_photozshiftandstretchfactory_no_globals():
+def test_nc_photozshiftandstretchfactory_no_globals() -> None:
factory = nc_factories.PhotoZShiftandStretchFactory()
with pytest.raises(ValueError, match="PhotoZShiftandStretch cannot be global"):
_ = factory.create_global()
-def test_nc_linearbiassystematicfactory_no_globals():
+def test_nc_linearbiassystematicfactory_no_globals() -> None:
factory = nc_factories.LinearBiasSystematicFactory()
with pytest.raises(ValueError, match="LinearBiasSystematic cannot be global"):
_ = factory.create_global()
-def test_nc_magnificationbiassystematicfactory_no_globals():
+def test_nc_magnificationbiassystematicfactory_no_globals() -> None:
factory = nc_factories.MagnificationBiasSystematicFactory()
with pytest.raises(
ValueError, match="MagnificationBiasSystematic cannot be global"
@@ -437,7 +463,7 @@ def test_nc_magnificationbiassystematicfactory_no_globals():
_ = factory.create_global()
-def test_nc_constantmagnificationbiassystematicfactory_no_globals():
+def test_nc_constantmagnificationbiassystematicfactory_no_globals() -> None:
factory = nc_factories.ConstantMagnificationBiasSystematicFactory()
with pytest.raises(
ValueError, match="ConstantMagnificationBiasSystematic cannot be global"
@@ -447,14 +473,14 @@ def test_nc_constantmagnificationbiassystematicfactory_no_globals():
def test_weak_lensing_systematic_factory(
wl_sys_factory: wl.WeakLensingSystematicFactory,
-):
+) -> None:
sys_pz_shift = wl_sys_factory.create("bin_1")
assert sys_pz_shift.parameter_prefix == "bin_1"
def test_wl_photozshiftandstretch_systematic(
tools_with_vanilla_cosmology: ModelingTools,
-):
+) -> None:
a = wl.PhotoZShiftandStretch("xxx")
assert isinstance(a, wl.PhotoZShiftandStretch)
assert a.parameter_prefix == "xxx"
@@ -489,7 +515,7 @@ def test_wl_photozshiftandstretch_systematic(
def test_nc_photozshiftandstretch_systematic(
tools_with_vanilla_cosmology: ModelingTools,
-):
+) -> None:
a = nc_sys.PhotoZShiftandStretch("xxx")
assert isinstance(a, nc_sys.PhotoZShiftandStretch)
assert a.parameter_prefix == "xxx"
@@ -537,7 +563,7 @@ def test_dndz_shift_active(
[npt.NDArray[np.float64], npt.NDArray[np.float64], float, float],
tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]],
],
-):
+) -> None:
sigma = 0.05
mu = 0.5
shift = 0.1
@@ -563,7 +589,7 @@ def test_dndz_shift_active(
assert_allclose(dndz_interp_vals, dndz_shifted_stretched, rtol=1.0e-6, atol=1.0e-6)
-def test_dndz_shift_and_stretch_active_negative_sigma():
+def test_dndz_shift_and_stretch_active_negative_sigma() -> None:
with pytest.raises(ValueError, match="Stretch Parameter must be positive"):
dndz_shift_and_stretch_active(
z=np.array([0.0, 0.1]),
@@ -573,7 +599,7 @@ def test_dndz_shift_and_stretch_active_negative_sigma():
)
-def test_dndz_shift_and_stretch_passive_negative_sigma():
+def test_dndz_shift_and_stretch_passive_negative_sigma() -> None:
with pytest.raises(ValueError, match="Stretch Parameter must be positive"):
dndz_shift_and_stretch_passive(
z=np.array([0.0, 0.1]),
@@ -586,7 +612,7 @@ def test_dndz_shift_and_stretch_passive_negative_sigma():
@pytest.mark.parametrize("shift,active", it.product([0.0, 0.1, -0.1], [True, False]))
def test_photoz_shift(
tools_with_vanilla_cosmology: ModelingTools, shift: float, active: bool
-):
+) -> None:
photoz_shift = nc_sys.PhotoZShift("John", active=active)
photoz_shift.update(ParamsMap({"John_delta_z": shift}))
sigma = 0.05
@@ -618,7 +644,7 @@ def test_photoz_shift_stretch(
shift: float,
stretch: float,
active: bool,
-):
+) -> None:
photoz_shift_stretch = nc_sys.PhotoZShiftandStretch("John", active=active)
photoz_shift_stretch.update(
ParamsMap({"John_delta_z": shift, "John_sigma_z": stretch})
@@ -650,7 +676,7 @@ def test_photoz_shift_stretch(
def _check_tatt_alignment_systematic_zdep(
sys: wl.TattAlignmentSystematic, include_z_dependence: bool
-):
+) -> None:
"""Check that the TattAlignmentSystematic has the expected z-dependence
parameters.
"""
@@ -672,7 +698,7 @@ def _check_tatt_alignment_systematic_zdep(
@pytest.mark.parametrize("include_z_dependence", [True, False])
-def test_tatt_alignment_systematics(include_z_dependence):
+def test_tatt_alignment_systematics(include_z_dependence: bool) -> None:
sys = wl.TattAlignmentSystematic(include_z_dependence=include_z_dependence)
assert isinstance(sys, wl.TattAlignmentSystematic)
_check_tatt_alignment_systematic_zdep(
@@ -681,7 +707,7 @@ def test_tatt_alignment_systematics(include_z_dependence):
@pytest.mark.parametrize("include_z_dependence", [True, False])
-def test_tatt_alignment_systematic_factory(include_z_dependence):
+def test_tatt_alignment_systematic_factory(include_z_dependence: bool) -> None:
factory = wl.TattAlignmentSystematicFactory(
include_z_dependence=include_z_dependence
)
diff --git a/tests/likelihood/gauss_family/statistic/test_binned_cluster_number_counts.py b/tests/likelihood/gauss_family/statistic/test_binned_cluster_number_counts.py
index 8aba79adc..1a37593b4 100644
--- a/tests/likelihood/gauss_family/statistic/test_binned_cluster_number_counts.py
+++ b/tests/likelihood/gauss_family/statistic/test_binned_cluster_number_counts.py
@@ -4,6 +4,8 @@
import pytest
import sacc
from crow import ClusterAbundance, ClusterShearProfile, kernel, mass_proxy
+from crow.cluster_modules.completeness_models import Completeness
+from crow.cluster_modules.purity_models import Purity
from crow.properties import ClusterProperty
from crow.recipes.binned_exact import ExactBinnedClusterRecipe
from crow.recipes.binned_grid import GridBinnedClusterRecipe
@@ -17,7 +19,9 @@
from firecrown.updatable import get_default_params_map
-def get_base_binned_exact(completeness, purity) -> ExactBinnedClusterRecipe:
+def get_base_binned_exact(
+ completeness: Completeness | None, purity: Purity | None
+) -> ExactBinnedClusterRecipe:
pivot_mass, pivot_redshift = 14.625862906, 0.6
cluster_recipe = ExactBinnedClusterRecipe(
cluster_theory=ClusterAbundance(
@@ -41,7 +45,7 @@ def get_base_binned_exact(completeness, purity) -> ExactBinnedClusterRecipe:
def get_base_binned_grid(
- completeness, purity, is_delta_sigma
+ completeness: Completeness | None, purity: Purity | None, is_delta_sigma: bool
) -> GridBinnedClusterRecipe:
pivot_mass, pivot_redshift = 14.625862906, 0.6
cluster_recipe = GridBinnedClusterRecipe(
diff --git a/tests/likelihood/gauss_family/statistic/test_statistic.py b/tests/likelihood/gauss_family/statistic/test_statistic.py
index daf0677cc..9d562570f 100644
--- a/tests/likelihood/gauss_family/statistic/test_statistic.py
+++ b/tests/likelihood/gauss_family/statistic/test_statistic.py
@@ -15,7 +15,7 @@
VECTOR_CLASSES = (firecrown.data_types.TheoryVector, firecrown.data_types.DataVector)
-def test_vector_create():
+def test_vector_create() -> None:
vals = np.random.random_sample((10,))
assert isinstance(vals, np.ndarray)
assert vals.dtype == np.float64
@@ -27,7 +27,7 @@ def test_vector_create():
assert np.array_equal(vals, result)
-def test_vector_from_list():
+def test_vector_from_list() -> None:
vals = [1.5, 2.5, -3.0, 10.0]
assert isinstance(vals, list)
assert len(vals) == 4
@@ -39,7 +39,7 @@ def test_vector_from_list():
assert result[i] == val
-def test_vector_slicing():
+def test_vector_slicing() -> None:
for cls in VECTOR_CLASSES:
vec = cls.create(np.random.random_sample((12,)))
assert isinstance(vec, cls)
@@ -48,7 +48,7 @@ def test_vector_slicing():
assert isinstance(middle_part, cls)
-def test_vector_copying():
+def test_vector_copying() -> None:
for cls in VECTOR_CLASSES:
vec = cls.create(np.random.random_sample((12,)))
assert isinstance(vec, cls)
@@ -58,7 +58,7 @@ def test_vector_copying():
assert isinstance(vec_copy, cls)
-def test_excplicit_vector_construction():
+def test_excplicit_vector_construction() -> None:
for cls in VECTOR_CLASSES:
vec = cls(shape=(4,), dtype=np.float64)
assert isinstance(vec, cls)
@@ -66,7 +66,7 @@ def test_excplicit_vector_construction():
assert vec.dtype == np.float64
-def test_ufunc_on_vector():
+def test_ufunc_on_vector() -> None:
data = np.array([0.0, 0.25, 0.50])
expected = np.sin(data)
for cls in VECTOR_CLASSES:
@@ -76,7 +76,7 @@ def test_ufunc_on_vector():
assert np.array_equal(result, expected)
-def test_vector_residuals():
+def test_vector_residuals() -> None:
theory = firecrown.data_types.TheoryVector.from_list([1.0, 2.0, 3.0])
data = firecrown.data_types.DataVector.from_list([1.1, 2.1, 3.1])
difference = firecrown.data_types.residuals(data, theory)
@@ -87,7 +87,7 @@ def test_vector_residuals():
def test_guarded_statistic_read_only_once(
sacc_data_for_trivial_stat: sacc.Sacc, trivial_stats: list[stat.TrivialStatistic]
-):
+) -> None:
gs = stat.GuardedStatistic(trivial_stats.pop())
assert not gs.statistic.ready
gs.read(sacc_data_for_trivial_stat)
@@ -100,13 +100,15 @@ def test_guarded_statistic_read_only_once(
def test_guarded_static_read_data_vector(
sacc_data_for_trivial_stat: sacc.Sacc, trivial_stats: list[stat.TrivialStatistic]
-):
+) -> None:
gs = stat.GuardedStatistic(trivial_stats.pop())
gs.read(sacc_data_for_trivial_stat)
assert_allclose(gs.get_data_vector(), [1.0, 4.0, -3.0])
-def test_guarded_statistic_get_data_before_read(trivial_stats):
+def test_guarded_statistic_get_data_before_read(
+ trivial_stats: list[stat.TrivialStatistic],
+) -> None:
s = trivial_stats.pop()
with pytest.raises(
stat.StatisticUnreadError,
@@ -117,13 +119,13 @@ def test_guarded_statistic_get_data_before_read(trivial_stats):
_ = g.get_data_vector()
-def test_statistic_get_data_vector_before_read():
+def test_statistic_get_data_vector_before_read() -> None:
s = stat.TrivialStatistic()
with pytest.raises(AssertionError):
_ = s.get_data_vector()
-def test_guarded_statiistic_compute_theory_before_read():
+def test_guarded_statiistic_compute_theory_before_read() -> None:
gs = stat.GuardedStatistic(stat.TrivialStatistic())
with pytest.raises(
RuntimeError,
@@ -132,13 +134,15 @@ def test_guarded_statiistic_compute_theory_before_read():
gs.compute_theory_vector(ModelingTools())
-def test_statistic_get_data_vector_after_read(sacc_data_for_trivial_stat):
+def test_statistic_get_data_vector_after_read(
+ sacc_data_for_trivial_stat: sacc.Sacc,
+) -> None:
s = stat.TrivialStatistic()
s.read(sacc_data_for_trivial_stat)
assert_allclose(s.get_data_vector(), [1.0, 4.0, -3.0])
-def test_statistic_get_theory_vector_before_compute():
+def test_statistic_get_theory_vector_before_compute() -> None:
s = stat.TrivialStatistic()
with pytest.raises(
RuntimeError, match="The theory for statistic .* has not been computed yet\\."
@@ -146,7 +150,9 @@ def test_statistic_get_theory_vector_before_compute():
_ = s.get_theory_vector()
-def test_statistic_get_theory_vector_after_compute(sacc_data_for_trivial_stat):
+def test_statistic_get_theory_vector_after_compute(
+ sacc_data_for_trivial_stat: sacc.Sacc,
+) -> None:
s = stat.TrivialStatistic()
s.read(sacc_data_for_trivial_stat)
s.update(ParamsMap(mean=10.5))
@@ -154,7 +160,9 @@ def test_statistic_get_theory_vector_after_compute(sacc_data_for_trivial_stat):
assert_allclose(s.get_theory_vector(), [10.5, 10.5, 10.5])
-def test_statistic_get_theory_vector_after_reset(sacc_data_for_trivial_stat):
+def test_statistic_get_theory_vector_after_reset(
+ sacc_data_for_trivial_stat: sacc.Sacc,
+) -> None:
s = stat.TrivialStatistic()
s.read(sacc_data_for_trivial_stat)
s.update(ParamsMap(mean=10.5))
@@ -166,7 +174,7 @@ def test_statistic_get_theory_vector_after_reset(sacc_data_for_trivial_stat):
_ = s.get_theory_vector()
-def test_statistic_compute_theory_vector_before_read():
+def test_statistic_compute_theory_vector_before_read() -> None:
s = stat.TrivialStatistic()
with pytest.raises(
RuntimeError,
@@ -175,7 +183,9 @@ def test_statistic_compute_theory_vector_before_read():
s.compute_theory_vector(ModelingTools())
-def test_statistic_compute_theory_vector_before_update(sacc_data_for_trivial_stat):
+def test_statistic_compute_theory_vector_before_update(
+ sacc_data_for_trivial_stat: sacc.Sacc,
+) -> None:
s = stat.TrivialStatistic()
s.read(sacc_data_for_trivial_stat)
with pytest.raises(
@@ -185,7 +195,9 @@ def test_statistic_compute_theory_vector_before_update(sacc_data_for_trivial_sta
s.compute_theory_vector(ModelingTools())
-def test_statistic_compute_theory_vector_after_update(sacc_data_for_trivial_stat):
+def test_statistic_compute_theory_vector_after_update(
+ sacc_data_for_trivial_stat: sacc.Sacc,
+) -> None:
s = stat.TrivialStatistic()
s.read(sacc_data_for_trivial_stat)
s.update(ParamsMap(mean=10.5))
diff --git a/tests/likelihood/gauss_family/statistic/test_two_point.py b/tests/likelihood/gauss_family/statistic/test_two_point.py
index caf207cb7..d285e4b88 100644
--- a/tests/likelihood/gauss_family/statistic/test_two_point.py
+++ b/tests/likelihood/gauss_family/statistic/test_two_point.py
@@ -3,6 +3,7 @@
"""
import re
+from pathlib import Path
from unittest.mock import MagicMock
import numpy as np
@@ -50,7 +51,7 @@
@pytest.fixture(name="include_rsd", params=[True, False], ids=["rsd", "no_rsd"])
-def fixture_include_rsd(request) -> bool:
+def fixture_include_rsd(request: pytest.FixtureRequest) -> bool:
"""Return whether to include RSD in the test."""
return request.param
@@ -90,18 +91,20 @@ def fixture_two_point_without_window(
@pytest.fixture(name="apply_interp_when", params=list(tp.ApplyInterpolationWhen))
-def fixture_apply_interp_when(request) -> tp.ApplyInterpolationWhen:
+def fixture_apply_interp_when(
+ request: pytest.FixtureRequest,
+) -> tp.ApplyInterpolationWhen:
return request.param
@pytest.fixture(name="window_fixture", params=["with_window", "no_window"])
-def fixture_window_data(request):
+def fixture_window_data(request: pytest.FixtureRequest) -> str:
"""Parameterized fixture for window vs no-window test data."""
return request.param
@pytest.fixture(name="binning_type", params=["lin", "log"])
-def fixture_binning_type(request) -> str:
+def fixture_binning_type(request: pytest.FixtureRequest) -> str:
"""Parameterized fixture for binning types."""
return request.param
@@ -153,15 +156,15 @@ def test_tracer_names() -> None:
def test_two_point_src0_src0_window_parameterized(
window_fixture: str,
- sacc_galaxy_cells_src0_src0_window,
- sacc_galaxy_cells_src0_src0_no_window,
+ sacc_galaxy_cells_src0_src0_window: tuple[sacc.Sacc, TomographicBin],
+ sacc_galaxy_cells_src0_src0_no_window: tuple[sacc.Sacc, TomographicBin],
) -> None:
"""Test TwoPoint theory calculations are repeatable for both window scenarios."""
if window_fixture == "with_window":
- sacc_data, _, _ = sacc_galaxy_cells_src0_src0_window
+ sacc_data, _ = sacc_galaxy_cells_src0_src0_window
expected_window = True
else: # no_window
- sacc_data, _, _ = sacc_galaxy_cells_src0_src0_no_window
+ sacc_data, _ = sacc_galaxy_cells_src0_src0_no_window
expected_window = False
src0 = WeakLensing(sacc_tracer="src0")
@@ -212,10 +215,11 @@ def test_two_point_generate_ell_or_theta() -> None:
def test_two_point_src0_src0_no_data_binning(
- sacc_galaxy_cells_src0_src0_no_data, binning_type: str
+ sacc_galaxy_cells_src0_src0_no_data: tuple[sacc.Sacc, TomographicBin],
+ binning_type: str,
) -> None:
"""Test TwoPoint with different binning types when no data is present."""
- sacc_data, _, _ = sacc_galaxy_cells_src0_src0_no_data
+ sacc_data, _ = sacc_galaxy_cells_src0_src0_no_data
src0 = WeakLensing(sacc_tracer="src0")
@@ -243,12 +247,18 @@ def test_two_point_src0_src0_no_data_binning(
assert all(statistic.ells <= 100)
-def test_two_point_lens0_lens0_no_data(sacc_galaxy_xis_lens0_lens0_no_data) -> None:
- sacc_data, _, _ = sacc_galaxy_xis_lens0_lens0_no_data
+def test_two_point_lens0_lens0_generates_configured_thetas_without_measurements(
+ sacc_galaxy_lens0_no_two_point_data: sacc.Sacc,
+) -> None:
+ """Generate a configured angular grid when correlation measurements are absent.
- src0 = NumberCounts(sacc_tracer="lens0")
+ This tests statistic setup, not a physical correlation prediction.
- ell_config: EllOrThetaConfig = {
+ :param sacc_galaxy_lens0_no_two_point_data: Redshift tracer without two-point data.
+ """
+ lens0 = NumberCounts(sacc_tracer="lens0")
+
+ theta_config: EllOrThetaConfig = {
"minimum": 0.0,
"maximum": 1.0,
"n": 5,
@@ -257,12 +267,12 @@ def test_two_point_lens0_lens0_no_data(sacc_galaxy_xis_lens0_lens0_no_data) -> N
statistic = tp.TwoPoint(
"galaxy_density_xi",
- src0,
- src0,
- ell_or_theta=ell_config,
+ lens0,
+ lens0,
+ ell_or_theta=theta_config,
)
with pytest.warns(UserWarning):
- statistic.read(sacc_data)
+ statistic.read(sacc_galaxy_lens0_no_two_point_data)
assert statistic.window is None
assert statistic.ells is None
@@ -277,7 +287,7 @@ def test_two_point_lens0_lens0_no_data(sacc_galaxy_xis_lens0_lens0_no_data) -> N
maximum=floats(min_value=51, max_value=1000),
n=integers(min_value=2, max_value=20),
)
-def test_ell_generation_bounds_property(minimum: float, maximum: float, n: int):
+def test_ell_generation_bounds_property(minimum: float, maximum: float, n: int) -> None:
"""Test that generated ells are always within specified bounds using hypothesis."""
# Skip invalid cases
assume(minimum < maximum)
@@ -306,7 +316,9 @@ def test_ell_generation_bounds_property(minimum: float, maximum: float, n: int):
maximum=floats(min_value=0.6, max_value=2.0),
n=integers(min_value=2, max_value=15),
)
-def test_theta_generation_bounds_property(minimum: float, maximum: float, n: int):
+def test_theta_generation_bounds_property(
+ minimum: float, maximum: float, n: int
+) -> None:
"""Generated thetas are always within specified bounds using hypothesis."""
# Skip invalid cases
assume(minimum < maximum)
@@ -331,8 +343,10 @@ def test_two_point_theory_construction() -> None:
assert theory.source1 is src0
-def test_two_point_lens0_lens0_config(sacc_galaxy_xis_lens0_lens0) -> None:
- sacc_data, _, _ = sacc_galaxy_xis_lens0_lens0
+def test_two_point_lens0_lens0_config(
+ sacc_galaxy_xis_lens0_lens0: tuple[sacc.Sacc, TomographicBin],
+) -> None:
+ sacc_data, _ = sacc_galaxy_xis_lens0_lens0
src0 = NumberCounts(sacc_tracer="lens0")
@@ -363,8 +377,10 @@ def test_two_point_lens0_lens0_config(sacc_galaxy_xis_lens0_lens0) -> None:
statistic.compute_theory_vector(tools)
-def test_two_point_src0_src0_no_data_error(sacc_galaxy_cells_src0_src0_no_data) -> None:
- sacc_data, _, _ = sacc_galaxy_cells_src0_src0_no_data
+def test_two_point_src0_src0_no_data_error(
+ sacc_galaxy_cells_src0_src0_no_data: tuple[sacc.Sacc, TomographicBin],
+) -> None:
+ sacc_data, _ = sacc_galaxy_cells_src0_src0_no_data
src0 = WeakLensing(sacc_tracer="src0")
@@ -380,14 +396,16 @@ def test_two_point_src0_src0_no_data_error(sacc_galaxy_cells_src0_src0_no_data)
statistic.read(sacc_data)
-def test_two_point_lens0_lens0_no_data_error(
- sacc_galaxy_xis_lens0_lens0_no_data,
+def test_two_point_lens0_lens0_requires_theta_config_without_measurements(
+ sacc_galaxy_lens0_no_two_point_data: sacc.Sacc,
) -> None:
- sacc_data, _, _ = sacc_galaxy_xis_lens0_lens0_no_data
+ """Reject setup without correlation measurements or a theta configuration.
- src0 = NumberCounts(sacc_tracer="lens0")
+ :param sacc_galaxy_lens0_no_two_point_data: Redshift tracer without two-point data.
+ """
+ lens0 = NumberCounts(sacc_tracer="lens0")
- statistic = tp.TwoPoint("galaxy_density_xi", src0, src0)
+ statistic = tp.TwoPoint("galaxy_density_xi", lens0, lens0)
with pytest.warns(UserWarning, match="Empty index selected"):
with pytest.raises(
RuntimeError,
@@ -396,13 +414,13 @@ def test_two_point_lens0_lens0_no_data_error(
"and no input theta values were given"
),
):
- statistic.read(sacc_data)
+ statistic.read(sacc_galaxy_lens0_no_two_point_data)
def test_two_point_src0_src0_data_and_conf_warn(
- sacc_galaxy_cells_src0_src0_window,
+ sacc_galaxy_cells_src0_src0_window: tuple[sacc.Sacc, TomographicBin],
) -> None:
- sacc_data, _, _ = sacc_galaxy_cells_src0_src0_window
+ sacc_data, _ = sacc_galaxy_cells_src0_src0_window
src0 = WeakLensing(sacc_tracer="src0")
@@ -424,8 +442,10 @@ def test_two_point_src0_src0_data_and_conf_warn(
statistic.read(sacc_data)
-def test_two_point_lens0_lens0_data_and_conf_warn(sacc_galaxy_xis_lens0_lens0) -> None:
- sacc_data, _, _ = sacc_galaxy_xis_lens0_lens0
+def test_two_point_lens0_lens0_data_and_conf_warn(
+ sacc_galaxy_xis_lens0_lens0: tuple[sacc.Sacc, TomographicBin],
+) -> None:
+ sacc_data, _ = sacc_galaxy_xis_lens0_lens0
src0 = NumberCounts(sacc_tracer="lens0")
@@ -644,7 +664,7 @@ class ModelWithApplyInterpWhen(BaseModel):
apply_interp_when: tp.ApplyInterpolationWhen
-def test_apply_interp_when_serialization_default():
+def test_apply_interp_when_serialization_default() -> None:
model = ModelWithApplyInterpWhen(
apply_interp_when=tp.ApplyInterpolationWhen.DEFAULT
)
@@ -657,7 +677,7 @@ def test_apply_interp_when_serialization_default():
assert model.apply_interp_when == tp.ApplyInterpolationWhen.DEFAULT
-def test_apply_interp_when_serialization_all():
+def test_apply_interp_when_serialization_all() -> None:
model = ModelWithApplyInterpWhen(apply_interp_when=tp.ApplyInterpolationWhen.ALL)
assert model.apply_interp_when == tp.ApplyInterpolationWhen.ALL
@@ -668,7 +688,7 @@ def test_apply_interp_when_serialization_all():
assert model.apply_interp_when == tp.ApplyInterpolationWhen.ALL
-def test_apply_interp_when_serialization_none():
+def test_apply_interp_when_serialization_none() -> None:
model = ModelWithApplyInterpWhen(apply_interp_when=tp.ApplyInterpolationWhen.NONE)
assert model.apply_interp_when == tp.ApplyInterpolationWhen.NONE
@@ -679,7 +699,9 @@ def test_apply_interp_when_serialization_none():
assert model.apply_interp_when == tp.ApplyInterpolationWhen.NONE
-def test_apply_interp_when_serialization(apply_interp_when: tp.ApplyInterpolationWhen):
+def test_apply_interp_when_serialization(
+ apply_interp_when: tp.ApplyInterpolationWhen,
+) -> None:
model = ModelWithApplyInterpWhen(apply_interp_when=apply_interp_when)
assert model.apply_interp_when == apply_interp_when
@@ -690,7 +712,7 @@ def test_apply_interp_when_serialization(apply_interp_when: tp.ApplyInterpolatio
assert model.apply_interp_when == apply_interp_when
-def test_apply_interp_when_serialization_error():
+def test_apply_interp_when_serialization_error() -> None:
with pytest.raises(
TypeError, match="Cannot parse ApplyInterpolationWhen from value: None"
):
@@ -704,12 +726,12 @@ def test_apply_interp_when_serialization_error():
def test_two_point_src0_src0_window_aiw(
- sacc_galaxy_cells_src0_src0_window: tuple[object, ...],
+ sacc_galaxy_cells_src0_src0_window: tuple[sacc.Sacc, TomographicBin],
apply_interp_when: tp.ApplyInterpolationWhen,
) -> None:
"""This test also makes sure that TwoPoint theory calculations are
repeatable."""
- sacc_data, _, _ = sacc_galaxy_cells_src0_src0_window
+ sacc_data, _ = sacc_galaxy_cells_src0_src0_window
src0 = WeakLensing(sacc_tracer="src0")
@@ -738,10 +760,10 @@ def test_two_point_src0_src0_window_aiw(
def test_two_point_src0_src0_no_window_aiw(
- sacc_galaxy_cells_src0_src0_no_window: tuple[object, ...],
+ sacc_galaxy_cells_src0_src0_no_window: tuple[sacc.Sacc, TomographicBin],
apply_interp_when: tp.ApplyInterpolationWhen,
) -> None:
- sacc_data, _, _ = sacc_galaxy_cells_src0_src0_no_window
+ sacc_data, _ = sacc_galaxy_cells_src0_src0_no_window
src0 = WeakLensing(sacc_tracer="src0")
@@ -800,7 +822,7 @@ def test_two_point_src0_src0_real_aiw(
assert len(cells) != len(statistic.theory.ells_for_xi)
-def test_calculate_pk_with_halo_model():
+def test_calculate_pk_with_halo_model() -> None:
"""Test calculate_pk function when tracers have halo model (covers line 126)."""
from unittest.mock import Mock, patch
@@ -863,7 +885,7 @@ def test_calculate_pk_with_halo_model():
tools.has_pk.assert_called_once_with("test_pk")
-def test_two_point_normalize_window_default():
+def test_two_point_normalize_window_default() -> None:
"""Test that TwoPoint.normalize_window defaults to True."""
source = NumberCounts(sacc_tracer="lens_0")
two_point = tp.TwoPoint(
@@ -874,7 +896,7 @@ def test_two_point_normalize_window_default():
assert two_point.normalize_window is True
-def test_two_point_normalize_window_false():
+def test_two_point_normalize_window_false() -> None:
"""Test that TwoPoint.normalize_window can be set to False."""
source = NumberCounts(sacc_tracer="lens_0")
two_point = tp.TwoPoint(
@@ -886,7 +908,7 @@ def test_two_point_normalize_window_false():
assert two_point.normalize_window is False
-def test_two_point_normalize_window_true_explicit():
+def test_two_point_normalize_window_true_explicit() -> None:
"""Test that TwoPoint.normalize_window can be explicitly set to True."""
source = NumberCounts(sacc_tracer="lens_0")
two_point = tp.TwoPoint(
@@ -899,7 +921,7 @@ def test_two_point_normalize_window_true_explicit():
@pytest.fixture(name="sacc_with_window_for_two_point")
-def fixture_sacc_with_window_for_two_point(tmp_path):
+def fixture_sacc_with_window_for_two_point(tmp_path: Path) -> sacc.Sacc:
"""Create a SACC file with window functions for TwoPoint testing."""
import pyccl
@@ -952,7 +974,9 @@ def fixture_sacc_with_window_for_two_point(tmp_path):
return sacc_data
-def test_two_point_normalize_window_used_in_read(sacc_with_window_for_two_point):
+def test_two_point_normalize_window_used_in_read(
+ sacc_with_window_for_two_point: sacc.Sacc,
+) -> None:
"""Test that normalize_window is actually used during read."""
# Use SACC data with window functions from fixture
sacc_data = sacc_with_window_for_two_point
diff --git a/tests/likelihood/gauss_family/test_const_gaussian.py b/tests/likelihood/gauss_family/test_const_gaussian.py
index b072a9d81..927d7fdb7 100644
--- a/tests/likelihood/gauss_family/test_const_gaussian.py
+++ b/tests/likelihood/gauss_family/test_const_gaussian.py
@@ -14,7 +14,7 @@
from firecrown.likelihood._gaussfamily import Statistic
from firecrown.likelihood._gaussian import ConstGaussian
from firecrown.likelihood._statistic import TrivialStatistic
-from firecrown.likelihood._two_point import TwoPoint
+from firecrown.likelihood._two_point import TwoPoint, TwoPointFactory
from firecrown.metadata_functions import TwoPointHarmonicIndex
from firecrown.metadata_types import Galaxies, TracerNames
from firecrown.modeling_tools import ModelingTools
@@ -23,6 +23,7 @@
RequiredParameters,
SamplerParameter,
)
+from tests._types import SaccGalaxyWindowedFixture
class StatisticWithoutIndices(TrivialStatistic):
@@ -36,18 +37,20 @@ def read(self, sacc_data: sacc.Sacc) -> None:
self.sacc_indices = None
-def test_require_nonempty_statistics():
+def test_require_nonempty_statistics() -> None:
with pytest.raises(ValueError):
_ = ConstGaussian(statistics=[])
-def test_get_cov_fails_before_read(trivial_stats):
+def test_get_cov_fails_before_read(trivial_stats: list[TrivialStatistic]) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
with pytest.raises(AssertionError):
_ = likelihood.get_cov()
-def test_read_with_wrong_statistic_fails(sacc_data_for_trivial_stat):
+def test_read_with_wrong_statistic_fails(
+ sacc_data_for_trivial_stat: sacc.Sacc,
+) -> None:
# Make the first statistic defective.
defective_stat = StatisticWithoutIndices()
likelihood = ConstGaussian(statistics=[defective_stat])
@@ -58,20 +61,26 @@ def test_read_with_wrong_statistic_fails(sacc_data_for_trivial_stat):
likelihood.read(sacc_data_for_trivial_stat)
-def test_get_cov_works_after_read(trivial_stats, sacc_data_for_trivial_stat):
+def test_get_cov_works_after_read(
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
assert np.all(likelihood.get_cov() == np.diag([4.0, 9.0, 16.0]))
-def test_get_cov_with_one_statistic(trivial_stats, sacc_data_for_trivial_stat):
+def test_get_cov_with_one_statistic(
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
assert np.all(likelihood.get_cov(trivial_stats[0]) == np.diag([4.0, 9.0, 16.0]))
-def test_get_cov_with_list_of_statistics(trivial_stats, sacc_data_for_trivial_stat):
+def test_get_cov_with_list_of_statistics(
+ trivial_stats: list[Statistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
@@ -80,7 +89,9 @@ def test_get_cov_with_list_of_statistics(trivial_stats, sacc_data_for_trivial_st
assert np.all(cov == np.diag([4.0, 9.0, 16.0]))
-def test_get_data_vector_fails_before_read(trivial_stats):
+def test_get_data_vector_fails_before_read(
+ trivial_stats: list[TrivialStatistic],
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
with pytest.raises(
AssertionError,
@@ -89,13 +100,17 @@ def test_get_data_vector_fails_before_read(trivial_stats):
_ = likelihood.get_data_vector()
-def test_get_data_vector_works_after_read(trivial_stats, sacc_data_for_trivial_stat):
+def test_get_data_vector_works_after_read(
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
assert np.all(likelihood.get_data_vector() == np.array([1.0, 4.0, -3.0]))
-def test_compute_theory_vector_fails_before_read(trivial_stats):
+def test_compute_theory_vector_fails_before_read(
+ trivial_stats: list[TrivialStatistic],
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
with pytest.raises(
AssertionError,
@@ -105,8 +120,8 @@ def test_compute_theory_vector_fails_before_read(trivial_stats):
def test_compute_theory_vector_fails_before_update(
- trivial_stats, sacc_data_for_trivial_stat
-):
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
with pytest.raises(
@@ -117,8 +132,8 @@ def test_compute_theory_vector_fails_before_update(
def test_compute_theory_vector_works_after_read_and_update(
- trivial_stats, sacc_data_for_trivial_stat
-):
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(firecrown.updatable.ParamsMap(mean=10.5))
@@ -128,7 +143,9 @@ def test_compute_theory_vector_works_after_read_and_update(
)
-def test_compute_theory_vector_called_twice(trivial_stats, sacc_data_for_trivial_stat):
+def test_compute_theory_vector_called_twice(
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(firecrown.updatable.ParamsMap(mean=10.5))
@@ -137,7 +154,9 @@ def test_compute_theory_vector_called_twice(trivial_stats, sacc_data_for_trivial
assert np.all(res_1 == res_2)
-def test_get_theory_vector_fails_before_read(trivial_stats):
+def test_get_theory_vector_fails_before_read(
+ trivial_stats: list[TrivialStatistic],
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
with pytest.raises(
AssertionError,
@@ -149,8 +168,8 @@ def test_get_theory_vector_fails_before_read(trivial_stats):
def test_get_theory_vector_fails_before_update(
- trivial_stats, sacc_data_for_trivial_stat
-):
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
with pytest.raises(
@@ -163,8 +182,8 @@ def test_get_theory_vector_fails_before_update(
def test_get_theory_vector_fails_before_compute_theory_vector(
- trivial_stats, sacc_data_for_trivial_stat
-):
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(firecrown.updatable.ParamsMap(mean=10.5))
@@ -178,8 +197,8 @@ def test_get_theory_vector_fails_before_compute_theory_vector(
def test_get_theory_vector_works_after_read_update_and_compute_theory_vector(
- trivial_stats, sacc_data_for_trivial_stat
-):
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(firecrown.updatable.ParamsMap(mean=10.5))
@@ -188,8 +207,8 @@ def test_get_theory_vector_works_after_read_update_and_compute_theory_vector(
def test_get_theory_vector_fails_after_read_update_compute_theory_vector_and_reset(
- trivial_stats, sacc_data_for_trivial_stat
-):
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(firecrown.updatable.ParamsMap(mean=10.5))
@@ -204,7 +223,9 @@ def test_get_theory_vector_fails_after_read_update_compute_theory_vector_and_res
_ = likelihood.get_theory_vector()
-def test_compute_chisq_fails_before_read(trivial_stats):
+def test_compute_chisq_fails_before_read(
+ trivial_stats: list[TrivialStatistic],
+) -> None:
"""Note that the error message from the direct call to compute_chisq notes
that update() must be called; this can only be called after read()."""
likelihood = ConstGaussian(statistics=trivial_stats)
@@ -215,14 +236,22 @@ def test_compute_chisq_fails_before_read(trivial_stats):
_ = likelihood.compute_chisq(ModelingTools())
-def test_compute_chisq(trivial_stats, sacc_data_for_trivial_stat, trivial_params):
+def test_compute_chisq(
+ trivial_stats: list[TrivialStatistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ trivial_params: firecrown.updatable.ParamsMap,
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(trivial_params)
assert likelihood.compute_chisq(ModelingTools()) == 2.0
-def test_deprecated_compute(trivial_stats, sacc_data_for_trivial_stat, trivial_params):
+def test_deprecated_compute(
+ trivial_stats: list[TrivialStatistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ trivial_params: firecrown.updatable.ParamsMap,
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(trivial_params)
@@ -233,8 +262,10 @@ def test_deprecated_compute(trivial_stats, sacc_data_for_trivial_stat, trivial_p
def test_chisquared_compute_vector_not_implemented(
- trivial_stats, sacc_data_for_trivial_stat, trivial_params
-):
+ trivial_stats: list[TrivialStatistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ trivial_params: firecrown.updatable.ParamsMap,
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(trivial_params)
@@ -253,7 +284,11 @@ def compute(
assert likelihood.compute_chisq(ModelingTools()) == 2.0
-def test_required_parameters(trivial_stats, sacc_data_for_trivial_stat, trivial_params):
+def test_required_parameters(
+ trivial_stats: list[TrivialStatistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ trivial_params: firecrown.updatable.ParamsMap,
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(trivial_params)
@@ -263,7 +298,11 @@ def test_required_parameters(trivial_stats, sacc_data_for_trivial_stat, trivial_
assert likelihood.required_parameters() == expected_params
-def test_derived_parameters(trivial_stats, sacc_data_for_trivial_stat, trivial_params):
+def test_derived_parameters(
+ trivial_stats: list[TrivialStatistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ trivial_params: firecrown.updatable.ParamsMap,
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(trivial_params)
@@ -271,7 +310,11 @@ def test_derived_parameters(trivial_stats, sacc_data_for_trivial_stat, trivial_p
assert likelihood.get_derived_parameters() == expected_params
-def test_reset(trivial_stats, sacc_data_for_trivial_stat, trivial_params):
+def test_reset(
+ trivial_stats: list[TrivialStatistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ trivial_params: firecrown.updatable.ParamsMap,
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(trivial_params)
@@ -282,7 +325,9 @@ def test_reset(trivial_stats, sacc_data_for_trivial_stat, trivial_params):
assert not trivial_stats[0].computed_theory_vector
-def test_missing_covariance(trivial_stats, sacc_with_data_points: sacc.Sacc):
+def test_missing_covariance(
+ trivial_stats: list[TrivialStatistic], sacc_with_data_points: sacc.Sacc
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
with pytest.raises(
RuntimeError,
@@ -293,10 +338,10 @@ def test_missing_covariance(trivial_stats, sacc_with_data_points: sacc.Sacc):
def test_using_good_sacc(
- trivial_stats,
+ trivial_stats: list[TrivialStatistic],
sacc_data_for_trivial_stat: sacc.Sacc,
tools_with_vanilla_cosmology: ModelingTools,
-):
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
params = firecrown.updatable.ParamsMap(mean=10.5)
@@ -307,8 +352,8 @@ def test_using_good_sacc(
def test_after_read_all_statistics_are_ready(
- trivial_stats, sacc_data_for_trivial_stat: sacc.Sacc
-):
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
for gs in likelihood.statistics:
@@ -317,10 +362,10 @@ def test_after_read_all_statistics_are_ready(
def test_make_realization_chisq(
- trivial_stats,
+ trivial_stats: list[TrivialStatistic],
sacc_data_for_trivial_stat: sacc.Sacc,
tools_with_vanilla_cosmology: ModelingTools,
-):
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
params = firecrown.updatable.ParamsMap(mean=10.5)
@@ -344,10 +389,10 @@ def test_make_realization_chisq(
def test_make_realization_chisq_mean(
- trivial_stats,
+ trivial_stats: list[TrivialStatistic],
sacc_data_for_trivial_stat: sacc.Sacc,
tools_with_vanilla_cosmology: ModelingTools,
-):
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
params = firecrown.updatable.ParamsMap(mean=10.5)
@@ -373,10 +418,10 @@ def test_make_realization_chisq_mean(
def test_make_realization_data_vector(
- trivial_stats,
+ trivial_stats: list[TrivialStatistic],
sacc_data_for_trivial_stat: sacc.Sacc,
tools_with_vanilla_cosmology: ModelingTools,
-):
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
params = firecrown.updatable.ParamsMap(mean=10.5)
@@ -416,10 +461,10 @@ def test_make_realization_data_vector(
def test_make_realization_no_noise(
- trivial_stats,
+ trivial_stats: list[TrivialStatistic],
sacc_data_for_trivial_stat: sacc.Sacc,
tools_with_vanilla_cosmology: ModelingTools,
-):
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
params = firecrown.updatable.ParamsMap(mean=10.5)
@@ -437,9 +482,9 @@ def test_make_realization_no_noise(
def test_get_sacc_indices(
- trivial_stats,
+ trivial_stats: list[TrivialStatistic],
sacc_data_for_trivial_stat: sacc.Sacc,
-):
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
@@ -454,9 +499,9 @@ def test_get_sacc_indices(
def test_get_sacc_indices_single_stat(
- trivial_stats,
+ trivial_stats: list[TrivialStatistic],
sacc_data_for_trivial_stat: sacc.Sacc,
-):
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
@@ -466,14 +511,17 @@ def test_get_sacc_indices_single_stat(
def test_access_required_parameters(
- trivial_stats,
-):
+ trivial_stats: list[TrivialStatistic],
+) -> None:
likelihood = ConstGaussian(statistics=trivial_stats)
params = likelihood.required_parameters().get_default_values()
assert params == {"mean": 0.0}
-def test_create_ready(sacc_galaxy_cwindows, tp_factory):
+def test_create_ready(
+ sacc_galaxy_cwindows: SaccGalaxyWindowedFixture,
+ tp_factory: TwoPointFactory,
+) -> None:
sacc_data, _, _ = sacc_galaxy_cwindows
two_point_harmonics = extract_all_harmonic_data(sacc_data)
@@ -485,7 +533,10 @@ def test_create_ready(sacc_galaxy_cwindows, tp_factory):
assert isinstance(likelihood, ConstGaussian)
-def test_create_ready_wrong_size(sacc_galaxy_cwindows, tp_factory):
+def test_create_ready_wrong_size(
+ sacc_galaxy_cwindows: SaccGalaxyWindowedFixture,
+ tp_factory: TwoPointFactory,
+) -> None:
sacc_data, _, _ = sacc_galaxy_cwindows
two_point_harmonics = extract_all_harmonic_data(sacc_data)
@@ -502,7 +553,7 @@ def test_create_ready_wrong_size(sacc_galaxy_cwindows, tp_factory):
ConstGaussian.create_ready(two_points, np.diag([1.0, 2.0, 3.0]))
-def test_create_ready_not_ready(tp_factory):
+def test_create_ready_not_ready(tp_factory: TwoPointFactory) -> None:
metadata: TwoPointHarmonicIndex = {
"data_type": "galaxy_density_xi",
"tracer_names": TracerNames("lens0", "lens0"),
@@ -519,8 +570,10 @@ def test_create_ready_not_ready(tp_factory):
def test_compute_chisq_without_cholesky(
- trivial_stats, sacc_data_for_trivial_stat, trivial_params
-):
+ trivial_stats: list[TrivialStatistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ trivial_params: firecrown.updatable.ParamsMap,
+) -> None:
"""Test compute_chisq with use_cholesky=False.
This test ensures that the parent GaussFamily.compute_chisq_impl() method
diff --git a/tests/likelihood/gauss_family/test_const_gaussianPM.py b/tests/likelihood/gauss_family/test_const_gaussianPM.py
index d057696a6..39555533e 100644
--- a/tests/likelihood/gauss_family/test_const_gaussianPM.py
+++ b/tests/likelihood/gauss_family/test_const_gaussianPM.py
@@ -2,7 +2,8 @@
import os
import re
-from collections.abc import Sequence
+from collections.abc import Callable, Sequence
+from typing import cast
import numpy as np
import numpy.typing as npt
@@ -16,9 +17,20 @@
import firecrown.likelihood.weak_lensing as wl
import firecrown.updatable
from firecrown.data_functions import extract_all_harmonic_data
-from firecrown.likelihood import ConstGaussianPM, Statistic, TrivialStatistic, TwoPoint
+from firecrown.likelihood import (
+ ConstGaussianPM,
+ Statistic,
+ TrivialStatistic,
+ TwoPoint,
+ TwoPointFactory,
+)
from firecrown.likelihood._gaussian_pointmass import PointMassData
-from firecrown.likelihood_base import SourceGalaxy, SourceGalaxyArgs, Tracer
+from firecrown.likelihood_base import (
+ GuardedStatistic,
+ SourceGalaxy,
+ SourceGalaxyArgs,
+ Tracer,
+)
from firecrown.metadata_functions import TwoPointHarmonicIndex
from firecrown.metadata_types import Galaxies, TracerNames
from firecrown.modeling_tools import ModelingTools
@@ -27,6 +39,7 @@
RequiredParameters,
SamplerParameter,
)
+from tests._types import SaccGalaxyWindowedFixture
# Tests that are inherited from ConstGaussian:
@@ -42,18 +55,20 @@ def read(self, sacc_data: sacc.Sacc) -> None:
self.sacc_indices = None
-def test_require_nonempty_statistics():
+def test_require_nonempty_statistics() -> None:
with pytest.raises(ValueError):
_ = ConstGaussianPM(statistics=[])
-def test_get_cov_fails_before_read(trivial_stats):
+def test_get_cov_fails_before_read(trivial_stats: list[TrivialStatistic]) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
with pytest.raises(AssertionError):
_ = likelihood.get_cov()
-def test_read_with_wrong_statistic_fails(sacc_data_for_trivial_stat):
+def test_read_with_wrong_statistic_fails(
+ sacc_data_for_trivial_stat: sacc.Sacc,
+) -> None:
# Make the first statistic defective.
defective_stat = StatisticWithoutIndices()
likelihood = ConstGaussianPM(statistics=[defective_stat])
@@ -64,20 +79,26 @@ def test_read_with_wrong_statistic_fails(sacc_data_for_trivial_stat):
likelihood.read(sacc_data_for_trivial_stat)
-def test_get_cov_works_after_read(trivial_stats, sacc_data_for_trivial_stat):
+def test_get_cov_works_after_read(
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
assert np.all(likelihood.get_cov() == np.diag([4.0, 9.0, 16.0]))
-def test_get_cov_with_one_statistic(trivial_stats, sacc_data_for_trivial_stat):
+def test_get_cov_with_one_statistic(
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
assert np.all(likelihood.get_cov(trivial_stats[0]) == np.diag([4.0, 9.0, 16.0]))
-def test_get_cov_with_list_of_statistics(trivial_stats, sacc_data_for_trivial_stat):
+def test_get_cov_with_list_of_statistics(
+ trivial_stats: list[Statistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
@@ -86,7 +107,9 @@ def test_get_cov_with_list_of_statistics(trivial_stats, sacc_data_for_trivial_st
assert np.all(cov == np.diag([4.0, 9.0, 16.0]))
-def test_get_data_vector_fails_before_read(trivial_stats):
+def test_get_data_vector_fails_before_read(
+ trivial_stats: list[TrivialStatistic],
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
with pytest.raises(
AssertionError,
@@ -95,13 +118,17 @@ def test_get_data_vector_fails_before_read(trivial_stats):
_ = likelihood.get_data_vector()
-def test_get_data_vector_works_after_read(trivial_stats, sacc_data_for_trivial_stat):
+def test_get_data_vector_works_after_read(
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
assert np.all(likelihood.get_data_vector() == np.array([1.0, 4.0, -3.0]))
-def test_compute_theory_vector_fails_before_read(trivial_stats):
+def test_compute_theory_vector_fails_before_read(
+ trivial_stats: list[TrivialStatistic],
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
with pytest.raises(
AssertionError,
@@ -111,8 +138,8 @@ def test_compute_theory_vector_fails_before_read(trivial_stats):
def test_compute_theory_vector_fails_before_update(
- trivial_stats, sacc_data_for_trivial_stat
-):
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
with pytest.raises(
@@ -123,8 +150,8 @@ def test_compute_theory_vector_fails_before_update(
def test_compute_theory_vector_works_after_read_and_update(
- trivial_stats, sacc_data_for_trivial_stat
-):
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(firecrown.updatable.ParamsMap(mean=10.5))
@@ -134,7 +161,9 @@ def test_compute_theory_vector_works_after_read_and_update(
)
-def test_compute_theory_vector_called_twice(trivial_stats, sacc_data_for_trivial_stat):
+def test_compute_theory_vector_called_twice(
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(firecrown.updatable.ParamsMap(mean=10.5))
@@ -143,7 +172,9 @@ def test_compute_theory_vector_called_twice(trivial_stats, sacc_data_for_trivial
assert np.all(res_1 == res_2)
-def test_get_theory_vector_fails_before_read(trivial_stats):
+def test_get_theory_vector_fails_before_read(
+ trivial_stats: list[TrivialStatistic],
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
with pytest.raises(
AssertionError,
@@ -155,8 +186,8 @@ def test_get_theory_vector_fails_before_read(trivial_stats):
def test_get_theory_vector_fails_before_update(
- trivial_stats, sacc_data_for_trivial_stat
-):
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
with pytest.raises(
@@ -169,8 +200,8 @@ def test_get_theory_vector_fails_before_update(
def test_get_theory_vector_fails_before_compute_theory_vector(
- trivial_stats, sacc_data_for_trivial_stat
-):
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(firecrown.updatable.ParamsMap(mean=10.5))
@@ -184,8 +215,8 @@ def test_get_theory_vector_fails_before_compute_theory_vector(
def test_get_theory_vector_works_after_read_update_and_compute_theory_vector(
- trivial_stats, sacc_data_for_trivial_stat
-):
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(firecrown.updatable.ParamsMap(mean=10.5))
@@ -194,8 +225,8 @@ def test_get_theory_vector_works_after_read_update_and_compute_theory_vector(
def test_get_theory_vector_fails_after_read_update_compute_theory_vector_and_reset(
- trivial_stats, sacc_data_for_trivial_stat
-):
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(firecrown.updatable.ParamsMap(mean=10.5))
@@ -210,7 +241,9 @@ def test_get_theory_vector_fails_after_read_update_compute_theory_vector_and_res
_ = likelihood.get_theory_vector()
-def test_compute_chisq_fails_before_read(trivial_stats):
+def test_compute_chisq_fails_before_read(
+ trivial_stats: list[TrivialStatistic],
+) -> None:
"""Note that the error message from the direct call to compute_chisq notes
that update() must be called; this can only be called after read()."""
likelihood = ConstGaussianPM(statistics=trivial_stats)
@@ -223,7 +256,11 @@ def test_compute_chisq_fails_before_read(trivial_stats):
_ = likelihood.compute_chisq(ModelingTools())
-def test_compute_chisq(trivial_stats, sacc_data_for_trivial_stat, trivial_params):
+def test_compute_chisq(
+ trivial_stats: list[TrivialStatistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ trivial_params: firecrown.updatable.ParamsMap,
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(trivial_params)
@@ -234,7 +271,11 @@ def test_compute_chisq(trivial_stats, sacc_data_for_trivial_stat, trivial_params
assert likelihood.compute_chisq(ModelingTools()) == 2.0
-def test_deprecated_compute(trivial_stats, sacc_data_for_trivial_stat, trivial_params):
+def test_deprecated_compute(
+ trivial_stats: list[TrivialStatistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ trivial_params: firecrown.updatable.ParamsMap,
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(trivial_params)
@@ -245,8 +286,10 @@ def test_deprecated_compute(trivial_stats, sacc_data_for_trivial_stat, trivial_p
def test_chisquared_compute_vector_not_implemented(
- trivial_stats, sacc_data_for_trivial_stat, trivial_params
-):
+ trivial_stats: list[TrivialStatistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ trivial_params: firecrown.updatable.ParamsMap,
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(trivial_params)
@@ -269,7 +312,11 @@ def compute(
assert likelihood.compute_chisq(ModelingTools()) == 2.0
-def test_required_parameters(trivial_stats, sacc_data_for_trivial_stat, trivial_params):
+def test_required_parameters(
+ trivial_stats: list[TrivialStatistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ trivial_params: firecrown.updatable.ParamsMap,
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(trivial_params)
@@ -279,7 +326,11 @@ def test_required_parameters(trivial_stats, sacc_data_for_trivial_stat, trivial_
assert likelihood.required_parameters() == expected_params
-def test_derived_parameters(trivial_stats, sacc_data_for_trivial_stat, trivial_params):
+def test_derived_parameters(
+ trivial_stats: list[TrivialStatistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ trivial_params: firecrown.updatable.ParamsMap,
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(trivial_params)
@@ -287,7 +338,11 @@ def test_derived_parameters(trivial_stats, sacc_data_for_trivial_stat, trivial_p
assert likelihood.get_derived_parameters() == expected_params
-def test_reset(trivial_stats, sacc_data_for_trivial_stat, trivial_params):
+def test_reset(
+ trivial_stats: list[TrivialStatistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ trivial_params: firecrown.updatable.ParamsMap,
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(trivial_params)
@@ -302,7 +357,9 @@ def test_reset(trivial_stats, sacc_data_for_trivial_stat, trivial_params):
assert not trivial_stats[0].computed_theory_vector
-def test_missing_covariance(trivial_stats, sacc_with_data_points: sacc.Sacc):
+def test_missing_covariance(
+ trivial_stats: list[TrivialStatistic], sacc_with_data_points: sacc.Sacc
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
with pytest.raises(
RuntimeError,
@@ -313,10 +370,10 @@ def test_missing_covariance(trivial_stats, sacc_with_data_points: sacc.Sacc):
def test_using_good_sacc(
- trivial_stats,
+ trivial_stats: list[TrivialStatistic],
sacc_data_for_trivial_stat: sacc.Sacc,
tools_with_vanilla_cosmology: ModelingTools,
-):
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
params = firecrown.updatable.ParamsMap(mean=10.5)
@@ -331,8 +388,9 @@ def test_using_good_sacc(
def test_after_read_all_statistics_are_ready(
- trivial_stats, sacc_data_for_trivial_stat: sacc.Sacc
-):
+ trivial_stats: list[TrivialStatistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
for gs in likelihood.statistics:
@@ -341,10 +399,10 @@ def test_after_read_all_statistics_are_ready(
def test_make_realization_chisq(
- trivial_stats,
+ trivial_stats: list[TrivialStatistic],
sacc_data_for_trivial_stat: sacc.Sacc,
tools_with_vanilla_cosmology: ModelingTools,
-):
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
params = firecrown.updatable.ParamsMap(mean=10.5)
@@ -376,10 +434,10 @@ def test_make_realization_chisq(
def test_make_realization_chisq_mean(
- trivial_stats,
+ trivial_stats: list[TrivialStatistic],
sacc_data_for_trivial_stat: sacc.Sacc,
tools_with_vanilla_cosmology: ModelingTools,
-):
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
params = firecrown.updatable.ParamsMap(mean=10.5)
@@ -413,10 +471,10 @@ def test_make_realization_chisq_mean(
def test_make_realization_data_vector(
- trivial_stats,
+ trivial_stats: list[TrivialStatistic],
sacc_data_for_trivial_stat: sacc.Sacc,
tools_with_vanilla_cosmology: ModelingTools,
-):
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
params = firecrown.updatable.ParamsMap(mean=10.5)
@@ -460,10 +518,10 @@ def test_make_realization_data_vector(
def test_make_realization_no_noise(
- trivial_stats,
+ trivial_stats: list[TrivialStatistic],
sacc_data_for_trivial_stat: sacc.Sacc,
tools_with_vanilla_cosmology: ModelingTools,
-):
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
params = firecrown.updatable.ParamsMap(mean=10.5)
@@ -485,9 +543,9 @@ def test_make_realization_no_noise(
def test_get_sacc_indices(
- trivial_stats,
+ trivial_stats: list[TrivialStatistic],
sacc_data_for_trivial_stat: sacc.Sacc,
-):
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
@@ -502,9 +560,9 @@ def test_get_sacc_indices(
def test_get_sacc_indices_single_stat(
- trivial_stats,
+ trivial_stats: list[TrivialStatistic],
sacc_data_for_trivial_stat: sacc.Sacc,
-):
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
@@ -514,14 +572,17 @@ def test_get_sacc_indices_single_stat(
def test_access_required_parameters(
- trivial_stats,
-):
+ trivial_stats: list[TrivialStatistic],
+) -> None:
likelihood = ConstGaussianPM(statistics=trivial_stats)
params = likelihood.required_parameters().get_default_values()
assert params == {"mean": 0.0}
-def test_create_ready(sacc_galaxy_cwindows, tp_factory):
+def test_create_ready(
+ sacc_galaxy_cwindows: SaccGalaxyWindowedFixture,
+ tp_factory: TwoPointFactory,
+) -> None:
sacc_data, _, _ = sacc_galaxy_cwindows
two_point_harmonics = extract_all_harmonic_data(sacc_data)
@@ -533,7 +594,10 @@ def test_create_ready(sacc_galaxy_cwindows, tp_factory):
assert isinstance(likelihood, ConstGaussianPM)
-def test_create_ready_wrong_size(sacc_galaxy_cwindows, tp_factory):
+def test_create_ready_wrong_size(
+ sacc_galaxy_cwindows: SaccGalaxyWindowedFixture,
+ tp_factory: TwoPointFactory,
+) -> None:
sacc_data, _, _ = sacc_galaxy_cwindows
two_point_harmonics = extract_all_harmonic_data(sacc_data)
@@ -550,7 +614,7 @@ def test_create_ready_wrong_size(sacc_galaxy_cwindows, tp_factory):
ConstGaussianPM.create_ready(two_points, np.diag([1.0, 2.0, 3.0]))
-def test_create_ready_not_ready(tp_factory):
+def test_create_ready_not_ready(tp_factory: TwoPointFactory) -> None:
metadata: TwoPointHarmonicIndex = {
"data_type": "galaxy_density_xi",
"tracer_names": TracerNames("lens0", "lens0"),
@@ -572,7 +636,14 @@ def test_create_ready_not_ready(tp_factory):
class MockStatistic:
"""A mock statistic with the relevant properties needed to test PM."""
- def __init__(self, sacc_data_type, source0, source1, thetas, get_data_vector):
+ def __init__(
+ self,
+ sacc_data_type: str,
+ source0: SourceGalaxy[SourceGalaxyArgs],
+ source1: SourceGalaxy[SourceGalaxyArgs],
+ thetas: list[float],
+ get_data_vector: Callable[[], npt.NDArray[np.float64]],
+ ) -> None:
self.sacc_data_type = sacc_data_type
self.source0 = source0
self.source1 = source1
@@ -630,7 +701,7 @@ def create_tracers(self, tools: ModelingTools) -> tuple[Sequence[Tracer], object
class MockStatisticContainer:
"""A mock statistic container with the relevant properties needed to test PM."""
- def __init__(self, statistic):
+ def __init__(self, statistic: object) -> None:
self.statistic = statistic
@@ -677,14 +748,14 @@ def fixture_minimal_const_gaussian_PM() -> ConstGaussianPM:
# pylint: disable=protected-access
-def test_precomputed_warning(minimal_const_gaussian_PM):
+def test_precomputed_warning(minimal_const_gaussian_PM: ConstGaussianPM) -> None:
# Check that running the precomputation twice gives a warning.
minimal_const_gaussian_PM._generate_maps()
with pytest.warns(UserWarning):
minimal_const_gaussian_PM._generate_maps()
-def test_uneven_nz_size_error_lens(minimal_const_gaussian_PM):
+def test_uneven_nz_size_error_lens(minimal_const_gaussian_PM: ConstGaussianPM) -> None:
# Check the case of uneven lens N(z) lengths.
tracer_args = SourceGalaxyArgs(
z=np.array([0.1, 0.2, 0.3]), dndz=np.array([1.0, 2.0, 3.0])
@@ -702,7 +773,8 @@ def test_uneven_nz_size_error_lens(minimal_const_gaussian_PM):
lambda: np.array([1.0, 2.0, 3.0]),
)
stat_container = MockStatisticContainer(statistic)
- minimal_const_gaussian_PM.statistics.append(stat_container)
+ # PM internals read only .statistic from these test doubles.
+ minimal_const_gaussian_PM.statistics.append(cast(GuardedStatistic, stat_container))
with pytest.raises(
AssertionError,
match=re.escape("N(z) sampling must be the same for all lens tracers."),
@@ -710,7 +782,9 @@ def test_uneven_nz_size_error_lens(minimal_const_gaussian_PM):
minimal_const_gaussian_PM._generate_maps()
-def test_uneven_nz_size_error_source(minimal_const_gaussian_PM):
+def test_uneven_nz_size_error_source(
+ minimal_const_gaussian_PM: ConstGaussianPM,
+) -> None:
# Check the case of uneven source N(z) lengths.
tracer_args = SourceGalaxyArgs(
z=np.array([0.1, 0.2, 0.3]), dndz=np.array([1.0, 2.0, 3.0])
@@ -728,7 +802,8 @@ def test_uneven_nz_size_error_source(minimal_const_gaussian_PM):
lambda: np.array([1.0, 2.0, 3.0]),
)
stat_container = MockStatisticContainer(statistic)
- minimal_const_gaussian_PM.statistics.append(stat_container)
+ # PM internals read only .statistic from these test doubles.
+ minimal_const_gaussian_PM.statistics.append(cast(GuardedStatistic, stat_container))
with pytest.raises(
AssertionError,
match=re.escape("N(z) sampling must be the same for all source tracers."),
@@ -736,7 +811,7 @@ def test_uneven_nz_size_error_source(minimal_const_gaussian_PM):
minimal_const_gaussian_PM._generate_maps()
-def test_prepare_integrand(minimal_const_gaussian_PM):
+def test_prepare_integrand(minimal_const_gaussian_PM: ConstGaussianPM) -> None:
# Check that _prepare_integrand() behaves as expected.
cosmo = pyccl.CosmologyVanillaLCDM()
@@ -760,7 +835,7 @@ def test_prepare_integrand(minimal_const_gaussian_PM):
assert np.all(minimal_const_gaussian_PM._prepare_integrand(cosmo)) >= 0.0
-def test_compute_betas(minimal_const_gaussian_PM):
+def test_compute_betas(minimal_const_gaussian_PM: ConstGaussianPM) -> None:
# Check that _compute_betas() generate the correct number of betas.
cosmo = pyccl.CosmologyVanillaLCDM()
tracer_args = SourceGalaxyArgs(
@@ -776,7 +851,8 @@ def test_compute_betas(minimal_const_gaussian_PM):
lambda: np.array([1.0, 2.0, 3.0]),
)
stat_container = MockStatisticContainer(statistic)
- minimal_const_gaussian_PM.statistics.append(stat_container)
+ # PM internals read only .statistic from these test doubles.
+ minimal_const_gaussian_PM.statistics.append(cast(GuardedStatistic, stat_container))
minimal_const_gaussian_PM._generate_maps()
assert np.shape(minimal_const_gaussian_PM._compute_betas(cosmo)) == (1, 2)
@@ -788,7 +864,7 @@ def fixture_sacc_data() -> sacc.Sacc:
return sacc.Sacc.load_fits(saccfile)
-def test_PM_correction_matrix(sacc_data):
+def test_PM_correction_matrix(sacc_data: sacc.Sacc) -> None:
# Check that the inverse covariance matrix changes.
stats = {}
stats["xip_src0_src0"] = TwoPoint(
@@ -818,7 +894,7 @@ def test_PM_correction_matrix(sacc_data):
assert not np.isinf(likelihood.inv_cov).any()
-def test_compute_chisq_with_correction(sacc_data):
+def test_compute_chisq_with_correction(sacc_data: sacc.Sacc) -> None:
# Test that compute_chisq_impl works correctly when inv_cov_correction is set
# This tests the truthy branch of the if statement at line 50
stats = {}
@@ -847,7 +923,7 @@ def test_compute_chisq_with_correction(sacc_data):
assert np.isfinite(chisq)
-def test_get_lens_statistic_not_found(sacc_data):
+def test_get_lens_statistic_not_found(sacc_data: sacc.Sacc) -> None:
# Test that _get_lens_statistic raises StopIteration when lens tracer not found
stats = {}
stats["gammat_lens0_src0"] = TwoPoint(
@@ -863,7 +939,7 @@ def test_get_lens_statistic_not_found(sacc_data):
likelihood._get_lens_statistic("nonexistent")
-def test_get_src_statistic_not_found(sacc_data):
+def test_get_src_statistic_not_found(sacc_data: sacc.Sacc) -> None:
# Test that _get_src_statistic raises StopIteration when source tracer not found
stats = {}
stats["gammat_lens0_src0"] = TwoPoint(
@@ -881,11 +957,15 @@ def test_get_src_statistic_not_found(sacc_data):
likelihood._get_src_statistic("nonexistent")
-def test_collect_data_vectors_missing_attributes():
+def test_collect_data_vectors_missing_attributes() -> None:
# Test that _collect_data_vectors raises StopIteration when statistics
# are missing required attributes
class IncompleteStatistic:
- def __init__(self):
+ sacc_data_type: str
+ source0: MockSource
+ source1: MockSource
+
+ def __init__(self) -> None:
# Missing 'thetas' attribute
self.sacc_data_type = "galaxy_shearDensity_xi_t"
tracer_args = SourceGalaxyArgs(z=np.array([0.1]), dndz=np.array([1.0]))
@@ -907,7 +987,10 @@ def __init__(self):
]
)
# Replace statistics with mock - use object.__setattr__ to bypass type checking
- object.__setattr__(likelihood, "statistics", [stat_container])
+ # The double omits `thetas` to trigger _collect_data_vectors' StopIteration.
+ object.__setattr__(
+ likelihood, "statistics", [cast(GuardedStatistic, stat_container)]
+ )
with pytest.raises(StopIteration, match="missing attributes"):
likelihood._collect_data_vectors()
diff --git a/tests/likelihood/gauss_family/test_student_t.py b/tests/likelihood/gauss_family/test_student_t.py
index 159a1577d..3243e11d5 100644
--- a/tests/likelihood/gauss_family/test_student_t.py
+++ b/tests/likelihood/gauss_family/test_student_t.py
@@ -17,44 +17,52 @@
@pytest.fixture(name="trivial_params_student_t")
-def fixture_trivial_params_student_t(trivial_params) -> ParamsMap:
+def fixture_trivial_params_student_t(trivial_params: ParamsMap) -> ParamsMap:
"""Return a ParamsMap with one parameter."""
trivial_params["nu"] = 5.0
return trivial_params
-def test_require_nonempty_statistics():
+def test_require_nonempty_statistics() -> None:
with pytest.raises(ValueError):
_ = StudentT(statistics=[])
-def test_make_realization_vector_not_supported(trivial_stats):
+def test_make_realization_vector_not_supported(
+ trivial_stats: list[Statistic],
+) -> None:
likelihood = StudentT(statistics=trivial_stats)
with pytest.raises(NotImplementedError, match="StudentT"):
likelihood.make_realization_vector()
-def test_update_fails_before_read(trivial_stats, trivial_params_student_t):
+def test_update_fails_before_read(
+ trivial_stats: list[Statistic], trivial_params_student_t: ParamsMap
+) -> None:
likelihood = StudentT(statistics=trivial_stats)
with pytest.raises(AssertionError):
likelihood.update(trivial_params_student_t)
-def test_get_cov_fails_before_read(trivial_stats):
+def test_get_cov_fails_before_read(trivial_stats: list[Statistic]) -> None:
likelihood = StudentT(statistics=trivial_stats)
with pytest.raises(AssertionError):
_ = likelihood.get_cov()
-def test_get_cov_works_after_read(trivial_stats, sacc_data_for_trivial_stat):
+def test_get_cov_works_after_read(
+ trivial_stats: list[Statistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = StudentT(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
assert np.all(likelihood.get_cov() == np.diag([4.0, 9.0, 16.0]))
def test_chisquared(
- trivial_stats, sacc_data_for_trivial_stat, trivial_params_student_t
-):
+ trivial_stats: list[Statistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ trivial_params_student_t: ParamsMap,
+) -> None:
trivial_params_student_t["nu"] = 5.0
likelihood = StudentT(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
@@ -63,8 +71,10 @@ def test_chisquared(
def test_required_parameters(
- trivial_stats, sacc_data_for_trivial_stat, trivial_params_student_t
-):
+ trivial_stats: list[Statistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ trivial_params_student_t: ParamsMap,
+) -> None:
likelihood = StudentT(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(trivial_params_student_t)
@@ -78,8 +88,10 @@ def test_required_parameters(
def test_derived_parameters(
- trivial_stats, sacc_data_for_trivial_stat, trivial_params_student_t
-):
+ trivial_stats: list[Statistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ trivial_params_student_t: ParamsMap,
+) -> None:
likelihood = StudentT(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(trivial_params_student_t)
@@ -87,7 +99,11 @@ def test_derived_parameters(
assert likelihood.get_derived_parameters() == expected_params
-def test_reset(trivial_stats, sacc_data_for_trivial_stat, trivial_params_student_t):
+def test_reset(
+ trivial_stats: list[Statistic],
+ sacc_data_for_trivial_stat: sacc.Sacc,
+ trivial_params_student_t: ParamsMap,
+) -> None:
likelihood = StudentT(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
likelihood.update(trivial_params_student_t)
@@ -98,7 +114,9 @@ def test_reset(trivial_stats, sacc_data_for_trivial_stat, trivial_params_student
assert not trivial_stats[0].computed_theory_vector
-def test_missing_covariance(trivial_stats, sacc_with_data_points: sacc.Sacc):
+def test_missing_covariance(
+ trivial_stats: list[Statistic], sacc_with_data_points: sacc.Sacc
+) -> None:
likelihood = StudentT(statistics=trivial_stats)
with pytest.raises(
RuntimeError,
@@ -109,10 +127,10 @@ def test_missing_covariance(trivial_stats, sacc_with_data_points: sacc.Sacc):
def test_using_good_sacc(
- trivial_stats,
+ trivial_stats: list[Statistic],
sacc_data_for_trivial_stat: sacc.Sacc,
tools_with_vanilla_cosmology: ModelingTools,
-):
+) -> None:
likelihood = StudentT(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
params = firecrown.updatable.ParamsMap(mean=10.5, nu=5.0)
@@ -123,8 +141,8 @@ def test_using_good_sacc(
def test_after_read_all_statistics_are_ready(
- trivial_stats, sacc_data_for_trivial_stat: sacc.Sacc
-):
+ trivial_stats: list[Statistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
likelihood = StudentT(statistics=trivial_stats)
likelihood.read(sacc_data_for_trivial_stat)
for gs in likelihood.statistics:
diff --git a/tests/likelihood/lkdir/lk_derived_parameter.py b/tests/likelihood/lkdir/lk_derived_parameter.py
index 5a46b64a5..665d11734 100644
--- a/tests/likelihood/lkdir/lk_derived_parameter.py
+++ b/tests/likelihood/lkdir/lk_derived_parameter.py
@@ -13,7 +13,9 @@
from . import lkmodule
-def build_likelihood(_: NamedParameters):
+def build_likelihood(
+ _: NamedParameters,
+) -> tuple[lkmodule.DerivedParameterLikelihood, ModelingTools]:
"""Return a DerivedParameterLikelihood object."""
tools = ModelingTools(
ccl_factory=CCLFactory(amplitude_parameter=PoweSpecAmplitudeParameter.SIGMA8)
diff --git a/tests/likelihood/lkdir/lk_needing_param.py b/tests/likelihood/lkdir/lk_needing_param.py
index 58af3a186..1f34deafd 100644
--- a/tests/likelihood/lkdir/lk_needing_param.py
+++ b/tests/likelihood/lkdir/lk_needing_param.py
@@ -13,7 +13,9 @@
from . import lkmodule
-def build_likelihood(params: NamedParameters):
+def build_likelihood(
+ params: NamedParameters,
+) -> tuple[lkmodule.ParamaterizedLikelihood, ModelingTools]:
"""Return a ParameterizedLikelihood object."""
tools = ModelingTools(
ccl_factory=CCLFactory(amplitude_parameter=PoweSpecAmplitudeParameter.SIGMA8)
diff --git a/tests/likelihood/lkdir/lk_sampler_parameter.py b/tests/likelihood/lkdir/lk_sampler_parameter.py
index 1a0159ba1..c0f389c8d 100644
--- a/tests/likelihood/lkdir/lk_sampler_parameter.py
+++ b/tests/likelihood/lkdir/lk_sampler_parameter.py
@@ -14,7 +14,9 @@
from . import lkmodule
-def build_likelihood(params: NamedParameters):
+def build_likelihood(
+ params: NamedParameters,
+) -> tuple[lkmodule.SamplerParameterLikelihood, ModelingTools]:
"""Return a SamplerParameterLikelihood object."""
tools = ModelingTools(
ccl_factory=CCLFactory(amplitude_parameter=PoweSpecAmplitudeParameter.SIGMA8)
diff --git a/tests/likelihood/lkdir/lkmodule.py b/tests/likelihood/lkdir/lkmodule.py
index f8ba95fab..578547db7 100644
--- a/tests/likelihood/lkdir/lkmodule.py
+++ b/tests/likelihood/lkdir/lkmodule.py
@@ -75,7 +75,7 @@ class DerivedParameterLikelihood(Likelihood):
"""A minimal likelihood for testing. This likelihood requires a parameter
named 'sacc_filename'."""
- def __init__(self):
+ def __init__(self) -> None:
"""Initialize the DerivedParameterLikelihood where _get_derived_parameters
creates a derived parameter called "derived_param0".
"""
@@ -95,16 +95,16 @@ def compute_loglike(self, tools: ModelingTools) -> float:
return -3.14
-def parameterized_likelihood(params: NamedParameters):
+def parameterized_likelihood(params: NamedParameters) -> ParamaterizedLikelihood:
"""Return a ParameterizedLikelihood object."""
return ParamaterizedLikelihood(params)
-def sampler_parameter_likelihood(params: NamedParameters):
+def sampler_parameter_likelihood(params: NamedParameters) -> SamplerParameterLikelihood:
"""Return a SamplerParameterLikelihood object."""
return SamplerParameterLikelihood(params)
-def derived_parameter_likelihood():
+def derived_parameter_likelihood() -> DerivedParameterLikelihood:
"""Return a DerivedParameterLikelihood object."""
return DerivedParameterLikelihood()
diff --git a/tests/likelihood/lkdir/lkscript.py b/tests/likelihood/lkdir/lkscript.py
index 3931e63d4..8e5e42b95 100644
--- a/tests/likelihood/lkdir/lkscript.py
+++ b/tests/likelihood/lkdir/lkscript.py
@@ -2,6 +2,7 @@
Provides a trivial likelihood factory function for testing purposes.
"""
+from firecrown.likelihood._likelihood import NamedParameters
from firecrown.modeling_tools import (
CCLFactory,
ModelingTools,
@@ -16,7 +17,9 @@
import lkmodule # type: ignore
-def build_likelihood(_):
+def build_likelihood(
+ _: NamedParameters,
+) -> tuple[lkmodule.EmptyLikelihood, ModelingTools]:
"""Return an EmptyLikelihood object."""
tools = ModelingTools(
ccl_factory=CCLFactory(amplitude_parameter=PoweSpecAmplitudeParameter.SIGMA8)
diff --git a/tests/likelihood/lkdir/lkscript_invalid.py b/tests/likelihood/lkdir/lkscript_invalid.py
index 3e1197f7c..5e0c5ffcf 100644
--- a/tests/likelihood/lkdir/lkscript_invalid.py
+++ b/tests/likelihood/lkdir/lkscript_invalid.py
@@ -5,9 +5,11 @@
a build_likelihood Callable.
"""
+from firecrown.likelihood._likelihood import NamedParameters
+
from . import lkmodule
-def not_a_build_likelihood(_):
+def not_a_build_likelihood(_: NamedParameters) -> lkmodule.EmptyLikelihood:
"""Return an EmptyLikelihood object."""
return lkmodule.empty_likelihood()
diff --git a/tests/likelihood/lkdir/lkscript_pure_ccl.py b/tests/likelihood/lkdir/lkscript_pure_ccl.py
index 899e2fc7f..03b21107b 100644
--- a/tests/likelihood/lkdir/lkscript_pure_ccl.py
+++ b/tests/likelihood/lkdir/lkscript_pure_ccl.py
@@ -2,6 +2,7 @@
Provides a trivial likelihood factory function with PURE_CCL_MODE for testing purposes.
"""
+from firecrown.likelihood._likelihood import NamedParameters
from firecrown.modeling_tools import (
CCLCreationMode,
CCLFactory,
@@ -12,7 +13,9 @@
from . import lkmodule
-def build_likelihood(_):
+def build_likelihood(
+ _: NamedParameters,
+) -> tuple[lkmodule.EmptyLikelihood, ModelingTools]:
"""Return an EmptyLikelihood object with PURE_CCL_MODE."""
tools = ModelingTools(
ccl_factory=CCLFactory(
diff --git a/tests/likelihood/lkdir/lkscript_returns_wrong_type.py b/tests/likelihood/lkdir/lkscript_returns_wrong_type.py
index 6e13b0f6d..d133fc775 100644
--- a/tests/likelihood/lkdir/lkscript_returns_wrong_type.py
+++ b/tests/likelihood/lkdir/lkscript_returns_wrong_type.py
@@ -5,7 +5,9 @@
a Likelihood object.
"""
+from firecrown.likelihood._likelihood import NamedParameters
-def build_likelihood(_):
+
+def build_likelihood(_: NamedParameters) -> str:
"""Return an EmptyLikelihood object."""
return "Not a Likelihood"
diff --git a/tests/likelihood/lkdir/lkscript_returns_wrong_type_tools.py b/tests/likelihood/lkdir/lkscript_returns_wrong_type_tools.py
index 81b84b4e2..35052ff87 100644
--- a/tests/likelihood/lkdir/lkscript_returns_wrong_type_tools.py
+++ b/tests/likelihood/lkdir/lkscript_returns_wrong_type_tools.py
@@ -5,9 +5,11 @@
a Likelihood object.
"""
+from firecrown.likelihood._likelihood import NamedParameters
+
from . import lkmodule
-def build_likelihood(_):
+def build_likelihood(_: NamedParameters) -> tuple[lkmodule.EmptyLikelihood, str]:
"""Return an EmptyLikelihood object."""
return lkmodule.empty_likelihood(), "Not a ModelingTools"
diff --git a/tests/likelihood/test_cosmosis_likelihood.py b/tests/likelihood/test_cosmosis_likelihood.py
index 8a5a151b5..2b9cdea02 100644
--- a/tests/likelihood/test_cosmosis_likelihood.py
+++ b/tests/likelihood/test_cosmosis_likelihood.py
@@ -14,13 +14,13 @@ def make_config() -> DataBlock:
return db
-def test_module_cleanup(config: DataBlock):
+def test_module_cleanup(config: DataBlock) -> None:
"""The module's cleanup function just returns zero."""
m = like.setup(config)
status = like.cleanup(m)
assert status == 0
-def test_module_init(config: DataBlock):
+def test_module_init(config: DataBlock) -> None:
module = like.setup(config)
assert isinstance(module, like.FirecrownLikelihood)
diff --git a/tests/likelihood/test_factories.py b/tests/likelihood/test_factories.py
index 95339c5cf..df4832e7d 100644
--- a/tests/likelihood/test_factories.py
+++ b/tests/likelihood/test_factories.py
@@ -103,7 +103,9 @@ def test_two_point_factory_dict() -> None:
"correlation_space",
[TwoPointCorrelationSpace.HARMONIC, TwoPointCorrelationSpace.REAL],
)
-def test_two_point_factory_to_from_dict(correlation_space) -> None:
+def test_two_point_factory_to_from_dict(
+ correlation_space: TwoPointCorrelationSpace,
+) -> None:
two_point_factory = TwoPointFactory(
correlation_space=correlation_space,
weak_lensing_factories=[
@@ -570,7 +572,9 @@ def test_build_two_point_likelihood_invalid_likelihood_config(tmp_path: Path) ->
_ = build_two_point_likelihood(build_parameters)
-def test_build_two_point_harmonic_with_filter(empty_factory_harmonic) -> None:
+def test_build_two_point_harmonic_with_filter(
+ empty_factory_harmonic: TwoPointFactory,
+) -> None:
two_point_experiment = TwoPointExperiment(
two_point_factory=empty_factory_harmonic,
data_source=DataSourceSacc(
@@ -594,7 +598,7 @@ def test_build_two_point_harmonic_with_filter(empty_factory_harmonic) -> None:
def test_build_two_point_harmonic_with_filter_require_filter(
- empty_factory_harmonic,
+ empty_factory_harmonic: TwoPointFactory,
) -> None:
two_point_experiment = TwoPointExperiment(
two_point_factory=empty_factory_harmonic,
@@ -619,7 +623,9 @@ def test_build_two_point_harmonic_with_filter_require_filter(
_ = two_point_experiment.make_likelihood()
-def test_build_two_point_harmonic_with_filter_empty(empty_factory_harmonic) -> None:
+def test_build_two_point_harmonic_with_filter_empty(
+ empty_factory_harmonic: TwoPointFactory,
+) -> None:
two_point_experiment = TwoPointExperiment(
two_point_factory=empty_factory_harmonic,
data_source=DataSourceSacc(
@@ -747,7 +753,7 @@ def test_build_from_measurement_harmonic_cwindow(
assert isinstance(two_point0, TwoPoint)
-def test_two_point_factory_get_wl_factory():
+def test_two_point_factory_get_wl_factory() -> None:
wl_factory1 = WeakLensingFactory(type_source=TypeSource("ts1"))
wl_factory2 = WeakLensingFactory(type_source=TypeSource("ts2"))
wl_factory_default = WeakLensingFactory()
@@ -766,7 +772,7 @@ def test_two_point_factory_get_wl_factory():
assert wl_factory0 is wl_factory
-def test_two_point_factory_get_nc_factory():
+def test_two_point_factory_get_nc_factory() -> None:
nc_factory1 = NumberCountsFactory(type_source=TypeSource("ts1"))
nc_factory2 = NumberCountsFactory(type_source=TypeSource("ts2"))
nc_factory_default = NumberCountsFactory()
@@ -785,7 +791,7 @@ def test_two_point_factory_get_nc_factory():
assert nc_factory0 is nc_factory
-def test_two_point_factory_two_equal_wls():
+def test_two_point_factory_two_equal_wls() -> None:
with pytest.raises(
ValueError, match="Duplicate WeakLensingFactory found for type_source ts1"
):
@@ -798,7 +804,7 @@ def test_two_point_factory_two_equal_wls():
)
-def test_two_point_factory_two_equal_ncs():
+def test_two_point_factory_two_equal_ncs() -> None:
with pytest.raises(
ValueError, match="Duplicate NumberCountsFactory found for type_source ts1"
):
@@ -811,7 +817,7 @@ def test_two_point_factory_two_equal_ncs():
)
-def test_two_point_factory_get_unavailable_wl_factory():
+def test_two_point_factory_get_unavailable_wl_factory() -> None:
factory = TwoPointFactory(
correlation_space=TwoPointCorrelationSpace.HARMONIC,
weak_lensing_factories=[
@@ -824,7 +830,7 @@ def test_two_point_factory_get_unavailable_wl_factory():
_ = factory.get_factory(Galaxies.SHEAR_E, type_source=TypeSource("ts2"))
-def test_two_point_factory_get_unavailable_nc_factory():
+def test_two_point_factory_get_unavailable_nc_factory() -> None:
factory = TwoPointFactory(
correlation_space=TwoPointCorrelationSpace.HARMONIC,
number_counts_factories=[
@@ -850,12 +856,12 @@ def test_two_point_factory_get_unavailable_nc_factory():
("../example.txt", Path("../example.txt")),
],
)
-def test_ensure_path(file, expected):
+def test_ensure_path(file: str | Path, expected: Path) -> None:
result = ensure_path(file)
assert result == expected
-def test_ensure_path_invalid():
+def test_ensure_path_invalid() -> None:
with pytest.raises(
AssertionError, match="Expected code to be unreachable, but got: 123"
):
@@ -863,7 +869,7 @@ def test_ensure_path_invalid():
def test_build_two_point_likelihood_harmonic_filters_result_empty(
- empty_factory_harmonic,
+ empty_factory_harmonic: TwoPointFactory,
) -> None:
"""Test case where filters remove all data in harmonic space."""
two_point_experiment = TwoPointExperiment(
@@ -1014,7 +1020,7 @@ def test_build_two_point_likelihood_real_with_filters_fast() -> None:
assert likelihood is not None
-def test_two_point_factory_two_equal_cmbs():
+def test_two_point_factory_two_equal_cmbs() -> None:
"""Test that duplicate CMBConvergenceFactory with same type_source raises error."""
with pytest.raises(
ValueError, match="Duplicate CMBConvergenceFactory found for type_source ts1"
@@ -1028,7 +1034,7 @@ def test_two_point_factory_two_equal_cmbs():
)
-def test_two_point_factory_get_cmb_factory():
+def test_two_point_factory_get_cmb_factory() -> None:
"""Test getting CMB factories by type_source."""
cmb_factory1 = CMBConvergenceFactory(type_source=TypeSource("ts1"))
cmb_factory2 = CMBConvergenceFactory(type_source=TypeSource("ts2"))
@@ -1049,7 +1055,7 @@ def test_two_point_factory_get_cmb_factory():
assert cmb_factory0 is cmb_factory
-def test_two_point_factory_get_unavailable_cmb_factory():
+def test_two_point_factory_get_unavailable_cmb_factory() -> None:
"""Test error when requesting unavailable CMB factory type_source."""
factory = TwoPointFactory(
correlation_space=TwoPointCorrelationSpace.HARMONIC,
@@ -1063,7 +1069,7 @@ def test_two_point_factory_get_unavailable_cmb_factory():
_ = factory.get_factory(CMB.CONVERGENCE, type_source=TypeSource("ts2"))
-def test_two_point_factory_cmb_measurement_handling():
+def test_two_point_factory_cmb_measurement_handling() -> None:
"""Test that CMB measurements are properly handled by get_factory."""
cmb_factory = CMBConvergenceFactory()
factory = TwoPointFactory(
@@ -1077,7 +1083,7 @@ def test_two_point_factory_cmb_measurement_handling():
assert result_factory is cmb_factory
-def test_two_point_factory_cmb_measurement_with_type_source():
+def test_two_point_factory_cmb_measurement_with_type_source() -> None:
"""Test CMB measurement handling with specific type_source."""
cmb_factory1 = CMBConvergenceFactory(type_source=TypeSource("ts1"))
cmb_factory2 = CMBConvergenceFactory(type_source=TypeSource("ts2"))
@@ -1101,7 +1107,7 @@ def test_two_point_factory_cmb_measurement_with_type_source():
assert result_factory2 is cmb_factory2
-def test_two_point_factory_all_cmb_types():
+def test_two_point_factory_all_cmb_types() -> None:
"""Test that all CMB measurement types are handled correctly."""
cmb_factory = CMBConvergenceFactory()
factory = TwoPointFactory(
@@ -1116,7 +1122,7 @@ def test_two_point_factory_all_cmb_types():
assert result_factory is cmb_factory
-def test_two_point_factory_measurement_not_supported():
+def test_two_point_factory_measurement_not_supported() -> None:
"""Test that measurements not supported by the factory raise an error."""
factory = TwoPointFactory(
correlation_space=TwoPointCorrelationSpace.HARMONIC,
@@ -1129,7 +1135,7 @@ def test_two_point_factory_measurement_not_supported():
_ = factory.get_factory(Clusters.COUNTS)
-def test_two_point_factory_all_factories():
+def test_two_point_factory_all_factories() -> None:
"""Test that all factory types are handled correctly."""
wl_factory = WeakLensingFactory(type_source=TypeSource("ts_wl"))
nc_factory = NumberCountsFactory(type_source=TypeSource("ts_nc"))
@@ -1154,19 +1160,19 @@ def test_two_point_factory_all_factories():
assert cmb_result is cmb_factory
-def test_load_sacc_data_file_not_found():
+def test_load_sacc_data_file_not_found() -> None:
"""Test load_sacc_data raises FileNotFoundError for non-existent file."""
with pytest.raises(FileNotFoundError, match="SACC file not found"):
load_sacc_data("nonexistent_file.fits")
-def test_load_sacc_data_file_not_found_with_path():
+def test_load_sacc_data_file_not_found_with_path() -> None:
"""Test load_sacc_data raises FileNotFoundError with Path object."""
with pytest.raises(FileNotFoundError, match="SACC file not found"):
load_sacc_data(Path("/tmp/nonexistent_file.sacc"))
-def test_load_sacc_data_both_formats_fail(tmp_path):
+def test_load_sacc_data_both_formats_fail(tmp_path: Path) -> None:
"""Test load_sacc_data raises ValueError when file is neither HDF5 nor FITS."""
# Create a file with invalid content (not HDF5, not FITS)
bad_file = tmp_path / "corrupted.sacc"
@@ -1182,7 +1188,7 @@ def test_load_sacc_data_both_formats_fail(tmp_path):
load_sacc_data(bad_file)
-def test_load_sacc_data_ambiguous_extension_hdf5_content(tmp_path):
+def test_load_sacc_data_ambiguous_extension_hdf5_content(tmp_path: Path) -> None:
"""Test load_sacc_data loads a .sacc-suffixed file with HDF5 content."""
hdf5_file = tmp_path / "data.sacc"
s = sacc.Sacc()
@@ -1194,7 +1200,7 @@ def test_load_sacc_data_ambiguous_extension_hdf5_content(tmp_path):
assert isinstance(sacc_data, sacc.Sacc)
-def test_load_sacc_data_ambiguous_extension_fits_content(tmp_path):
+def test_load_sacc_data_ambiguous_extension_fits_content(tmp_path: Path) -> None:
"""Test load_sacc_data loads a .sacc-suffixed file with FITS content."""
fits_file = tmp_path / "data.sacc"
s = sacc.Sacc()
@@ -1206,14 +1212,14 @@ def test_load_sacc_data_ambiguous_extension_fits_content(tmp_path):
assert isinstance(sacc_data, sacc.Sacc)
-def test_load_sacc_data_with_path_object():
+def test_load_sacc_data_with_path_object() -> None:
"""Test load_sacc_data works with Path object input."""
sacc_data = load_sacc_data(Path("tests/bug_398.sacc.gz"))
assert sacc_data is not None
assert isinstance(sacc_data, sacc.Sacc)
-def test_load_sacc_data_with_string():
+def test_load_sacc_data_with_string() -> None:
"""Test load_sacc_data works with string input."""
sacc_data = load_sacc_data("tests/bug_398.sacc.gz")
assert sacc_data is not None
@@ -1221,7 +1227,7 @@ def test_load_sacc_data_with_string():
@pytest.fixture(name="sacc_with_window", scope="function")
-def fixture_sacc_with_window(tmp_path: Path):
+def fixture_sacc_with_window(tmp_path: Path) -> Path:
"""Create a SACC file with window functions for testing normalize_window."""
# Create window function data
n_ell_bin = 5
@@ -1287,13 +1293,15 @@ def fixture_sacc_with_window(tmp_path: Path):
return sacc_file
-def test_data_source_sacc_normalize_window_default(sacc_with_window: Path):
+def test_data_source_sacc_normalize_window_default(sacc_with_window: Path) -> None:
"""Test that DataSourceSacc.normalize_window defaults to True."""
data_source = DataSourceSacc(sacc_data_file=str(sacc_with_window))
assert data_source.normalize_window is True
-def test_data_source_sacc_normalize_window_false_dict(sacc_with_window: Path):
+def test_data_source_sacc_normalize_window_false_dict(
+ sacc_with_window: Path,
+) -> None:
"""Test DataSourceSacc.normalize_window can be set to False via dict."""
data_source_dict = {
"sacc_data_file": str(sacc_with_window),
@@ -1303,7 +1311,9 @@ def test_data_source_sacc_normalize_window_false_dict(sacc_with_window: Path):
assert data_source.normalize_window is False
-def test_data_source_sacc_normalize_window_false_direct(sacc_with_window: Path):
+def test_data_source_sacc_normalize_window_false_direct(
+ sacc_with_window: Path,
+) -> None:
"""Test DataSourceSacc.normalize_window can be set to False directly."""
data_source = DataSourceSacc(
sacc_data_file=str(sacc_with_window), normalize_window=False
@@ -1311,7 +1321,9 @@ def test_data_source_sacc_normalize_window_false_direct(sacc_with_window: Path):
assert data_source.normalize_window is False
-def test_data_source_sacc_normalize_window_true_explicit(sacc_with_window: Path):
+def test_data_source_sacc_normalize_window_true_explicit(
+ sacc_with_window: Path,
+) -> None:
"""Test DataSourceSacc.normalize_window can be explicitly set to True."""
data_source = DataSourceSacc(
sacc_data_file=str(sacc_with_window), normalize_window=True
@@ -1322,7 +1334,7 @@ def test_data_source_sacc_normalize_window_true_explicit(sacc_with_window: Path)
def test_two_point_experiment_normalize_window_flows_through(
empty_factory_harmonic: TwoPointFactory,
sacc_with_window: Path,
-):
+) -> None:
"""Test that normalize_window flows through TwoPointExperiment to likelihood."""
# Create experiment with normalize_window=False
experiment = TwoPointExperiment(
@@ -1343,7 +1355,7 @@ def test_two_point_experiment_normalize_window_flows_through(
def test_two_point_experiment_normalize_window_default_flows_through(
empty_factory_harmonic: TwoPointFactory,
sacc_with_window: Path,
-):
+) -> None:
"""Test that default normalize_window=True flows through correctly."""
experiment = TwoPointExperiment(
two_point_factory=empty_factory_harmonic,
@@ -1358,7 +1370,7 @@ def test_two_point_experiment_normalize_window_default_flows_through(
assert likelihood is not None
-def test_normalize_window_affects_extraction(sacc_with_window: Path):
+def test_normalize_window_affects_extraction(sacc_with_window: Path) -> None:
"""Test that normalize_window parameter actually affects window extraction."""
sacc_data = load_sacc_data(sacc_with_window)
@@ -1404,7 +1416,7 @@ def test_normalize_window_affects_extraction(sacc_with_window: Path):
def test_two_point_experiment_yaml_with_normalize_window(
tmp_path: Path, sacc_with_window: Path
-):
+) -> None:
"""Test TwoPointExperiment loading from YAML with normalize_window=False."""
tmp_experiment_file = tmp_path / "experiment_no_norm.yaml"
# Use relative path from tmp_path to sacc_with_window
diff --git a/tests/likelihood/test_gauss_family.py b/tests/likelihood/test_gauss_family.py
index aa6d39192..0453d4718 100644
--- a/tests/likelihood/test_gauss_family.py
+++ b/tests/likelihood/test_gauss_family.py
@@ -7,7 +7,7 @@
import firecrown.likelihood._gaussian as g
-def test_init_rejects_non_statistics():
+def test_init_rejects_non_statistics() -> None:
with pytest.raises(
ValueError,
match=re.escape(
diff --git a/tests/likelihood/test_likelihood.py b/tests/likelihood/test_likelihood.py
index 825d320cf..b5cfff748 100644
--- a/tests/likelihood/test_likelihood.py
+++ b/tests/likelihood/test_likelihood.py
@@ -33,7 +33,7 @@ def compute_loglike(self, _: like.ModelingTools) -> float:
return -1.0
-def test_integration_error_generates_0_likelihood():
+def test_integration_error_generates_0_likelihood() -> None:
likelihood = LikelihoodThatThrowsIntegrationError()
with pytest.warns(
UserWarning,
@@ -42,13 +42,13 @@ def test_integration_error_generates_0_likelihood():
assert likelihood.compute_loglike_for_sampling(like.ModelingTools()) == -np.inf
-def test_other_error_propagates():
+def test_other_error_propagates() -> None:
likelihood = LikelihoodThatThrowsUnhandledError()
with pytest.raises(RuntimeError):
likelihood.compute_loglike_for_sampling(like.ModelingTools())
-def test_factory_returns_updated_likelihood():
+def test_factory_returns_updated_likelihood() -> None:
"""Test warning when factory returns an already-updated likelihood."""
class PreUpdatedLikelihood(like.Likelihood):
@@ -60,7 +60,7 @@ def read(self, sacc_data: sacc.Sacc) -> None:
def compute_loglike(self, tools: ModelingTools) -> float:
return 0.0
- def build_likelihood(_build_parameters: NamedParameters):
+ def build_likelihood(_build_parameters: NamedParameters) -> PreUpdatedLikelihood:
"""Factory that returns an updated likelihood."""
likelihood = PreUpdatedLikelihood()
# Pre-update the likelihood before returning it
@@ -80,7 +80,7 @@ def build_likelihood(_build_parameters: NamedParameters):
assert not likelihood.is_updated()
-def test_factory_returns_updated_tools():
+def test_factory_returns_updated_tools() -> None:
"""Test warning when factory returns already-updated tools."""
class TestLikelihood(like.Likelihood):
@@ -92,7 +92,9 @@ def read(self, sacc_data: sacc.Sacc) -> None:
def compute_loglike(self, tools: ModelingTools) -> float:
return 0.0
- def build_likelihood(_build_parameters: NamedParameters):
+ def build_likelihood(
+ _build_parameters: NamedParameters,
+ ) -> tuple[TestLikelihood, ModelingTools]:
"""Factory that returns an updated tools object."""
likelihood = TestLikelihood()
tools = ModelingTools()
diff --git a/tests/likelihood/test_load_likelihood.py b/tests/likelihood/test_load_likelihood.py
index cf176ca25..904643f87 100644
--- a/tests/likelihood/test_load_likelihood.py
+++ b/tests/likelihood/test_load_likelihood.py
@@ -15,7 +15,7 @@
)
-def test_load_likelihood_from_script_submodule():
+def test_load_likelihood_from_script_submodule() -> None:
dir_path = os.path.dirname(os.path.realpath(__file__))
load_likelihood_from_script(
@@ -23,7 +23,7 @@ def test_load_likelihood_from_script_submodule():
)
-def test_load_likelihood_from_script_submodule_invalid():
+def test_load_likelihood_from_script_submodule_invalid() -> None:
dir_path = os.path.dirname(os.path.realpath(__file__))
with pytest.raises(ValueError, match="Unrecognized Firecrown initialization file"):
@@ -32,7 +32,7 @@ def test_load_likelihood_from_script_submodule_invalid():
)
-def test_load_likelihood_from_script_submodule_no_build_likelihood():
+def test_load_likelihood_from_script_submodule_no_build_likelihood() -> None:
dir_path = os.path.dirname(os.path.realpath(__file__))
with pytest.raises(
@@ -43,7 +43,7 @@ def test_load_likelihood_from_script_submodule_no_build_likelihood():
)
-def test_load_likelihood_from_script_submodule_not_a_function():
+def test_load_likelihood_from_script_submodule_not_a_function() -> None:
dir_path = os.path.dirname(os.path.realpath(__file__))
with pytest.raises(
@@ -55,7 +55,7 @@ def test_load_likelihood_from_script_submodule_not_a_function():
)
-def test_load_likelihood_from_script_submodule_returns_wrong_type():
+def test_load_likelihood_from_script_submodule_returns_wrong_type() -> None:
dir_path = os.path.dirname(os.path.realpath(__file__))
with pytest.raises(
@@ -68,7 +68,7 @@ def test_load_likelihood_from_script_submodule_returns_wrong_type():
)
-def test_load_likelihood_from_script_submodule_returns_wrong_type_tools():
+def test_load_likelihood_from_script_submodule_returns_wrong_type_tools() -> None:
dir_path = os.path.dirname(os.path.realpath(__file__))
with pytest.raises(
@@ -81,7 +81,7 @@ def test_load_likelihood_from_script_submodule_returns_wrong_type_tools():
)
-def test_load_likelihood_from_script_submodule_old():
+def test_load_likelihood_from_script_submodule_old() -> None:
dir_path = os.path.dirname(os.path.realpath(__file__))
with pytest.deprecated_call():
@@ -91,7 +91,7 @@ def test_load_likelihood_from_script_submodule_old():
)
-def test_load_likelihood_from_script_correct_tools():
+def test_load_likelihood_from_script_correct_tools() -> None:
dir_path = os.path.dirname(os.path.realpath(__file__))
_, tools = load_likelihood_from_script(
@@ -101,7 +101,7 @@ def test_load_likelihood_from_script_correct_tools():
assert tools.test_attribute == "test" # type: ignore
-def test_load_likelihood():
+def test_load_likelihood() -> None:
dir_path = os.path.dirname(os.path.realpath(__file__))
_, tools = load_likelihood(
@@ -111,7 +111,7 @@ def test_load_likelihood():
assert tools.test_attribute == "test" # type: ignore
-def test_load_likelihood_from_module():
+def test_load_likelihood_from_module() -> None:
dir_path = os.path.dirname(os.path.realpath(__file__))
module_path = os.path.join(dir_path, "lkdir")
@@ -122,7 +122,7 @@ def test_load_likelihood_from_module():
assert tools.test_attribute == "test" # type: ignore
-def test_load_likelihood_from_module_not_in_path():
+def test_load_likelihood_from_module_not_in_path() -> None:
with pytest.raises(
ValueError,
match="Unrecognized Firecrown initialization module 'lkscript_not_in_path'. "
@@ -132,7 +132,7 @@ def test_load_likelihood_from_module_not_in_path():
_ = load_likelihood_from_module("lkscript_not_in_path", NamedParameters())
-def test_load_likelihood_not_in_path():
+def test_load_likelihood_not_in_path() -> None:
with pytest.raises(
ValueError,
match="Unrecognized Firecrown initialization file or module "
@@ -141,7 +141,7 @@ def test_load_likelihood_not_in_path():
_ = load_likelihood("lkscript_not_in_path", NamedParameters())
-def test_load_likelihood_from_module_function_missing_likelihood_config():
+def test_load_likelihood_from_module_function_missing_likelihood_config() -> None:
dir_path = os.path.dirname(os.path.realpath(__file__))
module_path = os.path.join(dir_path, "lkdir")
diff --git a/tests/likelihood/test_named_parameters.py b/tests/likelihood/test_named_parameters.py
index 9c0842895..53797f842 100644
--- a/tests/likelihood/test_named_parameters.py
+++ b/tests/likelihood/test_named_parameters.py
@@ -6,7 +6,7 @@
from firecrown.likelihood._likelihood import NamedParameters
-def test_named_parameters_sanity():
+def test_named_parameters_sanity() -> None:
params = NamedParameters({"a": True})
assert params.get_bool("a") is True
@@ -29,7 +29,7 @@ def test_named_parameters_sanity():
assert params.to_set() == {"a"}
-def test_named_parameters_default():
+def test_named_parameters_default() -> None:
params = NamedParameters({})
assert params.get_bool("a", True) is True
@@ -45,7 +45,7 @@ def test_named_parameters_default():
assert params.get_float("d", 1.0) == 2.2
-def test_named_parameters_wrong_type_bool():
+def test_named_parameters_wrong_type_bool() -> None:
params = NamedParameters({"a": True})
with pytest.raises(AssertionError):
params.get_string("a")
@@ -64,7 +64,7 @@ def test_named_parameters_wrong_type_bool():
params.get_float_array("a")
-def test_named_parameters_wrong_type_string():
+def test_named_parameters_wrong_type_string() -> None:
params = NamedParameters({"a": "Im a string"})
with pytest.raises(AssertionError):
params.get_bool("a")
@@ -82,7 +82,7 @@ def test_named_parameters_wrong_type_string():
params.get_float_array("a")
-def test_named_parameters_wrong_type_int():
+def test_named_parameters_wrong_type_int() -> None:
params = NamedParameters({"a": 1})
with pytest.raises(AssertionError):
params.get_bool("a")
@@ -100,7 +100,7 @@ def test_named_parameters_wrong_type_int():
params.get_float_array("a")
-def test_named_parameters_wrong_type_float():
+def test_named_parameters_wrong_type_float() -> None:
params = NamedParameters({"a": 1.0})
with pytest.raises(AssertionError):
params.get_bool("a")
@@ -118,7 +118,7 @@ def test_named_parameters_wrong_type_float():
params.get_float_array("a")
-def test_named_parameters_wrong_type_int_array():
+def test_named_parameters_wrong_type_int_array() -> None:
params = NamedParameters({"a": np.array([1, 2, 3])})
with pytest.raises(AssertionError):
params.get_bool("a")
@@ -137,7 +137,7 @@ def test_named_parameters_wrong_type_int_array():
# params.get_float_array("a")
-def test_named_parameters_wrong_type_float_array():
+def test_named_parameters_wrong_type_float_array() -> None:
params = NamedParameters({"a": np.array([1.0, 2.0, 3.0])})
with pytest.raises(AssertionError):
params.get_bool("a")
@@ -156,7 +156,7 @@ def test_named_parameters_wrong_type_float_array():
# params.get_int_array("a")
-def test_named_parameters_set_from_basic_dict_string():
+def test_named_parameters_set_from_basic_dict_string() -> None:
params = NamedParameters()
params.set_from_basic_dict({"a": "Im a string"})
assert params.get_string("a") == "Im a string"
@@ -166,7 +166,7 @@ def test_named_parameters_set_from_basic_dict_string():
assert params.get_string("b") == "Im another string"
-def test_named_parameters_set_from_basic_dict_int():
+def test_named_parameters_set_from_basic_dict_int() -> None:
params = NamedParameters()
params.set_from_basic_dict({"a": 1})
assert params.get_int("a") == 1
@@ -176,7 +176,7 @@ def test_named_parameters_set_from_basic_dict_int():
assert params.get_int("b") == 2
-def test_named_parameters_set_from_basic_dict_float():
+def test_named_parameters_set_from_basic_dict_float() -> None:
params = NamedParameters()
params.set_from_basic_dict({"a": 1.0})
assert params.get_float("a") == 1.0
@@ -186,7 +186,7 @@ def test_named_parameters_set_from_basic_dict_float():
assert params.get_float("b") == 2.0
-def test_named_parameters_set_from_basic_dict_bool():
+def test_named_parameters_set_from_basic_dict_bool() -> None:
params = NamedParameters()
params.set_from_basic_dict({"a": True})
assert params.get_bool("a") is True
@@ -196,7 +196,7 @@ def test_named_parameters_set_from_basic_dict_bool():
assert params.get_bool("b") is False
-def test_named_parameters_set_from_basic_dict_int_array():
+def test_named_parameters_set_from_basic_dict_int_array() -> None:
params = NamedParameters()
params.set_from_basic_dict({"a": [1, 2, 3]})
assert params.get_int_array("a").tolist() == [1, 2, 3]
@@ -206,7 +206,7 @@ def test_named_parameters_set_from_basic_dict_int_array():
assert params.get_int_array("b").tolist() == [4, 5, 6]
-def test_named_parameters_set_from_basic_dict_float_array():
+def test_named_parameters_set_from_basic_dict_float_array() -> None:
params = NamedParameters()
params.set_from_basic_dict({"a": [1.0, 2.0, 3.0]})
assert params.get_float_array("a").tolist() == [1.0, 2.0, 3.0]
@@ -216,7 +216,7 @@ def test_named_parameters_set_from_basic_dict_float_array():
assert params.get_float_array("b").tolist() == [4.0, 5.0, 6.0]
-def test_named_parameters_set_from_basic_dict_bool_array():
+def test_named_parameters_set_from_basic_dict_bool_array() -> None:
params = NamedParameters()
params.set_from_basic_dict({"a": [True, False, True]})
assert params.get_int_array("a").tolist() == [True, False, True]
@@ -226,7 +226,7 @@ def test_named_parameters_set_from_basic_dict_bool_array():
assert params.get_int_array("b").tolist() == [False, True, False]
-def test_named_parameters_set_from_basic_dict_mixed():
+def test_named_parameters_set_from_basic_dict_mixed() -> None:
params = NamedParameters()
params.set_from_basic_dict(
{
@@ -246,7 +246,7 @@ def test_named_parameters_set_from_basic_dict_mixed():
assert params.get_bool("f") is True
-def test_named_parameters_convert_to_basic_dict_string():
+def test_named_parameters_convert_to_basic_dict_string() -> None:
params = NamedParameters({"a": "Im a string"})
assert params.convert_to_basic_dict() == {"a": "Im a string"}
@@ -257,7 +257,7 @@ def test_named_parameters_convert_to_basic_dict_string():
}
-def test_named_parameters_convert_to_basic_dict_int():
+def test_named_parameters_convert_to_basic_dict_int() -> None:
params = NamedParameters({"a": 1})
assert params.convert_to_basic_dict() == {"a": 1}
@@ -265,7 +265,7 @@ def test_named_parameters_convert_to_basic_dict_int():
assert params.convert_to_basic_dict() == {"a": 1, "b": 2}
-def test_named_parameters_convert_to_basic_dict_float():
+def test_named_parameters_convert_to_basic_dict_float() -> None:
params = NamedParameters({"a": 1.0})
assert params.convert_to_basic_dict() == {"a": 1.0}
@@ -273,7 +273,7 @@ def test_named_parameters_convert_to_basic_dict_float():
assert params.convert_to_basic_dict() == {"a": 1.0, "b": 2.0}
-def test_named_parameters_convert_to_basic_dict_bool():
+def test_named_parameters_convert_to_basic_dict_bool() -> None:
params = NamedParameters({"a": True})
assert params.convert_to_basic_dict() == {"a": True}
@@ -281,7 +281,7 @@ def test_named_parameters_convert_to_basic_dict_bool():
assert params.convert_to_basic_dict() == {"a": True, "b": False}
-def test_named_parameters_convert_to_basic_dict_int_array():
+def test_named_parameters_convert_to_basic_dict_int_array() -> None:
params = NamedParameters({"a": np.array([1, 2, 3])})
assert params.convert_to_basic_dict() == {"a": [1, 2, 3]}
@@ -292,7 +292,7 @@ def test_named_parameters_convert_to_basic_dict_int_array():
}
-def test_named_parameters_convert_to_basic_dict_float_array():
+def test_named_parameters_convert_to_basic_dict_float_array() -> None:
params = NamedParameters({"a": np.array([1.0, 2.0, 3.0])})
assert params.convert_to_basic_dict() == {"a": [1.0, 2.0, 3.0]}
@@ -305,7 +305,7 @@ def test_named_parameters_convert_to_basic_dict_float_array():
}
-def test_named_parameters_convert_to_basic_dict_mixed():
+def test_named_parameters_convert_to_basic_dict_mixed() -> None:
params = NamedParameters(
{
"a": np.array([1, 2, 3]),
@@ -326,7 +326,7 @@ def test_named_parameters_convert_to_basic_dict_mixed():
}
-def test_named_parameters_to_set():
+def test_named_parameters_to_set() -> None:
params = NamedParameters({"a": True})
assert params.to_set() == {"a"}
@@ -337,38 +337,38 @@ def test_named_parameters_to_set():
assert params.to_set() == {"a", "b", "c"}
-def test_named_parameters_to_float_dict():
+def test_named_parameters_to_float_dict() -> None:
params = NamedParameters({"a": 1.0, "b": 2.0})
assert params.to_float_dict() == {"a": 1.0, "b": 2.0}
-def test_named_parameters_to_float_dict_wrong_type():
+def test_named_parameters_to_float_dict_wrong_type() -> None:
params = NamedParameters({"a": 1})
with pytest.raises(TypeError, match="only float values"):
params.to_float_dict()
-def test_invalid_set_from_basic_dict():
+def test_invalid_set_from_basic_dict() -> None:
params = NamedParameters()
with pytest.raises(ValueError):
params.set_from_basic_dict({"a": {"b": "c"}}) # type: ignore
-def test_invalid_set_from_basic_dict_sequence():
+def test_invalid_set_from_basic_dict_sequence() -> None:
params = NamedParameters()
with pytest.raises(ValueError):
params.set_from_basic_dict({"a": ["a", "b", "c"]}) # type: ignore
-def test_invalid_convert_to_basic_dict():
+def test_invalid_convert_to_basic_dict() -> None:
params = NamedParameters({"a": {"b": "c"}}) # type: ignore
with pytest.raises(ValueError):
params.convert_to_basic_dict()
-def test_invalid_convert_to_basic_dict_sequence():
+def test_invalid_convert_to_basic_dict_sequence() -> None:
params = NamedParameters({"a": np.array(["a", "b", "c"])})
with pytest.raises(ValueError):
params.convert_to_basic_dict()
diff --git a/tests/likelihood/test_weak_lensing.py b/tests/likelihood/test_weak_lensing.py
index efc84555a..9c9c7d835 100644
--- a/tests/likelihood/test_weak_lensing.py
+++ b/tests/likelihood/test_weak_lensing.py
@@ -15,7 +15,7 @@
@pytest.fixture
-def mock_tools():
+def mock_tools() -> Mock:
"""Create a mock ModelingTools object."""
tools = Mock(spec=ModelingTools)
mock_cosmo = Mock(spec=pyccl.Cosmology)
@@ -34,7 +34,7 @@ def mock_tools():
@pytest.fixture
-def sample_tracer_args():
+def sample_tracer_args() -> wl.WeakLensingArgs:
"""Create sample WeakLensingArgs for testing."""
z = np.linspace(0.1, 2.0, 50)
dndz = np.exp(-(((z - 0.5) / 0.2) ** 2))
@@ -49,7 +49,7 @@ def sample_tracer_args():
@pytest.fixture
-def mock_sacc_data():
+def mock_sacc_data() -> Mock:
"""Create a mock SACC data object."""
mock_sacc = Mock(spec=sacc.Sacc)
mock_tracer = Mock()
@@ -59,14 +59,16 @@ def mock_sacc_data():
return mock_sacc
-def test_multiplicative_shear_bias_init():
+def test_multiplicative_shear_bias_init() -> None:
"""Test MultiplicativeShearBias initialization."""
systematic = wl.MultiplicativeShearBias("test_tracer")
assert hasattr(systematic, "mult_bias")
assert hasattr(systematic, "parameter_prefix")
-def test_multiplicative_shear_bias_apply(mock_tools, sample_tracer_args):
+def test_multiplicative_shear_bias_apply(
+ mock_tools: Mock, sample_tracer_args: wl.WeakLensingArgs
+) -> None:
"""Test MultiplicativeShearBias apply method - covers line 112."""
systematic = wl.MultiplicativeShearBias("test_tracer")
# Update parameter values using ParamsMap
@@ -82,7 +84,7 @@ def test_multiplicative_shear_bias_apply(mock_tools, sample_tracer_args):
assert result.dndz is sample_tracer_args.dndz
-def test_linear_alignment_systematic_init_default():
+def test_linear_alignment_systematic_init_default() -> None:
"""Test LinearAlignmentSystematic default initialization."""
systematic = wl.LinearAlignmentSystematic()
assert hasattr(systematic, "ia_bias")
@@ -91,7 +93,7 @@ def test_linear_alignment_systematic_init_default():
assert hasattr(systematic, "z_piv")
-def test_linear_alignment_systematic_init_with_tracer():
+def test_linear_alignment_systematic_init_with_tracer() -> None:
"""Test LinearAlignmentSystematic initialization with tracer."""
systematic = wl.LinearAlignmentSystematic("test_tracer", alphag=2.0)
assert hasattr(systematic, "ia_bias")
@@ -99,8 +101,10 @@ def test_linear_alignment_systematic_init_with_tracer():
@patch("pyccl.growth_factor")
def test_linear_alignment_systematic_apply(
- mock_growth_factor, mock_tools, sample_tracer_args
-):
+ mock_growth_factor: Mock,
+ mock_tools: Mock,
+ sample_tracer_args: wl.WeakLensingArgs,
+) -> None:
mock_growth_factor.return_value = 0.8
systematic = wl.LinearAlignmentSystematic("test_tracer")
@@ -126,7 +130,7 @@ def test_linear_alignment_systematic_apply(
mock_growth_factor.assert_called()
-def test_massdep_linear_alignment_systematic_init_default():
+def test_massdep_linear_alignment_systematic_init_default() -> None:
"""Test MassDependentLinearAlignmentSystematic default initialization."""
systematic = wl.MassDependentLinearAlignmentSystematic()
assert hasattr(systematic, "ia_amplitude")
@@ -135,7 +139,9 @@ def test_massdep_linear_alignment_systematic_init_default():
assert hasattr(systematic, "log10_average_halo_mass")
-def test_massdep_linear_alignment_systematic_apply(mock_tools, sample_tracer_args):
+def test_massdep_linear_alignment_systematic_apply(
+ mock_tools: Mock, sample_tracer_args: wl.WeakLensingArgs
+) -> None:
systematic = wl.MassDependentLinearAlignmentSystematic("test_tracer")
# Update parameter values using ParamsMap
params = ParamsMap(
@@ -156,7 +162,7 @@ def test_massdep_linear_alignment_systematic_apply(mock_tools, sample_tracer_arg
assert np.array_equal(result.ia_bias[0], sample_tracer_args.z)
-def test_tatt_alignment_systematic_init_default():
+def test_tatt_alignment_systematic_init_default() -> None:
"""Test TattAlignmentSystematic default initialization."""
systematic = wl.TattAlignmentSystematic()
assert hasattr(systematic, "ia_a_1")
@@ -164,7 +170,7 @@ def test_tatt_alignment_systematic_init_default():
assert hasattr(systematic, "ia_a_d")
-def test_tatt_alignment_systematic_init_with_z_dependence():
+def test_tatt_alignment_systematic_init_with_z_dependence() -> None:
"""Test TattAlignmentSystematic with z dependence enabled."""
systematic = wl.TattAlignmentSystematic(include_z_dependence=True)
assert hasattr(systematic, "ia_a_1")
@@ -172,8 +178,10 @@ def test_tatt_alignment_systematic_init_with_z_dependence():
@patch("pyccl.nl_pt.translate_IA_norm")
def test_tatt_alignment_systematic_apply(
- mock_translate_ia, mock_tools, sample_tracer_args
-):
+ mock_translate_ia: Mock,
+ mock_tools: Mock,
+ sample_tracer_args: wl.WeakLensingArgs,
+) -> None:
"""Test TattAlignmentSystematic apply method."""
# Mock the translate_IA_norm function return values
c_1 = np.ones_like(sample_tracer_args.z) * 0.1
@@ -212,21 +220,23 @@ def test_tatt_alignment_systematic_apply(
assert len(result.ia_pt_c_2) == 2
-def test_hm_alignment_systematic_init():
+def test_hm_alignment_systematic_init() -> None:
"""Test HMAlignmentSystematic initialization - covers lines 326, 328, 331."""
systematic = wl.HMAlignmentSystematic()
assert hasattr(systematic, "ia_a_1h")
assert hasattr(systematic, "ia_a_2h")
-def test_hm_alignment_systematic_init_with_tracer():
+def test_hm_alignment_systematic_init_with_tracer() -> None:
"""Test HMAlignmentSystematic initialization with ignored tracer parameter."""
systematic = wl.HMAlignmentSystematic("ignored_tracer")
assert hasattr(systematic, "ia_a_1h")
assert hasattr(systematic, "ia_a_2h")
-def test_hm_alignment_systematic_apply(mock_tools, sample_tracer_args):
+def test_hm_alignment_systematic_apply(
+ mock_tools: Mock, sample_tracer_args: wl.WeakLensingArgs
+) -> None:
"""Test HMAlignmentSystematic apply method - covers line 344."""
systematic = wl.HMAlignmentSystematic()
# Update parameter values using ParamsMap
@@ -249,14 +259,14 @@ def test_hm_alignment_systematic_apply(mock_tools, sample_tracer_args):
class TestWeakLensing:
"""Test WeakLensing source class."""
- def test_init(self):
+ def test_init(self) -> None:
"""Test WeakLensing initialization."""
weak_lensing = wl.WeakLensing(sacc_tracer="test_tracer", scale=2.0)
assert weak_lensing.sacc_tracer == "test_tracer"
assert weak_lensing.scale == 2.0
assert weak_lensing.current_tracer_args is None
- def test_create_ready(self):
+ def test_create_ready(self) -> None:
"""Test WeakLensing.create_ready class method."""
zdist = TomographicBin(
bin_name="test_bin",
@@ -270,7 +280,7 @@ def test_create_ready(self):
assert hasattr(weak_lensing, "tracer_args")
assert weak_lensing.tracer_args.ia_bias is None
- def test_read(self, mock_sacc_data):
+ def test_read(self, mock_sacc_data: Mock) -> None:
"""Test WeakLensing _read method."""
weak_lensing = wl.WeakLensing(sacc_tracer="test_tracer")
weak_lensing._read(mock_sacc_data)
@@ -280,7 +290,7 @@ def test_read(self, mock_sacc_data):
mock_sacc_data.get_tracer.assert_called_with("test_tracer")
@patch("pyccl.WeakLensingTracer")
- def test_create_tracers_basic(self, mock_wl_tracer, mock_tools):
+ def test_create_tracers_basic(self, mock_wl_tracer: Mock, mock_tools: Mock) -> None:
"""Test WeakLensing create_tracers with basic configuration."""
mock_ccl_tracer = Mock()
mock_wl_tracer.return_value = mock_ccl_tracer
@@ -300,7 +310,9 @@ def test_create_tracers_basic(self, mock_wl_tracer, mock_tools):
@patch("pyccl.nl_pt.PTIntrinsicAlignmentTracer")
@patch("pyccl.WeakLensingTracer")
- def test_create_tracers_with_pt(self, mock_wl_tracer, mock_pt_tracer, mock_tools):
+ def test_create_tracers_with_pt(
+ self, mock_wl_tracer: Mock, mock_pt_tracer: Mock, mock_tools: Mock
+ ) -> None:
"""Test WeakLensing create_tracers with PT - covers lines 450-452, 455."""
mock_ccl_tracer = Mock()
mock_wl_tracer.return_value = mock_ccl_tracer
@@ -332,8 +344,8 @@ def test_create_tracers_with_pt(self, mock_wl_tracer, mock_pt_tracer, mock_tools
@patch("pyccl.halos.SatelliteShearHOD")
@patch("pyccl.WeakLensingTracer")
def test_create_tracers_with_hm(
- self, mock_wl_tracer, mock_halo_profile, mock_tools
- ):
+ self, mock_wl_tracer: Mock, mock_halo_profile: Mock, mock_tools: Mock
+ ) -> None:
"""Test WeakLensing create_tracers with HM - covers lines 462, 469, 472."""
mock_ccl_tracer = Mock()
mock_wl_tracer.return_value = mock_ccl_tracer
@@ -364,7 +376,7 @@ def test_create_tracers_with_hm(
assert hasattr(mock_profile, "ia_a_2h")
assert mock_profile.ia_a_2h == 1.0
- def test_get_scale(self):
+ def test_get_scale(self) -> None:
"""Test WeakLensing get_scale method."""
weak_lensing = wl.WeakLensing(sacc_tracer="test_tracer", scale=2.0)
weak_lensing.current_tracer_args = wl.WeakLensingArgs(
@@ -375,7 +387,7 @@ def test_get_scale(self):
assert weak_lensing.get_scale() == 3.0
- def test_update_with_systematics(self):
+ def test_update_with_systematics(self) -> None:
"""Test WeakLensing update method with systematics - covers line 398."""
systematic = wl.MultiplicativeShearBias("test_tracer")
weak_lensing = wl.WeakLensing(
@@ -389,7 +401,9 @@ def test_update_with_systematics(self):
assert weak_lensing.systematics is not None
@patch("pyccl.WeakLensingTracer")
- def test_create_tracers_with_systematics(self, mock_wl_tracer, mock_tools):
+ def test_create_tracers_with_systematics(
+ self, mock_wl_tracer: Mock, mock_tools: Mock
+ ) -> None:
"""Test WeakLensing create_tracers with systematics - covers line 421."""
mock_ccl_tracer = Mock()
mock_wl_tracer.return_value = mock_ccl_tracer
@@ -417,20 +431,20 @@ def test_create_tracers_with_systematics(self, mock_wl_tracer, mock_tools):
assert weak_lensing.current_tracer_args.scale == 1.1 # 1.0 * (1 + 0.1)
-def test_multiplicative_shear_bias_factory():
+def test_multiplicative_shear_bias_factory() -> None:
"""Test MultiplicativeShearBiasFactory."""
factory = wl.MultiplicativeShearBiasFactory()
bias = factory.create("test_bin")
assert isinstance(bias, wl.MultiplicativeShearBias)
-def test_multiplicative_shear_bias_factory_global_error():
+def test_multiplicative_shear_bias_factory_global_error() -> None:
factory = wl.MultiplicativeShearBiasFactory()
with pytest.raises(ValueError, match="MultiplicativeShearBias cannot be global"):
factory.create_global()
-def test_linear_alignment_factory():
+def test_linear_alignment_factory() -> None:
"""Test LinearAlignmentSystematicFactory."""
factory = wl.LinearAlignmentSystematicFactory(alphag=2.0)
systematic = factory.create("test_bin")
@@ -440,7 +454,7 @@ def test_linear_alignment_factory():
assert isinstance(global_systematic, wl.LinearAlignmentSystematic)
-def test_tatt_alignment_factory():
+def test_tatt_alignment_factory() -> None:
"""Test TattAlignmentSystematicFactory."""
factory = wl.TattAlignmentSystematicFactory(include_z_dependence=True)
systematic = factory.create("test_bin")
@@ -450,7 +464,7 @@ def test_tatt_alignment_factory():
assert isinstance(global_systematic, wl.TattAlignmentSystematic)
-def test_weak_lensing_factory():
+def test_weak_lensing_factory() -> None:
"""Test WeakLensingFactory."""
factory = wl.WeakLensingFactory(
per_bin_systematics=[wl.MultiplicativeShearBiasFactory()],
@@ -473,7 +487,7 @@ def test_weak_lensing_factory():
assert weak_lensing is wl2
-def test_weak_lensing_factory_from_metadata():
+def test_weak_lensing_factory_from_metadata() -> None:
"""Test WeakLensingFactory create_from_metadata_only."""
factory = wl.WeakLensingFactory()
@@ -486,26 +500,26 @@ def test_weak_lensing_factory_from_metadata():
assert weak_lensing is wl2
-def test_photoz_shift():
+def test_photoz_shift() -> None:
"""Test PhotoZShift systematic."""
systematic = wl.PhotoZShift("test_tracer")
assert hasattr(systematic, "delta_z")
-def test_photoz_shift_and_stretch():
+def test_photoz_shift_and_stretch() -> None:
"""Test PhotoZShiftandStretch systematic."""
systematic = wl.PhotoZShiftandStretch("test_tracer")
assert hasattr(systematic, "delta_z")
assert hasattr(systematic, "sigma_z")
-def test_select_field():
+def test_select_field() -> None:
"""Test SelectField systematic."""
systematic = wl.SelectField()
assert hasattr(systematic, "field")
-def test_weak_lensing_args_immutable():
+def test_weak_lensing_args_immutable() -> None:
"""Test that WeakLensingArgs is immutable (frozen dataclass)."""
args = wl.WeakLensingArgs(
z=np.array([0.1, 0.5, 1.0]),
@@ -520,7 +534,7 @@ def test_weak_lensing_args_immutable():
args.scale = 2.0 # type: ignore[misc]
-def test_systematic_with_none_tracer():
+def test_systematic_with_none_tracer() -> None:
"""Test systematics with None tracer name."""
# LinearAlignmentSystematic should accept None tracer
systematic = wl.LinearAlignmentSystematic(sacc_tracer=None)
@@ -532,7 +546,9 @@ def test_systematic_with_none_tracer():
@patch("pyccl.growth_factor")
-def test_linear_alignment_complex_calculation(mock_growth_factor, mock_tools):
+def test_linear_alignment_complex_calculation(
+ mock_growth_factor: Mock, mock_tools: Mock
+) -> None:
"""Test LinearAlignmentSystematic with complex parameter values."""
mock_growth_factor.return_value = np.array([0.7, 0.8, 0.9])
diff --git a/tests/metadata/test_bin_pair_selector.py b/tests/metadata/test_bin_pair_selector.py
index 2dcc11ac4..959959d51 100644
--- a/tests/metadata/test_bin_pair_selector.py
+++ b/tests/metadata/test_bin_pair_selector.py
@@ -15,7 +15,7 @@
from firecrown.metadata_functions import make_binned_two_point_filtered
-def test_pair_selector_register_missing_kind():
+def test_pair_selector_register_missing_kind() -> None:
with pytest.raises(
ValueError, match="MissingBinPairSelector has no default for 'kind'"
):
@@ -32,7 +32,7 @@ def keep(
_ = MissingBinPairSelector(kind="foo")
-def test_pair_selector_register_duplicate_kind():
+def test_pair_selector_register_duplicate_kind() -> None:
with pytest.raises(ValueError, match="Duplicate pair selector kind foo"):
@mt.register_bin_pair_selector
@@ -61,7 +61,7 @@ def keep(
_ = Duplicate1BinPairSelector()
-def test_pair_selector_auto(all_harmonic_bins):
+def test_pair_selector_auto(all_harmonic_bins: list[mt.TomographicBin]) -> None:
auto_pair_selector = (
mt.AutoNameBinPairSelector() & mt.AutoMeasurementBinPairSelector()
)
@@ -77,7 +77,7 @@ def test_pair_selector_auto(all_harmonic_bins):
assert two_point_xy.x_measurement == two_point_xy.y_measurement
-def test_pair_selector_auto_source(all_harmonic_bins):
+def test_pair_selector_auto_source(all_harmonic_bins: list[mt.TomographicBin]) -> None:
auto_pair_selector = (
mt.AutoNameBinPairSelector() & mt.AutoMeasurementBinPairSelector()
)
@@ -94,7 +94,7 @@ def test_pair_selector_auto_source(all_harmonic_bins):
assert two_point_xy.x_measurement in mt.GALAXY_SOURCE_TYPES
-def test_pair_selector_auto_lens(all_harmonic_bins):
+def test_pair_selector_auto_lens(all_harmonic_bins: list[mt.TomographicBin]) -> None:
auto_pair_selector = (
mt.AutoNameBinPairSelector() & mt.AutoMeasurementBinPairSelector()
)
@@ -111,7 +111,9 @@ def test_pair_selector_auto_lens(all_harmonic_bins):
assert two_point_xy.x_measurement in mt.GALAXY_LENS_TYPES
-def test_pair_selector_auto_source_lens(all_harmonic_bins):
+def test_pair_selector_auto_source_lens(
+ all_harmonic_bins: list[mt.TomographicBin],
+) -> None:
auto_pair_selector = (
mt.AutoNameBinPairSelector() & mt.AutoMeasurementBinPairSelector()
)
@@ -131,7 +133,7 @@ def test_pair_selector_auto_source_lens(all_harmonic_bins):
assert two_point_xy.x_measurement == two_point_xy.y_measurement
-def test_pair_selector_named(all_harmonic_bins):
+def test_pair_selector_named(all_harmonic_bins: list[mt.TomographicBin]) -> None:
named_pair_selector = mt.NamedBinPairSelector(names=[("bin_1_1", "bin_1_2")])
two_point_xy_combinations = make_binned_two_point_filtered(
@@ -146,7 +148,7 @@ def test_pair_selector_named(all_harmonic_bins):
}
-def test_pair_selector_type_source(all_harmonic_bins):
+def test_pair_selector_type_source(all_harmonic_bins: list[mt.TomographicBin]) -> None:
type_source_pair_selector = mt.TypeSourceBinPairSelector(
type_source=mt.TypeSource.DEFAULT
)
@@ -176,7 +178,7 @@ def test_pair_selector_type_source(all_harmonic_bins):
assert len(two_point_xy_combinations) == 1
-def test_pair_selector_not_named(all_harmonic_bins):
+def test_pair_selector_not_named(all_harmonic_bins: list[mt.TomographicBin]) -> None:
named_pair_selector = mt.NamedBinPairSelector(names=[("bin_1_1", "bin_1_2")])
two_point_xy_combinations = make_binned_two_point_filtered(
@@ -191,7 +193,9 @@ def test_pair_selector_not_named(all_harmonic_bins):
]
-def test_pair_selector_first_neighbor(many_harmonic_bins):
+def test_pair_selector_first_neighbor(
+ many_harmonic_bins: list[mt.TomographicBin],
+) -> None:
first_neighbor_pair_selector = mt.AutoNameDiffBinPairSelector(
neighbors_diff=[0, 1, -1]
)
@@ -221,7 +225,9 @@ def test_pair_selector_first_neighbor(many_harmonic_bins):
assert abs(index1 - index2) <= 1
-def test_pair_selector_first_neighbor_no_auto(many_harmonic_bins):
+def test_pair_selector_first_neighbor_no_auto(
+ many_harmonic_bins: list[mt.TomographicBin],
+) -> None:
first_neighbor_pair_selector = mt.AutoNameDiffBinPairSelector(
neighbors_diff=[1, -1]
)
@@ -243,7 +249,7 @@ def test_pair_selector_first_neighbor_no_auto(many_harmonic_bins):
assert abs(index1 - index2) == 1
-def test_pair_selector_auto_name_keep():
+def test_pair_selector_auto_name_keep() -> None:
z1 = mt.TomographicBin(
bin_name="bin_1",
z=np.array([0.1]),
@@ -261,7 +267,7 @@ def test_pair_selector_auto_name_keep():
assert not rule.keep((z1, z2), (mt.Galaxies.COUNTS, mt.Galaxies.COUNTS))
-def test_pair_selector_auto_measurement_keep():
+def test_pair_selector_auto_measurement_keep() -> None:
z1 = mt.TomographicBin(
bin_name="bin_1",
z=np.array([0.1]),
@@ -279,7 +285,7 @@ def test_pair_selector_auto_measurement_keep():
assert not rule.keep((z1, z2), (mt.Galaxies.COUNTS, mt.Galaxies.SHEAR_E))
-def test_pair_selector_named_keep():
+def test_pair_selector_named_keep() -> None:
z1 = mt.TomographicBin(
bin_name="bin_1",
z=np.array([0.1]),
@@ -296,7 +302,7 @@ def test_pair_selector_named_keep():
assert rule.keep((z1, z2), (mt.Galaxies.COUNTS, mt.Galaxies.COUNTS))
-def test_pair_selector_lens_keep():
+def test_pair_selector_lens_keep() -> None:
z1 = mt.TomographicBin(
bin_name="bin_1",
z=np.array([0.1]),
@@ -314,7 +320,7 @@ def test_pair_selector_lens_keep():
assert not rule.keep((z1, z2), (mt.Galaxies.SHEAR_E, mt.Galaxies.SHEAR_E))
-def test_pair_selector_source_keep():
+def test_pair_selector_source_keep() -> None:
z1 = mt.TomographicBin(
bin_name="src1",
z=np.array([0.1]),
@@ -331,7 +337,7 @@ def test_pair_selector_source_keep():
assert rule.keep((z1, z2), (mt.Galaxies.SHEAR_E, mt.Galaxies.SHEAR_E))
-def test_pair_selector_first_neighbor_mixed():
+def test_pair_selector_first_neighbor_mixed() -> None:
z1 = mt.TomographicBin(
bin_name="extra_src_a",
z=np.array([0.1]),
@@ -359,7 +365,7 @@ def test_pair_selector_first_neighbor_mixed():
assert rule.keep((z3, z3), (mt.Galaxies.SHEAR_E, mt.Galaxies.SHEAR_E))
-def test_pair_selector_serialization_and_or():
+def test_pair_selector_serialization_and_or() -> None:
pair_selector = (
mt.AutoNameBinPairSelector()
& mt.AutoMeasurementBinPairSelector()
@@ -382,7 +388,7 @@ def test_pair_selector_serialization_and_or():
assert pair_selector.model_dump() == pair_selector_from_yaml.model_dump()
-def test_pair_selector_serialization_simple_and():
+def test_pair_selector_serialization_simple_and() -> None:
pair_selector = mt.AutoNameBinPairSelector() & mt.AutoMeasurementBinPairSelector()
yaml_str = yaml.dump(pair_selector.model_dump(), sort_keys=False)
pair_selector_from_yaml = mt.BinPairSelector.model_validate(
@@ -392,7 +398,7 @@ def test_pair_selector_serialization_simple_and():
assert pair_selector.model_dump() == pair_selector_from_yaml.model_dump()
-def test_pair_selector_serialization_simple_or():
+def test_pair_selector_serialization_simple_or() -> None:
pair_selector = mt.AutoNameBinPairSelector() | mt.LensBinPairSelector()
yaml_str = yaml.dump(pair_selector.model_dump(), sort_keys=False)
pair_selector_from_yaml = mt.BinPairSelector.model_validate(
@@ -402,7 +408,7 @@ def test_pair_selector_serialization_simple_or():
assert pair_selector.model_dump() == pair_selector_from_yaml.model_dump()
-def test_pair_selector_serialization_nested_and_or():
+def test_pair_selector_serialization_nested_and_or() -> None:
pair_selector = (
(mt.AutoNameBinPairSelector() & mt.LensBinPairSelector())
| (
@@ -421,7 +427,7 @@ def test_pair_selector_serialization_nested_and_or():
assert pair_selector.model_dump() == pair_selector_from_yaml.model_dump()
-def test_pair_selector_serialization_negation():
+def test_pair_selector_serialization_negation() -> None:
base_rule = mt.AutoNameBinPairSelector()
neg_rule = ~base_rule
yaml_str = yaml.dump(neg_rule.model_dump(), sort_keys=False)
@@ -430,7 +436,7 @@ def test_pair_selector_serialization_negation():
assert neg_rule.model_dump() == rule_from_yaml.model_dump()
-def test_pair_selector_serialization_double_negation():
+def test_pair_selector_serialization_double_negation() -> None:
base_rule = mt.AutoNameBinPairSelector()
double_neg_rule = ~~base_rule
yaml_str = yaml.dump(double_neg_rule.model_dump(), sort_keys=False)
@@ -439,7 +445,7 @@ def test_pair_selector_serialization_double_negation():
assert double_neg_rule.model_dump() == rule_from_yaml.model_dump()
-def test_pair_selector_serialization_and_not():
+def test_pair_selector_serialization_and_not() -> None:
rule = mt.AutoNameBinPairSelector() & ~mt.LensBinPairSelector()
yaml_str = yaml.dump(rule.model_dump(), sort_keys=False)
rule_from_yaml = mt.BinPairSelector.model_validate(yaml.safe_load(yaml_str))
@@ -447,7 +453,7 @@ def test_pair_selector_serialization_and_not():
assert rule.model_dump() == rule_from_yaml.model_dump()
-def test_pair_selector_serialization_or_not():
+def test_pair_selector_serialization_or_not() -> None:
rule = mt.AutoNameBinPairSelector() | ~mt.LensBinPairSelector()
yaml_str = yaml.dump(rule.model_dump(), sort_keys=False)
rule_from_yaml = mt.BinPairSelector.model_validate(yaml.safe_load(yaml_str))
@@ -456,7 +462,7 @@ def test_pair_selector_serialization_or_not():
assert rule.model_dump() == rule_from_yaml.model_dump()
-def test_pair_selector_serialization_type_source():
+def test_pair_selector_serialization_type_source() -> None:
rule = mt.TypeSourceBinPairSelector(type_source=mt.TypeSource("NewTypeSource"))
yaml_str = yaml.dump(rule.model_dump(), sort_keys=False)
rule_from_yaml = mt.BinPairSelector.model_validate(yaml.safe_load(yaml_str))
@@ -466,7 +472,7 @@ def test_pair_selector_serialization_type_source():
assert rule.type_source == rule_from_yaml.type_source
-def test_pair_selector_deserialization_lens():
+def test_pair_selector_deserialization_lens() -> None:
yaml_str = """
kind: lens
"""
@@ -474,7 +480,7 @@ def test_pair_selector_deserialization_lens():
assert isinstance(rule, mt.LensBinPairSelector)
-def test_pair_selector_deserialization_source():
+def test_pair_selector_deserialization_source() -> None:
yaml_str = """
kind: source
"""
@@ -482,7 +488,7 @@ def test_pair_selector_deserialization_source():
assert isinstance(rule, mt.SourceBinPairSelector)
-def test_pair_selector_deserialization_named():
+def test_pair_selector_deserialization_named() -> None:
yaml_str = """
kind: named
names:
@@ -493,7 +499,7 @@ def test_pair_selector_deserialization_named():
assert rule.names == [("bin_1", "bin_2")]
-def test_pair_selector_deserialization_auto_name():
+def test_pair_selector_deserialization_auto_name() -> None:
yaml_str = """
kind: auto-name
"""
@@ -501,7 +507,7 @@ def test_pair_selector_deserialization_auto_name():
assert isinstance(rule, mt.AutoNameBinPairSelector)
-def test_pair_selector_deserialization_auto_measurement():
+def test_pair_selector_deserialization_auto_measurement() -> None:
yaml_str = """
kind: auto-measurement
"""
@@ -509,7 +515,7 @@ def test_pair_selector_deserialization_auto_measurement():
assert isinstance(rule, mt.AutoMeasurementBinPairSelector)
-def test_pair_selector_deserialization_not():
+def test_pair_selector_deserialization_not() -> None:
yaml_str = """
kind: not
pair_selector:
@@ -520,7 +526,7 @@ def test_pair_selector_deserialization_not():
assert isinstance(rule.pair_selector, mt.LensBinPairSelector)
-def test_pair_selector_deserialization_and():
+def test_pair_selector_deserialization_and() -> None:
yaml_str = """
kind: and
pair_selectors:
@@ -536,7 +542,7 @@ def test_pair_selector_deserialization_and():
assert isinstance(rule.pair_selectors[2], mt.SourceBinPairSelector)
-def test_pair_selector_deserialization_or():
+def test_pair_selector_deserialization_or() -> None:
yaml_str = """
kind: or
pair_selectors:
@@ -554,7 +560,7 @@ def test_pair_selector_deserialization_or():
assert isinstance(rule.pair_selectors[3], mt.AutoMeasurementBinPairSelector)
-def test_pair_selector_deserialization_nested_and_or():
+def test_pair_selector_deserialization_nested_and_or() -> None:
yaml_str = """
kind: and
pair_selectors:
@@ -580,7 +586,7 @@ def test_pair_selector_deserialization_nested_and_or():
assert isinstance(rule.pair_selectors[1], mt.AutoMeasurementBinPairSelector)
-def test_pair_selector_deserialization_nested_not():
+def test_pair_selector_deserialization_nested_not() -> None:
yaml_str = """
kind: not
pair_selector:
@@ -599,7 +605,7 @@ def test_pair_selector_deserialization_nested_not():
assert isinstance(rule.pair_selector.pair_selectors[2], mt.SourceBinPairSelector)
-def test_pair_selector_deserialization_nested_or_and():
+def test_pair_selector_deserialization_nested_or_and() -> None:
yaml_str = """
kind: or
pair_selectors:
@@ -625,7 +631,7 @@ def test_pair_selector_deserialization_nested_or_and():
assert isinstance(rule.pair_selectors[1], mt.AutoMeasurementBinPairSelector)
-def test_pair_selector_deserialization_invalid_kind():
+def test_pair_selector_deserialization_invalid_kind() -> None:
yaml_str = """
kind: not_a_valid_kind
"""
@@ -638,7 +644,7 @@ def test_pair_selector_deserialization_invalid_kind():
# ============================================================================
-def test_composite_selector_bad_selector_not_initialized():
+def test_composite_selector_bad_selector_not_initialized() -> None:
"""Test that CompositeSelector raises NotImplementedError when _impl is not set."""
z1 = mt.TomographicBin(
bin_name="bin_1",
@@ -671,7 +677,7 @@ def model_post_init(self, _: Any, /) -> None:
bad_composite.keep((z1, z2), (mt.Galaxies.COUNTS, mt.Galaxies.COUNTS))
-def test_auto_bin_pair_selector(all_harmonic_bins):
+def test_auto_bin_pair_selector(all_harmonic_bins: list[mt.TomographicBin]) -> None:
"""Test AutoBinPairSelector composite selector."""
auto_pair_selector = mt.AutoBinPairSelector()
@@ -686,7 +692,7 @@ def test_auto_bin_pair_selector(all_harmonic_bins):
assert two_point_xy.x_measurement == two_point_xy.y_measurement
-def test_auto_bin_pair_selector_keep():
+def test_auto_bin_pair_selector_keep() -> None:
"""Test AutoBinPairSelector keep method."""
z1 = mt.TomographicBin(
bin_name="bin_1",
@@ -709,7 +715,7 @@ def test_auto_bin_pair_selector_keep():
assert not rule.keep((z1, z1), (mt.Galaxies.COUNTS, mt.Galaxies.SHEAR_E))
-def test_source_lens_pair_selector():
+def test_source_lens_pair_selector() -> None:
"""Test SourceLensBinPairSelector with order-dependent matching."""
source_lens_pair_selector = mt.SourceLensBinPairSelector()
@@ -742,7 +748,7 @@ def test_source_lens_pair_selector():
assert two_point_xy.y_measurement == mt.Galaxies.COUNTS
-def test_source_lens_pair_selector_keep():
+def test_source_lens_pair_selector_keep() -> None:
"""Test SourceLensBinPairSelector keep method with fixed order."""
z_source = mt.TomographicBin(
bin_name="src1",
@@ -770,7 +776,7 @@ def test_source_lens_pair_selector_keep():
assert not rule.keep((z_lens, z_lens), (mt.Galaxies.COUNTS, mt.Galaxies.COUNTS))
-def test_auto_bin_pair_selector_serialization():
+def test_auto_bin_pair_selector_serialization() -> None:
"""Test serialization of AutoBinPairSelector."""
rule = mt.AutoBinPairSelector()
yaml_str = yaml.dump(rule.model_dump(), sort_keys=False)
@@ -779,7 +785,7 @@ def test_auto_bin_pair_selector_serialization():
assert rule == rule_from_yaml
-def test_source_lens_pair_selector_serialization():
+def test_source_lens_pair_selector_serialization() -> None:
"""Test serialization of SourceLensBinPairSelector."""
rule = mt.SourceLensBinPairSelector()
yaml_str = yaml.dump(rule.model_dump(), sort_keys=False)
@@ -788,7 +794,7 @@ def test_source_lens_pair_selector_serialization():
assert rule == rule_from_yaml
-def test_auto_bin_pair_selector_deserialization():
+def test_auto_bin_pair_selector_deserialization() -> None:
"""Test deserialization of AutoBinPairSelector."""
yaml_str = """
kind: auto-bin
@@ -797,7 +803,7 @@ def test_auto_bin_pair_selector_deserialization():
assert isinstance(rule, mt.AutoBinPairSelector)
-def test_source_lens_pair_selector_deserialization():
+def test_source_lens_pair_selector_deserialization() -> None:
"""Test deserialization of SourceLensBinPairSelector."""
yaml_str = """
kind: source-lens
@@ -811,7 +817,7 @@ def test_source_lens_pair_selector_deserialization():
# ============================================================================
-def test_cross_name_bin_pair_selector_keep():
+def test_cross_name_bin_pair_selector_keep() -> None:
"""Test CrossNameBinPairSelector keep method."""
z1 = mt.TomographicBin(
bin_name="bin_1",
@@ -832,7 +838,9 @@ def test_cross_name_bin_pair_selector_keep():
assert not rule.keep((z1, z1), (mt.Galaxies.COUNTS, mt.Galaxies.COUNTS))
-def test_cross_name_bin_pair_selector(all_harmonic_bins):
+def test_cross_name_bin_pair_selector(
+ all_harmonic_bins: list[mt.TomographicBin],
+) -> None:
"""Test CrossNameBinPairSelector filters out auto-name correlations."""
cross_name_selector = mt.CrossNameBinPairSelector()
@@ -847,7 +855,7 @@ def test_cross_name_bin_pair_selector(all_harmonic_bins):
assert two_point_xy.x.bin_name != two_point_xy.y.bin_name
-def test_cross_measurement_bin_pair_selector_keep():
+def test_cross_measurement_bin_pair_selector_keep() -> None:
"""Test CrossMeasurementBinPairSelector keep method."""
z1 = mt.TomographicBin(
bin_name="bin_1",
@@ -868,7 +876,9 @@ def test_cross_measurement_bin_pair_selector_keep():
assert not rule.keep((z1, z2), (mt.Galaxies.COUNTS, mt.Galaxies.COUNTS))
-def test_cross_measurement_bin_pair_selector(all_harmonic_bins):
+def test_cross_measurement_bin_pair_selector(
+ all_harmonic_bins: list[mt.TomographicBin],
+) -> None:
"""Test CrossMeasurementBinPairSelector.
Test filters out auto-measurement correlations."""
@@ -883,7 +893,7 @@ def test_cross_measurement_bin_pair_selector(all_harmonic_bins):
assert two_point_xy.x_measurement != two_point_xy.y_measurement
-def test_cross_bin_pair_selector_keep():
+def test_cross_bin_pair_selector_keep() -> None:
"""Test CrossBinPairSelector keep method."""
z1 = mt.TomographicBin(
bin_name="bin_1",
@@ -907,7 +917,7 @@ def test_cross_bin_pair_selector_keep():
assert rule.keep((z1, z1), (mt.Galaxies.COUNTS, mt.Galaxies.SHEAR_E))
-def test_cross_bin_pair_selector(all_harmonic_bins):
+def test_cross_bin_pair_selector(all_harmonic_bins: list[mt.TomographicBin]) -> None:
"""Test CrossBinPairSelector filters out auto-bin correlations."""
cross_bin_selector = mt.CrossBinPairSelector()
@@ -925,7 +935,7 @@ def test_cross_bin_pair_selector(all_harmonic_bins):
assert not is_auto_bin
-def test_cross_name_bin_pair_selector_serialization():
+def test_cross_name_bin_pair_selector_serialization() -> None:
"""Test serialization of CrossNameBinPairSelector."""
rule = mt.CrossNameBinPairSelector()
yaml_str = yaml.dump(rule.model_dump(), sort_keys=False)
@@ -934,7 +944,7 @@ def test_cross_name_bin_pair_selector_serialization():
assert rule == rule_from_yaml
-def test_cross_measurement_bin_pair_selector_serialization():
+def test_cross_measurement_bin_pair_selector_serialization() -> None:
"""Test serialization of CrossMeasurementBinPairSelector."""
rule = mt.CrossMeasurementBinPairSelector()
yaml_str = yaml.dump(rule.model_dump(), sort_keys=False)
@@ -943,7 +953,7 @@ def test_cross_measurement_bin_pair_selector_serialization():
assert rule == rule_from_yaml
-def test_cross_bin_pair_selector_serialization():
+def test_cross_bin_pair_selector_serialization() -> None:
"""Test serialization of CrossBinPairSelector."""
rule = mt.CrossBinPairSelector()
yaml_str = yaml.dump(rule.model_dump(), sort_keys=False)
@@ -952,7 +962,7 @@ def test_cross_bin_pair_selector_serialization():
assert rule == rule_from_yaml
-def test_cross_name_bin_pair_selector_deserialization():
+def test_cross_name_bin_pair_selector_deserialization() -> None:
"""Test deserialization of CrossNameBinPairSelector."""
yaml_str = """
kind: cross-name
@@ -961,7 +971,7 @@ def test_cross_name_bin_pair_selector_deserialization():
assert isinstance(rule, mt.CrossNameBinPairSelector)
-def test_cross_measurement_bin_pair_selector_deserialization():
+def test_cross_measurement_bin_pair_selector_deserialization() -> None:
"""Test deserialization of CrossMeasurementBinPairSelector."""
yaml_str = """
kind: cross-measurement
@@ -970,7 +980,7 @@ def test_cross_measurement_bin_pair_selector_deserialization():
assert isinstance(rule, mt.CrossMeasurementBinPairSelector)
-def test_cross_bin_pair_selector_deserialization():
+def test_cross_bin_pair_selector_deserialization() -> None:
"""Test deserialization of CrossBinPairSelector."""
yaml_str = """
kind: cross-bin
@@ -979,7 +989,7 @@ def test_cross_bin_pair_selector_deserialization():
assert isinstance(rule, mt.CrossBinPairSelector)
-def test_cross_selectors_are_inverses():
+def test_cross_selectors_are_inverses() -> None:
"""Test that Cross selectors are exact inverses of Auto selectors."""
z1 = mt.TomographicBin(
bin_name="bin_1",
@@ -1032,7 +1042,7 @@ def test_cross_selectors_are_inverses():
# ============================================================================
-def test_three_two_bin_pair_selector_keep():
+def test_three_two_bin_pair_selector_keep() -> None:
"""Test ThreeTwoBinPairSelector keep method with various combinations."""
selector = mt.ThreeTwoBinPairSelector()
@@ -1086,7 +1096,9 @@ def test_three_two_bin_pair_selector_keep():
)
-def test_three_two_bin_pair_selector_integration(all_harmonic_bins):
+def test_three_two_bin_pair_selector_integration(
+ all_harmonic_bins: list[mt.TomographicBin],
+) -> None:
"""Test ThreeTwoBinPairSelector with realistic bin structure."""
selector = mt.ThreeTwoBinPairSelector()
@@ -1141,7 +1153,7 @@ def test_three_two_bin_pair_selector_integration(all_harmonic_bins):
assert source_lens_auto_count == 0, "Should NOT have same-bin source-lens pairs"
-def test_three_two_bin_pair_selector_components():
+def test_three_two_bin_pair_selector_components() -> None:
"""Test that ThreeTwoBinPairSelector includes the right components."""
selector = mt.ThreeTwoBinPairSelector()
@@ -1197,7 +1209,7 @@ def test_three_two_bin_pair_selector_components():
assert not has_shear_counts_auto, "Should NOT include same-bin source-lens"
-def test_three_two_bin_pair_selector_serialization():
+def test_three_two_bin_pair_selector_serialization() -> None:
"""Test serialization of ThreeTwoBinPairSelector."""
selector = mt.ThreeTwoBinPairSelector()
yaml_str = yaml.dump(selector.model_dump(), sort_keys=False)
@@ -1206,7 +1218,7 @@ def test_three_two_bin_pair_selector_serialization():
assert selector == selector_from_yaml
-def test_three_two_bin_pair_selector_deserialization():
+def test_three_two_bin_pair_selector_deserialization() -> None:
"""Test deserialization of ThreeTwoBinPairSelector."""
yaml_str = """
kind: 3x2pt
@@ -1215,7 +1227,7 @@ def test_three_two_bin_pair_selector_deserialization():
assert isinstance(selector, mt.ThreeTwoBinPairSelector)
-def test_three_two_bin_pair_selector_distance_parameters():
+def test_three_two_bin_pair_selector_distance_parameters() -> None:
"""Test distance parameters for ThreeTwoBinPairSelector."""
selector = mt.ThreeTwoBinPairSelector(
source_dist=1, lens_dist=1, source_lens_dist=2
diff --git a/tests/metadata/test_cmb_tracer.py b/tests/metadata/test_cmb_tracer.py
index 2a572bb1e..8f8741cf2 100644
--- a/tests/metadata/test_cmb_tracer.py
+++ b/tests/metadata/test_cmb_tracer.py
@@ -13,7 +13,7 @@ def make_tomobin() -> TomographicBin:
)
-def test_cmblensing_basic():
+def test_cmblensing_basic() -> None:
cmb = CMBLensing(bin_name="cmb0", z_lss=1090.0)
assert cmb.bin_name == "cmb0"
assert cmb.z_lss == 1090.0
@@ -21,7 +21,7 @@ def test_cmblensing_basic():
assert cmb.measurement_list == [CMB.CONVERGENCE]
-def test_cmblensing_validation():
+def test_cmblensing_validation() -> None:
with pytest.raises(ValueError, match="bin_name should not be empty"):
CMBLensing(bin_name="", z_lss=1090.0)
@@ -37,7 +37,7 @@ def test_cmblensing_validation():
CMBLensing(bin_name="cmb0", z_lss=1100.0, measurements={Galaxies.COUNTS})
-def test_tomographicbin_equality_and_cmb_mismatch():
+def test_tomographicbin_equality_and_cmb_mismatch() -> None:
tb1 = make_tomobin()
tb2 = TomographicBin(
bin_name="src0",
@@ -58,7 +58,7 @@ def test_tomographicbin_equality_and_cmb_mismatch():
assert (cmb == object()) is False
-def test_cmblensing_equality():
+def test_cmblensing_equality() -> None:
c1 = CMBLensing(bin_name="cmb0", z_lss=1090.0)
c2 = CMBLensing(bin_name="cmb0", z_lss=1090.0)
assert c1 == c2
diff --git a/tests/metadata/test_combination_utils.py b/tests/metadata/test_combination_utils.py
index da7e27ea0..58db5fd72 100644
--- a/tests/metadata/test_combination_utils.py
+++ b/tests/metadata/test_combination_utils.py
@@ -22,7 +22,7 @@ def fixture_sample_combinations(
return make_all_photoz_bin_combinations(all_harmonic_bins)
-def test_filter_two_point_combinations_empty_input():
+def test_filter_two_point_combinations_empty_input() -> None:
"""Test filtering with an empty input list."""
selector = mt.AutoNameBinPairSelector()
result = filter_two_point_combinations([], selector)
@@ -31,7 +31,7 @@ def test_filter_two_point_combinations_empty_input():
def test_filter_two_point_combinations_all_pass(
sample_combinations: list[mt.TwoPointXY],
-):
+) -> None:
"""Test filtering where all combinations pass the selector."""
# Create a selector that accepts everything
# Using OR of complementary selectors
@@ -46,7 +46,7 @@ def test_filter_two_point_combinations_all_pass(
def test_filter_two_point_combinations_none_pass(
sample_combinations: list[mt.TwoPointXY],
-):
+) -> None:
"""Test filtering where no combinations pass the selector."""
# Create a selector that rejects everything by using contradictory conditions
selector = mt.AutoNameBinPairSelector() & mt.CrossNameBinPairSelector()
@@ -60,7 +60,7 @@ def test_filter_two_point_combinations_none_pass(
def test_filter_two_point_combinations_auto_name(
sample_combinations: list[mt.TwoPointXY],
-):
+) -> None:
"""Test filtering with AutoNameBinPairSelector."""
selector = mt.AutoNameBinPairSelector()
@@ -78,7 +78,7 @@ def test_filter_two_point_combinations_auto_name(
def test_filter_two_point_combinations_cross_name(
sample_combinations: list[mt.TwoPointXY],
-):
+) -> None:
"""Test filtering with CrossNameBinPairSelector."""
selector = mt.CrossNameBinPairSelector()
@@ -96,7 +96,7 @@ def test_filter_two_point_combinations_cross_name(
def test_filter_two_point_combinations_source_selector(
sample_combinations: list[mt.TwoPointXY],
-):
+) -> None:
"""Test filtering with SourceBinPairSelector."""
selector = mt.SourceBinPairSelector()
@@ -111,7 +111,7 @@ def test_filter_two_point_combinations_source_selector(
def test_filter_two_point_combinations_lens_selector(
sample_combinations: list[mt.TwoPointXY],
-):
+) -> None:
"""Test filtering with LensBinPairSelector."""
selector = mt.LensBinPairSelector()
@@ -126,7 +126,7 @@ def test_filter_two_point_combinations_lens_selector(
def test_filter_two_point_combinations_composite_and(
sample_combinations: list[mt.TwoPointXY],
-):
+) -> None:
"""Test filtering with composite AND selector."""
selector = mt.AutoNameBinPairSelector() & mt.SourceBinPairSelector()
@@ -144,7 +144,7 @@ def test_filter_two_point_combinations_composite_and(
def test_filter_two_point_combinations_composite_or(
sample_combinations: list[mt.TwoPointXY],
-):
+) -> None:
"""Test filtering with composite OR selector."""
selector = (mt.AutoNameBinPairSelector() & mt.SourceBinPairSelector()) | (
mt.AutoNameBinPairSelector() & mt.LensBinPairSelector()
@@ -171,7 +171,7 @@ def test_filter_two_point_combinations_composite_or(
def test_filter_two_point_combinations_not_selector(
sample_combinations: list[mt.TwoPointXY],
-):
+) -> None:
"""Test filtering with NOT selector."""
selector = ~mt.AutoNameBinPairSelector()
@@ -182,7 +182,7 @@ def test_filter_two_point_combinations_not_selector(
assert combo.x.bin_name != combo.y.bin_name
-def test_filter_two_point_combinations_named_selector():
+def test_filter_two_point_combinations_named_selector() -> None:
"""Test filtering with NamedBinPairSelector."""
# Create specific bins for this test
bin1 = mt.TomographicBin(
@@ -217,7 +217,7 @@ def test_filter_two_point_combinations_named_selector():
assert result[0].y.bin_name == "bin_2"
-def test_filter_two_point_combinations_preserves_order():
+def test_filter_two_point_combinations_preserves_order() -> None:
"""Test that filtering preserves the original order of combinations."""
# Create bins with specific names to control ordering
bins = [
@@ -248,7 +248,7 @@ def test_filter_two_point_combinations_preserves_order():
assert result == expected_order
-def test_filter_two_point_combinations_auto_measurement():
+def test_filter_two_point_combinations_auto_measurement() -> None:
"""Test filtering with AutoMeasurementBinPairSelector."""
bin1 = mt.TomographicBin(
bin_name="bin_1",
@@ -273,7 +273,7 @@ def test_filter_two_point_combinations_auto_measurement():
assert combo.x_measurement == combo.y_measurement
-def test_filter_two_point_combinations_cross_measurement():
+def test_filter_two_point_combinations_cross_measurement() -> None:
"""Test filtering with CrossMeasurementBinPairSelector."""
bin1 = mt.TomographicBin(
bin_name="bin_1",
@@ -292,7 +292,7 @@ def test_filter_two_point_combinations_cross_measurement():
assert combo.x_measurement != combo.y_measurement
-def test_filter_two_point_combinations_complex_selector():
+def test_filter_two_point_combinations_complex_selector() -> None:
"""Test filtering with a complex nested selector."""
bins = [
mt.TomographicBin(
@@ -329,7 +329,7 @@ def test_filter_two_point_combinations_complex_selector():
assert auto_source or cross_lens
-def test_filter_two_point_combinations_triple_negation():
+def test_filter_two_point_combinations_triple_negation() -> None:
"""Test filtering with triple negation selector."""
bins = [
mt.TomographicBin(
@@ -352,7 +352,7 @@ def test_filter_two_point_combinations_triple_negation():
assert combo.x.bin_name != combo.y.bin_name
-def test_filter_two_point_combinations_with_real_vs_harmonic():
+def test_filter_two_point_combinations_with_real_vs_harmonic() -> None:
"""Test that filter_two_point_combinations.
Test that filter_two_point_combinations works with different measurement
@@ -378,7 +378,7 @@ def test_filter_two_point_combinations_with_real_vs_harmonic():
assert result[0].y_measurement == mt.Galaxies.SHEAR_E
-def test_filter_two_point_combinations_left_right_measurement_selectors():
+def test_filter_two_point_combinations_left_right_measurement_selectors() -> None:
"""Test filtering with SourceLensBinPairSelector."""
bin1 = mt.TomographicBin(
bin_name="src",
@@ -408,7 +408,7 @@ def test_filter_two_point_combinations_left_right_measurement_selectors():
assert result[0].y_measurement in mt.GALAXY_LENS_TYPES
-def test_filter_two_point_combinations_idempotent():
+def test_filter_two_point_combinations_idempotent() -> None:
"""Test that applying the same filter twice gives the same result."""
bins = [
mt.TomographicBin(
@@ -430,7 +430,7 @@ def test_filter_two_point_combinations_idempotent():
assert result1 == result2
-def test_filter_two_point_combinations_commutative_and():
+def test_filter_two_point_combinations_commutative_and() -> None:
"""Test that AND selector is commutative."""
bins = [
mt.TomographicBin(
@@ -453,7 +453,7 @@ def test_filter_two_point_combinations_commutative_and():
assert result1 == result2
-def test_filter_two_point_combinations_commutative_or():
+def test_filter_two_point_combinations_commutative_or() -> None:
"""Test that OR selector is commutative."""
bins = [
mt.TomographicBin(
diff --git a/tests/metadata/test_data_functions.py b/tests/metadata/test_data_functions.py
index 6bb960c8f..1838e25d5 100644
--- a/tests/metadata/test_data_functions.py
+++ b/tests/metadata/test_data_functions.py
@@ -111,7 +111,9 @@ def fixture_real_bins(
for elem in it.combinations(ALL_HARMONIC_BINS, ncomb)
],
)
-def fixture_harmonic_filter_collection(request) -> TwoPointBinFilterCollection:
+def fixture_harmonic_filter_collection(
+ request: pytest.FixtureRequest,
+) -> TwoPointBinFilterCollection:
"""Create a TwoPointBinFilterCollection with harmonic filters."""
bin_filters = [
TwoPointBinFilter.from_args(name_a, m_a, name_b, m_b, 20, 60)
@@ -137,7 +139,9 @@ def fixture_harmonic_filter_collection(request) -> TwoPointBinFilterCollection:
for elem in it.combinations(ALL_REAL_BINS, ncomb)
],
)
-def fixture_real_filter_collection(request) -> TwoPointBinFilterCollection:
+def fixture_real_filter_collection(
+ request: pytest.FixtureRequest,
+) -> TwoPointBinFilterCollection:
"""Create a TwoPointBinFilterCollection with real filters."""
bin_filters = [
TwoPointBinFilter.from_args(name_a, m_a, name_b, m_b, 0.1, 0.5)
@@ -147,7 +151,7 @@ def fixture_real_filter_collection(request) -> TwoPointBinFilterCollection:
return TwoPointBinFilterCollection(filters=bin_filters)
-def test_two_point_bin_filter_construct():
+def test_two_point_bin_filter_construct() -> None:
bin_spec = [
TwoPointTracerSpec(name="bin_1", measurement=Galaxies.COUNTS),
TwoPointTracerSpec(name="bin_2", measurement=Galaxies.SHEAR_E),
@@ -164,7 +168,7 @@ def test_two_point_bin_filter_construct():
assert bin_filter_from_args.interval == (0.1, 0.5)
-def test_two_point_bin_filter_construct_auto():
+def test_two_point_bin_filter_construct_auto() -> None:
bin_spec = [TwoPointTracerSpec(name="bin_1", measurement=Galaxies.COUNTS)]
bin_filter = TwoPointBinFilter(spec=bin_spec, interval=(0.1, 0.5))
assert bin_filter.spec == bin_spec
@@ -178,7 +182,7 @@ def test_two_point_bin_filter_construct_auto():
assert bin_filter_from_args.interval == (0.1, 0.5)
-def test_two_point_bin_filter_construct_invalid_range():
+def test_two_point_bin_filter_construct_invalid_range() -> None:
bin_spec = [
TwoPointTracerSpec(name="bin_1", measurement=Galaxies.COUNTS),
TwoPointTracerSpec(name="bin_2", measurement=Galaxies.SHEAR_E),
@@ -189,14 +193,14 @@ def test_two_point_bin_filter_construct_invalid_range():
TwoPointBinFilter(spec=bin_spec, interval=(0.5, 0.1))
-def test_two_point_bin_filter_construct_empty_spec():
+def test_two_point_bin_filter_construct_empty_spec() -> None:
with pytest.raises(
ValueError, match="The bin_spec must contain one or two elements."
):
TwoPointBinFilter(spec=[], interval=(0.1, 0.5))
-def test_two_point_bin_filter_construct_too_many_spec():
+def test_two_point_bin_filter_construct_too_many_spec() -> None:
bin_spec = [
TwoPointTracerSpec(name="bin_1", measurement=Galaxies.COUNTS),
TwoPointTracerSpec(name="bin_2", measurement=Galaxies.SHEAR_E),
@@ -208,7 +212,7 @@ def test_two_point_bin_filter_construct_too_many_spec():
TwoPointBinFilter(spec=bin_spec, interval=(0.1, 0.5))
-def test_two_point_bin_filter_collection_construct():
+def test_two_point_bin_filter_collection_construct() -> None:
bin_spec = (
TwoPointTracerSpec(name="bin_1", measurement=Galaxies.COUNTS),
TwoPointTracerSpec(name="bin_2", measurement=Galaxies.SHEAR_E),
@@ -656,7 +660,7 @@ def test_bin_filter_methods(
assert bin_col.apply_filter_single(harmonic_window_bins[7])
-def test_raise_with_two_bins_same_name():
+def test_raise_with_two_bins_same_name() -> None:
# Here we test if make_all_photoz_bin_combinations raises an error when
# there are two bins with the same name and measurement.
bin1 = TomographicBin(
diff --git a/tests/metadata/test_metadata_two_point.py b/tests/metadata/test_metadata_two_point.py
index de376f546..bc08e4958 100644
--- a/tests/metadata/test_metadata_two_point.py
+++ b/tests/metadata/test_metadata_two_point.py
@@ -5,6 +5,7 @@
import dataclasses
import numpy as np
+import numpy.typing as npt
import pytest
import sacc
from numpy.testing import assert_array_equal
@@ -47,7 +48,7 @@
)
-def test_inferred_galaxy_z_dist():
+def test_inferred_galaxy_z_dist() -> None:
z_dist = TomographicBin(
bin_name="b_name1",
z=np.linspace(0, 1, 100),
@@ -62,7 +63,7 @@ def test_inferred_galaxy_z_dist():
assert z_dist.measurements == {Galaxies.COUNTS}
-def test_inferred_galaxy_z_dist_bad_shape():
+def test_inferred_galaxy_z_dist_bad_shape() -> None:
with pytest.raises(
ValueError, match="The z and dndz arrays should have the same shape."
):
@@ -74,7 +75,7 @@ def test_inferred_galaxy_z_dist_bad_shape():
)
-def test_inferred_galaxy_z_dist_bad_type():
+def test_inferred_galaxy_z_dist_bad_type() -> None:
with pytest.raises(
ValueError, match="The measurement should be a Galaxies Measurement."
):
@@ -86,7 +87,7 @@ def test_inferred_galaxy_z_dist_bad_type():
)
-def test_inferred_galaxy_z_dist_bad_name():
+def test_inferred_galaxy_z_dist_bad_name() -> None:
with pytest.raises(ValueError, match="The bin_name should not be empty."):
TomographicBin(
bin_name="",
@@ -96,7 +97,7 @@ def test_inferred_galaxy_z_dist_bad_name():
)
-def test_two_point_xy_gal_gal():
+def test_two_point_xy_gal_gal() -> None:
x = TomographicBin(
bin_name="b_name1",
z=np.linspace(0, 1, 100),
@@ -118,7 +119,7 @@ def test_two_point_xy_gal_gal():
assert xy.y_measurement == Galaxies.COUNTS
-def test_two_point_xy_gal_gal_invalid_x_measurement():
+def test_two_point_xy_gal_gal_invalid_x_measurement() -> None:
x = TomographicBin(
bin_name="b_name1",
z=np.linspace(0, 1, 100),
@@ -140,7 +141,7 @@ def test_two_point_xy_gal_gal_invalid_x_measurement():
)
-def test_two_point_xy_gal_gal_invalid_y_measurement():
+def test_two_point_xy_gal_gal_invalid_y_measurement() -> None:
x = TomographicBin(
bin_name="b_name1",
z=np.linspace(0, 1, 100),
@@ -162,7 +163,7 @@ def test_two_point_xy_gal_gal_invalid_y_measurement():
)
-def test_two_point_xy_cmb_gal():
+def test_two_point_xy_cmb_gal() -> None:
x = CMBLensing(
bin_name="b_name1",
z_lss=1100.0,
@@ -183,7 +184,7 @@ def test_two_point_xy_cmb_gal():
assert xy.y_measurement == Galaxies.COUNTS
-def test_two_point_xy_invalid():
+def test_two_point_xy_invalid() -> None:
x = TomographicBin(
bin_name="b_name1",
z=np.linspace(0, 1, 100),
@@ -205,11 +206,11 @@ def test_two_point_xy_invalid():
)
-def test_two_point_xy_neq_other_type(harmonic_two_point_xy: TwoPointXY):
+def test_two_point_xy_neq_other_type(harmonic_two_point_xy: TwoPointXY) -> None:
assert harmonic_two_point_xy != object()
-def test_two_point_harmonic():
+def test_two_point_harmonic() -> None:
x = TomographicBin(
bin_name="b_name1",
z=np.linspace(0, 1, 100),
@@ -234,7 +235,7 @@ def test_two_point_harmonic():
assert cells.n_observations() == 100
-def test_two_point_harmonic_invalid_ells():
+def test_two_point_harmonic_invalid_ells() -> None:
x = TomographicBin(
bin_name="b_name1",
z=np.linspace(0, 1, 100),
@@ -258,7 +259,7 @@ def test_two_point_harmonic_invalid_ells():
TwoPointHarmonic(ells=ells, XY=xy)
-def test_two_point_harmonic_invalid_type():
+def test_two_point_harmonic_invalid_type() -> None:
x = TomographicBin(
bin_name="b_name1",
z=np.linspace(0, 1, 100),
@@ -282,7 +283,7 @@ def test_two_point_harmonic_invalid_type():
TwoPointHarmonic(ells=ells, XY=xy)
-def test_two_point_cwindow(harmonic_two_point_xy: TwoPointXY):
+def test_two_point_cwindow(harmonic_two_point_xy: TwoPointXY) -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
weights = np.ones(400).reshape(-1, 4)
window_ells = np.array([0, 1, 2, 3], dtype=np.float64)
@@ -303,7 +304,7 @@ def test_two_point_cwindow(harmonic_two_point_xy: TwoPointXY):
def test_two_point_cwindow_wrong_data_shape(
harmonic_two_point_xy: TwoPointXY,
-):
+) -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
weights = np.ones(400).reshape(-1, 4)
window_ells = np.array([0, 1, 2, 3], dtype=np.float64)
@@ -329,7 +330,7 @@ def test_two_point_cwindow_wrong_data_shape(
)
-def test_two_point_measurement_invalid_metadata():
+def test_two_point_measurement_invalid_metadata() -> None:
data = (np.zeros(100) + 1.1).astype(np.float64)
indices = np.arange(100)
covariance_name = "cov"
@@ -345,7 +346,7 @@ def test_two_point_measurement_invalid_metadata():
)
-def test_two_point_cwindow_stringify(harmonic_two_point_xy: TwoPointXY):
+def test_two_point_cwindow_stringify(harmonic_two_point_xy: TwoPointXY) -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
weights = np.ones(400).reshape(-1, 4)
window_ells = np.array([0, 1, 2, 3], dtype=np.float64)
@@ -359,7 +360,7 @@ def test_two_point_cwindow_stringify(harmonic_two_point_xy: TwoPointXY):
)
-def test_two_point_cwindow_invalid():
+def test_two_point_cwindow_invalid() -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
weights = np.ones(400).reshape(-1, 4)
window_ells = np.array([0, 1, 2, 3], dtype=np.float64)
@@ -387,7 +388,7 @@ def test_two_point_cwindow_invalid():
TwoPointHarmonic(XY=xy, ells=ells, window=weights, window_ells=window_ells)
-def test_two_point_cwindow_invalid_window():
+def test_two_point_cwindow_invalid_window() -> None:
x = TomographicBin(
bin_name="b_name1",
z=np.linspace(0, 1, 100),
@@ -412,7 +413,7 @@ def test_two_point_cwindow_invalid_window():
)
-def test_two_point_cwindow_invalid_window_shape():
+def test_two_point_cwindow_invalid_window_shape() -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
weights = np.ones(400, dtype=np.float64)
@@ -438,7 +439,7 @@ def test_two_point_cwindow_invalid_window_shape():
TwoPointHarmonic(XY=xy, ells=ells, window=weights)
-def test_two_point_cwindow_window_ell_not_match():
+def test_two_point_cwindow_window_ell_not_match() -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
weights = np.ones(400).reshape(-1, 4)
@@ -464,7 +465,7 @@ def test_two_point_cwindow_window_ell_not_match():
TwoPointHarmonic(XY=xy, ells=ells[:10], window=weights)
-def test_two_point_cwindow_missing_window_ells():
+def test_two_point_cwindow_missing_window_ells() -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
weights = np.ones(400).reshape(-1, 4)
@@ -490,7 +491,7 @@ def test_two_point_cwindow_missing_window_ells():
TwoPointHarmonic(XY=xy, ells=ells, window=weights)
-def test_two_point_cwindow_window_ells_wrong_shape():
+def test_two_point_cwindow_window_ells_wrong_shape() -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
weights = np.ones(400).reshape(-1, 4)
@@ -522,7 +523,7 @@ def test_two_point_cwindow_window_ells_wrong_shape():
)
-def test_two_point_cwindow_window_ells_wrong_len():
+def test_two_point_cwindow_window_ells_wrong_len() -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
weights = np.ones(400).reshape(-1, 4)
@@ -554,7 +555,7 @@ def test_two_point_cwindow_window_ells_wrong_len():
)
-def test_two_point_cwindow_no_window_with_window_ells():
+def test_two_point_cwindow_no_window_with_window_ells() -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
x = TomographicBin(
@@ -580,7 +581,7 @@ def test_two_point_cwindow_no_window_with_window_ells():
TwoPointHarmonic(XY=xy, ells=ells, window_ells=np.linspace(0, 1, 9))
-def test_two_point_real():
+def test_two_point_real() -> None:
x = TomographicBin(
bin_name="b_name1",
z=np.linspace(0, 1, 100),
@@ -605,7 +606,7 @@ def test_two_point_real():
assert two_point.n_observations() == 100
-def test_two_point_real_invalid():
+def test_two_point_real_invalid() -> None:
x = TomographicBin(
bin_name="b_name1",
z=np.linspace(0, 1, 100),
@@ -629,35 +630,35 @@ def test_two_point_real_invalid():
TwoPointReal(XY=xy, thetas=theta)
-def test_harmonic_type_string_invalid():
+def test_harmonic_type_string_invalid() -> None:
with pytest.raises(
ValueError, match="Harmonic-space correlation not supported for shear T."
):
harmonic(Galaxies.SHEAR_T, Galaxies.COUNTS)
-def test_real_type_string_invalid():
+def test_real_type_string_invalid() -> None:
with pytest.raises(
ValueError, match="Real-space correlation not supported for shear E."
):
real(Galaxies.SHEAR_E, Galaxies.COUNTS)
-def test_tracer_names_serialization():
+def test_tracer_names_serialization() -> None:
tn = TracerNames("x", "y")
s = tn.to_yaml()
recovered = TracerNames.from_yaml(s)
assert tn == recovered
-def test_measurement_serialization():
+def test_measurement_serialization() -> None:
for t in ALL_MEASUREMENTS:
s = t.to_yaml()
recovered = type(t).from_yaml(s)
assert t == recovered
-def test_inferred_galaxy_zdist_serialization(harmonic_bin_1: TomographicBin):
+def test_inferred_galaxy_zdist_serialization(harmonic_bin_1: TomographicBin) -> None:
s = harmonic_bin_1.to_yaml()
# Take a look at how hideous the generated string
# is.
@@ -665,13 +666,13 @@ def test_inferred_galaxy_zdist_serialization(harmonic_bin_1: TomographicBin):
assert harmonic_bin_1 == recovered
-def test_two_point_xy_str(harmonic_two_point_xy: TwoPointXY):
+def test_two_point_xy_str(harmonic_two_point_xy: TwoPointXY) -> None:
assert str(harmonic_two_point_xy) == (
f"({harmonic_two_point_xy.x.bin_name}, " f"{harmonic_two_point_xy.y.bin_name})"
)
-def test_two_point_xy_serialization(harmonic_two_point_xy: TwoPointXY):
+def test_two_point_xy_serialization(harmonic_two_point_xy: TwoPointXY) -> None:
s = harmonic_two_point_xy.to_yaml()
# Take a look at how hideous the generated string
# is.
@@ -680,13 +681,13 @@ def test_two_point_xy_serialization(harmonic_two_point_xy: TwoPointXY):
assert str(harmonic_two_point_xy) == str(recovered)
-def test_two_point_harmonic_str(harmonic_two_point_xy: TwoPointXY):
+def test_two_point_harmonic_str(harmonic_two_point_xy: TwoPointXY) -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
cells = TwoPointHarmonic(ells=ells, XY=harmonic_two_point_xy)
assert str(cells) == f"{str(harmonic_two_point_xy)}[{cells.get_sacc_name()}]"
-def test_two_point_harmonic_serialization(harmonic_two_point_xy: TwoPointXY):
+def test_two_point_harmonic_serialization(harmonic_two_point_xy: TwoPointXY) -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
cells = TwoPointHarmonic(ells=ells, XY=harmonic_two_point_xy)
s = cells.to_yaml()
@@ -696,7 +697,7 @@ def test_two_point_harmonic_serialization(harmonic_two_point_xy: TwoPointXY):
assert str(cells) == str(recovered)
-def test_two_point_harmonic_cmp_invalid(harmonic_two_point_xy: TwoPointXY):
+def test_two_point_harmonic_cmp_invalid(harmonic_two_point_xy: TwoPointXY) -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
cells = TwoPointHarmonic(ells=ells, XY=harmonic_two_point_xy)
with pytest.raises(
@@ -706,7 +707,7 @@ def test_two_point_harmonic_cmp_invalid(harmonic_two_point_xy: TwoPointXY):
_ = cells == "Im not a TwoPointHarmonic"
-def test_two_point_harmonic_ells_wrong_shape(harmonic_two_point_xy: TwoPointXY):
+def test_two_point_harmonic_ells_wrong_shape(harmonic_two_point_xy: TwoPointXY) -> None:
ells = np.array(np.linspace(0, 100), dtype=np.int64).reshape(-1, 10)
with pytest.raises(
ValueError,
@@ -717,13 +718,13 @@ def test_two_point_harmonic_ells_wrong_shape(harmonic_two_point_xy: TwoPointXY):
def test_two_point_harmonic_with_window_serialization(
optimized_two_point_cwindow: TwoPointHarmonic,
-):
+) -> None:
s = optimized_two_point_cwindow.to_yaml()
recovered = TwoPointHarmonic.from_yaml(s)
assert optimized_two_point_cwindow == recovered
-def test_two_point_real_serialization(optimized_real_two_point_xy: TwoPointXY):
+def test_two_point_real_serialization(optimized_real_two_point_xy: TwoPointXY) -> None:
theta = np.array(np.linspace(0, 10, 10))
xi_theta = TwoPointReal(XY=optimized_real_two_point_xy, thetas=theta)
s = xi_theta.to_yaml()
@@ -733,7 +734,7 @@ def test_two_point_real_serialization(optimized_real_two_point_xy: TwoPointXY):
assert str(xi_theta) == str(recovered)
-def test_two_point_real_cmp_invalid(optimized_real_two_point_xy: TwoPointXY):
+def test_two_point_real_cmp_invalid(optimized_real_two_point_xy: TwoPointXY) -> None:
theta = np.array(np.linspace(0, 10, 10))
xi_theta = TwoPointReal(XY=optimized_real_two_point_xy, thetas=theta)
with pytest.raises(
@@ -743,7 +744,7 @@ def test_two_point_real_cmp_invalid(optimized_real_two_point_xy: TwoPointXY):
_ = xi_theta == "Im not a TwoPointReal"
-def test_two_point_real_wrong_shape(optimized_real_two_point_xy: TwoPointXY):
+def test_two_point_real_wrong_shape(optimized_real_two_point_xy: TwoPointXY) -> None:
theta = np.array(np.linspace(0, 10), dtype=np.float64).reshape(-1, 10)
with pytest.raises(
ValueError,
@@ -752,7 +753,9 @@ def test_two_point_real_wrong_shape(optimized_real_two_point_xy: TwoPointXY):
TwoPointReal(XY=optimized_real_two_point_xy, thetas=theta)
-def test_two_point_from_metadata_cells(harmonic_two_point_xy, tp_factory):
+def test_two_point_from_metadata_cells(
+ harmonic_two_point_xy: TwoPointXY, tp_factory: TwoPointFactory
+) -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
cells = TwoPointHarmonic(ells=ells, XY=harmonic_two_point_xy)
two_point = TwoPoint.from_metadata([cells], tp_factory).pop()
@@ -763,6 +766,8 @@ def test_two_point_from_metadata_cells(harmonic_two_point_xy, tp_factory):
assert isinstance(two_point.source0, SourceGalaxy)
assert isinstance(two_point.source1, SourceGalaxy)
+ assert isinstance(harmonic_two_point_xy.x, TomographicBin)
+ assert isinstance(harmonic_two_point_xy.y, TomographicBin)
assert_array_equal(two_point.source0.tracer_args.z, harmonic_two_point_xy.x.z)
assert_array_equal(two_point.source1.tracer_args.z, harmonic_two_point_xy.y.z)
@@ -771,7 +776,9 @@ def test_two_point_from_metadata_cells(harmonic_two_point_xy, tp_factory):
assert_array_equal(two_point.source1.tracer_args.dndz, harmonic_two_point_xy.y.dndz)
-def test_two_point_from_metadata_cwindow(two_point_cwindow, tp_factory):
+def test_two_point_from_metadata_cwindow(
+ two_point_cwindow: TwoPointHarmonic, tp_factory: TwoPointFactory
+) -> None:
two_point = TwoPoint.from_metadata([two_point_cwindow], tp_factory).pop()
assert two_point is not None
@@ -780,6 +787,8 @@ def test_two_point_from_metadata_cwindow(two_point_cwindow, tp_factory):
assert isinstance(two_point.source0, SourceGalaxy)
assert isinstance(two_point.source1, SourceGalaxy)
+ assert isinstance(two_point_cwindow.XY.x, TomographicBin)
+ assert isinstance(two_point_cwindow.XY.y, TomographicBin)
assert_array_equal(two_point.source0.tracer_args.z, two_point_cwindow.XY.x.z)
assert_array_equal(two_point.source1.tracer_args.z, two_point_cwindow.XY.y.z)
@@ -788,7 +797,9 @@ def test_two_point_from_metadata_cwindow(two_point_cwindow, tp_factory):
assert_array_equal(two_point.source1.tracer_args.dndz, two_point_cwindow.XY.y.dndz)
-def test_two_point_from_metadata_xi_theta(optimized_real_two_point_xy, tp_factory):
+def test_two_point_from_metadata_xi_theta(
+ optimized_real_two_point_xy: TwoPointXY, tp_factory: TwoPointFactory
+) -> None:
theta = np.array(np.linspace(0, 100, 100))
xi_theta = TwoPointReal(XY=optimized_real_two_point_xy, thetas=theta)
if xi_theta.get_sacc_name() == "galaxy_shear_xi_tt":
@@ -801,6 +812,8 @@ def test_two_point_from_metadata_xi_theta(optimized_real_two_point_xy, tp_factor
assert isinstance(two_point.source0, SourceGalaxy)
assert isinstance(two_point.source1, SourceGalaxy)
+ assert isinstance(optimized_real_two_point_xy.x, TomographicBin)
+ assert isinstance(optimized_real_two_point_xy.y, TomographicBin)
assert_array_equal(two_point.source0.tracer_args.z, optimized_real_two_point_xy.x.z)
assert_array_equal(two_point.source1.tracer_args.z, optimized_real_two_point_xy.y.z)
@@ -813,7 +826,9 @@ def test_two_point_from_metadata_xi_theta(optimized_real_two_point_xy, tp_factor
)
-def test_two_point_from_metadata_cells_unsupported_type(tp_factory):
+def test_two_point_from_metadata_cells_unsupported_type(
+ tp_factory: TwoPointFactory,
+) -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
@dataclasses.dataclass(frozen=True, kw_only=True)
@@ -851,7 +866,7 @@ def measurement_list(self) -> list[Measurement]:
@pytest.fixture(name="tp_factory_with_cmb")
-def fixture_tp_factory_with_cmb():
+def fixture_tp_factory_with_cmb() -> TwoPointFactory:
return TwoPointFactory(
correlation_space=TwoPointCorrelationSpace.HARMONIC,
weak_lensing_factories=[WeakLensingFactory()],
@@ -860,7 +875,9 @@ def fixture_tp_factory_with_cmb():
)
-def test_two_point_from_metadata_cmb_supported(tp_factory_with_cmb):
+def test_two_point_from_metadata_cmb_supported(
+ tp_factory_with_cmb: TwoPointFactory,
+) -> None:
"""Test that CMB measurements work when CMB factory is provided."""
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
x = CMBLensing(
@@ -889,7 +906,7 @@ def test_two_point_from_metadata_cmb_supported(tp_factory_with_cmb):
assert two_point.sacc_data_type == cells.get_sacc_name()
-def test_make_two_point_xy_valid_galaxies():
+def test_make_two_point_xy_valid_galaxies() -> None:
"""Test make_two_point_xy with valid galaxy measurements."""
x = TomographicBin(
bin_name="shear_bin_0",
@@ -915,7 +932,7 @@ def test_make_two_point_xy_valid_galaxies():
assert xy.y_measurement == Galaxies.SHEAR_E
-def test_make_two_point_xy_valid_cmb_galaxy():
+def test_make_two_point_xy_valid_cmb_galaxy() -> None:
"""Test make_two_point_xy with CMB-galaxy measurements."""
cmb = CMBLensing(
bin_name="cmb_convergence",
@@ -943,7 +960,7 @@ def test_make_two_point_xy_valid_cmb_galaxy():
assert xy.y_measurement == Galaxies.COUNTS
-def test_make_two_point_xy_valid_cmb_galaxy_needs_swap():
+def test_make_two_point_xy_valid_cmb_galaxy_needs_swap() -> None:
"""Test make_two_point_xy with CMB-galaxy measurements."""
cmb = CMBLensing(
bin_name="cmb_convergence",
@@ -973,7 +990,7 @@ def test_make_two_point_xy_valid_cmb_galaxy_needs_swap():
assert xy.y_measurement == Galaxies.COUNTS
-def test_make_two_point_xy_missing_tracer_zdist():
+def test_make_two_point_xy_missing_tracer_zdist() -> None:
"""Test make_two_point_xy raises exception when tracer zdist not found.
Verifies that make_two_point_xy raises a ValueError with informative message
@@ -1000,7 +1017,7 @@ def test_make_two_point_xy_missing_tracer_zdist():
assert "not found in inferred galaxy z distributions" in error_msg
-def test_make_two_point_xy_missing_x_measurement():
+def test_make_two_point_xy_missing_x_measurement() -> None:
"""Test make_two_point_xy when first tracer lacks required measurement."""
x = TomographicBin(
bin_name="shear_bin_0",
@@ -1031,7 +1048,7 @@ def test_make_two_point_xy_missing_x_measurement():
assert "shear_bin_1" in error_msg
-def test_make_two_point_xy_missing_y_measurement():
+def test_make_two_point_xy_missing_y_measurement() -> None:
"""Test make_two_point_xy when second tracer lacks required measurement."""
x = TomographicBin(
bin_name="shear_bin_0",
@@ -1061,7 +1078,7 @@ def test_make_two_point_xy_missing_y_measurement():
assert "shear_bin_1" in error_msg
-def test_make_two_point_xy_both_measurements_missing():
+def test_make_two_point_xy_both_measurements_missing() -> None:
"""Test make_two_point_xy when both tracers lack required measurements."""
x = TomographicBin(
bin_name="counts_bin_0",
@@ -1089,7 +1106,7 @@ def test_make_two_point_xy_both_measurements_missing():
)
-def test_make_two_point_xy_sacc_convention_explanation():
+def test_make_two_point_xy_sacc_convention_explanation() -> None:
"""Test that error message includes SACC convention explanation."""
x = CMBLensing(
bin_name="cmb_bin",
@@ -1118,8 +1135,13 @@ def test_make_two_point_xy_sacc_convention_explanation():
def test_extract_all_real_metadata_indices_no_swap(
- sacc_galaxy_xis_src0_lens0: tuple[object, ...],
-):
+ sacc_galaxy_xis_src0_lens0: tuple[
+ sacc.Sacc,
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ ],
+) -> None:
"""Test extract_all_real_metadata_indices with no tracer swap needed.
This test verifies that when tracers are in the correct order according to
@@ -1147,7 +1169,7 @@ def test_extract_all_real_metadata_indices_no_swap(
assert b == Galaxies.COUNTS
-def test_extract_all_real_metadata_indices_with_swap():
+def test_extract_all_real_metadata_indices_with_swap() -> None:
"""Test extract_all_real_metadata_indices when tracer swap is necessary.
This test creates a SACC file where tracers are in reversed order compared
@@ -1205,7 +1227,7 @@ def test_extract_all_real_metadata_indices_with_swap():
assert b == Galaxies.SHEAR_T
-def test_extract_all_real_metadata_indices_density_only():
+def test_extract_all_real_metadata_indices_density_only() -> None:
"""Test extract_all_real_metadata_indices with density-only measurement."""
sacc_data = sacc.Sacc()
@@ -1238,7 +1260,7 @@ def test_extract_all_real_metadata_indices_density_only():
assert b == Galaxies.COUNTS
-def test_extract_all_real_metadata_indices_shear_only():
+def test_extract_all_real_metadata_indices_shear_only() -> None:
"""Test extract_all_real_metadata_indices with shear-density measurement."""
sacc_data = sacc.Sacc()
@@ -1271,7 +1293,7 @@ def test_extract_all_real_metadata_indices_shear_only():
assert b == Galaxies.COUNTS
-def test_extract_all_real_metadata_indices_multiple_combinations():
+def test_extract_all_real_metadata_indices_multiple_combinations() -> None:
"""Test extract_all_real_metadata_indices with multiple tracer combinations."""
sacc_data = sacc.Sacc()
@@ -1318,8 +1340,13 @@ def test_extract_all_real_metadata_indices_multiple_combinations():
def test_extract_all_harmonic_metadata_indices_no_swap(
- sacc_galaxy_cells_src0_lens0: tuple[object, ...],
-):
+ sacc_galaxy_cells_src0_lens0: tuple[
+ sacc.Sacc,
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ ],
+) -> None:
"""Test extract_all_harmonic_metadata_indices with no tracer swap needed.
This test verifies that when tracers are in the correct order according to
@@ -1346,7 +1373,7 @@ def test_extract_all_harmonic_metadata_indices_no_swap(
assert b == Galaxies.COUNTS
-def test_extract_all_harmonic_metadata_indices_with_swap():
+def test_extract_all_harmonic_metadata_indices_with_swap() -> None:
"""Test extract_all_harmonic_metadata_indices when tracer swap is necessary.
This test creates a SACC file where tracers are in reversed order compared
@@ -1402,7 +1429,7 @@ def test_extract_all_harmonic_metadata_indices_with_swap():
assert b == Galaxies.SHEAR_E
-def test_extract_all_harmonic_metadata_indices_density_only():
+def test_extract_all_harmonic_metadata_indices_density_only() -> None:
"""Test extract_all_harmonic_metadata_indices with density-only measurement."""
sacc_data = sacc.Sacc()
@@ -1435,7 +1462,7 @@ def test_extract_all_harmonic_metadata_indices_density_only():
assert b == Galaxies.COUNTS
-def test_extract_all_harmonic_metadata_indices_shear_only():
+def test_extract_all_harmonic_metadata_indices_shear_only() -> None:
"""Test extract_all_harmonic_metadata_indices with shear-only measurement."""
sacc_data = sacc.Sacc()
@@ -1468,7 +1495,7 @@ def test_extract_all_harmonic_metadata_indices_shear_only():
assert b == Galaxies.SHEAR_E
-def test_extract_all_harmonic_metadata_indices_multiple_combinations():
+def test_extract_all_harmonic_metadata_indices_multiple_combinations() -> None:
"""Test extract_all_harmonic_metadata_indices with multiple tracer combinations."""
sacc_data = sacc.Sacc()
diff --git a/tests/metadata/test_metadata_two_point_measurement.py b/tests/metadata/test_metadata_two_point_measurement.py
index e3aee98ca..e6a854ec6 100644
--- a/tests/metadata/test_metadata_two_point_measurement.py
+++ b/tests/metadata/test_metadata_two_point_measurement.py
@@ -20,7 +20,7 @@
)
-def test_two_point_cells_with_data(harmonic_two_point_xy: TwoPointXY):
+def test_two_point_cells_with_data(harmonic_two_point_xy: TwoPointXY) -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
data = np.array(np.ones_like(ells) * 1.1, dtype=np.float64)
indices = np.arange(100)
@@ -42,7 +42,9 @@ def test_two_point_cells_with_data(harmonic_two_point_xy: TwoPointXY):
assert tpm.covariance_name == covariance_name
-def test_two_point_two_point_cwindow_with_data(harmonic_two_point_xy: TwoPointXY):
+def test_two_point_two_point_cwindow_with_data(
+ harmonic_two_point_xy: TwoPointXY,
+) -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
weights = np.zeros((100, 4), dtype=np.float64)
# Create a window with 4 bins, each containing 25 elements with a weight of 1.0.
@@ -83,7 +85,7 @@ def test_two_point_two_point_cwindow_with_data(harmonic_two_point_xy: TwoPointXY
assert tpm.covariance_name == covariance_name
-def test_two_point_xi_theta_with_data(optimized_real_two_point_xy: TwoPointXY):
+def test_two_point_xi_theta_with_data(optimized_real_two_point_xy: TwoPointXY) -> None:
thetas = np.linspace(0.0, 1.0, 100, dtype=np.float64)
data = np.array(np.zeros(100) + 1.1, dtype=np.float64)
indices = np.arange(100)
@@ -107,7 +109,9 @@ def test_two_point_xi_theta_with_data(optimized_real_two_point_xy: TwoPointXY):
assert tpm.covariance_name == covariance_name
-def test_two_point_cells_with_invalid_data_size(harmonic_two_point_xy: TwoPointXY):
+def test_two_point_cells_with_invalid_data_size(
+ harmonic_two_point_xy: TwoPointXY,
+) -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
data = np.array(np.zeros(101) + 1.1, dtype=np.float64)
indices = np.arange(101)
@@ -125,7 +129,9 @@ def test_two_point_cells_with_invalid_data_size(harmonic_two_point_xy: TwoPointX
)
-def test_two_point_cwindow_with_invalid_data_size(harmonic_two_point_xy: TwoPointXY):
+def test_two_point_cwindow_with_invalid_data_size(
+ harmonic_two_point_xy: TwoPointXY,
+) -> None:
ells = np.array(np.linspace(0, 100, 100), dtype=np.int64)
weights = np.ones(400).reshape(-1, 4)
window_ells = np.array([0, 1, 2, 3], dtype=np.float64)
@@ -154,7 +160,7 @@ def test_two_point_cwindow_with_invalid_data_size(harmonic_two_point_xy: TwoPoin
def test_two_point_xi_theta_with_invalid_data_size(
optimized_real_two_point_xy: TwoPointXY,
-):
+) -> None:
thetas = np.linspace(0.0, 1.0, 100, dtype=np.float64)
data = np.array(np.zeros(101) + 1.1, dtype=np.float64)
indices = np.arange(101)
@@ -172,7 +178,9 @@ def test_two_point_xi_theta_with_invalid_data_size(
)
-def test_two_point_measurement_invalid_data(optimized_real_two_point_xy: TwoPointXY):
+def test_two_point_measurement_invalid_data(
+ optimized_real_two_point_xy: TwoPointXY,
+) -> None:
thetas = np.linspace(0.0, 1.0, 5, dtype=np.float64)
data = np.array([1, 2, 3, 4, 5], dtype=np.float64).reshape(-1, 1)
indices = np.array([1, 2, 3, 4, 5])
@@ -189,7 +197,9 @@ def test_two_point_measurement_invalid_data(optimized_real_two_point_xy: TwoPoin
)
-def test_two_point_measurement_invalid_indices(optimized_real_two_point_xy: TwoPointXY):
+def test_two_point_measurement_invalid_indices(
+ optimized_real_two_point_xy: TwoPointXY,
+) -> None:
thetas = np.linspace(0.0, 1.0, 5, dtype=np.float64)
data = np.array([1, 2, 3, 4, 5])
indices = np.array([1, 2, 3, 4, 5]).reshape(-1, 1)
@@ -206,7 +216,7 @@ def test_two_point_measurement_invalid_indices(optimized_real_two_point_xy: TwoP
)
-def test_two_point_measurement_eq(optimized_real_two_point_xy: TwoPointXY):
+def test_two_point_measurement_eq(optimized_real_two_point_xy: TwoPointXY) -> None:
thetas = np.linspace(0.0, 1.0, 5, dtype=np.float64)
data = np.array([1, 2, 3, 4, 5])
indices = np.array([1, 2, 3, 4, 5])
@@ -226,7 +236,7 @@ def test_two_point_measurement_eq(optimized_real_two_point_xy: TwoPointXY):
assert measure_1 == measure_2
-def test_two_point_measurement_neq(optimized_real_two_point_xy: TwoPointXY):
+def test_two_point_measurement_neq(optimized_real_two_point_xy: TwoPointXY) -> None:
thetas = np.linspace(0.0, 1.0, 5, dtype=np.float64)
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0], dtype=np.float64)
indices = np.array([1, 2, 3, 4, 5])
@@ -274,7 +284,7 @@ def test_two_point_measurement_neq(optimized_real_two_point_xy: TwoPointXY):
def test_two_point_measurement_neq_other_type(
optimized_real_two_point_xy: TwoPointXY,
-):
+) -> None:
thetas = np.linspace(0.0, 1.0, 5, dtype=np.float64)
measurement = TwoPointMeasurement(
data=np.array([1.0, 2.0, 3.0, 4.0, 5.0]),
diff --git a/tests/metadata/test_metadata_two_point_sacc.py b/tests/metadata/test_metadata_two_point_sacc.py
index 7613c484e..af69a5412 100644
--- a/tests/metadata/test_metadata_two_point_sacc.py
+++ b/tests/metadata/test_metadata_two_point_sacc.py
@@ -23,6 +23,7 @@
TwoPointFactory,
use_source_factory,
)
+from firecrown.modeling_tools import ModelingTools
from firecrown.metadata_functions import (
extract_all_harmonic_metadata,
extract_all_harmonic_metadata_indices,
@@ -57,13 +58,14 @@
_type_to_sacc_string_real,
)
from firecrown.updatable import ParamsMap
+from tests._types import SaccGalaxyWindowedFixture
# pylint: disable=too-many-lines
@pytest.fixture(name="sacc_galaxy_src0_src0_invalid_data_type")
def fixture_sacc_galaxy_src0_src0_invalid_data_type(
- recwarn,
+ recwarn: pytest.WarningsRecorder,
) -> tuple[sacc.Sacc, np.ndarray, np.ndarray]:
"""Fixture for a SACC data without window functions."""
sacc_data = sacc.Sacc()
@@ -155,7 +157,16 @@ def fixture_sacc_galaxy_cells_three_tracers() -> (
return sacc_data, z, dndz0, dndz1, dndz2
-def test_extract_all_tracers_cells(sacc_galaxy_cells) -> None:
+def test_extract_all_tracers_cells(
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
sacc_data, tracers, _ = sacc_galaxy_cells
assert sacc_data is not None
all_tracers = extract_all_tracers_tomographic_bins(sacc_data)
@@ -166,7 +177,16 @@ def test_extract_all_tracers_cells(sacc_galaxy_cells) -> None:
assert_array_equal(tracer.dndz, orig_tracer[1])
-def test_extract_all_tracers_xis(sacc_galaxy_xis):
+def test_extract_all_tracers_xis(
+ sacc_galaxy_xis: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
sacc_data, tracers, _ = sacc_galaxy_xis
assert sacc_data is not None
all_tracers = extract_all_tracers_tomographic_bins(sacc_data)
@@ -177,21 +197,30 @@ def test_extract_all_tracers_xis(sacc_galaxy_xis):
assert_array_equal(tracer.dndz, orig_tracer[1])
-def test_extract_all_tracers_cells_src0_src0(sacc_galaxy_cells_src0_src0):
- sacc_data, z, dndz = sacc_galaxy_cells_src0_src0
+def test_extract_all_tracers_cells_src0_src0(
+ sacc_galaxy_cells_src0_src0: tuple[sacc.Sacc, TomographicBin],
+) -> None:
+ sacc_data, expected_bin = sacc_galaxy_cells_src0_src0
assert sacc_data is not None
all_tracers = extract_all_tracers_tomographic_bins(sacc_data)
assert len(all_tracers) == 1
for tracer in all_tracers:
- assert_array_equal(tracer.z, z)
- assert_array_equal(tracer.dndz, dndz)
+ assert_array_equal(tracer.z, expected_bin.z)
+ assert_array_equal(tracer.dndz, expected_bin.dndz)
assert tracer.bin_name == "src0"
assert tracer.measurements == {Galaxies.SHEAR_E}
-def test_extract_all_tracers_cells_src0_src1(sacc_galaxy_cells_src0_src1):
+def test_extract_all_tracers_cells_src0_src1(
+ sacc_galaxy_cells_src0_src1: tuple[
+ sacc.Sacc,
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ ],
+) -> None:
sacc_data, z, dndz0, dndz1 = sacc_galaxy_cells_src0_src1
assert sacc_data is not None
all_tracers = extract_all_tracers_tomographic_bins(sacc_data)
@@ -207,21 +236,30 @@ def test_extract_all_tracers_cells_src0_src1(sacc_galaxy_cells_src0_src1):
assert_array_equal(tracer.dndz, dndz1)
-def test_extract_all_tracers_cells_lens0_lens0(sacc_galaxy_cells_lens0_lens0):
- sacc_data, z, dndz = sacc_galaxy_cells_lens0_lens0
+def test_extract_all_tracers_cells_lens0_lens0(
+ sacc_galaxy_cells_lens0_lens0: tuple[sacc.Sacc, TomographicBin],
+) -> None:
+ sacc_data, expected_bin = sacc_galaxy_cells_lens0_lens0
assert sacc_data is not None
all_tracers = extract_all_tracers_tomographic_bins(sacc_data)
assert len(all_tracers) == 1
for tracer in all_tracers:
- assert_array_equal(tracer.z, z)
- assert_array_equal(tracer.dndz, dndz)
+ assert_array_equal(tracer.z, expected_bin.z)
+ assert_array_equal(tracer.dndz, expected_bin.dndz)
assert tracer.bin_name == "lens0"
assert tracer.measurements == {Galaxies.COUNTS}
-def test_extract_all_tracers_cells_lens0_lens1(sacc_galaxy_cells_lens0_lens1):
+def test_extract_all_tracers_cells_lens0_lens1(
+ sacc_galaxy_cells_lens0_lens1: tuple[
+ sacc.Sacc,
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ ],
+) -> None:
sacc_data, z, dndz0, dndz1 = sacc_galaxy_cells_lens0_lens1
assert sacc_data is not None
all_tracers = extract_all_tracers_tomographic_bins(sacc_data)
@@ -237,21 +275,30 @@ def test_extract_all_tracers_cells_lens0_lens1(sacc_galaxy_cells_lens0_lens1):
assert_array_equal(tracer.dndz, dndz1)
-def test_extract_all_tracers_xis_lens0_lens0(sacc_galaxy_xis_lens0_lens0):
- sacc_data, z, dndz = sacc_galaxy_xis_lens0_lens0
+def test_extract_all_tracers_xis_lens0_lens0(
+ sacc_galaxy_xis_lens0_lens0: tuple[sacc.Sacc, TomographicBin],
+) -> None:
+ sacc_data, expected_bin = sacc_galaxy_xis_lens0_lens0
assert sacc_data is not None
all_tracers = extract_all_tracers_tomographic_bins(sacc_data)
assert len(all_tracers) == 1
for tracer in all_tracers:
- assert_array_equal(tracer.z, z)
- assert_array_equal(tracer.dndz, dndz)
+ assert_array_equal(tracer.z, expected_bin.z)
+ assert_array_equal(tracer.dndz, expected_bin.dndz)
assert tracer.bin_name == "lens0"
assert tracer.measurements == {Galaxies.COUNTS}
-def test_extract_all_tracers_xis_lens0_lens1(sacc_galaxy_xis_lens0_lens1):
+def test_extract_all_tracers_xis_lens0_lens1(
+ sacc_galaxy_xis_lens0_lens1: tuple[
+ sacc.Sacc,
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ ],
+) -> None:
sacc_data, z, dndz0, dndz1 = sacc_galaxy_xis_lens0_lens1
assert sacc_data is not None
all_tracers = extract_all_tracers_tomographic_bins(sacc_data)
@@ -267,7 +314,14 @@ def test_extract_all_tracers_xis_lens0_lens1(sacc_galaxy_xis_lens0_lens1):
assert_array_equal(tracer.dndz, dndz1)
-def test_extract_all_trace_cells_src0_lens0(sacc_galaxy_cells_src0_lens0):
+def test_extract_all_trace_cells_src0_lens0(
+ sacc_galaxy_cells_src0_lens0: tuple[
+ sacc.Sacc,
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ ],
+) -> None:
sacc_data, z, dndz0, dndz1 = sacc_galaxy_cells_src0_lens0
assert sacc_data is not None
all_tracers = extract_all_tracers_tomographic_bins(sacc_data)
@@ -285,7 +339,14 @@ def test_extract_all_trace_cells_src0_lens0(sacc_galaxy_cells_src0_lens0):
assert tracer.measurements == {Galaxies.COUNTS}
-def test_extract_all_trace_xis_src0_lens0(sacc_galaxy_xis_src0_lens0):
+def test_extract_all_trace_xis_src0_lens0(
+ sacc_galaxy_xis_src0_lens0: tuple[
+ sacc.Sacc,
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ ],
+) -> None:
sacc_data, z, dndz0, dndz1 = sacc_galaxy_xis_src0_lens0
assert sacc_data is not None
all_tracers = extract_all_tracers_tomographic_bins(sacc_data)
@@ -304,8 +365,8 @@ def test_extract_all_trace_xis_src0_lens0(sacc_galaxy_xis_src0_lens0):
def test_extract_all_tracers_invalid_data_type(
- sacc_galaxy_src0_src0_invalid_data_type,
-):
+ sacc_galaxy_src0_src0_invalid_data_type: tuple[sacc.Sacc, np.ndarray, np.ndarray],
+) -> None:
sacc_data, _, _ = sacc_galaxy_src0_src0_invalid_data_type
assert sacc_data is not None
with pytest.raises(
@@ -493,7 +554,16 @@ def test_extract_all_tracers_projected_fields_map_tracer_without_data() -> None:
_ = extract_all_tracers_projected_fields(sacc_data)
-def test_extract_all_metadata_index_harmonics(sacc_galaxy_cells):
+def test_extract_all_metadata_index_harmonics(
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
sacc_data, _, tracer_pairs = sacc_galaxy_cells
all_data = extract_all_harmonic_metadata_indices(sacc_data)
@@ -504,7 +574,16 @@ def test_extract_all_metadata_index_harmonics(sacc_galaxy_cells):
assert (tracer_names, two_point["data_type"]) in tracer_pairs
-def test_extract_all_metadata_index_harmonics_by_type(sacc_galaxy_cells):
+def test_extract_all_metadata_index_harmonics_by_type(
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
sacc_data, _, tracer_pairs = sacc_galaxy_cells
all_data = extract_all_harmonic_metadata_indices(
@@ -517,7 +596,16 @@ def test_extract_all_metadata_index_harmonics_by_type(sacc_galaxy_cells):
assert (tracer_names, "galaxy_shear_cl_ee") in tracer_pairs
-def test_extract_all_metadata_index_reals(sacc_galaxy_xis):
+def test_extract_all_metadata_index_reals(
+ sacc_galaxy_xis: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
sacc_data, _, tracer_pairs = sacc_galaxy_xis
all_data = extract_all_real_metadata_indices(sacc_data)
@@ -551,11 +639,9 @@ def test_extract_all_metadata_index_reals_by_type(
def test_extract_no_window(
- sacc_galaxy_cells_src0_src0: tuple[
- sacc.Sacc, npt.NDArray[np.float64], npt.NDArray[np.float64]
- ],
+ sacc_galaxy_cells_src0_src0: tuple[sacc.Sacc, TomographicBin],
) -> None:
- sacc_data, _, _ = sacc_galaxy_cells_src0_src0
+ sacc_data, _ = sacc_galaxy_cells_src0_src0
indices = np.array([0, 1, 2], dtype=np.int64)
with warnings.catch_warnings():
@@ -570,10 +656,10 @@ def test_extract_no_window(
def test_extract_all_data_types_three_tracers_reals(
sacc_galaxy_xis_three_tracers: tuple[
sacc.Sacc,
- dict[str, object],
- dict[str, object],
- dict[str, object],
- dict[str, object],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
],
) -> None:
sacc_data, _, _, _, _ = sacc_galaxy_xis_three_tracers
@@ -591,10 +677,10 @@ def test_extract_all_data_types_three_tracers_reals(
def test_extract_all_data_types_three_tracers_harmonics(
sacc_galaxy_cells_three_tracers: tuple[
sacc.Sacc,
- dict[str, object],
- dict[str, object],
- dict[str, object],
- dict[str, object],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
],
) -> None:
sacc_data, _, _, _, _ = sacc_galaxy_cells_three_tracers
@@ -758,14 +844,7 @@ def test_extract_all_harmonic_data(
@pytest.mark.slow
def test_extract_all_harmonic_with_window_data(
- sacc_galaxy_cwindows: tuple[
- sacc.Sacc,
- dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
- dict[
- tuple[TracerNames, str],
- tuple[npt.NDArray[np.int64], npt.NDArray[np.float64], sacc.BandpowerWindow],
- ],
- ],
+ sacc_galaxy_cwindows: SaccGalaxyWindowedFixture,
) -> None:
sacc_data, _, tracer_pairs = sacc_galaxy_cwindows
@@ -799,7 +878,7 @@ def test_extract_all_real_data(
tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]],
],
],
-):
+) -> None:
sacc_data, _, tracer_pairs = sacc_galaxy_xis
two_point_xis = extract_all_real_data(sacc_data)
@@ -828,7 +907,7 @@ def test_constructor_harmonic_metadata(
],
],
tp_factory: TwoPointFactory,
-):
+) -> None:
sacc_data, _, tracer_pairs = sacc_galaxy_cells
two_point_harmonics = extract_all_harmonic_metadata(sacc_data)
@@ -845,7 +924,17 @@ def test_constructor_harmonic_metadata(
@pytest.mark.slow
-def test_constructor_harmonic_data(sacc_galaxy_cells, tp_factory):
+def test_constructor_harmonic_data(
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+ tp_factory: TwoPointFactory,
+) -> None:
sacc_data, _, tracer_pairs = sacc_galaxy_cells
two_point_harmonics = extract_all_harmonic_data(sacc_data)
@@ -865,7 +954,10 @@ def test_constructor_harmonic_data(sacc_galaxy_cells, tp_factory):
)
-def test_constructor_harmonic_with_window_metadata(sacc_galaxy_cwindows, tp_factory):
+def test_constructor_harmonic_with_window_metadata(
+ sacc_galaxy_cwindows: SaccGalaxyWindowedFixture,
+ tp_factory: TwoPointFactory,
+) -> None:
sacc_data, _, tracer_pairs = sacc_galaxy_cwindows
two_point_harmonics = extract_all_harmonic_metadata(sacc_data)
@@ -876,9 +968,8 @@ def test_constructor_harmonic_with_window_metadata(sacc_galaxy_cwindows, tp_fact
for two_point in two_points_new:
tracer_pairs_key = (two_point.sacc_tracers, two_point.sacc_data_type)
- _, _, window = tracer_pairs[tracer_pairs_key]
-
assert tracer_pairs_key in tracer_pairs
+ _, _, window = tracer_pairs[tracer_pairs_key]
assert two_point.ells is not None
assert two_point.window is not None
assert_array_equal(
@@ -888,7 +979,9 @@ def test_constructor_harmonic_with_window_metadata(sacc_galaxy_cwindows, tp_fact
assert_array_equal(two_point.ells, window.values)
-def test_extract_all_harmonic_metadata_normalize_true(sacc_galaxy_cwindows):
+def test_extract_all_harmonic_metadata_normalize_true(
+ sacc_galaxy_cwindows: SaccGalaxyWindowedFixture,
+) -> None:
"""Test that normalize=True normalizes windows in extract_all_harmonic_metadata."""
sacc_data, _, _ = sacc_galaxy_cwindows
@@ -903,7 +996,9 @@ def test_extract_all_harmonic_metadata_normalize_true(sacc_galaxy_cwindows):
assert_allclose(window_sum, np.ones_like(window_sum))
-def test_extract_all_harmonic_metadata_normalize_false(sacc_galaxy_cwindows):
+def test_extract_all_harmonic_metadata_normalize_false(
+ sacc_galaxy_cwindows: SaccGalaxyWindowedFixture,
+) -> None:
"""Test that normalize=False keeps windows unnormalized."""
sacc_data, _, _ = sacc_galaxy_cwindows
@@ -922,7 +1017,9 @@ def test_extract_all_harmonic_metadata_normalize_false(sacc_galaxy_cwindows):
assert not np.allclose(window_sum, np.ones_like(window_sum))
-def test_extract_all_harmonic_metadata_default_normalizes(sacc_galaxy_cwindows):
+def test_extract_all_harmonic_metadata_default_normalizes(
+ sacc_galaxy_cwindows: SaccGalaxyWindowedFixture,
+) -> None:
"""Test that the default behavior (no normalize parameter) normalizes windows."""
sacc_data, _, _ = sacc_galaxy_cwindows
@@ -937,7 +1034,7 @@ def test_extract_all_harmonic_metadata_default_normalizes(sacc_galaxy_cwindows):
assert_allclose(window_sum, np.ones_like(window_sum))
-def test_extract_window_function_raises_on_zero_weight():
+def test_extract_window_function_raises_on_zero_weight() -> None:
"""Test that extract_window_function raises ValueError for zero-weight columns."""
sacc_data = sacc.Sacc()
@@ -983,7 +1080,7 @@ def test_extract_window_function_raises_on_zero_weight():
extract_window_function(sacc_data, indices, normalize=True)
-def test_extract_window_function_raises_on_multiple_zero_weights():
+def test_extract_window_function_raises_on_multiple_zero_weights() -> None:
"""Test that extract_window_function reports multiple zero-weight columns."""
sacc_data = sacc.Sacc()
@@ -1029,7 +1126,7 @@ def test_extract_window_function_raises_on_multiple_zero_weights():
extract_window_function(sacc_data, indices, normalize=False)
-def test_extract_all_harmonic_metadata_raises_on_zero_weight():
+def test_extract_all_harmonic_metadata_raises_on_zero_weight() -> None:
"""Test that extract_all_harmonic_metadata raises ValueError for zero weights."""
sacc_data = sacc.Sacc()
@@ -1069,7 +1166,10 @@ def test_extract_all_harmonic_metadata_raises_on_zero_weight():
@pytest.mark.slow
-def test_constructor_harmonic_with_window_data(sacc_galaxy_cwindows, tp_factory):
+def test_constructor_harmonic_with_window_data(
+ sacc_galaxy_cwindows: SaccGalaxyWindowedFixture,
+ tp_factory: TwoPointFactory,
+) -> None:
sacc_data, _, tracer_pairs = sacc_galaxy_cwindows
two_point_harmonics = extract_all_harmonic_data(sacc_data)
@@ -1081,9 +1181,8 @@ def test_constructor_harmonic_with_window_data(sacc_galaxy_cwindows, tp_factory)
for two_point in two_points_new:
tracer_pairs_key = (two_point.sacc_tracers, two_point.sacc_data_type)
- _, Cell, window = tracer_pairs[tracer_pairs_key]
-
assert tracer_pairs_key in tracer_pairs
+ _, Cell, window = tracer_pairs[tracer_pairs_key]
assert two_point.ells is not None
assert_array_equal(two_point.get_data_vector(), Cell)
assert two_point.window is not None
@@ -1094,7 +1193,17 @@ def test_constructor_harmonic_with_window_data(sacc_galaxy_cwindows, tp_factory)
assert_array_equal(two_point.ells, window.values)
-def test_constructor_reals_metadata(sacc_galaxy_xis, tp_factory):
+def test_constructor_reals_metadata(
+ sacc_galaxy_xis: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]],
+ ],
+ ],
+ tp_factory: TwoPointFactory,
+) -> None:
sacc_data, _, tracer_pairs = sacc_galaxy_xis
two_point_reals = extract_all_real_metadata(sacc_data)
@@ -1111,7 +1220,17 @@ def test_constructor_reals_metadata(sacc_galaxy_xis, tp_factory):
@pytest.mark.slow
-def test_constructor_reals_data(sacc_galaxy_xis, tp_factory):
+def test_constructor_reals_data(
+ sacc_galaxy_xis: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]],
+ ],
+ ],
+ tp_factory: TwoPointFactory,
+) -> None:
sacc_data, _, tracer_pairs = sacc_galaxy_xis
two_point_reals = extract_all_real_data(sacc_data)
@@ -1132,8 +1251,17 @@ def test_constructor_reals_data(sacc_galaxy_xis, tp_factory):
def test_compare_constructors_harmonic(
- sacc_galaxy_cells, tp_factory, tools_with_vanilla_cosmology
-):
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+ tp_factory: TwoPointFactory,
+ tools_with_vanilla_cosmology: ModelingTools,
+) -> None:
sacc_data, _, _ = sacc_galaxy_cells
two_point_harmonics = extract_all_harmonic_data(sacc_data)
@@ -1178,8 +1306,10 @@ def test_compare_constructors_harmonic(
def test_compare_constructors_harmonic_with_window(
- sacc_galaxy_cwindows, tp_factory, tools_with_vanilla_cosmology
-):
+ sacc_galaxy_cwindows: SaccGalaxyWindowedFixture,
+ tp_factory: TwoPointFactory,
+ tools_with_vanilla_cosmology: ModelingTools,
+) -> None:
sacc_data, _, _ = sacc_galaxy_cwindows
two_point_harmonics = extract_all_harmonic_data(sacc_data)
@@ -1230,8 +1360,17 @@ def test_compare_constructors_harmonic_with_window(
def test_compare_constructors_reals(
- sacc_galaxy_xis, tp_factory, tools_with_vanilla_cosmology
-):
+ sacc_galaxy_xis: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]],
+ ],
+ ],
+ tp_factory: TwoPointFactory,
+ tools_with_vanilla_cosmology: ModelingTools,
+) -> None:
sacc_data, _, _ = sacc_galaxy_xis
two_point_xis = extract_all_real_data(sacc_data)
@@ -1275,7 +1414,16 @@ def test_compare_constructors_reals(
)
-def test_extract_all_data_harmonic_no_cov(sacc_galaxy_cells):
+def test_extract_all_data_harmonic_no_cov(
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
sacc_data, _, _ = sacc_galaxy_cells
sacc_data.covariance = None
with pytest.raises(
@@ -1285,7 +1433,16 @@ def test_extract_all_data_harmonic_no_cov(sacc_galaxy_cells):
_ = extract_all_harmonic_data(sacc_data)
-def test_extract_all_data_real_no_cov(sacc_galaxy_xis):
+def test_extract_all_data_real_no_cov(
+ sacc_galaxy_xis: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
sacc_data, _, _ = sacc_galaxy_xis
sacc_data.covariance = None
with pytest.raises(
@@ -1295,7 +1452,7 @@ def test_extract_all_data_real_no_cov(sacc_galaxy_xis):
_ = extract_all_real_data(sacc_data)
-def test_make_all_photoz_bin_combinations_with_cmb_basic():
+def test_make_all_photoz_bin_combinations_with_cmb_basic() -> None:
"""Test basic functionality of make_all_photoz_bin_combinations_with_cmb."""
# Create test galaxy bins
galaxy_bins = [
@@ -1338,7 +1495,7 @@ def test_make_all_photoz_bin_combinations_with_cmb_basic():
assert len(galaxy_combinations_in_result) == len(galaxy_only_combinations)
-def test_make_all_photoz_bin_combinations_with_cmb_with_auto():
+def test_make_all_photoz_bin_combinations_with_cmb_with_auto() -> None:
"""Test make_all_photoz_bin_combinations_with_cmb with CMB auto-correlation."""
galaxy_bins = [
TomographicBin(
@@ -1372,7 +1529,7 @@ def test_make_all_photoz_bin_combinations_with_cmb_with_auto():
assert cmb_auto.y.bin_name == "cmb_convergence"
-def test_make_all_photoz_bin_combinations_with_cmb_custom_tracer_name():
+def test_make_all_photoz_bin_combinations_with_cmb_custom_tracer_name() -> None:
"""Test make_all_photoz_bin_combinations_with_cmb with custom CMB tracer name."""
galaxy_bins = [
TomographicBin(
@@ -1406,7 +1563,7 @@ def test_make_all_photoz_bin_combinations_with_cmb_custom_tracer_name():
assert combo.y.bin_name == custom_name
-def test_make_all_photoz_bin_combinations_with_cmb_measurement_compatibility():
+def test_make_all_photoz_bin_combinations_with_cmb_measurement_compatibility() -> None:
"""Test that only compatible measurements create CMB-galaxy cross-correlations."""
galaxy_bins = [
TomographicBin(
@@ -1457,7 +1614,7 @@ def test_make_all_photoz_bin_combinations_with_cmb_measurement_compatibility():
assert expected in actual_combinations
-def test_make_all_photoz_bin_combinations_with_cmb_empty_input():
+def test_make_all_photoz_bin_combinations_with_cmb_empty_input() -> None:
"""Test make_all_photoz_bin_combinations_with_cmb with empty galaxy bins."""
combinations = make_all_photoz_bin_combinations_with_cmb([])
@@ -1465,7 +1622,7 @@ def test_make_all_photoz_bin_combinations_with_cmb_empty_input():
assert len(combinations) == 0
-def test_make_all_photoz_bin_combinations_with_cmb_cmb_bin_properties():
+def test_make_all_photoz_bin_combinations_with_cmb_cmb_bin_properties() -> None:
"""Test that the created CMB bin has correct properties."""
galaxy_bins = [
TomographicBin(
@@ -1491,7 +1648,9 @@ def test_make_all_photoz_bin_combinations_with_cmb_cmb_bin_properties():
@pytest.mark.parametrize("include_auto", [True, False])
-def test_make_all_photoz_bin_combinations_with_cmb_parametrized(include_auto: bool):
+def test_make_all_photoz_bin_combinations_with_cmb_parametrized(
+ include_auto: bool,
+) -> None:
"""Parametrized test for CMB auto-correlation inclusion."""
galaxy_bins = [
TomographicBin(
@@ -1522,7 +1681,7 @@ def test_make_all_photoz_bin_combinations_with_cmb_parametrized(include_auto: bo
assert cmb_auto_count == 0
-def test_make_all_photoz_bin_combinations_with_cmb_multiple_measurements():
+def test_make_all_photoz_bin_combinations_with_cmb_multiple_measurements() -> None:
"""Test with galaxy bins that have multiple measurement types."""
galaxy_bins = [
TomographicBin(
@@ -1566,7 +1725,7 @@ def test_make_all_photoz_bin_combinations_with_cmb_multiple_measurements():
assert Galaxies.SHEAR_E in galaxy_measurements
-def test_make_cmb_galaxy_combinations_only_basic():
+def test_make_cmb_galaxy_combinations_only_basic() -> None:
"""Test basic functionality of make_cmb_galaxy_combinations_only."""
# Create test galaxy bins
galaxy_bins = [
@@ -1621,7 +1780,7 @@ def test_make_cmb_galaxy_combinations_only_basic():
assert len(cmb_auto_combinations) == 0
-def test_make_cmb_galaxy_combinations_only_custom_tracer_name():
+def test_make_cmb_galaxy_combinations_only_custom_tracer_name() -> None:
"""Test make_cmb_galaxy_combinations_only with custom CMB tracer name."""
galaxy_bins = [
TomographicBin(
@@ -1655,7 +1814,7 @@ def test_make_cmb_galaxy_combinations_only_custom_tracer_name():
assert combo.y.bin_name == custom_name
-def test_make_cmb_galaxy_combinations_only_measurement_compatibility():
+def test_make_cmb_galaxy_combinations_only_measurement_compatibility() -> None:
"""Test that only compatible measurements create CMB-galaxy cross-correlations."""
galaxy_bins = [
TomographicBin(
@@ -1692,7 +1851,7 @@ def test_make_cmb_galaxy_combinations_only_measurement_compatibility():
assert expected in actual_combinations
-def test_make_cmb_galaxy_combinations_only_empty_input():
+def test_make_cmb_galaxy_combinations_only_empty_input() -> None:
"""Test make_cmb_galaxy_combinations_only with empty galaxy bins."""
combinations = make_cmb_galaxy_combinations_only([])
@@ -1700,7 +1859,7 @@ def test_make_cmb_galaxy_combinations_only_empty_input():
assert len(combinations) == 0
-def test_make_cmb_galaxy_combinations_only_incompatible_measurements_0():
+def test_make_cmb_galaxy_combinations_only_incompatible_measurements_0() -> None:
"""Test behavior with galaxy measurements incompatible with CMB convergence."""
# Create a galaxy bin with a measurement that might not be compatible
# (This test depends on what measurements are actually incompatible)
@@ -1726,7 +1885,7 @@ def test_make_cmb_galaxy_combinations_only_incompatible_measurements_0():
)
-def test_make_cmb_galaxy_combinations_only_cmb_bin_properties():
+def test_make_cmb_galaxy_combinations_only_cmb_bin_properties() -> None:
"""Test that the created CMB bin has correct properties."""
galaxy_bins = [
TomographicBin(
@@ -1751,7 +1910,7 @@ def test_make_cmb_galaxy_combinations_only_cmb_bin_properties():
assert cmb_bin.type_source == TypeSource.DEFAULT
-def test_make_cmb_galaxy_combinations_only_multiple_measurements():
+def test_make_cmb_galaxy_combinations_only_multiple_measurements() -> None:
"""Test with galaxy bins that have multiple measurement types."""
galaxy_bins = [
TomographicBin(
@@ -1782,7 +1941,7 @@ def test_make_cmb_galaxy_combinations_only_multiple_measurements():
assert Galaxies.SHEAR_E in galaxy_measurements
-def test_make_cmb_galaxy_combinations_only_symmetric_pairs():
+def test_make_cmb_galaxy_combinations_only_symmetric_pairs() -> None:
"""Test that symmetric pairs are created for each compatible measurement."""
galaxy_bins = [
TomographicBin(
@@ -1814,7 +1973,7 @@ def test_make_cmb_galaxy_combinations_only_symmetric_pairs():
assert not galaxy_first
-def test_make_cmb_galaxy_combinations_only_single_galaxy_bin():
+def test_make_cmb_galaxy_combinations_only_single_galaxy_bin() -> None:
"""Test with a single galaxy bin."""
galaxy_bins = [
TomographicBin(
@@ -1838,7 +1997,7 @@ def test_make_cmb_galaxy_combinations_only_single_galaxy_bin():
@pytest.mark.parametrize("cmb_name", ["cmb_convergence", "cmb_kappa", "planck_cmb"])
-def test_make_cmb_galaxy_combinations_only_parametrized_names(cmb_name: str):
+def test_make_cmb_galaxy_combinations_only_parametrized_names(cmb_name: str) -> None:
"""Parametrized test for different CMB tracer names."""
galaxy_bins = [
TomographicBin(
@@ -1861,7 +2020,7 @@ def test_make_cmb_galaxy_combinations_only_parametrized_names(cmb_name: str):
assert combo.y.bin_name == cmb_name
-def test_make_cmb_galaxy_combinations_only_vs_with_cmb():
+def test_make_cmb_galaxy_combinations_only_vs_with_cmb() -> None:
"""Test that this function is equivalent to
make_all_photoz_bin_combinations_with_cmb
without galaxy combinations."""
@@ -1914,7 +2073,7 @@ def test_make_cmb_galaxy_combinations_only_vs_with_cmb():
assert cmb_only_tuples == cmb_from_all_tuples
-def test_make_all_photoz_bin_combinations_with_cmb_incompatible_measurements():
+def test_make_all_photoz_bin_combinations_with_cmb_incompatible_measurements() -> None:
"""Test that incompatible measurements are skipped in CMB-galaxy combinations."""
galaxy_bins = [
TomographicBin(
@@ -1967,7 +2126,7 @@ def test_make_all_photoz_bin_combinations_with_cmb_incompatible_measurements():
assert Galaxies.SHEAR_T in galaxy_measurements
-def test_make_cmb_galaxy_combinations_only_incompatible_measurements():
+def test_make_cmb_galaxy_combinations_only_incompatible_measurements() -> None:
"""Test that incompatible measurements are skipped in CMB-galaxy combinations."""
galaxy_bins = [
TomographicBin(
@@ -2006,7 +2165,7 @@ def test_make_cmb_galaxy_combinations_only_incompatible_measurements():
assert Galaxies.SHEAR_T in galaxy_measurements
-def test_make_all_photoz_bin_combinations_with_cmb_all_incompatible():
+def test_make_all_photoz_bin_combinations_with_cmb_all_incompatible() -> None:
"""Test behavior when all galaxy measurements are incompatible with CMB."""
# Since we can't find truly incompatible measurements, let's test with
# measurements that we know ARE compatible and adjust expectations
@@ -2046,7 +2205,7 @@ def test_make_all_photoz_bin_combinations_with_cmb_all_incompatible():
assert len(combinations) == len(galaxy_only_combinations) + len(cmb_combinations)
-def test_make_cmb_galaxy_combinations_only_all_incompatible():
+def test_make_cmb_galaxy_combinations_only_all_incompatible() -> None:
"""Test behavior when all galaxy measurements are incompatible with CMB."""
# Since we can't find truly incompatible measurements, let's test with
# measurements that we know ARE compatible and adjust expectations
@@ -2065,7 +2224,7 @@ def test_make_cmb_galaxy_combinations_only_all_incompatible():
assert len(combinations) == 1
-def test_make_all_photoz_bin_combinations_with_cmb_empty():
+def test_make_all_photoz_bin_combinations_with_cmb_empty() -> None:
"""Test behavior when given an empty list of galaxy bins."""
galaxy_bins = [
TomographicBin(
@@ -2081,7 +2240,16 @@ def test_make_all_photoz_bin_combinations_with_cmb_empty():
assert len(combinations) == 0
-def test_extract_all_photoz_bin_combinations_with_selector(sacc_galaxy_cells):
+def test_extract_all_photoz_bin_combinations_with_selector(
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
"""Test extract_all_photoz_bin_combinations with bin_pair_selector."""
sacc_data, _, _ = sacc_galaxy_cells
@@ -2103,7 +2271,16 @@ def test_extract_all_photoz_bin_combinations_with_selector(sacc_galaxy_cells):
assert len(auto_combinations) > 0
-def test_extract_all_photoz_bin_combinations_with_source_selector(sacc_galaxy_cells):
+def test_extract_all_photoz_bin_combinations_with_source_selector(
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
"""Test extract_all_photoz_bin_combinations with source bin selector."""
sacc_data, _, _ = sacc_galaxy_cells
@@ -2122,7 +2299,16 @@ def test_extract_all_photoz_bin_combinations_with_source_selector(sacc_galaxy_ce
assert len(source_combinations) > 0
-def test_extract_all_photoz_bin_combinations_with_lens_selector(sacc_galaxy_cells):
+def test_extract_all_photoz_bin_combinations_with_lens_selector(
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
"""Test extract_all_photoz_bin_combinations with lens bin selector."""
sacc_data, _, _ = sacc_galaxy_cells
@@ -2140,7 +2326,16 @@ def test_extract_all_photoz_bin_combinations_with_lens_selector(sacc_galaxy_cell
assert len(lens_combinations) > 0
-def test_extract_all_harmonic_metadata_with_selector(sacc_galaxy_cells):
+def test_extract_all_harmonic_metadata_with_selector(
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
"""Test extract_all_harmonic_metadata with bin_pair_selector."""
sacc_data, _, _ = sacc_galaxy_cells
@@ -2167,7 +2362,16 @@ def test_extract_all_harmonic_metadata_with_selector(sacc_galaxy_cells):
assert isinstance(meta.ells, np.ndarray)
-def test_extract_all_harmonic_metadata_with_source_selector(sacc_galaxy_cells):
+def test_extract_all_harmonic_metadata_with_source_selector(
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
"""Test extract_all_harmonic_metadata with source bin selector."""
sacc_data, _, _ = sacc_galaxy_cells
@@ -2184,7 +2388,16 @@ def test_extract_all_harmonic_metadata_with_source_selector(sacc_galaxy_cells):
assert len(source_metadata) > 0
-def test_extract_all_harmonic_metadata_with_combined_selector(sacc_galaxy_cells):
+def test_extract_all_harmonic_metadata_with_combined_selector(
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
"""Test extract_all_harmonic_metadata with combined selectors."""
sacc_data, _, _ = sacc_galaxy_cells
@@ -2202,7 +2415,16 @@ def test_extract_all_harmonic_metadata_with_combined_selector(sacc_galaxy_cells)
assert len(filtered_metadata) > 0
-def test_extract_all_real_metadata_with_selector(sacc_galaxy_xis):
+def test_extract_all_real_metadata_with_selector(
+ sacc_galaxy_xis: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
"""Test extract_all_real_metadata with bin_pair_selector."""
sacc_data, _, _ = sacc_galaxy_xis
@@ -2229,7 +2451,16 @@ def test_extract_all_real_metadata_with_selector(sacc_galaxy_xis):
assert isinstance(meta.thetas, np.ndarray)
-def test_extract_all_real_metadata_with_lens_selector(sacc_galaxy_xis):
+def test_extract_all_real_metadata_with_lens_selector(
+ sacc_galaxy_xis: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
"""Test extract_all_real_metadata with lens bin selector."""
sacc_data, _, _ = sacc_galaxy_xis
@@ -2247,7 +2478,16 @@ def test_extract_all_real_metadata_with_lens_selector(sacc_galaxy_xis):
assert len(lens_metadata) > 0
-def test_extract_all_real_metadata_with_combined_selector(sacc_galaxy_xis):
+def test_extract_all_real_metadata_with_combined_selector(
+ sacc_galaxy_xis: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
"""Test extract_all_real_metadata with combined selectors."""
sacc_data, _, _ = sacc_galaxy_xis
@@ -2266,7 +2506,16 @@ def test_extract_all_real_metadata_with_combined_selector(sacc_galaxy_xis):
assert len(filtered_metadata) > 0
-def test_extract_all_harmonic_metadata_with_not_selector(sacc_galaxy_cells):
+def test_extract_all_harmonic_metadata_with_not_selector(
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
"""Test extract_all_harmonic_metadata with NOT selector."""
sacc_data, _, _ = sacc_galaxy_cells
@@ -2293,7 +2542,16 @@ def test_extract_all_harmonic_metadata_with_not_selector(sacc_galaxy_cells):
assert len(auto_metadata) + len(cross_metadata) == len(all_metadata)
-def test_extract_all_real_metadata_with_or_selector(sacc_galaxy_xis):
+def test_extract_all_real_metadata_with_or_selector(
+ sacc_galaxy_xis: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
"""Test extract_all_real_metadata with OR selector."""
sacc_data, _, _ = sacc_galaxy_xis
@@ -2325,7 +2583,16 @@ def test_extract_all_real_metadata_with_or_selector(sacc_galaxy_xis):
assert len(filtered_metadata) > 0
-def test_extract_with_selector_empty_result(sacc_galaxy_cells):
+def test_extract_with_selector_empty_result(
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
"""Test that selector can result in empty extraction."""
sacc_data, _, _ = sacc_galaxy_cells
@@ -2344,7 +2611,16 @@ def test_extract_with_selector_empty_result(sacc_galaxy_cells):
assert len(empty_harmonic) == 0
-def test_extract_with_selector_preserves_data_quality(sacc_galaxy_cells):
+def test_extract_with_selector_preserves_data_quality(
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
"""Test that using selector doesn't affect data quality of extracted metadata."""
sacc_data, _, _ = sacc_galaxy_cells
diff --git a/tests/metadata/test_metadata_two_point_types.py b/tests/metadata/test_metadata_two_point_types.py
index 3637e675e..53c4b3e40 100644
--- a/tests/metadata/test_metadata_two_point_types.py
+++ b/tests/metadata/test_metadata_two_point_types.py
@@ -34,6 +34,7 @@
Clusters,
Galaxies,
Measurement,
+ TomographicBin,
TracerNames,
TwoPointHarmonic,
TwoPointReal,
@@ -61,9 +62,10 @@
from firecrown.metadata_types._sacc_type_string import (
_type_to_sacc_string_real as real,
)
+from tests._types import SaccGalaxyWindowedFixture
-def test_order_enums():
+def test_order_enums() -> None:
assert compare_enums(CMB.CONVERGENCE, Clusters.COUNTS) < 0
assert compare_enums(Clusters.COUNTS, CMB.CONVERGENCE) > 0
@@ -80,7 +82,7 @@ def test_order_enums():
assert compare_enums(enumerand, enumerand) == 0
-def test_galaxies_is_shear():
+def test_galaxies_is_shear() -> None:
assert Galaxies.PART_OF_XI_MINUS == Galaxies.SHEAR_MINUS
assert Galaxies.PART_OF_XI_PLUS == Galaxies.SHEAR_PLUS
assert Galaxies.SHEAR_E.is_shear()
@@ -90,7 +92,7 @@ def test_galaxies_is_shear():
assert not Galaxies.COUNTS.is_shear()
-def testcompare_enums_wrong_type():
+def testcompare_enums_wrong_type() -> None:
with pytest.raises(
ValueError,
match=re.escape(
@@ -101,22 +103,22 @@ def testcompare_enums_wrong_type():
compare_enums(Galaxies.COUNTS, 1)
-def test_enumeration_equality_galaxy():
+def test_enumeration_equality_galaxy() -> None:
for e1, e2 in product(Galaxies, chain(CMB, Clusters)):
assert e1 != e2
-def test_enumeration_equality_cmb():
+def test_enumeration_equality_cmb() -> None:
for e1, e2 in product(CMB, chain(Galaxies, Clusters)):
assert e1 != e2
-def test_enumeration_equality_cluster():
+def test_enumeration_equality_cluster() -> None:
for e1, e2 in product(Clusters, chain(CMB, Galaxies)):
assert e1 != e2
-def test_exact_matches():
+def test_exact_matches() -> None:
for sacc_name, space, (enum_1, enum_2) in snm.mappings:
if space == "ell":
assert harmonic(enum_1, enum_2) == sacc_name
@@ -126,7 +128,7 @@ def test_exact_matches():
raise ValueError(f"Illegal 'space' value {space} in testing data")
-def test_translation_order_dependence():
+def test_translation_order_dependence() -> None:
for a, b in product(ALL_MEASUREMENTS, ALL_MEASUREMENTS):
assert isinstance(a, (Galaxies, CMB, Clusters))
assert isinstance(b, (Galaxies, CMB, Clusters))
@@ -143,7 +145,7 @@ def test_translation_order_dependence():
assert harmonic(a, b) != real(a, b)
-def test_unsupported_type_galaxy():
+def test_unsupported_type_galaxy() -> None:
unknown_type = MagicMock()
unknown_type.configure_mock(__eq__=MagicMock(return_value=False))
@@ -154,7 +156,7 @@ def test_unsupported_type_galaxy():
Galaxies.polarization(unknown_type)
-def test_unsupported_type_cmb():
+def test_unsupported_type_cmb() -> None:
unknown_type = MagicMock()
unknown_type.configure_mock(__eq__=MagicMock(return_value=False))
@@ -165,7 +167,7 @@ def test_unsupported_type_cmb():
CMB.polarization(unknown_type)
-def test_unsupported_type_cluster():
+def test_unsupported_type_cluster() -> None:
unknown_type = MagicMock()
unknown_type.configure_mock(__eq__=MagicMock(return_value=False))
@@ -176,7 +178,7 @@ def test_unsupported_type_cluster():
Clusters.polarization(unknown_type)
-def test_type_hashs():
+def test_type_hashs() -> None:
for e1, e2 in product(ALL_MEASUREMENTS, ALL_MEASUREMENTS):
if e1 == e2:
assert hash(e1) == hash(e2)
@@ -184,7 +186,7 @@ def test_type_hashs():
assert hash(e1) != hash(e2)
-def test_measurement_is_compatible():
+def test_measurement_is_compatible() -> None:
for a, b in product(ALL_MEASUREMENTS, ALL_MEASUREMENTS):
assert isinstance(a, (Galaxies, CMB, Clusters))
assert isinstance(b, (Galaxies, CMB, Clusters))
@@ -195,8 +197,15 @@ def test_measurement_is_compatible():
def test_extract_all_tracers_types_cells(
- sacc_galaxy_cells: tuple[sacc.Sacc, dict[str, object], dict[str, object]],
-):
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
sacc_data, _, _ = sacc_galaxy_cells
tracers, _ = extract_all_measured_types(sacc_data)
@@ -211,8 +220,8 @@ def test_extract_all_tracers_types_cells(
def test_extract_all_tracers_types_cwindows(
- sacc_galaxy_cwindows: tuple[sacc.Sacc, dict[str, object], dict[str, object]],
-):
+ sacc_galaxy_cwindows: SaccGalaxyWindowedFixture,
+) -> None:
sacc_data, _, _ = sacc_galaxy_cwindows
tracers, _ = extract_all_measured_types(sacc_data)
@@ -235,7 +244,7 @@ def test_extract_all_tracers_types_reals(
tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]],
],
],
-):
+) -> None:
sacc_data, _, _ = sacc_galaxy_xis
tracers, _ = extract_all_measured_types(sacc_data)
@@ -261,7 +270,7 @@ def test_extract_all_tracers_types_reals_inverted(
tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]],
],
],
-):
+) -> None:
sacc_data, _, _ = sacc_galaxy_xis_inverted
with pytest.warns(DeprecationWarning, match="AUTO-CORRECTION PERFORMED"):
@@ -287,7 +296,7 @@ def test_extract_all_tracers_types_cells_include_maybe(
tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
],
],
-):
+) -> None:
sacc_data, _, _ = sacc_galaxy_cells
assert extract_all_measured_types(sacc_data) == extract_all_measured_types(
@@ -296,15 +305,8 @@ def test_extract_all_tracers_types_cells_include_maybe(
def test_extract_all_tracers_types_cwindows_include_maybe(
- sacc_galaxy_cwindows: tuple[
- sacc.Sacc,
- dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
- dict[
- tuple[TracerNames, str],
- tuple[npt.NDArray[np.int64], npt.NDArray[np.float64], sacc.BandpowerWindow],
- ],
- ],
-):
+ sacc_galaxy_cwindows: SaccGalaxyWindowedFixture,
+) -> None:
sacc_data, _, _ = sacc_galaxy_cwindows
assert extract_all_measured_types(sacc_data) == extract_all_measured_types(
@@ -321,7 +323,7 @@ def test_extract_all_tracers_types_xi_thetas_include_maybe(
tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]],
],
],
-):
+) -> None:
sacc_data, _, _ = sacc_galaxy_xis
assert extract_all_measured_types(sacc_data) == extract_all_measured_types(
@@ -329,7 +331,7 @@ def test_extract_all_tracers_types_xi_thetas_include_maybe(
)
-def test_measurements_from_index1():
+def test_measurements_from_index1() -> None:
index: TwoPointRealIndex = {
"data_type": "galaxy_shearDensity_xi_t",
"tracer_names": TracerNames("src0", "lens0"),
@@ -342,7 +344,7 @@ def test_measurements_from_index1():
assert b == Galaxies.COUNTS
-def test_measurements_from_index2():
+def test_measurements_from_index2() -> None:
index: TwoPointRealIndex = {
"data_type": "galaxy_shearDensity_xi_t",
"tracer_names": TracerNames("lens0", "src0"),
@@ -355,7 +357,7 @@ def test_measurements_from_index2():
assert b == Galaxies.COUNTS
-def test_check_two_point_consistence_harmonic(two_point_cell: TwoPointHarmonic):
+def test_check_two_point_consistence_harmonic(two_point_cell: TwoPointHarmonic) -> None:
tpm = TwoPointMeasurement(
data=np.zeros(100),
indices=np.arange(100),
@@ -367,7 +369,7 @@ def test_check_two_point_consistence_harmonic(two_point_cell: TwoPointHarmonic):
def test_check_two_point_consistence_harmonic_real(
optimized_two_point_real: TwoPointReal,
-):
+) -> None:
tpm = TwoPointMeasurement(
data=np.zeros(100),
indices=np.arange(100),
@@ -381,7 +383,9 @@ def test_check_two_point_consistence_harmonic_real(
check_two_point_consistence_harmonic([tpm])
-def test_check_two_point_consistence_real(optimized_two_point_real: TwoPointReal):
+def test_check_two_point_consistence_real(
+ optimized_two_point_real: TwoPointReal,
+) -> None:
tpm = TwoPointMeasurement(
data=np.zeros(100),
indices=np.arange(100),
@@ -393,7 +397,7 @@ def test_check_two_point_consistence_real(optimized_two_point_real: TwoPointReal
def test_check_two_point_consistence_real_harmonic(
optimized_two_point_cell: TwoPointReal,
-):
+) -> None:
tpm = TwoPointMeasurement(
data=np.zeros(100),
indices=np.arange(100),
@@ -408,8 +412,15 @@ def test_check_two_point_consistence_real_harmonic(
def test_check_two_point_consistence_harmonic_mixing_cov(
- sacc_galaxy_cells: tuple[sacc.Sacc, dict[str, object], dict[str, object]],
-):
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
sacc_data, _, _ = sacc_galaxy_cells
tpms = extract_all_harmonic_data(sacc_data)
@@ -427,8 +438,15 @@ def test_check_two_point_consistence_harmonic_mixing_cov(
def test_check_two_point_consistence_real_mixing_cov(
- sacc_galaxy_xis: tuple[sacc.Sacc, dict[str, object], dict[str, object]],
-):
+ sacc_galaxy_xis: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
sacc_data, _, _ = sacc_galaxy_xis
tpms = extract_all_real_data(sacc_data)
@@ -445,8 +463,15 @@ def test_check_two_point_consistence_real_mixing_cov(
def test_check_two_point_consistence_harmonic_non_unique_indices(
- sacc_galaxy_cells: tuple[sacc.Sacc, dict[str, object], dict[str, object]],
-):
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
sacc_data, _, _ = sacc_galaxy_cells
tpms = extract_all_harmonic_data(sacc_data)
@@ -463,8 +488,15 @@ def test_check_two_point_consistence_harmonic_non_unique_indices(
def test_check_two_point_consistence_real_non_unique_indices(
- sacc_galaxy_xis: tuple[sacc.Sacc, dict[str, object], dict[str, object]],
-):
+ sacc_galaxy_xis: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
sacc_data, _, _ = sacc_galaxy_xis
tpms = extract_all_real_data(sacc_data)
@@ -480,8 +512,15 @@ def test_check_two_point_consistence_real_non_unique_indices(
def test_check_two_point_consistence_harmonic_indices_overlap(
- sacc_galaxy_cells: tuple[sacc.Sacc, dict[str, object], dict[str, object]],
-):
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
sacc_data, _, _ = sacc_galaxy_cells
tpms = extract_all_harmonic_data(sacc_data)
@@ -498,8 +537,15 @@ def test_check_two_point_consistence_harmonic_indices_overlap(
def test_check_two_point_consistence_real_indices_overlap(
- sacc_galaxy_xis: tuple[sacc.Sacc, dict[str, object], dict[str, object]],
-):
+ sacc_galaxy_xis: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
sacc_data, _, _ = sacc_galaxy_xis
tpms = extract_all_real_data(sacc_data)
@@ -517,7 +563,7 @@ def test_check_two_point_consistence_real_indices_overlap(
def test_extract_all_data_cells_order_convention(
sacc_galaxy_cells_order_convention: sacc.Sacc,
-):
+) -> None:
two_point_list = extract_all_harmonic_data(sacc_galaxy_cells_order_convention)
assert len(two_point_list) == 1
@@ -525,7 +571,7 @@ def test_extract_all_data_cells_order_convention(
assert two_point_list[0].metadata.XY.y.bin_name == "bin1"
-def test_measurements_types_single_galaxy_lens():
+def test_measurements_types_single_galaxy_lens() -> None:
"""Test measurements_types with single Galaxy lens measurement type."""
measurements: set[Measurement] = {Galaxies.COUNTS}
has_mixed, types = measurements_types(measurements)
@@ -534,7 +580,7 @@ def test_measurements_types_single_galaxy_lens():
assert types == ["Galaxy lens"]
-def test_measurements_types_single_galaxy_source():
+def test_measurements_types_single_galaxy_source() -> None:
"""Test measurements_types with single Galaxy source measurement type."""
measurements: set[Measurement] = {Galaxies.SHEAR_E}
has_mixed, types = measurements_types(measurements)
@@ -543,7 +589,7 @@ def test_measurements_types_single_galaxy_source():
assert types == ["Galaxy source"]
-def test_measurements_types_single_cmb():
+def test_measurements_types_single_cmb() -> None:
"""Test measurements_types with single CMB measurement type."""
measurements: set[Measurement] = {CMB.CONVERGENCE}
has_mixed, types = measurements_types(measurements)
@@ -552,7 +598,7 @@ def test_measurements_types_single_cmb():
assert types == ["CMB"]
-def test_measurements_types_single_cluster():
+def test_measurements_types_single_cluster() -> None:
"""Test measurements_types with single Cluster measurement type."""
measurements: set[Measurement] = {Clusters.COUNTS}
has_mixed, types = measurements_types(measurements)
@@ -561,7 +607,7 @@ def test_measurements_types_single_cluster():
assert types == ["Clusters"]
-def test_measurements_types_multiple_galaxy_source():
+def test_measurements_types_multiple_galaxy_source() -> None:
"""Test measurements_types with multiple Galaxy source measurements (same type)."""
measurements: set[Measurement] = {
Galaxies.SHEAR_E,
@@ -574,7 +620,7 @@ def test_measurements_types_multiple_galaxy_source():
assert types == ["Galaxy source"]
-def test_measurements_types_galaxy_lens_and_source():
+def test_measurements_types_galaxy_lens_and_source() -> None:
"""Test measurements_types with both Galaxy lens and source (mixed types)."""
measurements: set[Measurement] = {Galaxies.COUNTS, Galaxies.SHEAR_E}
has_mixed, types = measurements_types(measurements)
@@ -583,7 +629,7 @@ def test_measurements_types_galaxy_lens_and_source():
assert set(types) == {"Galaxy lens", "Galaxy source"}
-def test_measurements_types_galaxy_and_cmb():
+def test_measurements_types_galaxy_and_cmb() -> None:
"""Test measurements_types with Galaxy and CMB (mixed types)."""
measurements: set[Measurement] = {Galaxies.COUNTS, CMB.CONVERGENCE}
has_mixed, types = measurements_types(measurements)
@@ -592,7 +638,7 @@ def test_measurements_types_galaxy_and_cmb():
assert set(types) == {"Galaxy lens", "CMB"}
-def test_measurements_types_galaxy_and_cluster():
+def test_measurements_types_galaxy_and_cluster() -> None:
"""Test measurements_types with Galaxy and Cluster (mixed types)."""
measurements: set[Measurement] = {Galaxies.SHEAR_E, Clusters.COUNTS}
has_mixed, types = measurements_types(measurements)
@@ -601,7 +647,7 @@ def test_measurements_types_galaxy_and_cluster():
assert set(types) == {"Galaxy source", "Clusters"}
-def test_measurements_types_cmb_and_cluster():
+def test_measurements_types_cmb_and_cluster() -> None:
"""Test measurements_types with CMB and Cluster (mixed types)."""
measurements: set[Measurement] = {CMB.CONVERGENCE, Clusters.COUNTS}
has_mixed, types = measurements_types(measurements)
@@ -610,7 +656,7 @@ def test_measurements_types_cmb_and_cluster():
assert set(types) == {"CMB", "Clusters"}
-def test_measurements_types_all_three_types():
+def test_measurements_types_all_three_types() -> None:
"""Test measurements_types with Galaxy, CMB, and Cluster (three types)."""
measurements: set[Measurement] = {Galaxies.COUNTS, CMB.CONVERGENCE, Clusters.COUNTS}
has_mixed, types = measurements_types(measurements)
@@ -619,7 +665,7 @@ def test_measurements_types_all_three_types():
assert set(types) == {"Galaxy lens", "CMB", "Clusters"}
-def test_measurements_types_all_four_categories():
+def test_measurements_types_all_four_categories() -> None:
"""Test measurements_types with Galaxy lens, Galaxy source, CMB, and Cluster."""
measurements: set[Measurement] = {
Galaxies.COUNTS, # Galaxy lens
@@ -633,7 +679,7 @@ def test_measurements_types_all_four_categories():
assert set(types) == {"Galaxy lens", "Galaxy source", "CMB", "Clusters"}
-def test_measurements_types_empty_set():
+def test_measurements_types_empty_set() -> None:
"""Test measurements_types with empty measurement set."""
measurements: set[Measurement] = set()
has_mixed, types = measurements_types(measurements)
@@ -642,7 +688,7 @@ def test_measurements_types_empty_set():
assert not types
-def test_measurements_types_order_independent():
+def test_measurements_types_order_independent() -> None:
"""Test that measurements_types returns consistent results.
This test checks that measurements_types returns the same results regardless of set
@@ -658,7 +704,7 @@ def test_measurements_types_order_independent():
assert set(types1) == set(types2)
-def test_measurements_types_multiple_galaxy_and_cmb():
+def test_measurements_types_multiple_galaxy_and_cmb() -> None:
"""Test measurements_types with multiple Galaxy measurements and CMB."""
measurements: set[Measurement] = {
Galaxies.COUNTS, # Galaxy lens
@@ -673,8 +719,15 @@ def test_measurements_types_multiple_galaxy_and_cmb():
def test_extract_all_measured_mixed_types_with_genuinely_mixed_tracers(
- sacc_galaxy_cells: tuple[sacc.Sacc, dict[str, object], dict[str, object]],
-):
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
"""Test extract_all_measured_types with allow_mixed_types=True on mixed tracers.
This test verifies that when allow_mixed_types=True, the function permits
@@ -694,14 +747,14 @@ def test_extract_all_measured_mixed_types_with_genuinely_mixed_tracers(
def test_extract_all_measured_mixed_types_galaxy_only(
- sacc_galaxy_cells_src0_src0: tuple[sacc.Sacc, dict[str, object], dict[str, object]],
-):
+ sacc_galaxy_cells_src0_src0: tuple[sacc.Sacc, TomographicBin],
+) -> None:
"""Test extract_all_measured_types with allow_mixed_types=True on single type.
This test verifies that tracers with only one measurement type work
correctly with allow_mixed_types=True.
"""
- sacc_data, _, _ = sacc_galaxy_cells_src0_src0
+ sacc_data, _ = sacc_galaxy_cells_src0_src0
result, _ = extract_all_measured_types(sacc_data, allow_mixed_types=True)
@@ -710,16 +763,14 @@ def test_extract_all_measured_mixed_types_galaxy_only(
def test_extract_all_measured_mixed_types_density_only(
- sacc_galaxy_cells_lens0_lens0: tuple[
- sacc.Sacc, dict[str, object], dict[str, object]
- ],
-):
+ sacc_galaxy_cells_lens0_lens0: tuple[sacc.Sacc, TomographicBin],
+) -> None:
"""Test extract_all_measured_types with allow_mixed_types=True on density.
Verifies that galaxy density (COUNTS) measurements work correctly
with allow_mixed_types=True.
"""
- sacc_data, _, _ = sacc_galaxy_cells_lens0_lens0
+ sacc_data, _ = sacc_galaxy_cells_lens0_lens0
result, _ = extract_all_measured_types(sacc_data, allow_mixed_types=True)
@@ -730,11 +781,11 @@ def test_extract_all_measured_mixed_types_density_only(
def test_extract_all_measured_mixed_types_mixed_real_space(
sacc_galaxy_xis_src0_lens0: tuple[
sacc.Sacc,
- dict[str, object],
- dict[str, object],
- dict[str, object],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
],
-):
+) -> None:
"""Test extract_all_measured_types with allow_mixed_types=True on real-space data.
This test verifies behavior with real-space data (xi correlations)
@@ -753,7 +804,7 @@ def test_extract_all_measured_mixed_types_mixed_real_space(
assert Galaxies.COUNTS in result["lens0"]
-def test_extract_all_measured_mixed_types_no_auto_correction():
+def test_extract_all_measured_mixed_types_no_auto_correction() -> None:
"""Test that allow_mixed_types=True doesn't trigger auto-correction.
This test creates a SACC file where tracers have genuinely mixed types
@@ -802,7 +853,7 @@ def test_extract_all_measured_mixed_types_no_auto_correction():
assert Galaxies.COUNTS in result["tracer1"]
-def test_extract_all_measured_mixed_types_different_tracer_types():
+def test_extract_all_measured_mixed_types_different_tracer_types() -> None:
"""Test extract_all_measured_types with allow_mixed_types=True on different tracers.
This test verifies that allow_mixed_types=True correctly processes
@@ -839,7 +890,7 @@ def test_extract_all_measured_mixed_types_different_tracer_types():
assert Galaxies.COUNTS in result["lens_bin"]
-def test_extract_all_measured_mixed_types_multiple_measurements_same_tracer():
+def test_extract_all_measured_mixed_types_multiple_measurements_same_tracer() -> None:
"""Test extract_all_measured_types with multiple measurement types per tracer.
This test verifies that a tracer can simultaneously measure different
@@ -877,8 +928,15 @@ def test_extract_all_measured_mixed_types_multiple_measurements_same_tracer():
def test_extract_all_measured_types_allow_mixed_types_vs_false(
- sacc_galaxy_cells: tuple[sacc.Sacc, dict[str, object], dict[str, object]],
-):
+ sacc_galaxy_cells: tuple[
+ sacc.Sacc,
+ dict[str, tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]],
+ dict[
+ tuple[TracerNames, str],
+ tuple[npt.NDArray[np.int64], npt.NDArray[np.float64]],
+ ],
+ ],
+) -> None:
"""Test the difference between allow_mixed_types=True and False.
This test verifies that with allow_mixed_types=False, we may get
@@ -906,7 +964,7 @@ def test_extract_all_measured_types_allow_mixed_types_vs_false(
pass
-def test_extract_all_measured_types_raises_on_mixed_types_when_not_allowed():
+def test_extract_all_measured_types_raises_on_mixed_types_when_not_allowed() -> None:
"""Test that extract_all_measured_types raises ValueError for mixed types.
This test creates a SACC file with a tracer that has genuinely mixed
diff --git a/tests/models/cluster/test_abundance_data.py b/tests/models/cluster/test_abundance_data.py
index 617cb596d..acbe65407 100644
--- a/tests/models/cluster/test_abundance_data.py
+++ b/tests/models/cluster/test_abundance_data.py
@@ -9,7 +9,7 @@
)
-def test_create_abundance_data():
+def test_create_abundance_data() -> None:
s = sacc.Sacc()
ad = AbundanceData(s)
@@ -21,7 +21,9 @@ def test_create_abundance_data():
assert ad._survey_index == 0
-def test_get_survey_tracer_missing_survey_name(cluster_sacc_data: sacc.Sacc):
+def test_get_survey_tracer_missing_survey_name(
+ cluster_sacc_data: sacc.Sacc,
+) -> None:
ad = AbundanceData(cluster_sacc_data)
with pytest.raises(
ValueError,
@@ -30,7 +32,9 @@ def test_get_survey_tracer_missing_survey_name(cluster_sacc_data: sacc.Sacc):
ad.get_survey_tracer("the_black_lodge")
-def test_get_survey_tracer_wrong_tracer_type(cluster_sacc_data: sacc.Sacc):
+def test_get_survey_tracer_wrong_tracer_type(
+ cluster_sacc_data: sacc.Sacc,
+) -> None:
ad = AbundanceData(cluster_sacc_data)
with pytest.raises(
ValueError,
@@ -39,26 +43,28 @@ def test_get_survey_tracer_wrong_tracer_type(cluster_sacc_data: sacc.Sacc):
ad.get_survey_tracer("z_bin_tracer_1")
-def test_get_survey_tracer_returns_survey_tracer(cluster_sacc_data: sacc.Sacc):
+def test_get_survey_tracer_returns_survey_tracer(
+ cluster_sacc_data: sacc.Sacc,
+) -> None:
ad = AbundanceData(cluster_sacc_data)
survey = ad.get_survey_tracer("my_survey")
assert survey is not None
assert isinstance(survey, sacc.tracers.SurveyTracer)
-def test_get_bin_edges_cluster_counts(cluster_sacc_data: sacc.Sacc):
+def test_get_bin_edges_cluster_counts(cluster_sacc_data: sacc.Sacc) -> None:
ad = AbundanceData(cluster_sacc_data)
bins = ad.get_bin_edges("my_survey", ClusterProperty.COUNTS)
assert len(bins) == 2
-def test_get_bin_edges_cluster_mass(cluster_sacc_data: sacc.Sacc):
+def test_get_bin_edges_cluster_mass(cluster_sacc_data: sacc.Sacc) -> None:
ad = AbundanceData(cluster_sacc_data)
bins = ad.get_bin_edges("my_survey", ClusterProperty.MASS)
assert len(bins) == 2
-def test_get_bin_edges_counts_and_mass(cluster_sacc_data: sacc.Sacc):
+def test_get_bin_edges_counts_and_mass(cluster_sacc_data: sacc.Sacc) -> None:
ad = AbundanceData(cluster_sacc_data)
bins = ad.get_bin_edges(
"my_survey", (ClusterProperty.MASS | ClusterProperty.COUNTS)
@@ -66,7 +72,9 @@ def test_get_bin_edges_counts_and_mass(cluster_sacc_data: sacc.Sacc):
assert len(bins) == 2
-def test_get_bin_edges_counts_and_mass_and_shear(cluster_sacc_data: sacc.Sacc):
+def test_get_bin_edges_counts_and_mass_and_shear(
+ cluster_sacc_data: sacc.Sacc,
+) -> None:
ad = AbundanceData(cluster_sacc_data)
bins = ad.get_bin_edges(
"my_survey",
@@ -77,7 +85,7 @@ def test_get_bin_edges_counts_and_mass_and_shear(cluster_sacc_data: sacc.Sacc):
def test_observed_data_and_indices_by_survey_cluster_counts(
cluster_sacc_data: sacc.Sacc,
-):
+) -> None:
ad = AbundanceData(cluster_sacc_data)
data, indices = ad.get_observed_data_and_indices_by_survey(
"my_survey", ClusterProperty.COUNTS
@@ -88,7 +96,7 @@ def test_observed_data_and_indices_by_survey_cluster_counts(
def test_observed_data_and_indices_by_survey_cluster_mass(
cluster_sacc_data: sacc.Sacc,
-):
+) -> None:
ad = AbundanceData(cluster_sacc_data)
data, indices = ad.get_observed_data_and_indices_by_survey(
"my_survey", ClusterProperty.MASS
@@ -99,7 +107,7 @@ def test_observed_data_and_indices_by_survey_cluster_mass(
def test_observed_data_and_indices_by_survey_cluster_counts_and_mass(
cluster_sacc_data: sacc.Sacc,
-):
+) -> None:
ad = AbundanceData(cluster_sacc_data)
data, indices = ad.get_observed_data_and_indices_by_survey(
"my_survey", ClusterProperty.MASS | ClusterProperty.COUNTS
@@ -108,7 +116,7 @@ def test_observed_data_and_indices_by_survey_cluster_counts_and_mass(
assert len(indices) == 4
-def test_observed_data_and_indices_no_data_throws():
+def test_observed_data_and_indices_no_data_throws() -> None:
# pylint: disable=no-member
cc = sacc.standard_types.cluster_counts
@@ -138,7 +146,9 @@ def test_observed_data_and_indices_no_data_throws():
ad.get_observed_data_and_indices_by_survey("my_survey", ClusterProperty.MASS)
-def test_observed_data_and_indices_redshift_property(cluster_sacc_data: sacc.Sacc):
+def test_observed_data_and_indices_redshift_property(
+ cluster_sacc_data: sacc.Sacc,
+) -> None:
"""Test that REDSHIFT property is handled correctly (not COUNTS or MASS)."""
ad = AbundanceData(cluster_sacc_data)
# REDSHIFT is valid but not handled in get_observed_data_and_indices_by_survey
diff --git a/tests/models/cluster/test_binning.py b/tests/models/cluster/test_binning.py
index be560dc1c..004556ac9 100644
--- a/tests/models/cluster/test_binning.py
+++ b/tests/models/cluster/test_binning.py
@@ -8,7 +8,7 @@
from firecrown.models.cluster import NDimensionalBin, SaccBin, TupleBin
-def test_bin_str():
+def test_bin_str() -> None:
tracer_z = sacc.tracers.BinZTracer("", 0, 1)
tracer_lambda = sacc.tracers.BinRichnessTracer("", 4, 5)
tracer_radius = sacc.tracers.BinRadiusTracer("", 1, 2, 1.5)
@@ -16,7 +16,7 @@ def test_bin_str():
assert str(sb) == "[(0, 1), (4, 5), (1, 2)]\n"
-def test_create_sacc_bin_with_correct_dimension():
+def test_create_sacc_bin_with_correct_dimension() -> None:
tracer = sacc.tracers.SurveyTracer("", 1)
for i in range(10):
tracers = [tracer for _ in range(i)]
@@ -25,7 +25,7 @@ def test_create_sacc_bin_with_correct_dimension():
assert sb.dimension == i
-def test_sacc_bin_z_edges():
+def test_sacc_bin_z_edges() -> None:
tracer_z = sacc.tracers.BinZTracer("", 0, 1)
tracer_lambda = sacc.tracers.BinRichnessTracer("", 4, 5)
tracer_radius = sacc.tracers.BinRadiusTracer("", 1, 2, 1.5)
@@ -45,7 +45,7 @@ def test_sacc_bin_z_edges():
assert sb.z_edges == (0, 1)
-def test_sacc_bin_z_edges_throws_when_multiple_z_bins():
+def test_sacc_bin_z_edges_throws_when_multiple_z_bins() -> None:
tracer_z = sacc.tracers.BinZTracer("", 0, 1)
tracer_lambda = sacc.tracers.BinRichnessTracer("", 4, 5)
tracer_radius = sacc.tracers.BinRadiusTracer("", 1, 2, 1.5)
@@ -54,7 +54,7 @@ def test_sacc_bin_z_edges_throws_when_multiple_z_bins():
print(sb.z_edges)
-def test_sacc_bin_mass_proxy_edges_throws_when_multiple_mass_proxy_bins():
+def test_sacc_bin_mass_proxy_edges_throws_when_multiple_mass_proxy_bins() -> None:
tracer_z = sacc.tracers.BinZTracer("", 0, 1)
tracer_lambda = sacc.tracers.BinRichnessTracer("", 4, 5)
tracer_radius = sacc.tracers.BinRadiusTracer("", 1, 2, 1.5)
@@ -63,7 +63,7 @@ def test_sacc_bin_mass_proxy_edges_throws_when_multiple_mass_proxy_bins():
print(sb.mass_proxy_edges)
-def test_sacc_bin_radius_edges_throws_when_multiple_radius_bins():
+def test_sacc_bin_radius_edges_throws_when_multiple_radius_bins() -> None:
tracer_z = sacc.tracers.BinZTracer("", 0, 1)
tracer_lambda = sacc.tracers.BinRichnessTracer("", 4, 5)
tracer_radius = sacc.tracers.BinRadiusTracer("", 1, 2, 1.5)
@@ -72,7 +72,7 @@ def test_sacc_bin_radius_edges_throws_when_multiple_radius_bins():
print(sb.radius_edges)
-def test_sacc_bin_radius_center_throws_when_multiple_radius_bins():
+def test_sacc_bin_radius_center_throws_when_multiple_radius_bins() -> None:
tracer_z = sacc.tracers.BinZTracer("", 0, 1)
tracer_lambda = sacc.tracers.BinRichnessTracer("", 4, 5)
tracer_radius = sacc.tracers.BinRadiusTracer("", 1, 2, 1.5)
@@ -81,7 +81,7 @@ def test_sacc_bin_radius_center_throws_when_multiple_radius_bins():
print(sb.radius_center)
-def test_sacc_bin_richness_edges():
+def test_sacc_bin_richness_edges() -> None:
tracer_z = sacc.tracers.BinZTracer("", 0, 1)
tracer_lambda = sacc.tracers.BinRichnessTracer("", 4, 5)
sb = SaccBin([tracer_z, tracer_lambda])
@@ -93,7 +93,7 @@ def test_sacc_bin_richness_edges():
assert sb.mass_proxy_edges == (4, 5)
-def test_sacc_bin_radius_edges():
+def test_sacc_bin_radius_edges() -> None:
tracer_z = sacc.tracers.BinZTracer("", 0, 1)
tracer_lambda = sacc.tracers.BinRichnessTracer("", 4, 5)
tracer_radius = sacc.tracers.BinRadiusTracer("", 1, 2, 1.5)
@@ -113,7 +113,7 @@ def test_sacc_bin_radius_edges():
assert sb.radius_edges == (1, 2)
-def test_sacc_bin_radius_center():
+def test_sacc_bin_radius_center() -> None:
tracer_z = sacc.tracers.BinZTracer("", 0, 1)
tracer_lambda = sacc.tracers.BinRichnessTracer("", 4, 5)
tracer_radius = sacc.tracers.BinRadiusTracer("", 1, 2, 1.5)
@@ -136,7 +136,7 @@ def test_sacc_bin_radius_center():
assert radius_center == 1.5
-def test_equal_sacc_bins_are_equal():
+def test_equal_sacc_bins_are_equal() -> None:
tracer_z = sacc.tracers.BinZTracer("", 0, 1)
tracer_lambda = sacc.tracers.BinRichnessTracer("", 4, 5)
sb1 = SaccBin([tracer_z, tracer_lambda])
@@ -152,7 +152,7 @@ def test_equal_sacc_bins_are_equal():
assert sb1 is not sb2
-def test_sacc_bin_different_edges_not_equal():
+def test_sacc_bin_different_edges_not_equal() -> None:
tracer_z = sacc.tracers.BinZTracer("", 0, 1)
tracer_lambda = sacc.tracers.BinRichnessTracer("", 4, 5)
sb1 = SaccBin([tracer_z, tracer_lambda])
@@ -176,7 +176,7 @@ def test_sacc_bin_different_edges_not_equal():
assert sb1 != sb2
-def test_sacc_bin_different_dimensions_not_equal():
+def test_sacc_bin_different_dimensions_not_equal() -> None:
tracer_z = sacc.tracers.BinZTracer("", 0, 1)
tracer_z2 = sacc.tracers.BinZTracer("", 1, 2)
tracer_lambda = sacc.tracers.BinRichnessTracer("", 4, 5)
@@ -186,7 +186,7 @@ def test_sacc_bin_different_dimensions_not_equal():
assert sb1 != sb2
-def test_sacc_bin_must_be_equal_type():
+def test_sacc_bin_must_be_equal_type() -> None:
other_bin = Mock(spec=NDimensionalBin)
tracer_z = sacc.tracers.BinZTracer("", 0, 1)
@@ -196,7 +196,7 @@ def test_sacc_bin_must_be_equal_type():
assert sb != other_bin
-def test_create_tuple_bin():
+def test_create_tuple_bin() -> None:
tb = TupleBin([(1, 2), (3, 4), (1, 2, 1.5)])
assert tb is not None
assert tb.dimension == 3
@@ -206,7 +206,7 @@ def test_create_tuple_bin():
assert tb.radius_center == 1.5
-def test_tuple_bin_radius_center_requires_center_value():
+def test_tuple_bin_radius_center_requires_center_value() -> None:
tb = TupleBin([(1, 2), (3, 4), (1, 2)])
with pytest.raises(
@@ -215,7 +215,7 @@ def test_tuple_bin_radius_center_requires_center_value():
_ = tb.radius_center
-def test_tuple_bins_are_equal():
+def test_tuple_bins_are_equal() -> None:
tb1 = TupleBin([(1, 2), (3, 4)])
tb2 = TupleBin([(1, 2), (3, 4)])
assert tb1 == tb2
@@ -223,7 +223,7 @@ def test_tuple_bins_are_equal():
assert tb1 is not tb2
-def test_tuple_bin_neq_sacc_bin():
+def test_tuple_bin_neq_sacc_bin() -> None:
tb = TupleBin([(1, 2), (3, 4)])
tracer_z = sacc.tracers.BinZTracer("", 3, 4)
tracer_lambda = sacc.tracers.BinRichnessTracer("", 1, 2)
@@ -231,7 +231,7 @@ def test_tuple_bin_neq_sacc_bin():
assert tb != sb
-def test_tuple_bin_different_dimensions_not_equal():
+def test_tuple_bin_different_dimensions_not_equal() -> None:
tb1 = TupleBin([(1, 2), (3, 4), (5, 6)])
tb2 = TupleBin([(1, 2), (3, 4)])
assert tb1 != tb2
@@ -241,7 +241,7 @@ def test_tuple_bin_different_dimensions_not_equal():
assert tb1 != tb2
-def test_tuple_bin_different_bins_not_equal():
+def test_tuple_bin_different_bins_not_equal() -> None:
tb1 = TupleBin([(1, 2), (3, 4)])
tb2 = TupleBin([(1, 2), (3, 5)])
assert tb1 != tb2
diff --git a/tests/models/cluster/test_shear_data.py b/tests/models/cluster/test_shear_data.py
index 1fb0d3221..af270603e 100644
--- a/tests/models/cluster/test_shear_data.py
+++ b/tests/models/cluster/test_shear_data.py
@@ -9,7 +9,7 @@
)
-def test_create_deltasigma_data():
+def test_create_deltasigma_data() -> None:
s = sacc.Sacc()
dsd = ShearData(s)
@@ -23,7 +23,9 @@ def test_create_deltasigma_data():
assert dsd._radius_index == 3
-def test_get_survey_tracer_missing_survey_name(cluster_sacc_data: sacc.Sacc):
+def test_get_survey_tracer_missing_survey_name(
+ cluster_sacc_data: sacc.Sacc,
+) -> None:
dsd = ShearData(cluster_sacc_data)
with pytest.raises(
ValueError,
@@ -32,7 +34,9 @@ def test_get_survey_tracer_missing_survey_name(cluster_sacc_data: sacc.Sacc):
dsd.get_survey_tracer("the_black_lodge")
-def test_get_survey_tracer_wrong_tracer_type(cluster_sacc_data: sacc.Sacc):
+def test_get_survey_tracer_wrong_tracer_type(
+ cluster_sacc_data: sacc.Sacc,
+) -> None:
dsd = ShearData(cluster_sacc_data)
with pytest.raises(
ValueError,
@@ -65,14 +69,16 @@ def test_wrong_tracer_number(cluster_sacc_data: sacc.Sacc) -> None:
dsd._all_bin_combinations_for_data_type(cs, tracers_n)
-def test_get_survey_tracer_returns_survey_tracer(cluster_sacc_data: sacc.Sacc):
+def test_get_survey_tracer_returns_survey_tracer(
+ cluster_sacc_data: sacc.Sacc,
+) -> None:
dsd = ShearData(cluster_sacc_data)
survey = dsd.get_survey_tracer("my_survey")
assert survey is not None
assert isinstance(survey, sacc.tracers.SurveyTracer)
-def test_get_bin_edges_cluster_radius(cluster_sacc_data: sacc.Sacc):
+def test_get_bin_edges_cluster_radius(cluster_sacc_data: sacc.Sacc) -> None:
dsd = ShearData(cluster_sacc_data)
bins = dsd.get_bin_edges("my_survey", ClusterProperty.DELTASIGMA)
assert len(bins) == 2
@@ -80,7 +86,7 @@ def test_get_bin_edges_cluster_radius(cluster_sacc_data: sacc.Sacc):
def test_observed_data_and_indices_by_survey_cluster_deltasigma(
cluster_sacc_data: sacc.Sacc,
-):
+) -> None:
dsd = ShearData(cluster_sacc_data)
data, indices = dsd.get_observed_data_and_indices_by_survey(
"my_survey", ClusterProperty.DELTASIGMA
@@ -89,7 +95,7 @@ def test_observed_data_and_indices_by_survey_cluster_deltasigma(
assert len(indices) == 2
-def test_get_bin_edges_cluster_shear(cluster_sacc_data: sacc.Sacc):
+def test_get_bin_edges_cluster_shear(cluster_sacc_data: sacc.Sacc) -> None:
dsd = ShearData(cluster_sacc_data)
bins = dsd.get_bin_edges("my_survey", ClusterProperty.SHEAR)
assert len(bins) == 2
@@ -97,7 +103,7 @@ def test_get_bin_edges_cluster_shear(cluster_sacc_data: sacc.Sacc):
def test_observed_data_and_indices_by_survey_cluster_shear(
cluster_sacc_data: sacc.Sacc,
-):
+) -> None:
dsd = ShearData(cluster_sacc_data)
data, indices = dsd.get_observed_data_and_indices_by_survey(
"my_survey", ClusterProperty.SHEAR
@@ -106,7 +112,7 @@ def test_observed_data_and_indices_by_survey_cluster_shear(
assert len(indices) == 2
-def test_observed_data_and_indices_wrong_property():
+def test_observed_data_and_indices_wrong_property() -> None:
"""Test error when wrong property used with ShearData."""
s = sacc.Sacc()
ads = ShearData(s)
@@ -122,7 +128,7 @@ def test_observed_data_and_indices_wrong_property():
def test_observed_data_and_indices_both_deltasigma_and_shear(
cluster_sacc_data: sacc.Sacc,
-):
+) -> None:
"""Ensure error is raised if both DELTASIGMA and SHEAR are requested at once."""
dsd = ShearData(cluster_sacc_data)
with pytest.raises(
diff --git a/tests/models/two_point/test_interpolation.py b/tests/models/two_point/test_interpolation.py
index 940e2018e..cd5e77201 100644
--- a/tests/models/two_point/test_interpolation.py
+++ b/tests/models/two_point/test_interpolation.py
@@ -6,7 +6,7 @@
from firecrown.models.two_point import ApplyInterpolationWhen
-def test_apply_interpolation_when_none():
+def test_apply_interpolation_when_none() -> None:
"""Test ApplyInterpolationWhen.NONE flag."""
apply_interp_when = ApplyInterpolationWhen.NONE
assert apply_interp_when == ApplyInterpolationWhen.NONE
@@ -15,7 +15,7 @@ def test_apply_interpolation_when_none():
assert not apply_interp_when & ApplyInterpolationWhen.HARMONIC_WINDOW
-def test_apply_interpolation_when_all():
+def test_apply_interpolation_when_all() -> None:
"""Test ApplyInterpolationWhen.ALL flag."""
apply_interp_when = ApplyInterpolationWhen.ALL
assert apply_interp_when == ApplyInterpolationWhen.ALL
@@ -24,7 +24,7 @@ def test_apply_interpolation_when_all():
assert apply_interp_when & ApplyInterpolationWhen.HARMONIC_WINDOW
-def test_apply_interpolation_when_default():
+def test_apply_interpolation_when_default() -> None:
"""Test ApplyInterpolationWhen.DEFAULT flag composition."""
apply_interp_when = ApplyInterpolationWhen.DEFAULT
assert apply_interp_when == ApplyInterpolationWhen.DEFAULT
@@ -33,7 +33,7 @@ def test_apply_interpolation_when_default():
assert not apply_interp_when & ApplyInterpolationWhen.HARMONIC
-def test_apply_interpolation_when_real():
+def test_apply_interpolation_when_real() -> None:
"""Test ApplyInterpolationWhen.REAL flag."""
apply_interp_when = ApplyInterpolationWhen.REAL
assert apply_interp_when & ApplyInterpolationWhen.REAL
@@ -41,7 +41,7 @@ def test_apply_interpolation_when_real():
assert not apply_interp_when & ApplyInterpolationWhen.HARMONIC_WINDOW
-def test_apply_interpolation_when_harmonic():
+def test_apply_interpolation_when_harmonic() -> None:
"""Test ApplyInterpolationWhen.HARMONIC flag."""
apply_interp_when = ApplyInterpolationWhen.HARMONIC
assert not apply_interp_when & ApplyInterpolationWhen.REAL
@@ -49,7 +49,7 @@ def test_apply_interpolation_when_harmonic():
assert not apply_interp_when & ApplyInterpolationWhen.HARMONIC_WINDOW
-def test_apply_interpolation_when_harmonic_window():
+def test_apply_interpolation_when_harmonic_window() -> None:
"""Test ApplyInterpolationWhen.HARMONIC_WINDOW flag."""
apply_interp_when = ApplyInterpolationWhen.HARMONIC_WINDOW
assert not apply_interp_when & ApplyInterpolationWhen.REAL
@@ -57,7 +57,7 @@ def test_apply_interpolation_when_harmonic_window():
assert apply_interp_when & ApplyInterpolationWhen.HARMONIC_WINDOW
-def test_apply_interpolation_when_bitwise_or():
+def test_apply_interpolation_when_bitwise_or() -> None:
"""Test bitwise OR operations on ApplyInterpolationWhen flags."""
combined = ApplyInterpolationWhen.REAL | ApplyInterpolationWhen.HARMONIC
assert combined & ApplyInterpolationWhen.REAL
@@ -65,7 +65,7 @@ def test_apply_interpolation_when_bitwise_or():
assert not combined & ApplyInterpolationWhen.HARMONIC_WINDOW
-def test_apply_interpolation_when_iteration():
+def test_apply_interpolation_when_iteration() -> None:
"""Test that all ApplyInterpolationWhen values are iterable."""
all_values = list(ApplyInterpolationWhen)
assert len(all_values) >= 3 # At minimum: REAL, HARMONIC, HARMONIC_WINDOW
@@ -74,7 +74,7 @@ def test_apply_interpolation_when_iteration():
assert ApplyInterpolationWhen.HARMONIC_WINDOW in all_values
-def test_pydantic_schema_exists():
+def test_pydantic_schema_exists() -> None:
"""Test that Pydantic core schema can be retrieved."""
result = ApplyInterpolationWhen.__get_pydantic_core_schema__(
ApplyInterpolationWhen, None # type: ignore[arg-type]
@@ -82,7 +82,7 @@ def test_pydantic_schema_exists():
assert result is not None
-def test_pydantic_model_with_apply_interpolation_when():
+def test_pydantic_model_with_apply_interpolation_when() -> None:
"""Test using ApplyInterpolationWhen in a Pydantic model."""
class TestModel(BaseModel):
@@ -108,7 +108,7 @@ class TestModel(BaseModel):
assert model4.interp == ApplyInterpolationWhen.NONE
-def test_pydantic_serialization_with_model():
+def test_pydantic_serialization_with_model() -> None:
"""Test serialization of ApplyInterpolationWhen in Pydantic model."""
class TestModel(BaseModel):
@@ -134,7 +134,7 @@ class TestModel(BaseModel):
assert "HARMONIC" in data3["interp"]
-def test_pydantic_validation_errors():
+def test_pydantic_validation_errors() -> None:
"""Test that invalid inputs raise proper validation errors."""
class TestModel(BaseModel):
@@ -151,7 +151,7 @@ class TestModel(BaseModel):
TestModel(interp=123) # type: ignore[arg-type]
-def test_pydantic_serialize_none():
+def test_pydantic_serialize_none() -> None:
"""Test Pydantic serialization of NONE flag."""
schema = ApplyInterpolationWhen.__get_pydantic_core_schema__(
ApplyInterpolationWhen, None # type: ignore[arg-type]
@@ -164,7 +164,7 @@ def test_pydantic_serialize_none():
assert result == "NONE"
-def test_pydantic_serialize_single_flag():
+def test_pydantic_serialize_single_flag() -> None:
"""Test Pydantic serialization of a single flag."""
schema = ApplyInterpolationWhen.__get_pydantic_core_schema__(
ApplyInterpolationWhen, None # type: ignore[arg-type]
@@ -176,7 +176,7 @@ def test_pydantic_serialize_single_flag():
assert result == "REAL"
-def test_pydantic_serialize_multiple_flags():
+def test_pydantic_serialize_multiple_flags() -> None:
"""Test Pydantic serialization of combined flags."""
schema = ApplyInterpolationWhen.__get_pydantic_core_schema__(
ApplyInterpolationWhen, None # type: ignore[arg-type]
@@ -193,7 +193,7 @@ def test_pydantic_serialize_multiple_flags():
assert "|" in result
-def test_pydantic_serialize_default():
+def test_pydantic_serialize_default() -> None:
"""Test Pydantic serialization of DEFAULT flag."""
schema = ApplyInterpolationWhen.__get_pydantic_core_schema__(
ApplyInterpolationWhen, None # type: ignore[arg-type]
diff --git a/tests/models/two_point/test_power_spectrum.py b/tests/models/two_point/test_power_spectrum.py
index 5f03092da..05b1866c0 100644
--- a/tests/models/two_point/test_power_spectrum.py
+++ b/tests/models/two_point/test_power_spectrum.py
@@ -19,7 +19,7 @@
@pytest.fixture
-def mock_tools():
+def mock_tools() -> Mock:
"""Create a mock ModelingTools object."""
tools = Mock(spec=ModelingTools)
@@ -39,7 +39,7 @@ def mock_tools():
@pytest.fixture
-def mock_tracer_with_hm():
+def mock_tracer_with_hm() -> Mock:
"""Create a mock tracer that has halo model."""
tracer = Mock(spec=Tracer)
tracer.has_hm = True
@@ -55,7 +55,7 @@ def mock_tracer_with_hm():
@pytest.fixture
-def mock_tracer_without_hm():
+def mock_tracer_without_hm() -> Mock:
"""Create a mock tracer that does not have halo model."""
tracer = Mock(spec=Tracer)
tracer.has_hm = False
@@ -65,7 +65,7 @@ def mock_tracer_without_hm():
return tracer
-def test_both_tracers_have_hm(mock_tools, mock_tracer_with_hm):
+def test_both_tracers_have_hm(mock_tools: Mock, mock_tracer_with_hm: Mock) -> None:
"""Test case where both tracers have halo model."""
tracer0 = mock_tracer_with_hm
tracer1 = mock_tracer_with_hm
@@ -95,8 +95,10 @@ def test_both_tracers_have_hm(mock_tools, mock_tracer_with_hm):
def test_only_first_tracer_has_hm(
- mock_tools, mock_tracer_with_hm, mock_tracer_without_hm
-):
+ mock_tools: Mock,
+ mock_tracer_with_hm: Mock,
+ mock_tracer_without_hm: Mock,
+) -> None:
"""Test case where only the first tracer has halo model."""
tracer0 = mock_tracer_with_hm
tracer1 = mock_tracer_without_hm
@@ -120,8 +122,10 @@ def test_only_first_tracer_has_hm(
def test_only_second_tracer_has_hm(
- mock_tools, mock_tracer_with_hm, mock_tracer_without_hm
-):
+ mock_tools: Mock,
+ mock_tracer_with_hm: Mock,
+ mock_tracer_without_hm: Mock,
+) -> None:
"""Test case where only the second tracer has halo model."""
tracer0 = mock_tracer_without_hm
tracer1 = mock_tracer_with_hm
@@ -144,7 +148,7 @@ def test_only_second_tracer_has_hm(
assert result == mock_pk_total
-def test_mixed_tracer_requires_shear(mock_tools):
+def test_mixed_tracer_requires_shear(mock_tools: Mock) -> None:
"""Test that when not both tracers have HM, at least one must be 'shear'."""
# Create two tracers without HM and without shear to trigger AssertionError
tracer0 = Mock(spec=Tracer)
@@ -165,7 +169,9 @@ def test_mixed_tracer_requires_shear(mock_tools):
at_least_one_tracer_has_hm(mock_tools, tracer0, tracer1)
-def test_profile_assertion_for_mixed_hm(mock_tools, mock_tracer_without_hm):
+def test_profile_assertion_for_mixed_hm(
+ mock_tools: Mock, mock_tracer_without_hm: Mock
+) -> None:
"""Test assertion when HM tracer has None halo_profile in mixed case."""
# Create HM tracer with None halo_profile
tracer0 = Mock(spec=Tracer)
@@ -180,7 +186,7 @@ def test_profile_assertion_for_mixed_hm(mock_tools, mock_tracer_without_hm):
at_least_one_tracer_has_hm(mock_tools, tracer0, tracer1)
-def test_ia_bias_exponent_both_hm(mock_tools, mock_tracer_with_hm):
+def test_ia_bias_exponent_both_hm(mock_tools: Mock, mock_tracer_with_hm: Mock) -> None:
"""Test that IA bias exponent is 2 when both tracers have HM."""
tracer0 = mock_tracer_with_hm
tracer1 = mock_tracer_with_hm
@@ -221,8 +227,10 @@ def test_ia_bias_exponent_both_hm(mock_tools, mock_tracer_with_hm):
def test_halo_profile_nfw_configuration(
- mock_tools, mock_tracer_with_hm, mock_tracer_without_hm
-):
+ mock_tools: Mock,
+ mock_tracer_with_hm: Mock,
+ mock_tracer_without_hm: Mock,
+) -> None:
"""Test that HaloProfileNFW is configured correctly for non-HM tracers."""
tracer0 = mock_tracer_with_hm
tracer1 = mock_tracer_without_hm
@@ -257,7 +265,7 @@ def test_halo_profile_nfw_configuration(
assert result == mock_pk_total
-def test_pk2d_addition_result(mock_tools, mock_tracer_with_hm):
+def test_pk2d_addition_result(mock_tools: Mock, mock_tracer_with_hm: Mock) -> None:
"""Test that the function returns the sum of 1-halo and 2-halo power spectra."""
tracer0 = mock_tracer_with_hm
tracer1 = mock_tracer_with_hm
@@ -285,7 +293,7 @@ def test_pk2d_addition_result(mock_tools, mock_tracer_with_hm):
assert result is mock_pk_total # Ensure it's the exact same object
-def test_calculate_pk_with_existing_pk(mock_tools):
+def test_calculate_pk_with_existing_pk(mock_tools: Mock) -> None:
"""Test calculate_pk when power spectrum already exists in tools."""
pk_name = "existing_pk"
@@ -303,7 +311,7 @@ def test_calculate_pk_with_existing_pk(mock_tools):
assert result == mock_pk
-def test_calculate_pk_with_pt_tracers():
+def test_calculate_pk_with_pt_tracers() -> None:
"""Test calculate_pk when at least one tracer has PT."""
pk_name = "pt_pk"
@@ -330,7 +338,7 @@ def test_calculate_pk_with_pt_tracers():
assert result == mock_pk
-def test_calculate_pk_with_hm_tracers():
+def test_calculate_pk_with_hm_tracers() -> None:
"""Test calculate_pk when at least one tracer has HM."""
pk_name = "hm_pk"
@@ -357,7 +365,7 @@ def test_calculate_pk_with_hm_tracers():
assert result == mock_pk
-def test_calculate_pk_no_valid_method():
+def test_calculate_pk_no_valid_method() -> None:
"""Test calculate_pk raises ValueError when no valid method exists."""
pk_name = "invalid_pk"
@@ -376,7 +384,7 @@ def test_calculate_pk_no_valid_method():
calculate_pk(pk_name, mock_tools, tracer0, tracer1)
-def test_at_least_one_tracer_has_pt_both_have_pt():
+def test_at_least_one_tracer_has_pt_both_have_pt() -> None:
"""Test at_least_one_tracer_has_pt when both tracers have PT."""
mock_tools = Mock(spec=ModelingTools)
@@ -399,7 +407,7 @@ def test_at_least_one_tracer_has_pt_both_have_pt():
assert result == mock_pk
-def test_at_least_one_tracer_has_pt_first_missing_pt():
+def test_at_least_one_tracer_has_pt_first_missing_pt() -> None:
"""Test at_least_one_tracer_has_pt when first tracer does not have PT."""
mock_tools = Mock(spec=ModelingTools)
@@ -423,7 +431,7 @@ def test_at_least_one_tracer_has_pt_first_missing_pt():
assert result == mock_pk
-def test_at_least_one_tracer_has_pt_second_missing_pt():
+def test_at_least_one_tracer_has_pt_second_missing_pt() -> None:
"""Test at_least_one_tracer_has_pt when second tracer does not have PT."""
mock_tools = Mock(spec=ModelingTools)
diff --git a/tests/models/two_point/test_sacc_utils.py b/tests/models/two_point/test_sacc_utils.py
index 53b69a131..afab996e7 100644
--- a/tests/models/two_point/test_sacc_utils.py
+++ b/tests/models/two_point/test_sacc_utils.py
@@ -8,7 +8,7 @@
import firecrown.models.two_point as models
-def test_determine_ccl_kind():
+def test_determine_ccl_kind() -> None:
assert models.determine_ccl_kind("galaxy_density_cl") == "cl"
assert models.determine_ccl_kind("galaxy_shearDensity_cl_e") == "cl"
assert models.determine_ccl_kind("galaxy_shear_cl_ee") == "cl"
@@ -27,7 +27,7 @@ def test_determine_ccl_kind():
def test_calculate_pk_lacking_pk(
tools_with_vanilla_cosmology: mt.ModelingTools, empty_pyccl_tracer: pyccl.Tracer
-):
+) -> None:
dummy = source.Tracer(empty_pyccl_tracer)
with pytest.raises(ValueError):
_ = models.calculate_pk(
diff --git a/tests/models/two_point/test_theory.py b/tests/models/two_point/test_theory.py
index 18d1400d9..50e21a17e 100644
--- a/tests/models/two_point/test_theory.py
+++ b/tests/models/two_point/test_theory.py
@@ -12,24 +12,28 @@
from firecrown.modeling_tools import ModelingTools
from firecrown.models.two_point import ApplyInterpolationWhen, TwoPointTheory
from firecrown.updatable import ParamsMap
+from firecrown.updatable import UpdatableUsageRecord
from firecrown.utils import ClIntegrationOptions
# pylint: disable=protected-access
@pytest.fixture(name="mock_source")
-def fixture_mock_source():
+def fixture_mock_source() -> Mock:
"""Create a mock source that behaves like a real Updatable Source."""
source = Mock(spec=Source)
source.sacc_tracer = "tracer_1"
source.is_updated = Mock(return_value=False)
- def update_side_effect(_params, _updated_record=None):
+ def update_side_effect(
+ _params: ParamsMap,
+ _updated_record: list[UpdatableUsageRecord] | None = None,
+ ) -> None:
if source.is_updated():
return # Mimic Updatable: do nothing if already updated
source.is_updated.return_value = True
- def reset_side_effect():
+ def reset_side_effect() -> None:
source.is_updated.return_value = False
source.update = Mock(side_effect=update_side_effect)
@@ -38,18 +42,21 @@ def reset_side_effect():
@pytest.fixture(name="mock_source_pair")
-def fixture_mock_source_pair(mock_source):
+def fixture_mock_source_pair(mock_source: Mock) -> tuple[Mock, Mock]:
"""Create a pair of mock sources."""
source2 = Mock(spec=Source)
source2.sacc_tracer = "tracer_2"
source2.is_updated = Mock(return_value=False)
- def update_side_effect2(_params, _updated_record=None):
+ def update_side_effect2(
+ _params: ParamsMap,
+ _updated_record: list[UpdatableUsageRecord] | None = None,
+ ) -> None:
if source2.is_updated():
return
source2.is_updated.return_value = True
- def reset_side_effect2():
+ def reset_side_effect2() -> None:
source2.is_updated.return_value = False
source2.update = Mock(side_effect=update_side_effect2)
@@ -57,32 +64,7 @@ def reset_side_effect2():
return (mock_source, source2)
-class FakeSource(Source):
- """A minimal concrete Source implementation for testing."""
-
- def read_systematics(self, sacc_data: sacc.Sacc) -> None:
- pass
-
- def _read(self, sacc_data: sacc.Sacc) -> None:
- pass
-
- def _update_source(self, params: ParamsMap) -> None:
- pass
-
- def get_scale(self) -> float:
- return 1.0
-
- def create_tracers(self, tools: ModelingTools):
- return []
-
-
-@pytest.fixture
-def source_pair():
- """Create a pair of concrete FakeSource instances."""
- return (FakeSource("tracer_1"), FakeSource("tracer_2"))
-
-
-def test_two_point_theory_initialization():
+def test_two_point_theory_initialization() -> None:
"""Test basic TwoPointTheory initialization."""
source1 = Mock()
source2 = Mock()
@@ -100,7 +82,7 @@ def test_two_point_theory_initialization():
assert not theory.cells
-def test_two_point_theory_with_custom_interp_ells():
+def test_two_point_theory_with_custom_interp_ells() -> None:
"""Test TwoPointTheory with custom interpolation ells generator."""
source1 = Mock()
source2 = Mock()
@@ -117,7 +99,7 @@ def test_two_point_theory_with_custom_interp_ells():
assert len(theory.ells_for_xi) > 0
-def test_two_point_theory_with_ell_or_theta_config():
+def test_two_point_theory_with_ell_or_theta_config() -> None:
"""Test TwoPointTheory initialization with ell_or_theta configuration."""
source1 = Mock()
source2 = Mock()
@@ -134,7 +116,7 @@ def test_two_point_theory_with_ell_or_theta_config():
assert theory.ell_or_theta_config == ell_or_theta
-def test_two_point_theory_with_tracers():
+def test_two_point_theory_with_tracers() -> None:
"""Test TwoPointTheory initialization with explicit tracer names."""
source1 = Mock()
source2 = Mock()
@@ -149,7 +131,7 @@ def test_two_point_theory_with_tracers():
assert theory.sacc_tracers == tracers
-def test_two_point_theory_with_int_options():
+def test_two_point_theory_with_int_options() -> None:
"""Test TwoPointTheory with integration options."""
source1 = Mock()
source2 = Mock()
@@ -167,7 +149,7 @@ def test_two_point_theory_with_int_options():
assert theory.int_options == int_options
-def test_two_point_theory_with_apply_interp():
+def test_two_point_theory_with_apply_interp() -> None:
"""Test TwoPointTheory with custom apply_interp flag."""
source1 = Mock()
source2 = Mock()
@@ -181,7 +163,7 @@ def test_two_point_theory_with_apply_interp():
assert theory.apply_interp == ApplyInterpolationWhen.ALL
-def test_two_point_theory_source0_property(mock_source_pair):
+def test_two_point_theory_source0_property(mock_source_pair: tuple[Mock, Mock]) -> None:
"""Test source0 property returns first source."""
theory = TwoPointTheory(
sacc_data_type="galaxy_density_cl",
@@ -191,7 +173,7 @@ def test_two_point_theory_source0_property(mock_source_pair):
assert theory.source0 == mock_source_pair[0]
-def test_two_point_theory_source1_property(mock_source_pair):
+def test_two_point_theory_source1_property(mock_source_pair: tuple[Mock, Mock]) -> None:
"""Test source1 property returns second source."""
theory = TwoPointTheory(
sacc_data_type="galaxy_density_cl",
@@ -201,7 +183,7 @@ def test_two_point_theory_source1_property(mock_source_pair):
assert theory.source1 == mock_source_pair[1]
-def test_two_point_theory_update(mock_source_pair):
+def test_two_point_theory_update(mock_source_pair: tuple[Mock, Mock]) -> None:
"""Test update method calls update on sources."""
theory = TwoPointTheory(
sacc_data_type="galaxy_density_cl",
@@ -216,7 +198,7 @@ def test_two_point_theory_update(mock_source_pair):
assert mock_source_pair[1].is_updated()
-def test_two_point_theory_reset(mock_source_pair):
+def test_two_point_theory_reset(mock_source_pair: tuple[Mock, Mock]) -> None:
"""Test reset method calls reset on sources."""
theory = TwoPointTheory(
sacc_data_type="galaxy_density_cl",
@@ -236,7 +218,7 @@ def test_two_point_theory_reset(mock_source_pair):
assert not mock_source_pair[1].is_updated()
-def test_two_point_theory_initialize_sources_different_sources():
+def test_two_point_theory_initialize_sources_different_sources() -> None:
"""Test initialize_sources with two different sources."""
source1 = Mock()
source1.sacc_tracer = "tracer_1"
@@ -256,7 +238,7 @@ def test_two_point_theory_initialize_sources_different_sources():
assert theory.sacc_tracers == TracerNames("tracer_1", "tracer_2")
-def test_two_point_theory_initialize_sources_same_source():
+def test_two_point_theory_initialize_sources_same_source() -> None:
"""Test initialize_sources with the same source for both."""
source = Mock()
source.sacc_tracer = "tracer_1"
@@ -274,7 +256,7 @@ def test_two_point_theory_initialize_sources_same_source():
assert theory.sacc_tracers == TracerNames("tracer_1", "tracer_1")
-def test_two_point_theory_get_tracers_and_scales_different_sources():
+def test_two_point_theory_get_tracers_and_scales_different_sources() -> None:
"""Test get_tracers_and_scales with different sources."""
source1 = Mock()
source1_tracers = [Mock(), Mock()]
@@ -300,7 +282,7 @@ def test_two_point_theory_get_tracers_and_scales_different_sources():
assert scale1 == 2.0
-def test_two_point_theory_get_tracers_and_scales_same_source():
+def test_two_point_theory_get_tracers_and_scales_same_source() -> None:
"""Test get_tracers_and_scales with the same source."""
source = Mock()
source_tracers = [Mock(), Mock()]
@@ -325,7 +307,7 @@ def test_two_point_theory_get_tracers_and_scales_same_source():
assert scale1 == 1.5
-def test_two_point_theory_generate_ells_for_interpolation():
+def test_two_point_theory_generate_ells_for_interpolation() -> None:
"""Test generate_ells_for_interpolation method."""
source1 = Mock()
source2 = Mock()
diff --git a/tests/test_base_likelihood.py b/tests/test_base_likelihood.py
index 7ecfa11e8..664eaec28 100644
--- a/tests/test_base_likelihood.py
+++ b/tests/test_base_likelihood.py
@@ -3,24 +3,27 @@
"""
import numpy as np
+import numpy.typing as npt
import pytest
+import sacc
import firecrown.likelihood._likelihood as lk
+from firecrown.modeling_tools import ModelingTools
class MinimalLikelihood(lk.Likelihood):
"""A likelihood implementing every method of the base class trivially."""
- def compute_loglike(self, _):
+ def compute_loglike(self, _: ModelingTools) -> float:
return -1.0
- def read(self, _):
+ def read(self, _: sacc.Sacc) -> None:
pass
- def make_realization_vector(self):
+ def make_realization_vector(self) -> npt.NDArray[np.float64]:
return np.zeros(0)
-def test_unimplemented_make_realization_vector():
+def test_unimplemented_make_realization_vector() -> None:
with pytest.raises(NotImplementedError):
lk.Likelihood.make_realization_vector(MinimalLikelihood())
diff --git a/tests/test_bug_413.py b/tests/test_bug_413.py
index 4c92a60e3..40c44b724 100644
--- a/tests/test_bug_413.py
+++ b/tests/test_bug_413.py
@@ -2,6 +2,8 @@
from typing import Tuple
+import numpy as np
+import numpy.typing as npt
import pyccl
import sacc
@@ -76,7 +78,14 @@ def make_twopoint_with_optional_systematics(
return a, b, statistic, tools
-def test_calculate_pk(sacc_galaxy_xis_lens0_lens1):
+def test_calculate_pk(
+ sacc_galaxy_xis_lens0_lens1: tuple[
+ sacc.Sacc,
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ ],
+) -> None:
# Set up a TwoPoint object in which the first source has a PT systematic
# and the second source doe not have a PT systematic.
diff --git a/tests/test_ccl_factory_deprecated.py b/tests/test_ccl_factory_deprecated.py
index 6b5e24a4d..fd2c29610 100644
--- a/tests/test_ccl_factory_deprecated.py
+++ b/tests/test_ccl_factory_deprecated.py
@@ -14,7 +14,7 @@
import pytest
-def test_ccl_factory_deprecation_warning():
+def test_ccl_factory_deprecation_warning() -> None:
"""Test that importing ccl_factory emits DeprecationWarning.
This must be the first test that imports the module, as subsequent imports
@@ -34,7 +34,7 @@ def test_ccl_factory_deprecation_warning():
assert firecrown.ccl_factory is not None # Verify import succeeded
-def test_ccl_factory_deprecation_warning_content():
+def test_ccl_factory_deprecation_warning_content() -> None:
"""Test the deprecation warning mentions modeling_tools.
This test relies on module caching, so it won't see the warning.
@@ -48,7 +48,7 @@ def test_ccl_factory_deprecation_warning_content():
# If we get here without error, the import worked
-def test_all_items_importable():
+def test_all_items_importable() -> None:
"""Test that all __all__ items can be imported from deprecated package."""
# pylint: disable=import-outside-toplevel
from firecrown.ccl_factory import (
@@ -81,7 +81,7 @@ def test_all_items_importable():
@pytest.mark.filterwarnings(
r"ignore:firecrown\.ccl_factory is deprecated.*:DeprecationWarning"
)
-def test_items_identical_to_new_location():
+def test_items_identical_to_new_location() -> None:
"""Test that imported items are the same objects as in modeling_tools."""
# pylint: disable=import-outside-toplevel
# Import from both locations
@@ -141,7 +141,7 @@ def test_items_identical_to_new_location():
assert OldPowerSpec is PowerSpec
-def test_module_import_as_alias():
+def test_module_import_as_alias() -> None:
"""Test importing the module with an alias."""
# pylint: disable=import-outside-toplevel
import firecrown.ccl_factory as fac
@@ -152,7 +152,7 @@ def test_module_import_as_alias():
assert hasattr(fac, "CCLCreationMode")
-def test_ccl_factory_all_list():
+def test_ccl_factory_all_list() -> None:
"""Test that __all__ is preserved in deprecated module."""
# pylint: disable=import-outside-toplevel
import firecrown.ccl_factory
@@ -173,7 +173,7 @@ def test_ccl_factory_all_list():
assert set(firecrown.ccl_factory.__all__) == set(expected_all)
-def test_ccl_factory_functional():
+def test_ccl_factory_functional() -> None:
"""Test that CCLFactory from deprecated module is functional."""
# pylint: disable=import-outside-toplevel
from firecrown.ccl_factory import CCLFactory, PoweSpecAmplitudeParameter
diff --git a/tests/test_cmb_factories.py b/tests/test_cmb_factories.py
index ddb500b2c..744241000 100644
--- a/tests/test_cmb_factories.py
+++ b/tests/test_cmb_factories.py
@@ -15,7 +15,7 @@
from firecrown.updatable import ParamsMap
-def test_cmb_convergence_args():
+def test_cmb_convergence_args() -> None:
"""Test CMBConvergenceArgs creation and properties."""
args = CMBConvergenceArgs(scale=2.0, field="delta_matter", z_source=1090.0)
@@ -24,7 +24,7 @@ def test_cmb_convergence_args():
assert args.z_source == 1090.0
-def test_cmb_convergence_init():
+def test_cmb_convergence_init() -> None:
"""Test CMBConvergence initialization."""
cmb_conv = CMBConvergence(sacc_tracer="cmb", scale=1.5, z_source=1090.0)
@@ -34,7 +34,7 @@ def test_cmb_convergence_init():
assert cmb_conv.current_tracer_args is None
-def test_cmb_convergence_create_ready():
+def test_cmb_convergence_create_ready() -> None:
"""Test CMBConvergence.create_ready method."""
cmb_conv = CMBConvergence.create_ready(
sacc_tracer="cmb", scale=2.0, z_source=1090.0
@@ -48,7 +48,7 @@ def test_cmb_convergence_create_ready():
assert cmb_conv.tracer_args.z_source == 1090.0
-def test_cmb_convergence_read_systematics():
+def test_cmb_convergence_read_systematics() -> None:
"""Test that read_systematics does nothing for CMB sources."""
cmb_conv = CMBConvergence(sacc_tracer="cmb")
@@ -59,9 +59,9 @@ def test_cmb_convergence_read_systematics():
cmb_conv.read_systematics(mock_sacc)
-def test_cmb_convergence_read(sacc_galaxy_cells_src0_src0):
+def test_cmb_convergence_read() -> None:
"""Test CMBConvergence _read method."""
- sacc_data, _, _ = sacc_galaxy_cells_src0_src0
+ sacc_data = sacc.Sacc()
cmb_conv = CMBConvergence.create_ready(sacc_tracer="cmb", scale=1.0)
@@ -72,7 +72,7 @@ def test_cmb_convergence_read(sacc_galaxy_cells_src0_src0):
assert cmb_conv.tracer_args.field == "delta_matter"
-def test_cmb_convergence_read_missing_tracer_args():
+def test_cmb_convergence_read_missing_tracer_args() -> None:
"""Test that _read properly initializes tracer_args."""
cmb_conv = CMBConvergence(sacc_tracer="cmb", scale=2.0, z_source=1090.0)
@@ -92,7 +92,9 @@ def test_cmb_convergence_read_missing_tracer_args():
assert cmb_conv.tracer_args.field == "delta_matter"
-def test_cmb_convergence_create_tracers(tools_with_vanilla_cosmology: ModelingTools):
+def test_cmb_convergence_create_tracers(
+ tools_with_vanilla_cosmology: ModelingTools,
+) -> None:
"""Test CMBConvergence create_tracers method."""
cmb_conv = CMBConvergence.create_ready(
sacc_tracer="cmb", scale=1.0, z_source=1100.0
@@ -108,7 +110,7 @@ def test_cmb_convergence_create_tracers(tools_with_vanilla_cosmology: ModelingTo
assert cmb_conv.current_tracer_args == tracer_args
-def test_cmb_convergence_get_scale():
+def test_cmb_convergence_get_scale() -> None:
"""Test CMBConvergence get_scale method."""
cmb_conv = CMBConvergence.create_ready(sacc_tracer="cmb", scale=2.5)
@@ -122,7 +124,7 @@ def test_cmb_convergence_get_scale():
assert cmb_conv.get_scale() == 2.5
-def test_cmb_convergence_factory_init():
+def test_cmb_convergence_factory_init() -> None:
"""Test CMBConvergenceFactory initialization."""
factory = CMBConvergenceFactory(z_source=1090.0, scale=2.0)
@@ -131,7 +133,7 @@ def test_cmb_convergence_factory_init():
assert not factory._cache # pylint: disable=protected-access
-def test_cmb_convergence_factory_create():
+def test_cmb_convergence_factory_create() -> None:
"""Test CMBConvergenceFactory create method."""
factory = CMBConvergenceFactory(z_source=1090.0, scale=1.5)
@@ -149,7 +151,7 @@ def test_cmb_convergence_factory_create():
assert cmb_conv.z_source == 1090.0
-def test_cmb_convergence_factory_create_caching():
+def test_cmb_convergence_factory_create_caching() -> None:
"""Test that CMBConvergenceFactory caches created objects."""
factory = CMBConvergenceFactory()
@@ -166,7 +168,7 @@ def test_cmb_convergence_factory_create_caching():
assert cmb_conv1 is cmb_conv2
-def test_cmb_convergence_factory_create_from_metadata_only():
+def test_cmb_convergence_factory_create_from_metadata_only() -> None:
"""Test CMBConvergenceFactory create_from_metadata_only method."""
factory = CMBConvergenceFactory(z_source=1100.0, scale=1.0)
@@ -177,7 +179,7 @@ def test_cmb_convergence_factory_create_from_metadata_only():
assert cmb_conv.z_source == 1100.0
-def test_cmb_convergence_factory_create_from_metadata_caching():
+def test_cmb_convergence_factory_create_from_metadata_caching() -> None:
"""Test that create_from_metadata_only also uses caching."""
factory = CMBConvergenceFactory()
@@ -188,7 +190,7 @@ def test_cmb_convergence_factory_create_from_metadata_caching():
assert cmb_conv1 is cmb_conv2
-def test_cmb_convergence_no_systematics():
+def test_cmb_convergence_no_systematics() -> None:
"""Test that CMB sources have no systematics."""
cmb_conv = CMBConvergence(sacc_tracer="cmb")
@@ -196,7 +198,7 @@ def test_cmb_convergence_no_systematics():
assert not hasattr(cmb_conv, "systematics")
-def test_cmb_convergence_update_params():
+def test_cmb_convergence_update_params() -> None:
"""Test that CMBConvergence can handle parameter updates."""
cmb_conv = CMBConvergence.create_ready(sacc_tracer="cmb")
@@ -206,7 +208,7 @@ def test_cmb_convergence_update_params():
cmb_conv.update(params)
-def test_cmb_convergence_args_immutable():
+def test_cmb_convergence_args_immutable() -> None:
"""Test that CMBConvergenceArgs is immutable."""
args = CMBConvergenceArgs(scale=1.0)
@@ -215,7 +217,7 @@ def test_cmb_convergence_args_immutable():
args.scale = 2.0 # type: ignore[misc]
-def test_cmb_convergence_factory_different_params():
+def test_cmb_convergence_factory_different_params() -> None:
"""Test factory with different parameters creates different objects."""
factory1 = CMBConvergenceFactory(z_source=1090.0, scale=1.0)
factory2 = CMBConvergenceFactory(z_source=1100.0, scale=2.0)
@@ -238,7 +240,7 @@ def test_cmb_convergence_factory_different_params():
@pytest.mark.parametrize("z_source", [1090.0, 1100.0, 1110.0])
def test_cmb_convergence_different_z_source(
z_source: float, tools_with_vanilla_cosmology: ModelingTools
-):
+) -> None:
"""Test CMBConvergence with different z_source values."""
cmb_conv = CMBConvergence.create_ready(sacc_tracer="cmb", z_source=z_source)
@@ -249,7 +251,7 @@ def test_cmb_convergence_different_z_source(
@pytest.mark.parametrize("scale", [0.5, 1.0, 1.5, 2.0])
-def test_cmb_convergence_different_scales(scale: float):
+def test_cmb_convergence_different_scales(scale: float) -> None:
"""Test CMBConvergence with different scale values."""
cmb_conv = CMBConvergence.create_ready(sacc_tracer="cmb", scale=scale)
diff --git a/tests/test_data_functions.py b/tests/test_data_functions.py
index 04c0c4ac2..0131dbbdd 100644
--- a/tests/test_data_functions.py
+++ b/tests/test_data_functions.py
@@ -23,8 +23,12 @@
],
)
def test_ensure_no_overlaps(
- measurement, index_set, index_sets, other_measurements, expected_result
-):
+ measurement: str,
+ index_set: set[int],
+ index_sets: list[set[int]],
+ other_measurements: list[str],
+ expected_result: type[ValueError] | None,
+) -> None:
if expected_result is None:
ensure_no_overlaps(measurement, index_set, index_sets, other_measurements)
else:
@@ -34,12 +38,12 @@ def test_ensure_no_overlaps(
# Additional test for empty other_measurements and index_sets
-def test_empty_other_measurements_and_index_sets():
+def test_empty_other_measurements_and_index_sets() -> None:
ensure_no_overlaps("A", {1, 2}, [], [])
# Additional test for overlap with the last set in the list
-def test_overlap_with_last_set():
+def test_overlap_with_last_set() -> None:
with pytest.raises(ValueError) as excinfo:
ensure_no_overlaps("A", {1}, [{3, 4}, {5, 6}, {1, 7}], ["B", "C", "D"])
assert "overlap" in str(excinfo.value), "Error message should contain 'overlap'"
@@ -47,10 +51,10 @@ def test_overlap_with_last_set():
# Test for edge case where the index_set is empty but there are non-empty set
# in index_sets
-def test_empty_index_set_with_non_empty_index_sets():
+def test_empty_index_set_with_non_empty_index_sets() -> None:
ensure_no_overlaps("A", set(), [{1}, {2}], ["B", "C"])
# Test for edge case where all sets are empty
-def test_all_sets_empty():
+def test_all_sets_empty() -> None:
ensure_no_overlaps("A", set(), [set(), set()], ["B", "C"])
diff --git a/tests/test_descriptors.py b/tests/test_descriptors.py
index d7025246d..802d42f83 100644
--- a/tests/test_descriptors.py
+++ b/tests/test_descriptors.py
@@ -18,7 +18,7 @@ class HasUOF:
x = TypeFloat(allow_none=True)
- def __init__(self):
+ def __init__(self) -> None:
"""Initialize a HasUOF object with default value `self.x=None`."""
self.x = None
@@ -28,7 +28,7 @@ class HasCOF:
x = TypeFloat(1.0, 3.0, allow_none=True)
- def __init__(self):
+ def __init__(self) -> None:
"""Initialize a HasCOF object with default value of `self.x=None`."""
self.x = None
@@ -38,7 +38,7 @@ class HasURF:
x = TypeFloat()
- def __init__(self):
+ def __init__(self) -> None:
"""Initialize a HasURF object with default value `self.x=0.0`."""
self.x = 0.0
@@ -48,7 +48,7 @@ class HasCRF:
x = TypeFloat(1.0, 3.0)
- def __init__(self):
+ def __init__(self) -> None:
"""Initialize a HasCRF with the default value `self.x=2.0`."""
self.x = 2.0
@@ -58,7 +58,7 @@ class HasLowerBound:
x = TypeFloat(minvalue=0.0)
- def __init__(self):
+ def __init__(self) -> None:
"""Initialize a HasLowerBound object with the default value
`self.x=0.0`."""
self.x = 0.0
@@ -69,7 +69,7 @@ class HasUpperBound:
x = TypeFloat(maxvalue=1.0)
- def __init__(self):
+ def __init__(self) -> None:
"""Initialize a HasUpperBound object with the default value
`self.x=1.0`."""
self.x = 1.0
@@ -78,7 +78,8 @@ def __init__(self):
class NotStringy:
"""A class that can not be turned into a string."""
- def __str__(self):
+ # This negative-test double deliberately violates object.__str__'s str contract.
+ def __str__(self) -> None: # type: ignore[override]
"""Does not return a string"""
@@ -112,7 +113,7 @@ class StartsWithCow:
x = TypeString(predicate=lambda s: s.startswith("cow"))
-def test_unconstrained_optional_float():
+def test_unconstrained_optional_float() -> None:
d = HasUOF()
with pytest.raises(TypeError):
d.x = 3 # not a literal float
@@ -128,7 +129,7 @@ def test_unconstrained_optional_float():
assert d.x == math.inf
-def test_constrained_optional_float():
+def test_constrained_optional_float() -> None:
d = HasCOF()
with pytest.raises(TypeError):
d.x = 3 # not a literal float
@@ -149,7 +150,7 @@ def test_constrained_optional_float():
assert d.x == 3.0
-def test_unconstrained_required_float():
+def test_unconstrained_required_float() -> None:
d = HasURF()
with pytest.raises(TypeError):
d.x = 3 # not a literal float
@@ -163,7 +164,7 @@ def test_unconstrained_required_float():
assert d.x == math.inf
-def test_constrained_required_float():
+def test_constrained_required_float() -> None:
d = HasCRF()
with pytest.raises(TypeError):
d.x = 3 # not a literal float
@@ -184,7 +185,7 @@ def test_constrained_required_float():
assert d.x == 3.0
-def test_lower_bound_float():
+def test_lower_bound_float() -> None:
d = HasLowerBound()
assert d.x == 0.0
@@ -203,7 +204,7 @@ def test_lower_bound_float():
assert d.x == math.inf
-def test_upper_bound_float():
+def test_upper_bound_float() -> None:
d = HasUpperBound()
assert d.x == 1.0
@@ -218,14 +219,14 @@ def test_upper_bound_float():
assert d.x == -math.inf
-def test_reading_string():
+def test_reading_string() -> None:
d = HasString()
d.x = "cow"
assert d.x == "cow"
-def test_string_conversion_failure():
+def test_string_conversion_failure() -> None:
d = HasString()
with pytest.raises(TypeError):
# We ignore type checking on this line because we are testing the error
@@ -233,21 +234,21 @@ def test_string_conversion_failure():
d.x = NotStringy() # type: ignore
-def test_string_too_short():
+def test_string_too_short() -> None:
d = HasShortBound()
d.x = "walrus"
with pytest.raises(ValueError):
d.x = "cow"
-def test_string_too_long():
+def test_string_too_long() -> None:
d = HasLongBound()
d.x = "ou"
with pytest.raises(ValueError):
d.x = "cow"
-def test_string_predicate():
+def test_string_predicate() -> None:
d = StartsWithCow()
d.x = "cowabunga"
with pytest.raises(ValueError):
@@ -255,7 +256,7 @@ def test_string_predicate():
# Tests for _base module
-def test_base_module_exports_math():
+def test_base_module_exports_math() -> None:
"""Test that _base module exports math."""
# Import the module to ensure coverage
# pylint: disable=import-outside-toplevel
@@ -267,7 +268,7 @@ def test_base_module_exports_math():
assert "math" in base_module.__all__
-def test_base_module_exports_callable():
+def test_base_module_exports_callable() -> None:
"""Test that _base module exports Callable."""
# Import the module to ensure coverage
# pylint: disable=import-outside-toplevel
diff --git a/tests/test_fctools_refactor.py b/tests/test_fctools_refactor.py
index 13a99ac37..0ffc82c60 100644
--- a/tests/test_fctools_refactor.py
+++ b/tests/test_fctools_refactor.py
@@ -7,6 +7,7 @@
import contextlib
import io
import json
+from pathlib import Path
from rich.console import Console
@@ -14,7 +15,7 @@
from firecrown.fctools import print_code as pc
-def test_parse_duration_line(tmp_path):
+def test_parse_duration_line(tmp_path: Path) -> None:
# private helper is nested; test via the public parse_timing_data API
console = Console()
tmp = tmp_path / "tmp_test_durations.txt"
@@ -28,7 +29,7 @@ def test_parse_duration_line(tmp_path):
assert timings["tests/test_mod.py::test_func"] == 0.12
-def test_load_json_timing(tmp_path):
+def test_load_json_timing(tmp_path: Path) -> None:
console = Console()
data = {"tests": [{"nodeid": "tests/t.py::test_a", "duration": 0.5}]}
p = tmp_path / "t.json"
@@ -46,7 +47,7 @@ class Dummy:
A = 1
-def test_build_class_code():
+def test_build_class_code() -> None:
# Capture stdout of the public display function and assert the content
buf = io.StringIO()
with contextlib.redirect_stdout(buf):
diff --git a/tests/test_hm_systematics.py b/tests/test_hm_systematics.py
index 92f7392e4..7a9575645 100644
--- a/tests/test_hm_systematics.py
+++ b/tests/test_hm_systematics.py
@@ -41,7 +41,9 @@ def fixture_sacc_data() -> sacc.Sacc:
@pytest.mark.slow
-def test_hm_systematics(weak_lensing_source, sacc_data):
+def test_hm_systematics(
+ weak_lensing_source: wl.WeakLensing, sacc_data: sacc.Sacc
+) -> None:
# The following disabling of pylint warnings are TEMPORARY. Disabling warnings is
# generally not a good practice. In this case, the warnings are indicating that this
# test is too complicated.
diff --git a/tests/test_likelihood_factories_two_point.py b/tests/test_likelihood_factories_two_point.py
index 6efeb5ea3..6d9a2c709 100644
--- a/tests/test_likelihood_factories_two_point.py
+++ b/tests/test_likelihood_factories_two_point.py
@@ -7,7 +7,7 @@
"""
-def test_two_point_factory_importable():
+def test_two_point_factory_importable() -> None:
"""Verify TwoPointFactory is importable from firecrown.likelihood.factories."""
# pylint: disable=import-outside-toplevel
from firecrown.likelihood.factories import TwoPointFactory
@@ -15,7 +15,7 @@ def test_two_point_factory_importable():
assert TwoPointFactory is not None
-def test_two_point_factory_identical_to_likelihood():
+def test_two_point_factory_identical_to_likelihood() -> None:
"""Verify TwoPointFactory from factories is identical to firecrown.likelihood."""
# pylint: disable=import-outside-toplevel
from firecrown.likelihood import TwoPointFactory
@@ -24,7 +24,7 @@ def test_two_point_factory_identical_to_likelihood():
assert FactoriesTWPF is TwoPointFactory
-def test_two_point_factory_in_all():
+def test_two_point_factory_in_all() -> None:
"""Verify TwoPointFactory is listed in __all__ of firecrown.likelihood.factories."""
# pylint: disable=import-outside-toplevel
import firecrown.likelihood.factories as factories_module
@@ -32,7 +32,7 @@ def test_two_point_factory_in_all():
assert "TwoPointFactory" in factories_module.__all__
-def test_two_point_factory_is_pydantic_model():
+def test_two_point_factory_is_pydantic_model() -> None:
"""Verify TwoPointFactory is a Pydantic BaseModel subclass."""
# pylint: disable=import-outside-toplevel
from pydantic import BaseModel
@@ -42,7 +42,7 @@ def test_two_point_factory_is_pydantic_model():
assert issubclass(TwoPointFactory, BaseModel)
-def test_two_point_factory_has_correlation_space_field():
+def test_two_point_factory_has_correlation_space_field() -> None:
"""Verify TwoPointFactory exposes the correlation_space field."""
# pylint: disable=import-outside-toplevel
from firecrown.likelihood.factories import TwoPointFactory
diff --git a/tests/test_likelihood_gaussian_deprecated.py b/tests/test_likelihood_gaussian_deprecated.py
index e6fc46b2d..9ee52e62c 100644
--- a/tests/test_likelihood_gaussian_deprecated.py
+++ b/tests/test_likelihood_gaussian_deprecated.py
@@ -14,7 +14,7 @@
import pytest
-def test_gaussian_deprecation_warning():
+def test_gaussian_deprecation_warning() -> None:
"""Importing firecrown.likelihood.gaussian emits a DeprecationWarning.
This must be the first test that imports the module, as subsequent imports
@@ -31,7 +31,7 @@ def test_gaussian_deprecation_warning():
import firecrown.likelihood.gaussian # noqa: F401
-def test_const_gaussian_importable():
+def test_const_gaussian_importable() -> None:
"""Verify ConstGaussian is importable from the deprecated module."""
# pylint: disable=import-outside-toplevel
from firecrown.likelihood.gaussian import ConstGaussian
@@ -39,7 +39,7 @@ def test_const_gaussian_importable():
assert ConstGaussian is not None
-def test_const_gaussian_identical_to_new_location():
+def test_const_gaussian_identical_to_new_location() -> None:
"""Verify ConstGaussian from deprecated module is the same as from _gaussian."""
# pylint: disable=import-outside-toplevel
from firecrown.likelihood._gaussian import ConstGaussian
@@ -48,7 +48,7 @@ def test_const_gaussian_identical_to_new_location():
assert OldConstGaussian is ConstGaussian
-def test_const_gaussian_in_all():
+def test_const_gaussian_in_all() -> None:
"""Verify ConstGaussian is listed in __all__ of the deprecated module."""
# pylint: disable=import-outside-toplevel
import firecrown.likelihood.gaussian as gaussian_module
diff --git a/tests/test_modeling_tools.py b/tests/test_modeling_tools.py
index f67fff4cd..eb5743352 100644
--- a/tests/test_modeling_tools.py
+++ b/tests/test_modeling_tools.py
@@ -151,7 +151,7 @@ def test_modeling_tools_get_cM_relation_with_setting() -> None:
class DummyPowerspectrumModifier(PowerspectrumModifier):
"""Dummy power spectrum modifier for testing."""
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
self.name = "dummy:dummy"
diff --git a/tests/test_modeling_tools_ccl_factory.py b/tests/test_modeling_tools_ccl_factory.py
index 0e58893f3..af276c416 100644
--- a/tests/test_modeling_tools_ccl_factory.py
+++ b/tests/test_modeling_tools_ccl_factory.py
@@ -2,6 +2,7 @@
import itertools as it
import re
+from typing import cast
import numpy as np
import pyccl
@@ -29,12 +30,14 @@
@pytest.fixture(name="amplitude_parameter", params=list(PoweSpecAmplitudeParameter))
-def fixture_amplitude_parameter(request):
+def fixture_amplitude_parameter(
+ request: pytest.FixtureRequest,
+) -> PoweSpecAmplitudeParameter:
return request.param
@pytest.fixture(name="neutrino_mass_splits", params=list(NeutrinoMassSplits))
-def fixture_neutrino_mass_splits(request):
+def fixture_neutrino_mass_splits(request: pytest.FixtureRequest) -> NeutrinoMassSplits:
return request.param
@@ -43,7 +46,7 @@ def fixture_neutrino_mass_splits(request):
params=[True, False],
ids=["require_nonlinear_pk", "no_require_nonlinear_pk"],
)
-def fixture_require_nonlinear_pk(request):
+def fixture_require_nonlinear_pk(request: pytest.FixtureRequest) -> bool:
return request.param
@@ -55,7 +58,7 @@ def fixture_require_nonlinear_pk(request):
CCLCreationMode.MU_SIGMA_ISITGR,
],
)
-def fixture_ccl_creation_mode(request) -> CCLCreationMode:
+def fixture_ccl_creation_mode(request: pytest.FixtureRequest) -> CCLCreationMode:
"""Fixture providing each CCLCreationMode."""
return request.param
@@ -71,7 +74,9 @@ def fixture_ccl_creation_mode(request) -> CCLCreationMode:
],
ids=["no_camb", "mead", "mead_kmax", "mead_kmax_lmax", "ppf"],
)
-def fixture_camb_extra_params(request) -> CAMBExtraParams | None:
+def fixture_camb_extra_params(
+ request: pytest.FixtureRequest,
+) -> CAMBExtraParams | None:
"""Fixture providing each possible CAMBExtraParams configuration."""
if request.param is not None:
return CAMBExtraParams.model_validate(request.param)
@@ -109,7 +114,9 @@ def fixture_camb_extra_params(request) -> CAMBExtraParams | None:
],
ids=lambda x: x[2], # Use the third element (id string) as the test id
)
-def fixture_ccl_creation_mode_and_camb_params(request):
+def fixture_ccl_creation_mode_and_camb_params(
+ request: pytest.FixtureRequest,
+) -> tuple[CCLCreationMode, CAMBExtraParams | None]:
"""Provides valid combinations of creation mode and CAMB params.
CAMB extra parameters are only compatible with PURE_CCL_MODE, so this
@@ -132,7 +139,9 @@ def fixture_ccl_creation_mode_and_camb_params(request):
params=[None, {"a_spline_na": 451}],
ids=["default", "set_a_spline_na"],
)
-def fixture_ccl_spline_params(request) -> CCLSplineParams | None:
+def fixture_ccl_spline_params(
+ request: pytest.FixtureRequest,
+) -> CCLSplineParams | None:
return CCLSplineParams(**request.param) if request.param is not None else None
@@ -173,7 +182,7 @@ def fixture_ccl_spline_params(request) -> CCLSplineParams | None:
params=[BACKGROUND, BACKGROUND | PK_LINEAR, BACKGROUND | PK_LINEAR | PK_NONLIN],
ids=["background", "background_linear_pk", "background_linear_pk_nonlinear_pk"],
)
-def fixture_calculator_args(request) -> CCLCalculatorArgs:
+def fixture_calculator_args(request: pytest.FixtureRequest) -> CCLCalculatorArgs:
return request.param
@@ -202,7 +211,9 @@ def fixture_calculator_args(request) -> CCLCalculatorArgs:
],
ids=lambda x: x[2], # Use the third element (id string) as the test id
)
-def fixture_require_nonlinear_pk_and_calculator_args(request):
+def fixture_require_nonlinear_pk_and_calculator_args(
+ request: pytest.FixtureRequest,
+) -> tuple[bool, CCLCalculatorArgs]:
"""Fixture providing valid combinations of require_nonlinear_pk and calculator_args.
Nonlinear PK requires linear PK to be present, so this fixture only generates
@@ -219,7 +230,9 @@ def fixture_require_nonlinear_pk_and_calculator_args(request):
"transfer_function",
list(CCLPureModeTransferFunction),
)
-def test_ccl_factory_pure_mode_transfer_function(transfer_function):
+def test_ccl_factory_pure_mode_transfer_function(
+ transfer_function: CCLPureModeTransferFunction,
+) -> None:
ccl_factory = CCLFactory(
creation_mode=CCLCreationMode.PURE_CCL_MODE,
pure_ccl_transfer_function=transfer_function,
@@ -233,7 +246,7 @@ def test_ccl_factory_pure_mode_transfer_function(transfer_function):
assert isinstance(cosmo, pyccl.Cosmology)
-def test_ccl_factory_invalid_pure_mode_transfer_function():
+def test_ccl_factory_invalid_pure_mode_transfer_function() -> None:
with pytest.raises(ValueError, match="is not a valid CCLPureModeTransferFunction"):
CCLFactory(
creation_mode=CCLCreationMode.PURE_CCL_MODE,
@@ -249,7 +262,7 @@ def test_setting_each_spline_param(
# param_value to be tested.
ccl_creation_mode, camb_extra_params = ccl_creation_mode_and_camb_params
- def test_helper(param_name: str, param_value: float | int):
+ def test_helper(param_name: str, param_value: float | int) -> None:
# Using combined fixture ensures only valid combinations are tested
original_param_value = getattr(pyccl.spline_params, param_name.upper())
args = {param_name: param_value}
@@ -302,7 +315,7 @@ def test_helper(param_name: str, param_value: float | int):
test_helper("n_ell_corr", 4444)
-def test_ccl_spline_params_validation():
+def test_ccl_spline_params_validation() -> None:
with pytest.raises(pydantic.ValidationError):
_ = CCLSplineParams(logm_spline_min=20, logm_spline_max=10)
with pytest.raises(pydantic.ValidationError):
@@ -311,7 +324,7 @@ def test_ccl_spline_params_validation():
_ = CCLSplineParams(ell_min_corr=100, ell_max_corr=10)
-def test_ccl_spline_params_context_manager_exception():
+def test_ccl_spline_params_context_manager_exception() -> None:
with CCLSplineParams(k_max=900) as params:
assert params.k_max == 900
with pytest.raises(AssertionError):
@@ -319,7 +332,7 @@ def test_ccl_spline_params_context_manager_exception():
assert False
-def _nu_mass_is_list(mass_split: NeutrinoMassSplits):
+def _nu_mass_is_list(mass_split: NeutrinoMassSplits) -> bool:
"""Check if the neutrino mass split is a list.
This function is used to check if the neutrino mass split is a list or a sum.
@@ -845,7 +858,7 @@ def test_ccl_factory_invalid_extra_params() -> None:
CCLFactory(not_a_valid_param="Im not a valid value")
-def test_validate_creation_mode_incompatible():
+def test_validate_creation_mode_incompatible() -> None:
ccl_factory = CCLFactory(creation_mode=CCLCreationMode.PURE_CCL_MODE)
params = get_default_params_map(ccl_factory)
ccl_factory.update(params)
@@ -1171,7 +1184,11 @@ def test_camb_extra_params_set_hm_parameters_wrong_name() -> None:
),
],
)
-def test_ccl_factory_using_camb(creation_mode, transfer_function, expected):
+def test_ccl_factory_using_camb(
+ creation_mode: CCLCreationMode,
+ transfer_function: CCLPureModeTransferFunction,
+ expected: bool,
+) -> None:
factory = CCLFactory(
creation_mode=creation_mode,
pure_ccl_transfer_function=transfer_function,
@@ -1227,8 +1244,11 @@ def test_ccl_factory_using_camb(creation_mode, transfer_function, expected):
],
)
def test_ccl_factory_ccl_powerspectra(
- creation_mode, transfer_function, nonlinear_pk, matter_pk_str
-):
+ creation_mode: CCLCreationMode,
+ transfer_function: CCLPureModeTransferFunction,
+ nonlinear_pk: bool,
+ matter_pk_str: str,
+) -> None:
factory = CCLFactory(
creation_mode=creation_mode,
pure_ccl_transfer_function=transfer_function,
@@ -1248,7 +1268,11 @@ def test_ccl_factory_ccl_powerspectra(
[0.0, 0.1, 0.2], [(2.0e-9, None), (None, 0.81)], list(NeutrinoMassSplits)
),
)
-def test_ccl_factory_parameters_passthrough_all(m_nu, As_sigma8, mass_split) -> None:
+def test_ccl_factory_parameters_passthrough_all(
+ m_nu: float,
+ As_sigma8: tuple[float | None, float | None],
+ mass_split: NeutrinoMassSplits,
+) -> None:
"""Ensure all cosmology parameters provided by the user are passed through
unchanged to the created CCL cosmology when using the CCLFactory/ModelingTools
plumbing.
@@ -1259,7 +1283,7 @@ def test_ccl_factory_parameters_passthrough_all(m_nu, As_sigma8, mass_split) ->
specifically exercised since that was the reported failing case.
"""
As, sigma8 = As_sigma8
- cosmo_dict = {
+ cosmo_dict: dict[str, float | list[float]] = {
"Omega_c": 0.2906682,
"Omega_b": 0.04575,
"h": 0.6714,
@@ -1295,7 +1319,8 @@ def test_ccl_factory_parameters_passthrough_all(m_nu, As_sigma8, mass_split) ->
cosmo_dict["m_nu_2"] = 0.02
cosmo_dict["m_nu_3"] = 0.03
- tools.update(ParamsMap(cosmo_dict))
+ # At this point the list form of m_nu has not yet replaced its scalar form.
+ tools.update(ParamsMap(cast(dict[str, float], cosmo_dict)))
tools.prepare()
if m_nu_is_list:
diff --git a/tests/test_modeling_tools_deprecated.py b/tests/test_modeling_tools_deprecated.py
index ac891f19b..1565c6d87 100644
--- a/tests/test_modeling_tools_deprecated.py
+++ b/tests/test_modeling_tools_deprecated.py
@@ -13,7 +13,7 @@
from firecrown.modeling_tools import ModelingTools
-def test_no_deprecated_args_no_warning():
+def test_no_deprecated_args_no_warning() -> None:
"""Verify no DeprecationWarning is emitted without deprecated args."""
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
@@ -22,7 +22,7 @@ def test_no_deprecated_args_no_warning():
assert len(deprecations) == 0
-def test_cluster_abundance_none_warns():
+def test_cluster_abundance_none_warns() -> None:
"""Passing cluster_abundance=None emits a DeprecationWarning."""
with pytest.warns(
DeprecationWarning,
@@ -31,7 +31,7 @@ def test_cluster_abundance_none_warns():
ModelingTools(cluster_abundance=None)
-def test_cluster_deltasigma_none_warns():
+def test_cluster_deltasigma_none_warns() -> None:
"""Passing cluster_deltasigma=None emits a DeprecationWarning."""
with pytest.warns(
DeprecationWarning,
@@ -40,7 +40,7 @@ def test_cluster_deltasigma_none_warns():
ModelingTools(cluster_deltasigma=None)
-def test_both_deprecated_args_warn():
+def test_both_deprecated_args_warn() -> None:
"""Passing both deprecated args emits two DeprecationWarnings."""
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
@@ -52,7 +52,7 @@ def test_both_deprecated_args_warn():
assert any("cluster_deltasigma" in m for m in messages)
-def test_modeling_tools_still_functional_with_deprecated_args():
+def test_modeling_tools_still_functional_with_deprecated_args() -> None:
"""Verify ModelingTools is functional when constructed with deprecated args."""
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
diff --git a/tests/test_number_counts_factories.py b/tests/test_number_counts_factories.py
index b12138013..df1622830 100644
--- a/tests/test_number_counts_factories.py
+++ b/tests/test_number_counts_factories.py
@@ -32,7 +32,7 @@ def fixture_nc_sys_factory() -> nc_factories.NumberCountsSystematicFactory:
return nc_factories.PhotoZShiftFactory()
-def test_photozshift_not_applied_to_photometic_measurement():
+def test_photozshift_not_applied_to_photometic_measurement() -> None:
factory = nc_factories.PhotoZShiftFactory()
assert factory is not None
diff --git a/tests/test_number_counts_magnification_bias_systematic.py b/tests/test_number_counts_magnification_bias_systematic.py
index fdb80b808..e87e650eb 100644
--- a/tests/test_number_counts_magnification_bias_systematic.py
+++ b/tests/test_number_counts_magnification_bias_systematic.py
@@ -11,7 +11,7 @@
import firecrown.updatable as fp
-def test_creation_nc_magnification_bias_systematic():
+def test_creation_nc_magnification_bias_systematic() -> None:
sys = nc_sys.MagnificationBiasSystematic(sacc_tracer="lens0")
assert sys.parameter_prefix == "lens0"
assert sys.eta is None
@@ -23,7 +23,7 @@ def test_creation_nc_magnification_bias_systematic():
def test_update_nc_magnification_bias_systematic(
tools_with_vanilla_cosmology: mt.ModelingTools,
-):
+) -> None:
sys = nc_sys.MagnificationBiasSystematic(sacc_tracer="lens0")
assert sys.parameter_prefix == "lens0"
sys.update(
@@ -61,7 +61,7 @@ def test_update_nc_magnification_bias_systematic(
def test_update_nc_magnification_bias_systematic_with_mag_bias(
tools_with_vanilla_cosmology: mt.ModelingTools,
-):
+) -> None:
sys = nc_sys.MagnificationBiasSystematic(sacc_tracer="lens0")
assert sys.parameter_prefix == "lens0"
sys.update(
diff --git a/tests/test_number_counts_source.py b/tests/test_number_counts_source.py
index f85c2257c..42856fdf1 100644
--- a/tests/test_number_counts_source.py
+++ b/tests/test_number_counts_source.py
@@ -9,7 +9,7 @@
def test_get_derived_parameters(
harmonic_bin_1: mt.TomographicBin,
tools_with_vanilla_cosmology: mtools.ModelingTools,
-):
+) -> None:
ncs = nc.NumberCounts.create_ready(harmonic_bin_1, derived_scale=True)
ncs.update(updatable.ParamsMap({"bin_1_bias": 1.0}))
ncs.create_tracers(tools_with_vanilla_cosmology)
diff --git a/tests/test_parameters_deprecated.py b/tests/test_parameters_deprecated.py
index 54f18ab8e..ef27076c8 100644
--- a/tests/test_parameters_deprecated.py
+++ b/tests/test_parameters_deprecated.py
@@ -10,7 +10,7 @@
import pytest
-def test_parameters_module_emits_deprecation_warning():
+def test_parameters_module_emits_deprecation_warning() -> None:
"""Importing firecrown.parameters should emit a DeprecationWarning."""
# Remove the module from sys.modules if it's already imported
# so we can import it fresh and catch the warning
@@ -34,7 +34,7 @@ def test_parameters_module_emits_deprecation_warning():
assert "firecrown.updatable" in str(w[0].message)
-def test_parameters_exports_all_names():
+def test_parameters_exports_all_names() -> None:
"""All expected names should be available from firecrown.parameters."""
# pylint: disable=import-outside-toplevel
import firecrown.parameters as params
@@ -55,7 +55,7 @@ def test_parameters_exports_all_names():
assert hasattr(params, name), f"Missing export: {name}"
-def test_parameters_exports_are_same_as_updatable():
+def test_parameters_exports_are_same_as_updatable() -> None:
"""Exported names should be the same objects as in firecrown.updatable."""
# pylint: disable=import-outside-toplevel
import firecrown.parameters as params
@@ -81,7 +81,7 @@ def test_parameters_exports_are_same_as_updatable():
), f"{name} from parameters is not the same object as from updatable"
-def test_params_map_from_deprecated_module():
+def test_params_map_from_deprecated_module() -> None:
"""Ensure ParamsMap imported from deprecated module works correctly."""
# pylint: disable=import-outside-toplevel
from firecrown.parameters import ParamsMap
@@ -94,7 +94,7 @@ def test_params_map_from_deprecated_module():
@pytest.mark.filterwarnings(
r"ignore:.*firecrown\.parameters module is deprecated.*:DeprecationWarning"
)
-def test_required_parameters_from_deprecated_module():
+def test_required_parameters_from_deprecated_module() -> None:
"""Ensure RequiredParameters imported from deprecated module works correctly."""
# pylint: disable=import-outside-toplevel
from firecrown.parameters import RequiredParameters, SamplerParameter
@@ -109,7 +109,7 @@ def test_required_parameters_from_deprecated_module():
assert "param2" in req_params.get_params_names()
-def test_derived_parameter_from_deprecated_module():
+def test_derived_parameter_from_deprecated_module() -> None:
"""Ensure DerivedParameter imported from deprecated module works correctly."""
# pylint: disable=import-outside-toplevel
from firecrown.parameters import DerivedParameter
diff --git a/tests/test_pt_systematics.py b/tests/test_pt_systematics.py
index 7a1678d79..c685d4162 100644
--- a/tests/test_pt_systematics.py
+++ b/tests/test_pt_systematics.py
@@ -56,7 +56,11 @@ def fixture_sacc_data() -> sacc.Sacc:
return sacc.Sacc.load_fits(saccfile)
-def test_pt_systematics(weak_lensing_source, number_counts_source, sacc_data):
+def test_pt_systematics(
+ weak_lensing_source: wl.WeakLensing,
+ number_counts_source: nc.NumberCounts,
+ sacc_data: sacc.Sacc,
+) -> None:
# The following disabling of pylint warnings are TEMPORARY. Disabling warnings is
# generally not a good practice. In this case, the warnings are indicating that this
# test is too complicated.
@@ -253,7 +257,7 @@ def test_pt_systematics(weak_lensing_source, number_counts_source, sacc_data):
assert np.allclose(cl_gg_theory, cells_gg_total, atol=0, rtol=1e-7)
-def test_pt_mixed_systematics(sacc_data):
+def test_pt_mixed_systematics(sacc_data: sacc.Sacc) -> None:
# The following disabling of pylint warnings are TEMPORARY. Disabling warnings is
# generally not a good practice. In this case, the warnings are indicating that this
# test is too complicated.
@@ -385,7 +389,7 @@ def test_pt_mixed_systematics(sacc_data):
assert np.allclose(cl_gI, cells_gI, atol=0, rtol=1e-7)
-def test_pt_mixed_systematics_zdep(sacc_data):
+def test_pt_mixed_systematics_zdep(sacc_data: sacc.Sacc) -> None:
# The following disabling of pylint warnings are TEMPORARY. Disabling warnings is
# generally not a good practice. In this case, the warnings are indicating that this
# test is too complicated.
@@ -525,7 +529,11 @@ def test_pt_mixed_systematics_zdep(sacc_data):
assert np.allclose(cl_gI, cells_gI, atol=0, rtol=1e-7)
-def test_pt_systematics_zdep(weak_lensing_source, number_counts_source, sacc_data):
+def test_pt_systematics_zdep(
+ weak_lensing_source: wl.WeakLensing,
+ number_counts_source: nc.NumberCounts,
+ sacc_data: sacc.Sacc,
+) -> None:
# The following disabling of pylint warnings are TEMPORARY. Disabling warnings is
# generally not a good practice. In this case, the warnings are indicating that this
# test is too complicated.
@@ -730,7 +738,9 @@ def test_pt_systematics_zdep(weak_lensing_source, number_counts_source, sacc_dat
assert np.allclose(cl_gg_theory, cells_gg_total, atol=0, rtol=1e-7)
-def test_linear_bias_systematic(tools_with_vanilla_cosmology: ModelingTools):
+def test_linear_bias_systematic(
+ tools_with_vanilla_cosmology: ModelingTools,
+) -> None:
a = nc_sys.LinearBiasSystematic("xxx")
assert isinstance(a, nc_sys.LinearBiasSystematic)
assert a.parameter_prefix == "xxx"
diff --git a/tests/test_pyccl.py b/tests/test_pyccl.py
index 2eb8cedd5..736558fdd 100644
--- a/tests/test_pyccl.py
+++ b/tests/test_pyccl.py
@@ -11,30 +11,32 @@
@pytest.fixture(name="cosmo_params_1", scope="session")
-def fixture_cosmo_params_1():
+def fixture_cosmo_params_1() -> dict[str, float]:
return {"Omega_c": 0.0, "Omega_b": 0.0, "h": 1.0, "A_s": 0.0, "n_s": 0.0}
@pytest.fixture(name="cosmo_params_2", scope="session")
-def fixture_cosmo_params_2():
+def fixture_cosmo_params_2() -> dict[str, float]:
return {"Omega_c": 0.0, "Omega_b": 0.0, "h": 1.0, "A_s": 0.0, "n_s": 0.25}
-def test_alias_of_cosmology_hashes_equal(cosmo_params_1):
+def test_alias_of_cosmology_hashes_equal(cosmo_params_1: dict[str, float]) -> None:
x = pyccl.Cosmology(**cosmo_params_1)
y = x
assert x == y
assert hash(x) == hash(y)
-def test_unequal_cosmologies_hash_unequal(cosmo_params_1, cosmo_params_2):
+def test_unequal_cosmologies_hash_unequal(
+ cosmo_params_1: dict[str, float], cosmo_params_2: dict[str, float]
+) -> None:
x = pyccl.Cosmology(**cosmo_params_1)
y = pyccl.Cosmology(**cosmo_params_2)
assert x != y
assert hash(x) != hash(y)
-def test_equal_cosmologies_hash_equal(cosmo_params_1):
+def test_equal_cosmologies_hash_equal(cosmo_params_1: dict[str, float]) -> None:
# This test verifies expected (but not really desired) behavior. Two
# Cosmology variables only have equal hashes when they are in fact they
# are aliases for the same object. They also test as equal only if they
diff --git a/tests/test_scale_cuts_with_window.py b/tests/test_scale_cuts_with_window.py
index 62f29c53d..297df7c07 100644
--- a/tests/test_scale_cuts_with_window.py
+++ b/tests/test_scale_cuts_with_window.py
@@ -3,6 +3,7 @@
from pathlib import Path
import numpy as np
+import numpy.typing as npt
import pyccl as ccl
import pytest
import sacc
@@ -23,7 +24,9 @@
@pytest.fixture(name="window_function_data", scope="module")
-def fixture_window_function():
+def fixture_window_function() -> (
+ tuple[npt.NDArray[np.float64], npt.NDArray[np.int64], npt.NDArray[np.float64]]
+):
"""Generate window function data."""
n_ell_bin = 5
ell_bin_edges = np.geomspace(10, 500, n_ell_bin + 1)
@@ -43,7 +46,23 @@ def fixture_window_function():
@pytest.fixture(name="minimal_3x2pt_sacc", scope="module")
-def fixture_minimal_3x2pt_sacc(window_function_data):
+def fixture_minimal_3x2pt_sacc(
+ window_function_data: tuple[
+ npt.NDArray[np.float64], npt.NDArray[np.int64], npt.NDArray[np.float64]
+ ],
+) -> tuple[
+ sacc.Sacc,
+ dict[
+ str,
+ tuple[
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.int64],
+ npt.NDArray[np.float64],
+ ],
+ ],
+ ccl.Cosmology,
+]:
"""Generate SACC data with window functions.
At the moment, this only adds cosmic shear data."""
sacc_data = sacc.Sacc()
@@ -104,7 +123,7 @@ def fixture_minimal_3x2pt_sacc(window_function_data):
("src1", "src1", 200),
],
)
-def fixture_cut(request):
+def fixture_cut(request: pytest.FixtureRequest) -> tuple[str, str, int]:
return request.param
@@ -118,8 +137,22 @@ def fixture_cut(request):
def test_scale_cuts_with_bandpower_window_label(
- minimal_3x2pt_sacc, cut, tmp_path: Path
-):
+ minimal_3x2pt_sacc: tuple[
+ sacc.Sacc,
+ dict[
+ str,
+ tuple[
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.int64],
+ npt.NDArray[np.float64],
+ ],
+ ],
+ ccl.Cosmology,
+ ],
+ cut: tuple[str, str, int],
+ tmp_path: Path,
+) -> None:
"""Test that the scale cuts with bandpower windows work correctly."""
sacc_data, ccl_cell, cosmo = minimal_3x2pt_sacc
@@ -190,8 +223,23 @@ def test_scale_cuts_with_bandpower_window_label(
],
)
def test_scale_cuts_with_bandpower_window_support(
- minimal_3x2pt_sacc, cut, method, tmp_path: Path
-):
+ minimal_3x2pt_sacc: tuple[
+ sacc.Sacc,
+ dict[
+ str,
+ tuple[
+ npt.NDArray[np.float64],
+ npt.NDArray[np.float64],
+ npt.NDArray[np.int64],
+ npt.NDArray[np.float64],
+ ],
+ ],
+ ccl.Cosmology,
+ ],
+ cut: tuple[str, str, int],
+ method: tuple[TwoPointFilterMethod, float],
+ tmp_path: Path,
+) -> None:
"""Test that the scale cuts with bandpower windows work correctly."""
sacc_data, ccl_cell, cosmo = minimal_3x2pt_sacc
diff --git a/tests/test_two_point_deprecated.py b/tests/test_two_point_deprecated.py
index 919c42874..8800a4a03 100644
--- a/tests/test_two_point_deprecated.py
+++ b/tests/test_two_point_deprecated.py
@@ -14,7 +14,7 @@
import pytest
-def test_two_point_deprecation_warning():
+def test_two_point_deprecation_warning() -> None:
"""Test that importing two_point emits DeprecationWarning.
This must be the first test that imports the module, as subsequent imports
@@ -32,7 +32,7 @@ def test_two_point_deprecation_warning():
import firecrown.likelihood.two_point # noqa: F401
-def test_two_point_deprecation_warning_content():
+def test_two_point_deprecation_warning_content() -> None:
"""Test the deprecation warning mentions firecrown.likelihood.
This test relies on module caching, so it won't see the warning.
@@ -44,7 +44,7 @@ def test_two_point_deprecation_warning_content():
# If we get here without error, the import worked
-def test_all_items_importable():
+def test_all_items_importable() -> None:
"""Test that all __all__ items can be imported from deprecated module."""
# pylint: disable=import-outside-toplevel
from firecrown.likelihood.two_point import (
@@ -67,7 +67,7 @@ def test_all_items_importable():
assert use_source_factory_metadata_index is not None
-def test_items_identical_to_new_location():
+def test_items_identical_to_new_location() -> None:
"""Test that imported items are the same objects as in _two_point."""
# pylint: disable=import-outside-toplevel
from firecrown.likelihood._two_point import (
@@ -111,7 +111,7 @@ def test_items_identical_to_new_location():
assert old_use_source_factory_metadata_index is use_source_factory_metadata_index
-def test_module_import_as_alias():
+def test_module_import_as_alias() -> None:
"""Test importing the module with an alias."""
# pylint: disable=import-outside-toplevel
import firecrown.likelihood.two_point as tp
@@ -122,7 +122,7 @@ def test_module_import_as_alias():
assert hasattr(tp, "calculate_angular_cl")
-def test_two_point_all_list():
+def test_two_point_all_list() -> None:
"""Test that __all__ is preserved in deprecated module."""
# pylint: disable=import-outside-toplevel
import firecrown.likelihood.two_point
diff --git a/tests/test_updatable_parameters.py b/tests/test_updatable_parameters.py
index 075653ece..33f6c354b 100644
--- a/tests/test_updatable_parameters.py
+++ b/tests/test_updatable_parameters.py
@@ -24,14 +24,14 @@
)
-def test_register_new_updatable_parameter_with_no_arg():
+def test_register_new_updatable_parameter_with_no_arg() -> None:
"""Calling parameters.create() with no argument should return an
SamplerParameter"""
a_parameter = register_new_updatable_parameter(default_value=1.0)
assert isinstance(a_parameter, SamplerParameter)
-def test_register_new_updatable_parameter_with_float_arg():
+def test_register_new_updatable_parameter_with_float_arg() -> None:
"""Calling parameters.create() with a float argument should return a
InternalParameter ."""
a_parameter = register_new_updatable_parameter(value=1.5, default_value=1.0)
@@ -39,7 +39,7 @@ def test_register_new_updatable_parameter_with_float_arg():
assert a_parameter.get_value() == 1.5
-def test_register_new_updatable_parameter_with_wrong_arg():
+def test_register_new_updatable_parameter_with_wrong_arg() -> None:
"""Calling parameters.create() with an org that is neither float nor None should
raise a TypeError."""
with pytest.raises(TypeError):
@@ -48,7 +48,7 @@ def test_register_new_updatable_parameter_with_wrong_arg():
)
-def test_register_new_updatable_parameter_with_shared_true():
+def test_register_new_updatable_parameter_with_shared_true() -> None:
"""Calling parameters.create() with shared=True should return a SamplerParameter
with shared=True, meaning the parameter is shared across instances."""
a_parameter = register_new_updatable_parameter(default_value=1.0, shared=True)
@@ -56,7 +56,7 @@ def test_register_new_updatable_parameter_with_shared_true():
assert a_parameter.shared is True
-def test_register_new_updatable_parameter_with_shared_false():
+def test_register_new_updatable_parameter_with_shared_false() -> None:
"""Calling parameters.create() with shared=False (default) should return a
SamplerParameter with shared=False, meaning each instance has its own parameter."""
a_parameter = register_new_updatable_parameter(default_value=1.0, shared=False)
@@ -68,7 +68,7 @@ def test_register_new_updatable_parameter_with_shared_false():
assert a_parameter_default.shared is False
-def test_sampler_parameter_shared_ignores_prefix():
+def test_sampler_parameter_shared_ignores_prefix() -> None:
"""When shared=True, the SamplerParameter should ignore the prefix in
set_fullname, making it shared across all instances."""
sp = SamplerParameter(default_value=1.0, shared=True)
@@ -80,7 +80,7 @@ def test_sampler_parameter_shared_ignores_prefix():
assert sp.fullname == "my_name"
-def test_sampler_parameter_not_shared_uses_prefix():
+def test_sampler_parameter_not_shared_uses_prefix() -> None:
"""When shared=False (default), the SamplerParameter should use the prefix
in set_fullname, making each instance have its own parameter."""
sp = SamplerParameter(default_value=1.0, shared=False)
@@ -92,7 +92,7 @@ def test_sampler_parameter_not_shared_uses_prefix():
assert sp.fullname == "my_prefix_my_name"
-def test_sampler_parameter_equality_with_shared():
+def test_sampler_parameter_equality_with_shared() -> None:
"""Test that SamplerParameter equality considers the shared attribute."""
sp1 = SamplerParameter(default_value=1.0, name="a", shared=True)
sp2 = SamplerParameter(default_value=1.0, name="a", shared=True)
@@ -102,7 +102,7 @@ def test_sampler_parameter_equality_with_shared():
assert sp1 != sp3
-def test_shared_parameter_across_updatable_instances():
+def test_shared_parameter_across_updatable_instances() -> None:
"""Test that shared=True parameters are consistent across multiple
instances of the same Updatable class.
@@ -161,7 +161,7 @@ def __init__(self, prefix: str | None = None):
assert instance2.local_param == 20.0
-def test_get_default_params_with_shared_parameters():
+def test_get_default_params_with_shared_parameters() -> None:
"""Test that get_default_params and get_default_params_map work correctly
when two instances of the same Updatable class share a parameter.
@@ -218,7 +218,7 @@ def __init__(self, prefix: str | None = None):
assert instance2.global_param == 1.0
-def test_required_parameters_length():
+def test_required_parameters_length() -> None:
empty = RequiredParameters([])
assert len(empty) == 0
a = RequiredParameters([SamplerParameter(name="a", default_value=3.14)])
@@ -232,7 +232,7 @@ def test_required_parameters_length():
assert len(b) == 2
-def test_required_parameters_equality_testing():
+def test_required_parameters_equality_testing() -> None:
a1 = RequiredParameters([SamplerParameter(name="a", default_value=2)])
a2 = RequiredParameters([SamplerParameter(name="a", default_value=2)])
assert a1 == a2
@@ -245,7 +245,7 @@ def test_required_parameters_equality_testing():
_ = a1 == 10
-def test_get_params_names_does_not_allow_mutation():
+def test_get_params_names_does_not_allow_mutation() -> None:
"""The caller of RequiredParameters.get_params_names should not be able to modify
the state of the object on which the call was made."""
orig = RequiredParameters(
@@ -261,7 +261,7 @@ def test_get_params_names_does_not_allow_mutation():
assert set(orig.get_params_names()) == {"a", "b"}
-def test_params_map():
+def test_params_map() -> None:
my_params = ParamsMap({"a": 1.0})
x = my_params.get_from_prefix_param(None, "a")
assert x == 1
@@ -271,7 +271,7 @@ def test_params_map():
_ = my_params.get_from_prefix_param(None, "no_such_name")
-def test_params_map_getitem():
+def test_params_map_getitem() -> None:
a = ParamsMap({"a": 1.0})
assert a.get_unused_keys() == {"a"}
assert a["a"] == 1
@@ -281,7 +281,7 @@ def test_params_map_getitem():
_ = a["b"]
-def test_get_uses_params():
+def test_get_uses_params() -> None:
a = ParamsMap({"a": 1.0})
assert a.used_keys == set()
v = a.get("no_such_key", -1)
@@ -292,7 +292,7 @@ def test_get_uses_params():
assert a.used_keys == {"a"}
-def test_params_map_wrong_type():
+def test_params_map_wrong_type() -> None:
with pytest.raises(
TypeError, match="Value for parameter a is not a float or a list of floats.*"
):
@@ -301,7 +301,7 @@ def test_params_map_wrong_type():
)
-def test_params_map_wrong_type_list():
+def test_params_map_wrong_type_list() -> None:
with pytest.raises(
TypeError, match="Value for parameter a is not a float or a list of floats.*"
):
@@ -310,26 +310,26 @@ def test_params_map_wrong_type_list():
)
-def test_parameter_get_full_name_reject_empty_name():
+def test_parameter_get_full_name_reject_empty_name() -> None:
with pytest.raises(ValueError):
_ = parameter_get_full_name(None, "")
with pytest.raises(ValueError):
_ = parameter_get_full_name("cow", "")
-def test_parameter_get_full_name_with_prefix():
+def test_parameter_get_full_name_with_prefix() -> None:
full_name = parameter_get_full_name("my_prefix", "my_name")
# TODO: do we really want to allow underscores in parameter names, when we
# are using the underscore as our separator?
assert full_name == "my_prefix_my_name"
-def test_parameter_get_full_name_without_prefix():
+def test_parameter_get_full_name_without_prefix() -> None:
full_name = parameter_get_full_name(None, "nomen_foo")
assert full_name == "nomen_foo"
-def test_derived_parameter_scalar():
+def test_derived_parameter_scalar() -> None:
derived_param = DerivedParameter("sec1", "name1", 3.14)
assert isinstance(derived_param.get_val(), float)
@@ -337,7 +337,7 @@ def test_derived_parameter_scalar():
assert derived_param.get_full_name() == "sec1--name1"
-def test_derived_parameter_wrong_type():
+def test_derived_parameter_wrong_type() -> None:
"""Try instantiating DerivedParameter objects with wrong types."""
with pytest.raises(TypeError):
@@ -354,7 +354,7 @@ def test_derived_parameter_wrong_type():
)
-def test_derived_parameters_collection():
+def test_derived_parameters_collection() -> None:
olist = [
DerivedParameter("sec1", "name1", 3.14),
DerivedParameter("sec2", "name2", 2.72),
@@ -365,7 +365,7 @@ def test_derived_parameters_collection():
assert orig.get_derived_list() == olist
-def test_derived_parameters_collection_rejects_bad_list():
+def test_derived_parameters_collection_rejects_bad_list() -> None:
badlist = [1, 3, 5]
with pytest.raises(TypeError):
# We have to tell mypy to ignore the type error on the
@@ -374,7 +374,7 @@ def test_derived_parameters_collection_rejects_bad_list():
_ = DerivedParameterCollection(badlist) # type: ignore
-def test_derived_parameters_collection_add():
+def test_derived_parameters_collection_add() -> None:
olist = [
DerivedParameter("sec1", "name1", 3.14),
DerivedParameter("sec2", "name2", 2.72),
@@ -391,7 +391,7 @@ def test_derived_parameters_collection_add():
assert val == derived_parameter.get_val()
-def test_derived_parameters_collection_add_iter():
+def test_derived_parameters_collection_add_iter() -> None:
olist1 = [
DerivedParameter("sec1", "name1", 3.14),
DerivedParameter("sec2", "name2", 2.72),
@@ -415,14 +415,14 @@ def test_derived_parameters_collection_add_iter():
assert val == derived_parameter.get_val()
-def test_derived_parameter_eq():
+def test_derived_parameter_eq() -> None:
dv1 = DerivedParameter("sec1", "name1", 3.14)
dv2 = DerivedParameter("sec1", "name1", 3.14)
assert dv1 == dv2
-def test_derived_parameter_eq_invalid():
+def test_derived_parameter_eq_invalid() -> None:
dv1 = DerivedParameter("sec1", "name1", 3.14)
with pytest.raises(
@@ -433,7 +433,7 @@ def test_derived_parameter_eq_invalid():
_ = dv1 == 1.0
-def test_derived_parameters_collection_eq():
+def test_derived_parameters_collection_eq() -> None:
olist1 = [
DerivedParameter("sec1", "name1", 3.14),
DerivedParameter("sec2", "name2", 2.72),
@@ -451,7 +451,7 @@ def test_derived_parameters_collection_eq():
assert dpc1 == dpc2
-def test_derived_parameters_collection_eq_invalid():
+def test_derived_parameters_collection_eq_invalid() -> None:
olist1 = [
DerivedParameter("sec1", "name1", 3.14),
DerivedParameter("sec2", "name2", 2.72),
@@ -467,47 +467,47 @@ def test_derived_parameters_collection_eq_invalid():
_ = dpc1 == 1.0
-def test_sampler_parameter_no_prefix():
+def test_sampler_parameter_no_prefix() -> None:
sp = SamplerParameter(name="name1", default_value=1)
assert sp.name == "name1"
assert sp.fullname == "name1"
-def test_sampler_parameter_with_prefix():
+def test_sampler_parameter_with_prefix() -> None:
sp = SamplerParameter(name="name1", prefix="prefix1", default_value=1)
assert sp.name == "name1"
assert sp.fullname == "prefix1_name1"
-def test_sampler_parameter_with_value():
+def test_sampler_parameter_with_value() -> None:
sp = SamplerParameter(name="name1", default_value=2)
assert sp is not None
-def test_sampler_parameter_with_value_and_prefix():
+def test_sampler_parameter_with_value_and_prefix() -> None:
sp = SamplerParameter(name="name1", prefix="prefix1", default_value=2)
assert sp is not None
-def test_sampler_parameter_with_value_and_prefix_and_fullname():
+def test_sampler_parameter_with_value_and_prefix_and_fullname() -> None:
sp = SamplerParameter(name="name1", prefix="prefix1", default_value=2)
assert sp.fullname == "prefix1_name1"
-def test_sample_parameter_hash():
+def test_sample_parameter_hash() -> None:
sp1 = SamplerParameter(name="name1", default_value=3.14)
sp2 = SamplerParameter(name="name1", default_value=3.14)
assert hash(sp1) == hash(sp2)
-def test_sampler_parameter_eq():
+def test_sampler_parameter_eq() -> None:
sp1 = SamplerParameter(name="name1", default_value=3.14)
sp2 = SamplerParameter(name="name1", default_value=3.14)
assert sp1 == sp2
-def test_sampler_parameter_eq_invalid():
+def test_sampler_parameter_eq_invalid() -> None:
sp1 = SamplerParameter(name="name1", default_value=3.14)
with pytest.raises(
NotImplementedError,
@@ -519,25 +519,25 @@ def test_sampler_parameter_eq_invalid():
_ = sp1 == 1.0
-def test_sampler_parameter_ne():
+def test_sampler_parameter_ne() -> None:
sp1 = SamplerParameter(name="name1", default_value=3.14)
sp2 = SamplerParameter(name="name2", default_value=3.14)
assert sp1 != sp2
-def test_sampler_parameter_default_value():
+def test_sampler_parameter_default_value() -> None:
sp = SamplerParameter(name="name1", default_value=3.14)
assert sp.get_default_value() == 3.14
-def test_sampler_parameter_default_value_no_name():
+def test_sampler_parameter_default_value_no_name() -> None:
sp = SamplerParameter(default_value=2.72)
with pytest.raises(ValueError, match="Parameter name is not set"):
_ = sp.name
-def test_required_parameters_get_names():
+def test_required_parameters_get_names() -> None:
rp = RequiredParameters(
[
SamplerParameter(name="name1", default_value=3.14),
@@ -547,7 +547,7 @@ def test_required_parameters_get_names():
assert set(rp.get_params_names()) == {"name1", "name2"}
-def test_required_parameters_get_default_values():
+def test_required_parameters_get_default_values() -> None:
rp = RequiredParameters(
[
SamplerParameter(name="name1", default_value=3.14),
@@ -558,7 +558,7 @@ def test_required_parameters_get_default_values():
assert rp.get_default_values() == {"name1": 3.14, "name2": 2.72, "name3": 2.3}
-def test_add_required_parameter():
+def test_add_required_parameter() -> None:
coll = DerivedParameterCollection([])
coll.add_required_parameter(
DerivedParameter(section="barnyard", name="cow", val=1.0)
@@ -574,14 +574,14 @@ def test_add_required_parameter():
)
-def test_setting_internal_parameter():
+def test_setting_internal_parameter() -> None:
a_parameter = register_new_updatable_parameter(value=1.0, default_value=2.0)
assert a_parameter.value == 1.0
a_parameter.set_value(2.0)
assert a_parameter.value == 2.0
-def test_used_and_unused_params():
+def test_used_and_unused_params() -> None:
"""Test that get_unused_keys works as expected."""
params = ParamsMap({"a": 1.0, "b": 2.0, "c": 3.0})
@@ -608,7 +608,7 @@ def test_used_and_unused_params():
assert unused == set()
-def test_handle_unused_params():
+def test_handle_unused_params() -> None:
"""Test that handle_unused_params works as expected."""
params = ParamsMap({"a": 1.0, "b": 2.0, "c": 3.0})
@@ -645,7 +645,7 @@ def test_handle_unused_params():
handle_unused_params(params=params, updated_records=[], raise_on_unused=True)
-def test_handle_unused_params_includes_updated_records_in_message():
+def test_handle_unused_params_includes_updated_records_in_message() -> None:
params = ParamsMap({"x": 1.0})
# Create a simple UpdatableUsageRecord structure
@@ -690,7 +690,7 @@ def test_handle_unused_params_includes_updated_records_in_message():
assert "Parent(p) => Child(c):" in err_msg or "Parent(p):" in err_msg
-def test_params_map_union():
+def test_params_map_union() -> None:
p1 = ParamsMap({"a": 1.0})
p2 = ParamsMap({"b": 2.0})
p3 = p1.union(p2)
@@ -717,7 +717,7 @@ def test_params_map_union():
p1.union(p2)
-def test_params_get():
+def test_params_get() -> None:
params = ParamsMap({"a": 1.0})
assert params.get("a") == 1.0
assert params.get("b", 2.0) == 2.0
@@ -725,13 +725,13 @@ def test_params_get():
params.get("b")
-def test_params_map_items():
+def test_params_map_items() -> None:
d = {"a": 1.0, "b": 2.0}
params = ParamsMap(d)
assert params.items() == d.items()
-def test_params_map_lower_case_lookup():
+def test_params_map_lower_case_lookup() -> None:
"""Ensure get_from_full_name respects the lower-case fallback when enabled."""
p = ParamsMap({"my_key": 4.2})
# lookup with different case should fail until we enable lower-case handling
@@ -744,14 +744,14 @@ def test_params_map_lower_case_lookup():
assert val == 4.2
-def test_params_map_list_with_ints_raises_typeerror():
+def test_params_map_list_with_ints_raises_typeerror() -> None:
"""A list value containing ints (not floats) should trigger the list
element type check and raise TypeError."""
with pytest.raises(TypeError, match="Value for parameter a is not a float"):
_ = ParamsMap({"a": [1, 2.0]}) # type: ignore[arg-type]
-def test_params_map_setitem():
+def test_params_map_setitem() -> None:
"""Test ParamsMap.__setitem__() method for setting values."""
params = ParamsMap({"a": 1.0})
params["b"] = 2.0
@@ -760,7 +760,7 @@ def test_params_map_setitem():
assert params["a"] == 3.0
-def test_params_map_contains():
+def test_params_map_contains() -> None:
"""Test ParamsMap.__contains__() method with in operator."""
params = ParamsMap({"a": 1.0, "b": 2.0})
assert "a" in params
@@ -769,7 +769,7 @@ def test_params_map_contains():
assert "nonexistent" not in params
-def test_params_map_copy():
+def test_params_map_copy() -> None:
"""Test ParamsMap.copy() creates an independent copy."""
original = ParamsMap({"a": 1.0, "b": 2.0})
_ = original["a"] # Mark 'a' as used
@@ -795,7 +795,7 @@ def test_params_map_copy():
assert original.lower_case is False
-def test_params_map_update_duplicate_key():
+def test_params_map_update_duplicate_key() -> None:
"""Test ParamsMap.update() raises error for duplicate keys."""
params = ParamsMap({"a": 1.0})
@@ -808,7 +808,7 @@ def test_params_map_update_duplicate_key():
params.update({"a": 3.0})
-def test_params_map_keys():
+def test_params_map_keys() -> None:
"""Test ParamsMap.keys() returns correct set of keys."""
params = ParamsMap({"a": 1.0, "b": 2.0, "c": 3.0})
keys = params.keys()
@@ -821,7 +821,7 @@ def test_params_map_keys():
assert params.keys() == {"a", "b", "c"}
-def test_required_parameters_subtraction():
+def test_required_parameters_subtraction() -> None:
"""Test RequiredParameters.__sub__() subtraction operator."""
param_a = SamplerParameter(name="a", default_value=1.0)
param_b = SamplerParameter(name="b", default_value=2.0)
@@ -843,7 +843,7 @@ def test_required_parameters_subtraction():
assert set(params2.get_params_names()) == {"b", "d"}
-def test_required_parameters_addition():
+def test_required_parameters_addition() -> None:
"""Test RequiredParameters.__add__() addition operator."""
param_a = SamplerParameter(name="a", default_value=1.0)
param_b = SamplerParameter(name="b", default_value=2.0)
@@ -864,7 +864,7 @@ def test_required_parameters_addition():
assert set(params2.get_params_names()) == {"c"}
-def test_sampler_parameter_set_fullname():
+def test_sampler_parameter_set_fullname() -> None:
"""Test SamplerParameter.set_fullname() method."""
sp = SamplerParameter(default_value=1.0)
@@ -885,7 +885,7 @@ def test_sampler_parameter_set_fullname():
assert sp.fullname == "another_name"
-def test_params_map_union_no_common_keys():
+def test_params_map_union_no_common_keys() -> None:
"""Test ParamsMap.union() when there are no common keys.
This covers the branch where the for loop over common keys is not entered.
@@ -902,7 +902,7 @@ def test_params_map_union_no_common_keys():
assert p3.get_from_full_name("d") == 4.0
-def test_params_map_union_common_keys_same_values():
+def test_params_map_union_common_keys_same_values() -> None:
"""Test ParamsMap.union() when common keys have the same values.
This covers the branch where common keys exist but don't trigger
@@ -919,7 +919,7 @@ def test_params_map_union_common_keys_same_values():
assert p3.get_from_full_name("c") == 3.0
-def test_params_map_lower_case_key_not_found():
+def test_params_map_lower_case_key_not_found() -> None:
"""Test ParamsMap with lower_case enabled but key still not found.
This covers the branch where lower_case is True but the lowercased
@@ -933,7 +933,7 @@ def test_params_map_lower_case_key_not_found():
_ = p.get_from_full_name("NONEXISTENT")
-def test_handle_unused_params_all_used():
+def test_handle_unused_params_all_used() -> None:
"""Test handle_unused_params when all parameters are used.
This covers the early return branch when there are no unused keys.
@@ -949,7 +949,7 @@ def test_handle_unused_params_all_used():
handle_unused_params(params=params, updated_records=[], raise_on_unused=True)
-def test_params_map_with_list_of_floats():
+def test_params_map_with_list_of_floats() -> None:
"""Test ParamsMap accepts a list of floats as a valid value.
This covers the branch in validate_params_map_value where
diff --git a/tests/test_utils.py b/tests/test_utils.py
index de4a90777..7f3d1091b 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -7,6 +7,7 @@
from typing import cast
import numpy as np
+import numpy.typing as npt
import pyccl
import pytest
import sacc
@@ -28,19 +29,23 @@
save_to_sacc,
upper_triangle_indices,
)
+from firecrown.likelihood._statistic import TrivialStatistic
+from firecrown.modeling_tools import ModelingTools
-def test_upper_triangle_indices_nonzero():
+def test_upper_triangle_indices_nonzero() -> None:
indices = list(upper_triangle_indices(3))
assert indices == [(0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2)]
-def test_upper_triangle_indices_zero():
+def test_upper_triangle_indices_zero() -> None:
indices = list(upper_triangle_indices(0))
assert not indices
-def test_save_to_sacc(trivial_stats, sacc_data_for_trivial_stat):
+def test_save_to_sacc(
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
stat = trivial_stats[0]
stat.read(sacc_data_for_trivial_stat)
idx = np.arange(stat.count)
@@ -55,7 +60,9 @@ def test_save_to_sacc(trivial_stats, sacc_data_for_trivial_stat):
assert all(new_sacc.data[i].value == d for i, d in zip(idx, new_data_vector))
-def test_save_to_sacc_strict_fail(trivial_stats, sacc_data_for_trivial_stat):
+def test_save_to_sacc_strict_fail(
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
stat = trivial_stats[0]
stat.read(sacc_data_for_trivial_stat)
idx = np.arange(stat.count - 1)
@@ -70,7 +77,9 @@ def test_save_to_sacc_strict_fail(trivial_stats, sacc_data_for_trivial_stat):
)
-def test_save_to_sacc_non_sttrict(trivial_stats, sacc_data_for_trivial_stat):
+def test_save_to_sacc_non_sttrict(
+ trivial_stats: list[TrivialStatistic], sacc_data_for_trivial_stat: sacc.Sacc
+) -> None:
stat = trivial_stats[0]
stat.read(sacc_data_for_trivial_stat)
idx = np.arange(stat.count)
@@ -98,7 +107,7 @@ def _make_minimal_sacc() -> sacc.Sacc:
@pytest.mark.parametrize("suffix", [".fits", *_AMBIGUOUS_SUFFIXES])
-def test_load_sacc_data_loads_fits(tmp_path, suffix):
+def test_load_sacc_data_loads_fits(tmp_path: Path, suffix: str) -> None:
"""load_sacc_data reads FITS content, including from ambiguous extensions.
When the extension does not announce a format (e.g. the ``.sacc`` files
@@ -115,7 +124,7 @@ def test_load_sacc_data_loads_fits(tmp_path, suffix):
@pytest.mark.parametrize("suffix", [".hdf5", ".h5", *_AMBIGUOUS_SUFFIXES])
-def test_load_sacc_data_loads_hdf5(tmp_path, suffix):
+def test_load_sacc_data_loads_hdf5(tmp_path: Path, suffix: str) -> None:
"""load_sacc_data reads HDF5 content, including from ambiguous extensions.
This is the case that regressed under SACC 2.2: an HDF5 file named with an
@@ -131,7 +140,7 @@ def test_load_sacc_data_loads_hdf5(tmp_path, suffix):
assert len(loaded.tracers) == 1
-def test_load_sacc_data_accepts_string_path(tmp_path):
+def test_load_sacc_data_accepts_string_path(tmp_path: Path) -> None:
"""load_sacc_data accepts a string path as well as a Path object."""
input_file = tmp_path / "data.sacc"
_make_minimal_sacc().save_fits(str(input_file), overwrite=True)
@@ -141,13 +150,13 @@ def test_load_sacc_data_accepts_string_path(tmp_path):
assert isinstance(loaded, sacc.Sacc)
-def test_load_sacc_data_missing_file_raises(tmp_path):
+def test_load_sacc_data_missing_file_raises(tmp_path: Path) -> None:
"""load_sacc_data raises FileNotFoundError for a non-existent file."""
with pytest.raises(FileNotFoundError, match="SACC file not found"):
load_sacc_data(tmp_path / "does_not_exist.sacc")
-def test_load_sacc_data_unrecognized_content_raises(tmp_path):
+def test_load_sacc_data_unrecognized_content_raises(tmp_path: Path) -> None:
"""load_sacc_data raises ValueError when content is neither FITS nor HDF5."""
bad_file = tmp_path / "corrupted.sacc"
bad_file.write_text("This is not a valid SACC file format")
@@ -164,16 +173,16 @@ def test_load_sacc_data_unrecognized_content_raises(tmp_path):
@pytest.mark.parametrize("value", ["some/path.sacc", Path("some/path.sacc")])
-def test_ensure_path_returns_path(value):
+def test_ensure_path_returns_path(value: str | Path) -> None:
"""ensure_path returns a Path for both str and Path inputs."""
result = ensure_path(value)
assert isinstance(result, Path)
assert result == Path("some/path.sacc")
-def test_compare_optional_arrays_():
- x = np.array([1, 2, 3])
- y = np.array([1, 2, 3])
+def test_compare_optional_arrays_() -> None:
+ x: npt.NDArray[np.int64] = np.array([1, 2, 3])
+ y: npt.NDArray[np.int64] = np.array([1, 2, 3])
assert compare_optional_arrays(x, y)
z = np.array([1, 2, 4])
@@ -194,7 +203,7 @@ def test_base_model_from_yaml_wrong() -> None:
_ = base_model_from_yaml(cast(type[BaseModel], str), "wrong")
-def test_compare_optionals():
+def test_compare_optionals() -> None:
x = "test"
y = "test"
assert compare_optionals(x, y)
@@ -216,7 +225,7 @@ def test_compare_optionals():
name="limber_method",
params=[ClLimberMethod.GSL_SPLINE, ClLimberMethod.GSL_QAG_QUAD],
)
-def fixture_limber_method(request):
+def fixture_limber_method(request: pytest.FixtureRequest) -> ClLimberMethod:
return request.param
@@ -224,17 +233,17 @@ def fixture_limber_method(request):
name="limber_max_error",
params=[None, 0.1, 0.2],
)
-def fixture_limber_max_error(request):
+def fixture_limber_max_error(request: pytest.FixtureRequest) -> float | None:
return request.param
@pytest.fixture(name="fkem_chi_min", params=[None, 0.05, 0.082])
-def fixture_fkem_chi_min(request):
+def fixture_fkem_chi_min(request: pytest.FixtureRequest) -> float | None:
return request.param
@pytest.fixture(name="fkem_Nchi", params=[None, 10, 20])
-def fixture_fkem_Nchi(request):
+def fixture_fkem_Nchi(request: pytest.FixtureRequest) -> int | None:
return request.param
@@ -242,11 +251,11 @@ def fixture_fkem_Nchi(request):
name="l_limber",
params=[40, 60],
)
-def fixture_l_limber(request):
+def fixture_l_limber(request: pytest.FixtureRequest) -> int:
return request.param
-def test_cl_integration_options_limber(limber_method: ClLimberMethod):
+def test_cl_integration_options_limber(limber_method: ClLimberMethod) -> None:
int_options = ClIntegrationOptions(
method=ClIntegrationMethod.LIMBER, limber_method=limber_method
)
@@ -265,7 +274,7 @@ def test_cl_integration_options_limber(limber_method: ClLimberMethod):
assert int_options == int_options2
-def test_cl_integration_options_limber_yaml(limber_method: ClLimberMethod):
+def test_cl_integration_options_limber_yaml(limber_method: ClLimberMethod) -> None:
int_options_yaml = f"""
method: LIMBER
limber_method: {limber_method.lower()}
@@ -280,7 +289,7 @@ def test_cl_integration_options_fkem_auto(
limber_max_error: float | None,
fkem_chi_min: float | None,
fkem_Nchi: int | None,
-):
+) -> None:
int_options = ClIntegrationOptions(
method=ClIntegrationMethod.FKEM_AUTO,
limber_method=limber_method,
@@ -322,7 +331,7 @@ def test_cl_integration_options_fkem_auto_yaml(
limber_max_error: float | None,
fkem_chi_min: float | None,
fkem_Nchi: int | None,
-):
+) -> None:
int_options_yaml = f"""
method: FKEM_AUTO
limber_method: {limber_method.lower()}
@@ -343,7 +352,7 @@ def test_cl_integration_options_fkem_l_limber(
fkem_chi_min: float | None,
fkem_Nchi: int | None,
l_limber: int,
-):
+) -> None:
int_options = ClIntegrationOptions(
method=ClIntegrationMethod.FKEM_L_LIMBER,
limber_method=limber_method,
@@ -381,7 +390,7 @@ def test_cl_integration_options_fkem_l_limber_yaml(
fkem_chi_min: float | None,
fkem_Nchi: int | None,
l_limber: int,
-):
+) -> None:
int_options_yaml = f"""
method: FKEM_L_LIMBER
limber_method: {limber_method.lower()}
@@ -397,7 +406,7 @@ def test_cl_integration_options_fkem_l_limber_yaml(
assert int_options.fkem_Nchi == fkem_Nchi
-def test_cl_integration_options_yaml_invalid():
+def test_cl_integration_options_yaml_invalid() -> None:
int_options_yaml = """
method: Im_not_a_valid_method
limber_method: qag_quad
@@ -451,7 +460,7 @@ def test_cl_integration_options_yaml_invalid():
base_model_from_yaml(ClIntegrationOptions, int_options_yaml)
-def test_cl_integration_options_limber_invalid():
+def test_cl_integration_options_limber_invalid() -> None:
with pytest.raises(
ValueError, match="l_limber is incompatible with ClIntegrationMethod.LIMBER"
):
@@ -490,7 +499,7 @@ def test_cl_integration_options_limber_invalid():
)
-def test_cl_integration_options_fkem_auto_invalid():
+def test_cl_integration_options_fkem_auto_invalid() -> None:
with pytest.raises(
ValueError,
match="l_limber is incompatible with ClIntegrationMethod.FKEM_AUTO",
@@ -502,7 +511,7 @@ def test_cl_integration_options_fkem_auto_invalid():
)
-def test_cl_integration_options_fkem_l_limber_invalid():
+def test_cl_integration_options_fkem_l_limber_invalid() -> None:
with pytest.raises(
ValueError,
match="limber_max_error is incompatible with ClIntegrationMethod.FKEM_L_LIMBER",
@@ -524,7 +533,7 @@ def test_cl_integration_options_fkem_l_limber_invalid():
)
-def test_cl_integration_test_cmparison():
+def test_cl_integration_test_cmparison() -> None:
int_options = ClIntegrationOptions(
method=ClIntegrationMethod.LIMBER, limber_method=ClLimberMethod.GSL_SPLINE
)
@@ -536,7 +545,7 @@ def test_cl_integration_test_cmparison():
)
-def test_make_log_interpolator_positive():
+def test_make_log_interpolator_positive() -> None:
x = np.arange(1, 3000)
y = np.exp(x / 1.0e3) * x**1.43
@@ -545,7 +554,7 @@ def test_make_log_interpolator_positive():
assert_allclose(f(x), y, atol=0.0, rtol=1e-12)
-def test_make_log_interpolator_negative():
+def test_make_log_interpolator_negative() -> None:
x = np.arange(1, 3000)
y = np.exp(x / 1.0e3) * (x - 1000.5)
@@ -554,7 +563,7 @@ def test_make_log_interpolator_negative():
assert_allclose(f(x), y, atol=0.0, rtol=1e-12)
-def test_cached_angular_cl(tools_with_vanilla_cosmology):
+def test_cached_angular_cl(tools_with_vanilla_cosmology: ModelingTools) -> None:
tools = tools_with_vanilla_cosmology
cosmo = tools.get_ccl_cosmology()
@@ -572,7 +581,9 @@ def test_cached_angular_cl(tools_with_vanilla_cosmology):
assert np.all(np.isfinite(cl))
-def test_cached_angular_cl_with_options(tools_with_vanilla_cosmology):
+def test_cached_angular_cl_with_options(
+ tools_with_vanilla_cosmology: ModelingTools,
+) -> None:
tools = tools_with_vanilla_cosmology
cosmo = tools.get_ccl_cosmology()
@@ -605,11 +616,15 @@ def test_cached_angular_cl_with_options(tools_with_vanilla_cosmology):
(ClIntegrationMethod.FKEM_L_LIMBER, "fkem_l_limber"),
],
)
-def test_yaml_serializable_to_yaml(method, expected):
+def test_yaml_serializable_to_yaml(method: ClIntegrationMethod, expected: str) -> None:
# Add test to verify all enum values are covered
all_methods = set(ClIntegrationMethod)
+ # Pytest's store_mark adds pytestmark; callable annotations cannot express it.
test_methods = {
- param[0] for param in test_yaml_serializable_to_yaml.pytestmark[0].args[1]
+ param[0]
+ for param in (
+ test_yaml_serializable_to_yaml.pytestmark # type: ignore[attr-defined]
+ )[0].args[1]
}
assert (
all_methods == test_methods
@@ -627,11 +642,17 @@ def test_yaml_serializable_to_yaml(method, expected):
("fkem_l_limber", ClIntegrationMethod.FKEM_L_LIMBER),
],
)
-def test_yaml_serializable_from_yaml(yaml_str, expected):
+def test_yaml_serializable_from_yaml(
+ yaml_str: str, expected: ClIntegrationMethod
+) -> None:
# Add test to verify all enum values are covered
all_methods = set(ClIntegrationMethod)
+ # Pytest's store_mark adds pytestmark; callable annotations cannot express it.
test_methods = {
- param[1] for param in test_yaml_serializable_from_yaml.pytestmark[0].args[1]
+ param[1]
+ for param in (
+ test_yaml_serializable_from_yaml.pytestmark # type: ignore[attr-defined]
+ )[0].args[1]
}
assert (
all_methods == test_methods
diff --git a/tests/test_version.py b/tests/test_version.py
index d3d140f2a..72360d1ca 100644
--- a/tests/test_version.py
+++ b/tests/test_version.py
@@ -11,7 +11,7 @@
SEMVER_PATTERN = re.compile(r"^\d+\.\d+\.\d+(?:a\d+)?$")
-def test_version_format():
+def test_version_format() -> None:
"""Test that version follows semantic versioning format.
This test validates the version format rather than a specific value,
diff --git a/tests/updatable/test_base.py b/tests/updatable/test_base.py
index ee5fd08da..bcf9014cb 100644
--- a/tests/updatable/test_base.py
+++ b/tests/updatable/test_base.py
@@ -3,6 +3,7 @@
from itertools import permutations
import numpy as np
+import numpy.typing as npt
import pytest
from firecrown import updatable
@@ -24,13 +25,13 @@
# pylint: disable-msg=E1101
-def test_get_params_names():
+def test_get_params_names() -> None:
obj = SimpleUpdatable()
found_names = obj.get_params_names()
assert set(found_names) == {"x", "y"}
-def test_simple_updatable():
+def test_simple_updatable() -> None:
obj = SimpleUpdatable()
expected_params = RequiredParameters(
[
@@ -52,7 +53,7 @@ def test_simple_updatable():
assert obj.is_updated()
-def test_set_sampler_parameter():
+def test_set_sampler_parameter() -> None:
my_updatable = MinimalUpdatable()
my_param = updatable.register_new_updatable_parameter(default_value=42.0)
my_param.set_fullname(prefix=None, name="the_meaning_of_life")
@@ -62,7 +63,7 @@ def test_set_sampler_parameter():
assert my_updatable.the_meaning_of_life is None
-def test_set_sampler_parameter_rejects_internal_parameter():
+def test_set_sampler_parameter_rejects_internal_parameter() -> None:
my_updatable = MinimalUpdatable()
my_param = updatable.register_new_updatable_parameter(
value=42.0, default_value=41.0
@@ -72,7 +73,7 @@ def test_set_sampler_parameter_rejects_internal_parameter():
my_updatable.set_sampler_parameter(my_param) # type: ignore[arg-type]
-def test_set_sampler_parameter_rejects_duplicates():
+def test_set_sampler_parameter_rejects_duplicates() -> None:
my_updatable = MinimalUpdatable()
my_param = updatable.register_new_updatable_parameter(default_value=42.0)
my_param.set_fullname(prefix=None, name="the_meaning_of_life")
@@ -85,7 +86,7 @@ def test_set_sampler_parameter_rejects_duplicates():
my_updatable.set_sampler_parameter(my_param_same)
-def test_set_internal_parameter():
+def test_set_internal_parameter() -> None:
my_updatable = MinimalUpdatable()
my_updatable.set_internal_parameter(
"the_meaning_of_life",
@@ -96,7 +97,7 @@ def test_set_internal_parameter():
assert my_updatable.the_meaning_of_life == 1.0
-def test_set_parameter_using_internal_parameter():
+def test_set_parameter_using_internal_parameter() -> None:
my_updatable = MinimalUpdatable()
ip = updatable.InternalParameter(2112)
my_updatable.set_parameter("epic_Rush_album", ip)
@@ -105,7 +106,7 @@ def test_set_parameter_using_internal_parameter():
assert my_updatable.epic_Rush_album == 2112
-def test_set_internal_parameter_rejects_sampler_parameter():
+def test_set_internal_parameter_rejects_sampler_parameter() -> None:
my_updatable = MinimalUpdatable()
with pytest.raises(TypeError):
my_updatable.set_internal_parameter(
@@ -116,7 +117,7 @@ def test_set_internal_parameter_rejects_sampler_parameter():
)
-def test_set_internal_parameter_rejects_duplicates():
+def test_set_internal_parameter_rejects_duplicates() -> None:
my_updatable = MinimalUpdatable()
my_updatable.set_internal_parameter(
"the_meaning_of_life",
@@ -130,7 +131,7 @@ def test_set_internal_parameter_rejects_duplicates():
)
-def test_set_parameter():
+def test_set_parameter() -> None:
my_updatable = MinimalUpdatable()
my_updatable.set_parameter(
"the_meaning_of_life",
@@ -148,7 +149,7 @@ def test_set_parameter():
assert my_updatable.no_meaning_of_life is None
-def test_update_rejects_internal_parameters():
+def test_update_rejects_internal_parameters() -> None:
my_updatable = MinimalUpdatable()
my_updatable.set_internal_parameter(
"the_meaning_of_life",
@@ -167,7 +168,7 @@ def test_update_rejects_internal_parameters():
assert my_updatable.the_meaning_of_life == 2.0
-def test_setattr_with_list_of_updatables():
+def test_setattr_with_list_of_updatables() -> None:
"""Test setting an attribute to a list of Updatable objects.
This tests the code path in __setattr__ that handles iterables containing
@@ -195,7 +196,7 @@ def test_setattr_with_list_of_updatables():
assert child2.a == 4.0
-def test_update_already_updated_with_updated_record():
+def test_update_already_updated_with_updated_record() -> None:
"""Test calling update() twice with updated_record parameter.
When an object is already updated and update() is called again with
@@ -222,7 +223,7 @@ def test_update_already_updated_with_updated_record():
assert updated_records2[0].internal_params == []
-def test_update_already_updated_without_record():
+def test_update_already_updated_without_record() -> None:
"""Test calling update() twice without updated_record parameter.
When an object is already updated and update() is called again without
@@ -249,7 +250,7 @@ def test_update_already_updated_without_record():
assert obj.y == 2.0
-def test_reset_when_not_updated():
+def test_reset_when_not_updated() -> None:
"""Test calling reset() on an object that hasn't been updated.
Should return early without doing anything (lines 234-235 in _base.py).
@@ -270,7 +271,7 @@ def test_reset_when_not_updated():
assert obj.y is None
-def test_reset_with_nested_updatables_and_sampler_params():
+def test_reset_with_nested_updatables_and_sampler_params() -> None:
"""Test reset() with nested updatables and sampler parameters.
Verifies that reset():
@@ -306,7 +307,7 @@ def test_reset_with_nested_updatables_and_sampler_params():
assert child.a is None
-def test_tuple_attribute_adds_to_updatables():
+def test_tuple_attribute_adds_to_updatables() -> None:
"""Test that setting a tuple attribute adds Updatable elements to _updatables.
When an Updatable container has an attribute set to an iterable containing
@@ -327,7 +328,9 @@ def test_tuple_attribute_adds_to_updatables():
@pytest.fixture(name="nested_updatables", params=permutations(range(3)))
-def fixture_nested_updatables(request):
+def fixture_nested_updatables(
+ request: pytest.FixtureRequest,
+) -> npt.NDArray[np.object_]:
updatables = np.array(
[MinimalUpdatable(), SimpleUpdatable(), UpdatableWithDerived()]
)
@@ -340,7 +343,9 @@ def fixture_nested_updatables(request):
return updatables
-def test_nesting_updatables_missing_parameters(nested_updatables):
+def test_nesting_updatables_missing_parameters(
+ nested_updatables: npt.NDArray[np.object_],
+) -> None:
base = nested_updatables[0]
assert isinstance(base, Updatable)
@@ -373,7 +378,9 @@ def test_nesting_updatables_missing_parameters(nested_updatables):
assert my_updatable.is_updated()
-def test_nesting_updatables_required_parameters(nested_updatables):
+def test_nesting_updatables_required_parameters(
+ nested_updatables: npt.NDArray[np.object_],
+) -> None:
base = nested_updatables[0]
assert isinstance(base, Updatable)
@@ -388,7 +395,9 @@ def test_nesting_updatables_required_parameters(nested_updatables):
)
-def test_nesting_updatables_derived_parameters(nested_updatables):
+def test_nesting_updatables_derived_parameters(
+ nested_updatables: npt.NDArray[np.object_],
+) -> None:
base = nested_updatables[0]
assert isinstance(base, Updatable)
diff --git a/tests/updatable/test_collection.py b/tests/updatable/test_collection.py
index ec32fec1e..7706344a7 100644
--- a/tests/updatable/test_collection.py
+++ b/tests/updatable/test_collection.py
@@ -15,7 +15,7 @@
# pylint: disable-msg=E1101
-def test_updatable_collection_record():
+def test_updatable_collection_record() -> None:
"""Test record creation for UpdatableCollection."""
coll = UpdatableCollection([SimpleUpdatable("first"), MinimalUpdatable("second")])
@@ -36,7 +36,7 @@ def test_updatable_collection_record():
assert second_record.sampler_params == ["a"]
-def test_updatable_collection_appends():
+def test_updatable_collection_appends() -> None:
coll: UpdatableCollection[Updatable] = UpdatableCollection()
assert len(coll) == 0
@@ -67,7 +67,7 @@ def test_updatable_collection_appends():
)
-def test_updatable_collection_updates():
+def test_updatable_collection_updates() -> None:
coll: UpdatableCollection[Updatable] = UpdatableCollection()
assert len(coll) == 0
@@ -85,7 +85,7 @@ def test_updatable_collection_updates():
assert first.y == 5.5
-def test_updatable_collection_rejects_nonupdatables():
+def test_updatable_collection_rejects_nonupdatables() -> None:
coll: UpdatableCollection[Updatable] = UpdatableCollection()
assert len(coll) == 0
@@ -94,7 +94,7 @@ def test_updatable_collection_rejects_nonupdatables():
assert len(coll) == 0
-def test_updatable_collection_construction():
+def test_updatable_collection_construction() -> None:
good_list = [SimpleUpdatable(), SimpleUpdatable()]
good = UpdatableCollection(good_list)
assert len(good) == 2
@@ -104,7 +104,7 @@ def test_updatable_collection_construction():
_ = UpdatableCollection(bad_list) # pylint: disable-msg=W0612
-def test_updatable_collection_insertion():
+def test_updatable_collection_insertion() -> None:
x = UpdatableCollection([MinimalUpdatable()])
assert len(x) == 1
assert isinstance(x[0], MinimalUpdatable)
@@ -117,7 +117,7 @@ def test_updatable_collection_insertion():
x[0] = 1
-def test_updatable_collection_is_updated():
+def test_updatable_collection_is_updated() -> None:
obj: UpdatableCollection[Updatable] = UpdatableCollection([SimpleUpdatable()])
new_params = {"x": -1.0, "y": 5.5}
@@ -126,13 +126,13 @@ def test_updatable_collection_is_updated():
assert obj.is_updated()
-def test_updatablecollection_without_derived_parameters():
+def test_updatablecollection_without_derived_parameters() -> None:
obj: UpdatableCollection[Updatable] = UpdatableCollection()
assert obj.get_derived_parameters() is None
-def test_updatablecollection_with_items_without_derived_parameters():
+def test_updatablecollection_with_items_without_derived_parameters() -> None:
"""get_derived_parameters returns None when all items have no derived parameters."""
obj: UpdatableCollection[Updatable] = UpdatableCollection()
@@ -155,7 +155,7 @@ def test_updatablecollection_with_items_without_derived_parameters():
assert obj.get_derived_parameters() is None
-def test_collection_update_already_updated():
+def test_collection_update_already_updated() -> None:
"""Test calling update() twice on an UpdatableCollection.
The second call should return early without updating items again
@@ -186,7 +186,7 @@ def test_collection_update_already_updated():
assert obj2.a == 3.0
-def test_collection_reset_with_items():
+def test_collection_reset_with_items() -> None:
"""Test reset() on an UpdatableCollection with items.
Verifies that reset() sets _updated to False and calls reset() on all
diff --git a/tests/updatable/test_interface.py b/tests/updatable/test_interface.py
index 91b69123a..fc29a9c2f 100644
--- a/tests/updatable/test_interface.py
+++ b/tests/updatable/test_interface.py
@@ -12,7 +12,7 @@
from tests.updatable.updatable_test_support import SimpleUpdatable
-def test_warn_override():
+def test_warn_override() -> None:
BadUpdatable = type(
"BadUpdatable", (Updatable,), {"update": lambda self, params: None}
)
@@ -22,7 +22,7 @@ def test_warn_override():
assert any("update" in str(r.message) for r in record)
-def test_raise_override():
+def test_raise_override() -> None:
BadUpdatable = type(
"BadUpdatable", (Updatable,), {"update": lambda self, params: None}
)
@@ -31,7 +31,7 @@ def test_raise_override():
assert_updatable_interface(obj, raise_on_override=True)
-def test_collection_items():
+def test_collection_items() -> None:
BadUpdatable = type(
"BadUpdatable", (Updatable,), {"update": lambda self, params: None}
)
@@ -40,7 +40,7 @@ def test_collection_items():
assert_updatable_interface(coll)
-def test_collection_override():
+def test_collection_override() -> None:
"""Ensure overriding UpdatableCollection methods is detected."""
# create a subclass of UpdatableCollection that overrides 'update'
BadCollection = type(
@@ -52,7 +52,7 @@ def test_collection_override():
assert_updatable_interface(coll)
-def test_recurses_attributes():
+def test_recurses_attributes() -> None:
BadUpdatable = type(
"BadUpdatable", (Updatable,), {"update": lambda self, params: None}
)
@@ -63,7 +63,7 @@ def test_recurses_attributes():
assert_updatable_interface(parent)
-def test_exact_single_method_override():
+def test_exact_single_method_override() -> None:
"""Assert the warning lists the single overridden method exactly."""
BadUpdatable = type("BadUpdatable", (Updatable,), {"reset": lambda self: None})
obj = BadUpdatable()
@@ -73,7 +73,7 @@ def test_exact_single_method_override():
assert "['reset']" in str(record[0].message)
-def test_exact_multiple_method_override():
+def test_exact_multiple_method_override() -> None:
"""Assert the warning lists multiple overridden methods in the defined order."""
impl = {
"update": (lambda self, params: None),
@@ -87,7 +87,7 @@ def test_exact_multiple_method_override():
assert "['update', 'required_parameters']" in str(record[0].message)
-def test_collection_exact_methods():
+def test_collection_exact_methods() -> None:
"""Ensure UpdatableCollection overrides are reported with exact methods."""
impl = {"reset": (lambda self: None), "get_derived_parameters": (lambda self: None)}
BadCollection = type("BadCollection", (UpdatableCollection,), impl)
@@ -97,7 +97,7 @@ def test_collection_exact_methods():
assert "['reset', 'get_derived_parameters']" in str(record[0].message)
-def test_recursive_flag_prevents_recursion():
+def test_recursive_flag_prevents_recursion() -> None:
"""If recursive=False, child updatables should not be checked."""
BadUpdatable = type(
"BadUpdatable", (Updatable,), {"update": lambda self, params: None}
@@ -113,7 +113,7 @@ def test_recursive_flag_prevents_recursion():
assert len(w) == 0
-def test_collection_recursive_flag_prevents_recursion():
+def test_collection_recursive_flag_prevents_recursion() -> None:
"""If recursive=False, items inside an UpdatableCollection should not be checked."""
BadUpdatable = type(
"BadUpdatable", (Updatable,), {"update": lambda self, params: None}
@@ -127,7 +127,7 @@ def test_collection_recursive_flag_prevents_recursion():
assert len(w) == 0
-def test_collection_recursive_raise_on_override():
+def test_collection_recursive_raise_on_override() -> None:
BadUpdatable = type(
"BadUpdatable", (Updatable,), {"update": lambda self, params: None}
)
@@ -137,7 +137,7 @@ def test_collection_recursive_raise_on_override():
assert_updatable_interface(coll, recursive=True, raise_on_override=True)
-def test_non_updatable_input_raises_typeerror():
+def test_non_updatable_input_raises_typeerror() -> None:
"""Passing a non-Updatable and non-UpdatableCollection should raise TypeError."""
with pytest.raises(TypeError):
assert_updatable_interface(42) # type: ignore
diff --git a/tests/updatable/test_records.py b/tests/updatable/test_records.py
index 1a115fccd..820707246 100644
--- a/tests/updatable/test_records.py
+++ b/tests/updatable/test_records.py
@@ -9,7 +9,7 @@
)
-def test_updatable_reports():
+def test_updatable_reports() -> None:
su = SimpleUpdatable("bob")
mu = MinimalUpdatable("larry")
su.mu = mu # pylint: disable=attribute-defined-outside-init
@@ -27,7 +27,7 @@ def test_updatable_reports():
assert "Sampler parameters used: ['a']" in after_use
-def test_updatable_record_single():
+def test_updatable_record_single() -> None:
"""Test record creation for a single Updatable without nesting."""
obj = SimpleUpdatable("test")
params = ParamsMap({"test_x": 1.0, "test_y": 2.0})
@@ -44,7 +44,7 @@ def test_updatable_record_single():
assert len(record.child_records) == 0
-def test_updatable_record_with_internal_params():
+def test_updatable_record_with_internal_params() -> None:
"""Test record creation with both sampler and internal parameters."""
obj = SimpleUpdatable("test")
obj.set_internal_parameter(
@@ -67,7 +67,7 @@ def test_updatable_record_with_internal_params():
assert sorted(record.internal_params) == ["internal1", "internal2"]
-def test_updatable_record_nested():
+def test_updatable_record_nested() -> None:
"""Test record creation for nested Updatable objects."""
parent = SimpleUpdatable("parent")
child = MinimalUpdatable("child")
@@ -91,7 +91,7 @@ def test_updatable_record_nested():
assert child_record.sampler_params == ["a"]
-def test_updatable_record_complex_hierarchy():
+def test_updatable_record_complex_hierarchy() -> None:
"""Test record creation for a complex hierarchy of nested objects."""
root = SimpleUpdatable("root")
branch1 = MinimalUpdatable("branch1")
@@ -142,7 +142,7 @@ def test_updatable_record_complex_hierarchy():
assert leaf2_record.cls == "UpdatableWithDerived"
-def test_updatable_record_empty_params():
+def test_updatable_record_empty_params() -> None:
"""Test record creation for an object with no parameters."""
class EmptyUpdatable(Updatable):
@@ -160,7 +160,7 @@ class EmptyUpdatable(Updatable):
assert len(record.internal_params) == 0
-def test_updatable_usage_record_empty_and_print_empty():
+def test_updatable_usage_record_empty_and_print_empty() -> None:
rec = UpdatableUsageRecord(
cls="EmptyUpdatable",
prefix="pfx",
@@ -181,7 +181,7 @@ def test_updatable_usage_record_empty_and_print_empty():
assert lines == ["EmptyUpdatable(pfx): "]
-def test_updatable_usage_record_parent_collapses_and_printing():
+def test_updatable_usage_record_parent_collapses_and_printing() -> None:
child = UpdatableUsageRecord(
cls="Child",
prefix="c",
@@ -208,7 +208,7 @@ def test_updatable_usage_record_parent_collapses_and_printing():
]
-def test_updatable_usage_record_indent_and_child_recursion():
+def test_updatable_usage_record_indent_and_child_recursion() -> None:
child = UpdatableUsageRecord(
cls="Child",
prefix="c",
@@ -239,7 +239,7 @@ def test_updatable_usage_record_indent_and_child_recursion():
assert lines == expected
-def test_updatable_usage_record_empty_child_and_print_empty_options():
+def test_updatable_usage_record_empty_child_and_print_empty_options() -> None:
# child is empty
child = UpdatableUsageRecord(
cls="Child",
@@ -266,7 +266,7 @@ def test_updatable_usage_record_empty_child_and_print_empty_options():
assert lines == ["Parent(p) => Child(c): "]
-def test_updatable_usage_record_already_updated_flag():
+def test_updatable_usage_record_already_updated_flag() -> None:
"""If an UpdatableUsageRecord indicates it was already updated, the
get_log_lines should return a single line noting it was already updated.
"""
@@ -284,7 +284,7 @@ def test_updatable_usage_record_already_updated_flag():
assert lines == ["Already: (already updated)"]
-def test_updatable_usage_record_internal_params_only():
+def test_updatable_usage_record_internal_params_only() -> None:
"""If sampler_params is empty but internal_params is non-empty,
is_empty should be False and get_log_lines should show the internal
parameters line (this covers the second early-return branch).
diff --git a/tests/updatable/test_utils.py b/tests/updatable/test_utils.py
index d853be93e..9823a0931 100644
--- a/tests/updatable/test_utils.py
+++ b/tests/updatable/test_utils.py
@@ -4,7 +4,7 @@
from tests.updatable.updatable_test_support import MinimalUpdatable, SimpleUpdatable
-def test_get_default_params_empty_args():
+def test_get_default_params_empty_args() -> None:
"""Test get_default_params() with no arguments.
Should return an empty dictionary (lines 19-23 in _utils.py).
@@ -14,7 +14,7 @@ def test_get_default_params_empty_args():
assert isinstance(result, dict)
-def test_get_default_params_map_empty_args():
+def test_get_default_params_map_empty_args() -> None:
"""Test get_default_params_map() with no arguments.
Should return an empty ParamsMap (lines 32-33 in _utils.py).
@@ -24,7 +24,7 @@ def test_get_default_params_map_empty_args():
assert len(result.keys()) == 0
-def test_get_default_params_with_multiple_updatables():
+def test_get_default_params_with_multiple_updatables() -> None:
"""Test get_default_params() with multiple updatables.
Verifies that all default values are collected correctly.
diff --git a/tests/updatable/updatable_test_support.py b/tests/updatable/updatable_test_support.py
index 49f73f776..dd8612d64 100644
--- a/tests/updatable/updatable_test_support.py
+++ b/tests/updatable/updatable_test_support.py
@@ -29,7 +29,7 @@ def __init__(self, prefix: str | None = None):
class UpdatableWithDerived(Updatable):
"""A concrete type that implements Updatable that implements derived parameters."""
- def __init__(self):
+ def __init__(self) -> None:
"""Initialize object with defaulted values."""
super().__init__()