laco-pytest 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,29 @@
1
+ Metadata-Version: 2.4
2
+ Name: laco-pytest
3
+ Version: 1.0.0
4
+ Summary: pytest fixtures and helpers for laco.
5
+ Author-email: Kurt Stolle <kurt@khws.io>
6
+ Requires-Python: >=3.13
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: laco>=1.0.0
9
+ Requires-Dist: pytest>=8.0
10
+
11
+ # Laco-Pytest
12
+
13
+ Pytest plugin and fixtures for laco.
14
+
15
+ Part of the [laco](https://github.com/khwstolle/laco) project — see the [root README](../../README.md) for an overview.
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ pip install laco-pytest
21
+ ```
22
+
23
+ ## Features
24
+
25
+ `laco_config` fixture, `laco_config_file` fixture, `--laco-config` CLI option
26
+
27
+ ## Usage
28
+
29
+ See [`docs/index.md`](docs/index.md) for the full guide.
@@ -0,0 +1,19 @@
1
+ # Laco-Pytest
2
+
3
+ Pytest plugin and fixtures for laco.
4
+
5
+ Part of the [laco](https://github.com/khwstolle/laco) project — see the [root README](../../README.md) for an overview.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ pip install laco-pytest
11
+ ```
12
+
13
+ ## Features
14
+
15
+ `laco_config` fixture, `laco_config_file` fixture, `--laco-config` CLI option
16
+
17
+ ## Usage
18
+
19
+ See [`docs/index.md`](docs/index.md) for the full guide.
@@ -0,0 +1,22 @@
1
+ [build-system]
2
+ requires = ["setuptools>=75", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "laco-pytest"
7
+ version = "1.0.0"
8
+ description = "pytest fixtures and helpers for laco."
9
+ readme = "README.md"
10
+ requires-python = ">=3.13"
11
+ authors = [{ name = "Kurt Stolle", email = "kurt@khws.io" }]
12
+ dependencies = ["laco>=1.0.0", "pytest>=8.0"]
13
+
14
+ [project.entry-points."pytest11"]
15
+ laco = "laco.integrations.pytest.plugin"
16
+
17
+ [tool.setuptools.packages.find]
18
+ where = ["sources"]
19
+ namespaces = true
20
+
21
+ [tool.uv.sources]
22
+ laco = { workspace = true }
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,6 @@
1
+ """pytest helpers for laco — re-exports the plugin fixtures for direct import."""
2
+
3
+ from laco.integrations.pytest.plugin import laco_config as laco_config
4
+ from laco.integrations.pytest.plugin import laco_config_file as laco_config_file
5
+
6
+ __all__ = ["laco_config", "laco_config_file"]
@@ -0,0 +1,131 @@
1
+ """pytest plugin — auto-registered via the ``pytest11`` entry point.
2
+
3
+ Provides:
4
+
5
+ - ``laco_config_file`` — session-scoped fixture: path to the config under
6
+ test, resolved from the ``--laco-config`` CLI option.
7
+ - ``laco_config`` — function-scoped fixture: loaded DictConfig with optional
8
+ per-test overrides via indirect parametrize.
9
+
10
+ Examples
11
+ --------
12
+ ::
13
+
14
+ # Override the default config path for the whole session:
15
+ # pytest --laco-config configs/train.py
16
+
17
+ # In tests:
18
+ def test_lr(laco_config):
19
+ assert laco_config.lr > 0
20
+
21
+
22
+ # Parametrise overrides:
23
+ @pytest.mark.parametrize("laco_config", [{"lr": 1e-3}, {"lr": 1e-4}], indirect=True)
24
+ def test_lr_values(laco_config):
25
+ assert laco_config.lr in (1e-3, 1e-4)
26
+ """
27
+
28
+ from __future__ import annotations
29
+
30
+ import typing
31
+
32
+ import pytest
33
+
34
+ if typing.TYPE_CHECKING:
35
+ from omegaconf import DictConfig
36
+
37
+
38
+ def pytest_addoption(parser: pytest.Parser) -> None:
39
+ parser.addoption(
40
+ "--laco-config",
41
+ default=None,
42
+ metavar="PATH",
43
+ help="Path to the default laco config file used by the laco_config fixture.",
44
+ )
45
+
46
+
47
+ @pytest.fixture(scope="session")
48
+ def laco_config_file(request: pytest.FixtureRequest) -> str | None:
49
+ """Return the path to the laco config under test (``--laco-config`` option).
50
+
51
+ Returns
52
+ -------
53
+ str | None
54
+ The path passed to ``--laco-config``, or ``None`` if not provided.
55
+ """
56
+ return request.config.getoption("--laco-config")
57
+
58
+
59
+ @pytest.fixture
60
+ def laco_config(
61
+ request: pytest.FixtureRequest,
62
+ laco_config_file: str | None,
63
+ ) -> DictConfig:
64
+ """Load and return a laco DictConfig, optionally with per-test overrides.
65
+
66
+ When used with ``indirect=True`` parametrize, the parameter may be:
67
+
68
+ - A ``dict`` of override key-value pairs (e.g. ``{"lr": 1e-3}``).
69
+ - A ``list[str]`` of Hydra-style override strings (e.g. ``["lr=1e-3"]``).
70
+ - A path ``str`` overriding the config file for this test only.
71
+
72
+ Parameters
73
+ ----------
74
+ request : pytest.FixtureRequest
75
+ Pytest fixture request object.
76
+ laco_config_file : str | None
77
+ Session-level config path from ``--laco-config``, or ``None``.
78
+
79
+ Returns
80
+ -------
81
+ DictConfig
82
+ Resolved laco DictConfig, with any per-test overrides applied.
83
+
84
+ Examples
85
+ --------
86
+ ::
87
+
88
+ def test_default(laco_config):
89
+ assert laco_config.epochs == 10
90
+
91
+
92
+ @pytest.mark.parametrize("laco_config", [{"epochs": 5}], indirect=True)
93
+ def test_overridden(laco_config):
94
+ assert laco_config.epochs == 5
95
+ """
96
+ import laco
97
+ from laco._overrides import apply_overrides
98
+
99
+ param = getattr(request, "param", None)
100
+
101
+ # Determine config path
102
+ if isinstance(param, str) and not isinstance(param, dict):
103
+ # The param is itself a config path
104
+ path = param
105
+ overrides: list[str] = []
106
+ else:
107
+ path = laco_config_file
108
+ if path is None:
109
+ msg = (
110
+ "laco_config fixture requires either --laco-config CLI option "
111
+ "or a path string passed via indirect parametrize."
112
+ )
113
+ pytest.fail(msg)
114
+ if isinstance(param, dict):
115
+ overrides = []
116
+ for k, v in param.items():
117
+ if v is None:
118
+ overrides.append(f"{k}=null")
119
+ elif isinstance(v, str):
120
+ overrides.append(f"{k}={v!r}")
121
+ else:
122
+ overrides.append(f"{k}={v}")
123
+ elif isinstance(param, list):
124
+ overrides = param
125
+ else:
126
+ overrides = []
127
+
128
+ cfg = laco.load(path)
129
+ if overrides:
130
+ cfg = apply_overrides(cfg, overrides)
131
+ return cfg
@@ -0,0 +1,29 @@
1
+ Metadata-Version: 2.4
2
+ Name: laco-pytest
3
+ Version: 1.0.0
4
+ Summary: pytest fixtures and helpers for laco.
5
+ Author-email: Kurt Stolle <kurt@khws.io>
6
+ Requires-Python: >=3.13
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: laco>=1.0.0
9
+ Requires-Dist: pytest>=8.0
10
+
11
+ # Laco-Pytest
12
+
13
+ Pytest plugin and fixtures for laco.
14
+
15
+ Part of the [laco](https://github.com/khwstolle/laco) project — see the [root README](../../README.md) for an overview.
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ pip install laco-pytest
21
+ ```
22
+
23
+ ## Features
24
+
25
+ `laco_config` fixture, `laco_config_file` fixture, `--laco-config` CLI option
26
+
27
+ ## Usage
28
+
29
+ See [`docs/index.md`](docs/index.md) for the full guide.
@@ -0,0 +1,11 @@
1
+ README.md
2
+ pyproject.toml
3
+ sources/laco/integrations/pytest/__init__.py
4
+ sources/laco/integrations/pytest/plugin.py
5
+ sources/laco_pytest.egg-info/PKG-INFO
6
+ sources/laco_pytest.egg-info/SOURCES.txt
7
+ sources/laco_pytest.egg-info/dependency_links.txt
8
+ sources/laco_pytest.egg-info/entry_points.txt
9
+ sources/laco_pytest.egg-info/requires.txt
10
+ sources/laco_pytest.egg-info/top_level.txt
11
+ tests/test_laco_pytest.py
@@ -0,0 +1,2 @@
1
+ [pytest11]
2
+ laco = laco.integrations.pytest.plugin
@@ -0,0 +1,2 @@
1
+ laco>=1.0.0
2
+ pytest>=8.0
@@ -0,0 +1,40 @@
1
+ """Tests for laco-pytest."""
2
+
3
+
4
+ def test_import():
5
+ import laco.integrations.pytest # noqa: F401
6
+
7
+
8
+ def test_public_api():
9
+ import laco.integrations.pytest as laco_pytest
10
+
11
+ assert hasattr(laco_pytest, "laco_config")
12
+ assert hasattr(laco_pytest, "laco_config_file")
13
+ assert set(laco_pytest.__all__) == {"laco_config", "laco_config_file"}
14
+
15
+
16
+ def test_plugin_registers_option(pytestconfig):
17
+ """The --laco-config option should be registered by the plugin."""
18
+ known = {opt.dest for opt in pytestconfig._parser._anonymous.options}
19
+ assert "laco_config" in known
20
+
21
+
22
+ def test_laco_config_file_fixture_default(testdir):
23
+ """laco_config_file returns None when --laco-config is not passed."""
24
+ testdir.makepyfile("""
25
+ def test_default(laco_config_file):
26
+ assert laco_config_file is None
27
+ """)
28
+ result = testdir.runpytest()
29
+ result.assert_outcomes(passed=1)
30
+
31
+
32
+ def test_laco_config_fixture_fails_without_path(testdir):
33
+ """laco_config fails with a clear message when no path is configured."""
34
+ testdir.makepyfile("""
35
+ def test_no_path(laco_config):
36
+ pass
37
+ """)
38
+ result = testdir.runpytest()
39
+ result.assert_outcomes(failed=1)
40
+ result.stdout.fnmatch_lines(["*--laco-config*"])