canopee 0.0.2__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.
canopee-0.0.2/PKG-INFO ADDED
@@ -0,0 +1,116 @@
1
+ Metadata-Version: 2.3
2
+ Name: canopee
3
+ Version: 0.0.2
4
+ Summary: A type-safe python configuration library
5
+ Author: Alexandre Mayerowitz
6
+ Author-email: Alexandre Mayerowitz <alexandre.mayerowitz@gmail.com>
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
15
+ Classifier: Topic :: Software Development :: Quality Assurance
16
+ Classifier: Topic :: Software Development :: Testing
17
+ Classifier: Topic :: Software Development :: Libraries
18
+ Requires-Dist: pydantic>=2.12.5
19
+ Requires-Dist: tomli-w>=1.2.0
20
+ Requires-Python: >=3.11
21
+ Project-URL: Repository, https://github.com/mayeroa/canopee
22
+ Project-URL: Homepage, https://mayeroa.github.io/canopee/
23
+ Project-URL: Documentation, https://mayeroa.github.io/canopee/
24
+ Project-URL: Issues, https://github.com/mayeroa/canopee/issues
25
+ Description-Content-Type: text/markdown
26
+
27
+ <div align="center">
28
+ <h1>🌲 Canopee</h1>
29
+ <p><strong>A type-safe, fluent configuration library for Python 3.11+.</strong></p>
30
+ <p>
31
+ <a href="https://pypi.org/project/canopee/"><img src="https://img.shields.io/pypi/v/canopee.svg" alt="PyPI version"></a>
32
+ <a href="https://pypi.org/project/canopee/"><img src="https://img.shields.io/pypi/pyversions/canopee.svg" alt="Python versions"></a>
33
+ <a href="https://github.com/canopee-py/canopee/actions"><img src="https://img.shields.io/github/actions/workflow/status/canopee-py/canopee/ci.yml?branch=main" alt="CI Status"></a>
34
+ </p>
35
+ </div>
36
+
37
+ ---
38
+
39
+ **Canopee** is a production-ready configuration library that treats Python as the ultimate config DSL.
40
+
41
+ Built on top of Pydantic v2, it removes the brittleness of YAMLs, silent mutation footguns, and metaclass magic, giving you IDE autocomplete, instant validation, and elegant hyperparameter sweeping out of the box.
42
+
43
+ ## 🌟 Why Canopee?
44
+
45
+ * **Always Valid**: Configs are validated precisely at construction. No runtime surprises.
46
+ * **Immutable**: `ConfigBase` objects are `frozen=True`. They can be hashed, cached, and safely passed across threads.
47
+ * **Type-Safe Evolution**: Evolve new variants purely with Python keywords via the `.evolve(**kwargs)` method.
48
+ * **First-Class Sweeps**: Define hyperparameter search spaces directly over your types, using strategies like *grid*, *random*, or *optuna*.
49
+ * **Symmetric I/O**: Naturally save and load instances via `.toml`, `.yaml`, or `.json` extensions natively, or inject CLI/Env overrides securely.
50
+
51
+ ## 🚀 Quickstart
52
+
53
+ ### Installation
54
+ ```bash
55
+ pip install canopee
56
+ ```
57
+
58
+ ### Basic Usage
59
+
60
+ Subclass `ConfigBase` as you would any Pydantic model.
61
+
62
+ ```python
63
+ from canopee import ConfigBase
64
+ from pydantic import computed_field
65
+
66
+ class TrainingConfig(ConfigBase):
67
+ learning_rate: float = 1e-3
68
+ epochs: int = 20
69
+ batch_size: int = 128
70
+
71
+ @computed_field
72
+ @property
73
+ def total_steps(self) -> int:
74
+ return self.epochs * (10_000 // self.batch_size)
75
+
76
+ # 1. Instantiate (validated instantly)
77
+ cfg = TrainingConfig()
78
+
79
+ # 2. Evolve (returns a new modified frozen instance, IDE autocomplete works perfectly!)
80
+ fast_cfg = cfg.evolve(epochs=5, learning_rate=5e-3)
81
+
82
+ # Computed fields naturally update based on the new instance values
83
+ print(fast_cfg.total_steps)
84
+
85
+ # 3. Save it to disk (JSON, TOML, YAML supported out-of-the-box)
86
+ fast_cfg.save("experiment.toml")
87
+ ```
88
+
89
+ ### Sweeps
90
+
91
+ Native support for generating massive, reproducible configuration variants.
92
+
93
+ ```python
94
+ from canopee.sweep import Sweep, log_uniform, choice
95
+
96
+ def train(cfg: TrainingConfig) -> float:
97
+ # return accuracy metric here
98
+ return 0.95
99
+
100
+ best_cfg = (
101
+ Sweep(TrainingConfig())
102
+ .vary("learning_rate", log_uniform(1e-5, 1e-1))
103
+ .vary("batch_size", choice(32, 64, 128))
104
+ .strategy("random", n_samples=20, seed=42)
105
+ .run(train)
106
+ .best(minimize=False)
107
+ )
108
+ ```
109
+
110
+ ## 📖 Documentation
111
+
112
+ The full documentation—including Guides on advanced `ConfigStore` registries and `cli/env` Source merging—can be generated by running:
113
+
114
+ ```bash
115
+ uv run zensical serve
116
+ ```
@@ -0,0 +1,90 @@
1
+ <div align="center">
2
+ <h1>🌲 Canopee</h1>
3
+ <p><strong>A type-safe, fluent configuration library for Python 3.11+.</strong></p>
4
+ <p>
5
+ <a href="https://pypi.org/project/canopee/"><img src="https://img.shields.io/pypi/v/canopee.svg" alt="PyPI version"></a>
6
+ <a href="https://pypi.org/project/canopee/"><img src="https://img.shields.io/pypi/pyversions/canopee.svg" alt="Python versions"></a>
7
+ <a href="https://github.com/canopee-py/canopee/actions"><img src="https://img.shields.io/github/actions/workflow/status/canopee-py/canopee/ci.yml?branch=main" alt="CI Status"></a>
8
+ </p>
9
+ </div>
10
+
11
+ ---
12
+
13
+ **Canopee** is a production-ready configuration library that treats Python as the ultimate config DSL.
14
+
15
+ Built on top of Pydantic v2, it removes the brittleness of YAMLs, silent mutation footguns, and metaclass magic, giving you IDE autocomplete, instant validation, and elegant hyperparameter sweeping out of the box.
16
+
17
+ ## 🌟 Why Canopee?
18
+
19
+ * **Always Valid**: Configs are validated precisely at construction. No runtime surprises.
20
+ * **Immutable**: `ConfigBase` objects are `frozen=True`. They can be hashed, cached, and safely passed across threads.
21
+ * **Type-Safe Evolution**: Evolve new variants purely with Python keywords via the `.evolve(**kwargs)` method.
22
+ * **First-Class Sweeps**: Define hyperparameter search spaces directly over your types, using strategies like *grid*, *random*, or *optuna*.
23
+ * **Symmetric I/O**: Naturally save and load instances via `.toml`, `.yaml`, or `.json` extensions natively, or inject CLI/Env overrides securely.
24
+
25
+ ## 🚀 Quickstart
26
+
27
+ ### Installation
28
+ ```bash
29
+ pip install canopee
30
+ ```
31
+
32
+ ### Basic Usage
33
+
34
+ Subclass `ConfigBase` as you would any Pydantic model.
35
+
36
+ ```python
37
+ from canopee import ConfigBase
38
+ from pydantic import computed_field
39
+
40
+ class TrainingConfig(ConfigBase):
41
+ learning_rate: float = 1e-3
42
+ epochs: int = 20
43
+ batch_size: int = 128
44
+
45
+ @computed_field
46
+ @property
47
+ def total_steps(self) -> int:
48
+ return self.epochs * (10_000 // self.batch_size)
49
+
50
+ # 1. Instantiate (validated instantly)
51
+ cfg = TrainingConfig()
52
+
53
+ # 2. Evolve (returns a new modified frozen instance, IDE autocomplete works perfectly!)
54
+ fast_cfg = cfg.evolve(epochs=5, learning_rate=5e-3)
55
+
56
+ # Computed fields naturally update based on the new instance values
57
+ print(fast_cfg.total_steps)
58
+
59
+ # 3. Save it to disk (JSON, TOML, YAML supported out-of-the-box)
60
+ fast_cfg.save("experiment.toml")
61
+ ```
62
+
63
+ ### Sweeps
64
+
65
+ Native support for generating massive, reproducible configuration variants.
66
+
67
+ ```python
68
+ from canopee.sweep import Sweep, log_uniform, choice
69
+
70
+ def train(cfg: TrainingConfig) -> float:
71
+ # return accuracy metric here
72
+ return 0.95
73
+
74
+ best_cfg = (
75
+ Sweep(TrainingConfig())
76
+ .vary("learning_rate", log_uniform(1e-5, 1e-1))
77
+ .vary("batch_size", choice(32, 64, 128))
78
+ .strategy("random", n_samples=20, seed=42)
79
+ .run(train)
80
+ .best(minimize=False)
81
+ )
82
+ ```
83
+
84
+ ## 📖 Documentation
85
+
86
+ The full documentation—including Guides on advanced `ConfigStore` registries and `cli/env` Source merging—can be generated by running:
87
+
88
+ ```bash
89
+ uv run zensical serve
90
+ ```
@@ -0,0 +1,69 @@
1
+ [build-system]
2
+ requires = ["uv_build>=0.10.8,<0.11.0"]
3
+ build-backend = "uv_build"
4
+
5
+ [project]
6
+ name = "canopee"
7
+ version = "0.0.2"
8
+ description = "A type-safe python configuration library"
9
+ readme = "README.md"
10
+ authors = [
11
+ { name = "Alexandre Mayerowitz", email = "alexandre.mayerowitz@gmail.com" },
12
+ ]
13
+ requires-python = ">=3.11"
14
+ dependencies = ["pydantic>=2.12.5", "tomli-w>=1.2.0"]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: 3.13",
23
+ "Programming Language :: Python :: 3.14",
24
+ "Topic :: Software Development :: Quality Assurance",
25
+ "Topic :: Software Development :: Testing",
26
+ "Topic :: Software Development :: Libraries",
27
+ ]
28
+
29
+ [project.urls]
30
+ Repository = "https://github.com/mayeroa/canopee"
31
+ Homepage = "https://mayeroa.github.io/canopee/"
32
+ Documentation = "https://mayeroa.github.io/canopee/"
33
+ Issues = "https://github.com/mayeroa/canopee/issues"
34
+
35
+ [dependency-groups]
36
+ click = ["click>=8.3.1"]
37
+ dev = [
38
+ "mkdocs-material>=9.7.4",
39
+ "pytest>=9.0.2",
40
+ "pytest-cov>=7.0.0",
41
+ "ruff>=0.15.4",
42
+ "zensical>=0.0.24",
43
+ ]
44
+ ml = ["lightning>=2.6.1", "torch>=2.10.0", "torchvision>=0.25.0"]
45
+ typer = ["typer>=0.24.1"]
46
+
47
+ [tool.ruff.lint]
48
+ extend-select = [
49
+ "F", # Pyflakes rules
50
+ "W", # PyCodeStyle warnings
51
+ "E", # PyCodeStyle errors
52
+ "I", # Sort imports properly
53
+ "UP", # Warn if certain things can changed due to newer Python versions
54
+ "C4", # Catch incorrect use of comprehensions, dict, list, etc
55
+ "FA", # Enforce from __future__ import annotations
56
+ "ISC", # Good use of string concatenation
57
+ "ICN", # Use common import conventions
58
+ "RET", # Good return practices
59
+ "SIM", # Common simplification rules
60
+ "TID", # Some good import practices
61
+ "TC", # Enforce importing certain types in a TYPE_CHECKING block
62
+ "PTH", # Use pathlib instead of os.path
63
+ "TD", # Be diligent with TODO comments
64
+ "NPY", # Some numpy-specific things
65
+ ]
66
+
67
+
68
+ [tool.pytest.ini_options]
69
+ addopts = "--maxfail=1 --cov=canopee"
@@ -0,0 +1,77 @@
1
+ """
2
+ canopee
3
+ ~~~~~~~
4
+
5
+ A type-safe, Pydantic-native configuration library with elegant
6
+ composition, immutable configs, and a powerful Sweep engine.
7
+
8
+ Quick start::
9
+
10
+ from canopee import ConfigBase
11
+ from pydantic import Field, computed_field
12
+
13
+ class TrainingConfig(ConfigBase):
14
+ lr: float = Field(default=1e-3, ge=0.0, le=1.0)
15
+ epochs: int = 10
16
+
17
+ @computed_field
18
+ @property
19
+ def warmup_steps(self) -> int:
20
+ return self.epochs * 100
21
+
22
+ cfg = TrainingConfig()
23
+
24
+ # Dict / dot-path override:
25
+ fast = cfg | {"lr": 1e-2, "epochs": 3}
26
+
27
+ # Typed keyword override:
28
+ fast = cfg.evolve(lr=1e-2, epochs=3)
29
+
30
+ # Save / load:
31
+ save(cfg, "run.toml")
32
+ cfg2 = load(TrainingConfig, "run.toml")
33
+
34
+ # String serialization:
35
+ text = dumps(cfg, "yaml")
36
+ cfg3 = loads(TrainingConfig, "yaml", text)
37
+ """
38
+
39
+ from canopee import sweep as sweep
40
+ from canopee.cli import clify, ArgparseBackend, ClickBackend, TyperBackend
41
+ from canopee.core import ConfigBase, diff, evolve, to_flat
42
+ from canopee.sources import (
43
+ CLISource,
44
+ DictSource,
45
+ EnvSource,
46
+ FileSource,
47
+ Source,
48
+ merge_sources,
49
+ )
50
+ from canopee.serialization import dumps, load, loads, save
51
+ from canopee.store import ConfigStore, global_store
52
+
53
+ __all__ = [
54
+ "ConfigBase",
55
+ "ConfigStore",
56
+ "global_store",
57
+ "Source",
58
+ "EnvSource",
59
+ "CLISource",
60
+ "FileSource",
61
+ "DictSource",
62
+ "merge_sources",
63
+ "sweep",
64
+ "clify",
65
+ "ArgparseBackend",
66
+ "ClickBackend",
67
+ "TyperBackend",
68
+ "evolve",
69
+ "diff",
70
+ "to_flat",
71
+ "save",
72
+ "load",
73
+ "dumps",
74
+ "loads",
75
+ ]
76
+
77
+ __version__ = "0.1.0"