toml-repo 0.1.2__py3-none-any.whl
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.
- toml_repo/__init__.py +19 -0
- toml_repo/http_client.py +5 -0
- toml_repo/manager.py +141 -0
- toml_repo/py.typed +1 -0
- toml_repo/repo.py +735 -0
- toml_repo-0.1.2.dist-info/METADATA +151 -0
- toml_repo-0.1.2.dist-info/RECORD +9 -0
- toml_repo-0.1.2.dist-info/WHEEL +4 -0
- toml_repo-0.1.2.dist-info/licenses/LICENSE +674 -0
toml_repo/__init__.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The toml_repo package provides a generic TOML-based repository manager.
|
|
3
|
+
|
|
4
|
+
It handles finding, loading, merging, and searching TOML configuration repositories
|
|
5
|
+
with support for multiple URL schemes (file://, pkg://, http://), import resolution,
|
|
6
|
+
and precedence-based configuration merging.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .manager import RepoManager
|
|
10
|
+
from .repo import REPO_REF, Repo, get_config_suffix, set_config_suffix, set_pkg_resource_root
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"RepoManager",
|
|
14
|
+
"Repo",
|
|
15
|
+
"get_config_suffix",
|
|
16
|
+
"set_config_suffix",
|
|
17
|
+
"set_pkg_resource_root",
|
|
18
|
+
"REPO_REF",
|
|
19
|
+
]
|
toml_repo/http_client.py
ADDED
toml_repo/manager.py
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Manages the repository of TOML-based processing recipes and configurations.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
# pyright: reportImportCycles=false
|
|
6
|
+
# The circular dependency between manager.py and repo.py is properly handled
|
|
7
|
+
# using TYPE_CHECKING and local imports where needed.
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import logging
|
|
12
|
+
from typing import TYPE_CHECKING, Any, overload
|
|
13
|
+
|
|
14
|
+
from multidict import MultiDict
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from toml_repo.repo import Repo
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class RepoManager:
|
|
21
|
+
"""
|
|
22
|
+
Manages the collection of TOML repositories.
|
|
23
|
+
|
|
24
|
+
This class is responsible for finding, loading, and providing an API
|
|
25
|
+
for searching through known repositories defined in TOML configuration files.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self):
|
|
29
|
+
"""
|
|
30
|
+
Initializes the RepoManager.
|
|
31
|
+
"""
|
|
32
|
+
self.repos: list[Repo] = []
|
|
33
|
+
|
|
34
|
+
# Most users will just want to read from merged
|
|
35
|
+
self.merged: MultiDict[Any] = MultiDict()
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def regular_repos(self) -> list[Repo]:
|
|
39
|
+
"We exclude certain repo types (preferences, recipe) from the list of repos users care about."
|
|
40
|
+
return [
|
|
41
|
+
r
|
|
42
|
+
for r in self.repos
|
|
43
|
+
if r.kind() not in ["preferences", "recipe"] and not r.is_scheme("pkg")
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
def add_repo(self, url: str) -> Repo:
|
|
47
|
+
from toml_repo.repo import Repo # Local import to avoid circular dependency
|
|
48
|
+
|
|
49
|
+
logging.debug(f"Adding repo: {url}")
|
|
50
|
+
r = Repo(url)
|
|
51
|
+
self.repos.append(r)
|
|
52
|
+
|
|
53
|
+
# FIXME, generate the merged dict lazily
|
|
54
|
+
self._add_merged(r)
|
|
55
|
+
|
|
56
|
+
# if this new repo has sub-repos, add them too
|
|
57
|
+
r.add_by_repo_refs(self)
|
|
58
|
+
|
|
59
|
+
return r
|
|
60
|
+
|
|
61
|
+
def get_repo_by_url(self, url: str) -> Repo | None:
|
|
62
|
+
"""
|
|
63
|
+
Retrieves a repository by its URL.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
url: The URL of the repository to retrieve.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
The Repo instance with the matching URL, or None if not found.
|
|
70
|
+
"""
|
|
71
|
+
for repo in self.repos:
|
|
72
|
+
if repo.url == url:
|
|
73
|
+
return repo
|
|
74
|
+
return None
|
|
75
|
+
|
|
76
|
+
def get_repo_by_kind(self, kind: str) -> Repo | None:
|
|
77
|
+
"""
|
|
78
|
+
Retrieves the first repository matching the specified kind.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
kind: The kind of repository to search for (e.g., "recipe", "preferences").
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
The first Repo instance matching the kind, or None if not found.
|
|
85
|
+
"""
|
|
86
|
+
for repo in self.repos:
|
|
87
|
+
if repo.kind() == kind:
|
|
88
|
+
return repo
|
|
89
|
+
return None
|
|
90
|
+
|
|
91
|
+
# If a default was provided use that type for return
|
|
92
|
+
@overload
|
|
93
|
+
def get[T](self, key: str, default: T) -> T | Any: ...
|
|
94
|
+
|
|
95
|
+
@overload
|
|
96
|
+
def get(self, key: str, default: None = None) -> Any | None: ...
|
|
97
|
+
|
|
98
|
+
def get[T](self, key: str, default: T | None = None) -> T | Any | None:
|
|
99
|
+
"""
|
|
100
|
+
Searches for a key across all repositories and returns the first value found.
|
|
101
|
+
The search is performed in reverse order of repository loading, so the
|
|
102
|
+
most recently added repositories have precedence.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
key: The dot-separated key to search for (e.g., "repo.kind").
|
|
106
|
+
default: The value to return if the key is not found in any repo.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
The found value or the default.
|
|
110
|
+
"""
|
|
111
|
+
# Iterate in reverse to give precedence to later-loaded repos
|
|
112
|
+
for repo in reversed(self.repos):
|
|
113
|
+
value = repo.get(key)
|
|
114
|
+
if value is not None:
|
|
115
|
+
return value
|
|
116
|
+
|
|
117
|
+
return default
|
|
118
|
+
|
|
119
|
+
def dump(self):
|
|
120
|
+
"""
|
|
121
|
+
Prints a detailed, multi-line description of the combined top-level keys
|
|
122
|
+
and values from all repositories, using a MultiDict for aggregation.
|
|
123
|
+
This is useful for debugging and inspecting the consolidated configuration.
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
combined_config = self.merged
|
|
127
|
+
logging.info("RepoManager Dump")
|
|
128
|
+
for key, value in combined_config.items():
|
|
129
|
+
# tomlkit.items() can return complex types (e.g., ArrayOfTables, Table)
|
|
130
|
+
# For a debug dump, a simple string representation is usually sufficient.
|
|
131
|
+
logging.info(" %s: %s", key, value)
|
|
132
|
+
|
|
133
|
+
def _add_merged(self, repo: Repo) -> None:
|
|
134
|
+
for key, value in repo.config.items():
|
|
135
|
+
self.merged.add(key, value)
|
|
136
|
+
|
|
137
|
+
def __str__(self):
|
|
138
|
+
lines = [f"RepoManager with {len(self.repos)} repositories:"]
|
|
139
|
+
for i, repo in enumerate(self.repos):
|
|
140
|
+
lines.append(f" [{i}] {repo.url}")
|
|
141
|
+
return "\n".join(lines)
|
toml_repo/py.typed
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
py.typed
|