hammad-python 0.0.30__py3-none-any.whl → 0.0.32__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.
- ham/__init__.py +200 -0
- {hammad_python-0.0.30.dist-info → hammad_python-0.0.32.dist-info}/METADATA +6 -32
- hammad_python-0.0.32.dist-info/RECORD +6 -0
- hammad/__init__.py +0 -84
- hammad/_internal.py +0 -256
- hammad/_main.py +0 -226
- hammad/cache/__init__.py +0 -40
- hammad/cache/base_cache.py +0 -181
- hammad/cache/cache.py +0 -169
- hammad/cache/decorators.py +0 -261
- hammad/cache/file_cache.py +0 -80
- hammad/cache/ttl_cache.py +0 -74
- hammad/cli/__init__.py +0 -33
- hammad/cli/animations.py +0 -573
- hammad/cli/plugins.py +0 -867
- hammad/cli/styles/__init__.py +0 -55
- hammad/cli/styles/settings.py +0 -139
- hammad/cli/styles/types.py +0 -358
- hammad/cli/styles/utils.py +0 -634
- hammad/data/__init__.py +0 -90
- hammad/data/collections/__init__.py +0 -49
- hammad/data/collections/collection.py +0 -326
- hammad/data/collections/indexes/__init__.py +0 -37
- hammad/data/collections/indexes/qdrant/__init__.py +0 -1
- hammad/data/collections/indexes/qdrant/index.py +0 -723
- hammad/data/collections/indexes/qdrant/settings.py +0 -94
- hammad/data/collections/indexes/qdrant/utils.py +0 -210
- hammad/data/collections/indexes/tantivy/__init__.py +0 -1
- hammad/data/collections/indexes/tantivy/index.py +0 -426
- hammad/data/collections/indexes/tantivy/settings.py +0 -40
- hammad/data/collections/indexes/tantivy/utils.py +0 -176
- hammad/data/configurations/__init__.py +0 -35
- hammad/data/configurations/configuration.py +0 -564
- hammad/data/models/__init__.py +0 -50
- hammad/data/models/extensions/__init__.py +0 -4
- hammad/data/models/extensions/pydantic/__init__.py +0 -42
- hammad/data/models/extensions/pydantic/converters.py +0 -759
- hammad/data/models/fields.py +0 -546
- hammad/data/models/model.py +0 -1078
- hammad/data/models/utils.py +0 -280
- hammad/data/sql/__init__.py +0 -24
- hammad/data/sql/database.py +0 -576
- hammad/data/sql/types.py +0 -127
- hammad/data/types/__init__.py +0 -75
- hammad/data/types/file.py +0 -431
- hammad/data/types/multimodal/__init__.py +0 -36
- hammad/data/types/multimodal/audio.py +0 -200
- hammad/data/types/multimodal/image.py +0 -182
- hammad/data/types/text.py +0 -1308
- hammad/formatting/__init__.py +0 -33
- hammad/formatting/json/__init__.py +0 -27
- hammad/formatting/json/converters.py +0 -158
- hammad/formatting/text/__init__.py +0 -63
- hammad/formatting/text/converters.py +0 -723
- hammad/formatting/text/markdown.py +0 -131
- hammad/formatting/yaml/__init__.py +0 -26
- hammad/formatting/yaml/converters.py +0 -5
- hammad/genai/__init__.py +0 -217
- hammad/genai/a2a/__init__.py +0 -32
- hammad/genai/a2a/workers.py +0 -552
- hammad/genai/agents/__init__.py +0 -59
- hammad/genai/agents/agent.py +0 -1973
- hammad/genai/agents/run.py +0 -1024
- hammad/genai/agents/types/__init__.py +0 -42
- hammad/genai/agents/types/agent_context.py +0 -13
- hammad/genai/agents/types/agent_event.py +0 -128
- hammad/genai/agents/types/agent_hooks.py +0 -220
- hammad/genai/agents/types/agent_messages.py +0 -31
- hammad/genai/agents/types/agent_response.py +0 -125
- hammad/genai/agents/types/agent_stream.py +0 -327
- hammad/genai/graphs/__init__.py +0 -125
- hammad/genai/graphs/_utils.py +0 -190
- hammad/genai/graphs/base.py +0 -1828
- hammad/genai/graphs/plugins.py +0 -316
- hammad/genai/graphs/types.py +0 -638
- hammad/genai/models/__init__.py +0 -1
- hammad/genai/models/embeddings/__init__.py +0 -43
- hammad/genai/models/embeddings/model.py +0 -226
- hammad/genai/models/embeddings/run.py +0 -163
- hammad/genai/models/embeddings/types/__init__.py +0 -37
- hammad/genai/models/embeddings/types/embedding_model_name.py +0 -75
- hammad/genai/models/embeddings/types/embedding_model_response.py +0 -76
- hammad/genai/models/embeddings/types/embedding_model_run_params.py +0 -66
- hammad/genai/models/embeddings/types/embedding_model_settings.py +0 -47
- hammad/genai/models/language/__init__.py +0 -57
- hammad/genai/models/language/model.py +0 -1098
- hammad/genai/models/language/run.py +0 -878
- hammad/genai/models/language/types/__init__.py +0 -40
- hammad/genai/models/language/types/language_model_instructor_mode.py +0 -47
- hammad/genai/models/language/types/language_model_messages.py +0 -28
- hammad/genai/models/language/types/language_model_name.py +0 -239
- hammad/genai/models/language/types/language_model_request.py +0 -127
- hammad/genai/models/language/types/language_model_response.py +0 -217
- hammad/genai/models/language/types/language_model_response_chunk.py +0 -56
- hammad/genai/models/language/types/language_model_settings.py +0 -89
- hammad/genai/models/language/types/language_model_stream.py +0 -600
- hammad/genai/models/language/utils/__init__.py +0 -28
- hammad/genai/models/language/utils/requests.py +0 -421
- hammad/genai/models/language/utils/structured_outputs.py +0 -135
- hammad/genai/models/model_provider.py +0 -4
- hammad/genai/models/multimodal.py +0 -47
- hammad/genai/models/reranking.py +0 -26
- hammad/genai/types/__init__.py +0 -1
- hammad/genai/types/base.py +0 -215
- hammad/genai/types/history.py +0 -290
- hammad/genai/types/tools.py +0 -507
- hammad/logging/__init__.py +0 -35
- hammad/logging/decorators.py +0 -834
- hammad/logging/logger.py +0 -1018
- hammad/mcp/__init__.py +0 -53
- hammad/mcp/client/__init__.py +0 -35
- hammad/mcp/client/client.py +0 -624
- hammad/mcp/client/client_service.py +0 -400
- hammad/mcp/client/settings.py +0 -178
- hammad/mcp/servers/__init__.py +0 -26
- hammad/mcp/servers/launcher.py +0 -1161
- hammad/runtime/__init__.py +0 -32
- hammad/runtime/decorators.py +0 -142
- hammad/runtime/run.py +0 -299
- hammad/service/__init__.py +0 -49
- hammad/service/create.py +0 -527
- hammad/service/decorators.py +0 -283
- hammad/types.py +0 -288
- hammad/typing/__init__.py +0 -435
- hammad/web/__init__.py +0 -43
- hammad/web/http/__init__.py +0 -1
- hammad/web/http/client.py +0 -944
- hammad/web/models.py +0 -275
- hammad/web/openapi/__init__.py +0 -1
- hammad/web/openapi/client.py +0 -740
- hammad/web/search/__init__.py +0 -1
- hammad/web/search/client.py +0 -1023
- hammad/web/utils.py +0 -472
- hammad_python-0.0.30.dist-info/RECORD +0 -135
- {hammad → ham}/py.typed +0 -0
- {hammad_python-0.0.30.dist-info → hammad_python-0.0.32.dist-info}/WHEEL +0 -0
- {hammad_python-0.0.30.dist-info → hammad_python-0.0.32.dist-info}/licenses/LICENSE +0 -0
@@ -1,564 +0,0 @@
|
|
1
|
-
"""hammad.data.configurations.configuration"""
|
2
|
-
|
3
|
-
import os
|
4
|
-
import configparser
|
5
|
-
from pathlib import Path
|
6
|
-
from typing import Any, Self
|
7
|
-
from dotenv import load_dotenv, dotenv_values
|
8
|
-
import httpx
|
9
|
-
import msgspec
|
10
|
-
import yaml
|
11
|
-
|
12
|
-
from ..types.file import File, FileSource
|
13
|
-
from ..models.fields import field
|
14
|
-
|
15
|
-
__all__ = (
|
16
|
-
"Configuration",
|
17
|
-
"read_configuration_from_file",
|
18
|
-
"read_configuration_from_url",
|
19
|
-
"read_configuration_from_os_vars",
|
20
|
-
"read_configuration_from_os_prefix",
|
21
|
-
"read_configuration_from_dotenv",
|
22
|
-
)
|
23
|
-
|
24
|
-
|
25
|
-
class Configuration(File):
|
26
|
-
"""Model / structure representation for configuration objects
|
27
|
-
for both module or application level usage. This class is
|
28
|
-
nothing more than a glorified key-value store with a
|
29
|
-
few extra features.
|
30
|
-
|
31
|
-
Inherits from File to provide file operations and extends
|
32
|
-
with configuration-specific functionality."""
|
33
|
-
|
34
|
-
# Configuration-specific fields
|
35
|
-
config_data: dict[str, Any] = field(default_factory=dict)
|
36
|
-
"""The actual configuration key-value pairs."""
|
37
|
-
|
38
|
-
format_type: str | None = field(default=None)
|
39
|
-
"""The format type of the configuration (json, toml, yaml, ini, env)."""
|
40
|
-
|
41
|
-
def __post_init__(self):
|
42
|
-
"""Initialize configuration data from file data if available."""
|
43
|
-
super().__post_init__()
|
44
|
-
|
45
|
-
# If we have data but no config_data, try to parse it
|
46
|
-
if self.data is not None and not self.config_data:
|
47
|
-
self._parse_data()
|
48
|
-
|
49
|
-
def _parse_data(self) -> None:
|
50
|
-
"""Parse the file data into configuration format."""
|
51
|
-
if not self.data:
|
52
|
-
return
|
53
|
-
|
54
|
-
content = self.data if isinstance(self.data, str) else self.data.decode("utf-8")
|
55
|
-
|
56
|
-
# Determine format from extension or type
|
57
|
-
format_type = self._detect_format()
|
58
|
-
|
59
|
-
try:
|
60
|
-
if format_type == "json":
|
61
|
-
self.config_data = msgspec.json.decode(content.encode("utf-8"))
|
62
|
-
elif format_type == "toml":
|
63
|
-
self.config_data = msgspec.toml.decode(content.encode("utf-8"))
|
64
|
-
elif format_type == "yaml":
|
65
|
-
# Use PyYAML with unsafe_load for YAML tags like !!python/name:
|
66
|
-
# This is needed for files like mkdocs.yml that use custom constructors
|
67
|
-
try:
|
68
|
-
self.config_data = yaml.unsafe_load(content)
|
69
|
-
except yaml.constructor.ConstructorError:
|
70
|
-
# Fallback to safe_load if unsafe_load fails
|
71
|
-
self.config_data = yaml.safe_load(content)
|
72
|
-
elif format_type == "ini":
|
73
|
-
parser = configparser.ConfigParser()
|
74
|
-
parser.read_string(content)
|
75
|
-
self.config_data = {
|
76
|
-
section: dict(parser[section]) for section in parser.sections()
|
77
|
-
}
|
78
|
-
elif format_type == "env":
|
79
|
-
# Parse as dotenv format
|
80
|
-
lines = content.strip().split("\n")
|
81
|
-
config_data = {}
|
82
|
-
for line in lines:
|
83
|
-
line = line.strip()
|
84
|
-
if line and not line.startswith("#") and "=" in line:
|
85
|
-
key, value = line.split("=", 1)
|
86
|
-
config_data[key.strip()] = value.strip().strip("\"'")
|
87
|
-
self.config_data = config_data
|
88
|
-
|
89
|
-
self.format_type = format_type
|
90
|
-
except Exception as e:
|
91
|
-
raise ValueError(
|
92
|
-
f"Failed to parse configuration data as {format_type}: {e}"
|
93
|
-
)
|
94
|
-
|
95
|
-
def _detect_format(self) -> str:
|
96
|
-
"""Detect the configuration format from extension or content."""
|
97
|
-
if self.format_type:
|
98
|
-
return self.format_type
|
99
|
-
|
100
|
-
# Try to detect from file extension
|
101
|
-
# Get extension directly from source path to avoid caching issues
|
102
|
-
if self.source.path:
|
103
|
-
ext = self.source.path.suffix.lower()
|
104
|
-
if ext in [".json"]:
|
105
|
-
return "json"
|
106
|
-
elif ext in [".toml"]:
|
107
|
-
return "toml"
|
108
|
-
elif ext in [".yaml", ".yml"]:
|
109
|
-
return "yaml"
|
110
|
-
elif ext in [".ini", ".cfg", ".conf"]:
|
111
|
-
return "ini"
|
112
|
-
elif ext in [".env"]:
|
113
|
-
return "env"
|
114
|
-
elif self.extension:
|
115
|
-
ext = self.extension.lower()
|
116
|
-
if ext in [".json"]:
|
117
|
-
return "json"
|
118
|
-
elif ext in [".toml"]:
|
119
|
-
return "toml"
|
120
|
-
elif ext in [".yaml", ".yml"]:
|
121
|
-
return "yaml"
|
122
|
-
elif ext in [".ini", ".cfg", ".conf"]:
|
123
|
-
return "ini"
|
124
|
-
elif ext in [".env"]:
|
125
|
-
return "env"
|
126
|
-
|
127
|
-
# Try to detect from MIME type
|
128
|
-
if self.type:
|
129
|
-
if "json" in self.type:
|
130
|
-
return "json"
|
131
|
-
elif "yaml" in self.type:
|
132
|
-
return "yaml"
|
133
|
-
|
134
|
-
# Default fallback - try to parse as JSON first
|
135
|
-
return "json"
|
136
|
-
|
137
|
-
def _serialize_data(self, format_type: str | None = None) -> str:
|
138
|
-
"""Serialize configuration data to string format."""
|
139
|
-
format_type = format_type or self.format_type or "json"
|
140
|
-
|
141
|
-
if format_type == "json":
|
142
|
-
return msgspec.json.encode(self.config_data).decode("utf-8")
|
143
|
-
elif format_type == "toml":
|
144
|
-
return msgspec.toml.encode(self.config_data).decode("utf-8")
|
145
|
-
elif format_type == "yaml":
|
146
|
-
return yaml.dump(
|
147
|
-
self.config_data, default_flow_style=False, allow_unicode=True
|
148
|
-
)
|
149
|
-
elif format_type == "ini":
|
150
|
-
parser = configparser.ConfigParser()
|
151
|
-
for section_name, section_data in self.config_data.items():
|
152
|
-
parser[section_name] = section_data
|
153
|
-
import io
|
154
|
-
|
155
|
-
output = io.StringIO()
|
156
|
-
parser.write(output)
|
157
|
-
return output.getvalue()
|
158
|
-
elif format_type == "env":
|
159
|
-
lines = []
|
160
|
-
for key, value in self.config_data.items():
|
161
|
-
# Simple escaping for shell variables
|
162
|
-
if isinstance(value, str) and (
|
163
|
-
" " in value or '"' in value or "'" in value
|
164
|
-
):
|
165
|
-
value = f'"{value}"'
|
166
|
-
lines.append(f"{key}={value}")
|
167
|
-
return "\n".join(lines)
|
168
|
-
else:
|
169
|
-
raise ValueError(f"Unsupported format: {format_type}")
|
170
|
-
|
171
|
-
@classmethod
|
172
|
-
def from_dotenv(cls, path: str | Path | None = None) -> Self:
|
173
|
-
"""Loads a .env file and creates a configuration object
|
174
|
-
from it.
|
175
|
-
|
176
|
-
NOTE: This does not set any environment variables.
|
177
|
-
|
178
|
-
Args:
|
179
|
-
path: The path to the .env file to load. If not provided,
|
180
|
-
the .env file in the current working directory will be used.
|
181
|
-
"""
|
182
|
-
if path is None:
|
183
|
-
path = Path.cwd() / ".env"
|
184
|
-
else:
|
185
|
-
path = Path(path)
|
186
|
-
|
187
|
-
if not path.exists():
|
188
|
-
raise FileNotFoundError(f"Environment file not found: {path}")
|
189
|
-
|
190
|
-
# Use dotenv_values to parse without setting environment variables
|
191
|
-
config_data = dotenv_values(path)
|
192
|
-
|
193
|
-
return cls(
|
194
|
-
config_data=dict(config_data),
|
195
|
-
format_type="env",
|
196
|
-
source=FileSource(
|
197
|
-
is_file=True,
|
198
|
-
path=path,
|
199
|
-
size=path.stat().st_size if path.exists() else None,
|
200
|
-
),
|
201
|
-
type="text/plain",
|
202
|
-
)
|
203
|
-
|
204
|
-
@classmethod
|
205
|
-
def from_os_prefix(cls, prefix: str) -> Self:
|
206
|
-
"""Creates a new configuration object using all variables
|
207
|
-
that begin with the given prefix.
|
208
|
-
|
209
|
-
Args:
|
210
|
-
prefix: The prefix to use to filter the variables.
|
211
|
-
"""
|
212
|
-
config_data = {}
|
213
|
-
for key, value in os.environ.items():
|
214
|
-
if key.startswith(prefix):
|
215
|
-
# Remove prefix and convert to lowercase
|
216
|
-
config_key = key[len(prefix) :].lstrip("_").lower()
|
217
|
-
config_data[config_key] = value
|
218
|
-
|
219
|
-
return cls(
|
220
|
-
config_data=config_data,
|
221
|
-
format_type="env",
|
222
|
-
source=FileSource(),
|
223
|
-
type="text/plain",
|
224
|
-
)
|
225
|
-
|
226
|
-
@classmethod
|
227
|
-
def from_os_vars(cls, vars: list[str]) -> Self:
|
228
|
-
"""Pulls a certain set of environment variables and
|
229
|
-
creates a configuration object from them.
|
230
|
-
|
231
|
-
Args:
|
232
|
-
vars: A list of environment variable names to pull.
|
233
|
-
"""
|
234
|
-
config_data = {}
|
235
|
-
for var in vars:
|
236
|
-
if var in os.environ:
|
237
|
-
config_data[var] = os.environ[var]
|
238
|
-
|
239
|
-
return cls(
|
240
|
-
config_data=config_data,
|
241
|
-
format_type="env",
|
242
|
-
source=FileSource(),
|
243
|
-
type="text/plain",
|
244
|
-
)
|
245
|
-
|
246
|
-
@classmethod
|
247
|
-
def from_file(
|
248
|
-
cls,
|
249
|
-
path: str | Path,
|
250
|
-
) -> Self:
|
251
|
-
"""Parses a file to return a configuration object. This
|
252
|
-
utilizes the following file types:
|
253
|
-
|
254
|
-
- json
|
255
|
-
- toml
|
256
|
-
- yaml
|
257
|
-
- ini
|
258
|
-
- env
|
259
|
-
"""
|
260
|
-
# Use the parent File class to load the file
|
261
|
-
file_obj = File.from_path(path, lazy=False)
|
262
|
-
|
263
|
-
# Create a Configuration object from the File object
|
264
|
-
config = cls(
|
265
|
-
data=file_obj.data,
|
266
|
-
type=file_obj.type,
|
267
|
-
source=file_obj.source,
|
268
|
-
)
|
269
|
-
|
270
|
-
# Parse the data
|
271
|
-
config._parse_data()
|
272
|
-
|
273
|
-
return config
|
274
|
-
|
275
|
-
@classmethod
|
276
|
-
def from_url(
|
277
|
-
cls,
|
278
|
-
url: str,
|
279
|
-
*,
|
280
|
-
timeout: float = 30.0,
|
281
|
-
headers: dict[str, str] | None = None,
|
282
|
-
) -> Self:
|
283
|
-
"""Load configuration from a URL supporting various formats.
|
284
|
-
|
285
|
-
Args:
|
286
|
-
url: The URL to load configuration from
|
287
|
-
timeout: Request timeout in seconds
|
288
|
-
headers: Optional HTTP headers to include in the request
|
289
|
-
|
290
|
-
Returns:
|
291
|
-
A new Configuration instance
|
292
|
-
"""
|
293
|
-
with httpx.Client(timeout=timeout) as client:
|
294
|
-
response = client.get(url, headers=headers or {})
|
295
|
-
response.raise_for_status()
|
296
|
-
|
297
|
-
# Get content as text
|
298
|
-
content = response.text
|
299
|
-
|
300
|
-
# Determine format from URL extension or content-type
|
301
|
-
format_type = None
|
302
|
-
if url.endswith(".json"):
|
303
|
-
format_type = "json"
|
304
|
-
elif url.endswith((".yaml", ".yml")):
|
305
|
-
format_type = "yaml"
|
306
|
-
elif url.endswith(".toml"):
|
307
|
-
format_type = "toml"
|
308
|
-
elif url.endswith((".ini", ".cfg", ".conf")):
|
309
|
-
format_type = "ini"
|
310
|
-
elif url.endswith(".env"):
|
311
|
-
format_type = "env"
|
312
|
-
else:
|
313
|
-
# Try to detect from content-type header
|
314
|
-
content_type = response.headers.get("content-type", "").lower()
|
315
|
-
if "json" in content_type:
|
316
|
-
format_type = "json"
|
317
|
-
elif "yaml" in content_type:
|
318
|
-
format_type = "yaml"
|
319
|
-
|
320
|
-
config = cls(
|
321
|
-
data=content,
|
322
|
-
type=response.headers.get("content-type"),
|
323
|
-
format_type=format_type,
|
324
|
-
source=FileSource(
|
325
|
-
is_url=True,
|
326
|
-
url=url,
|
327
|
-
size=len(content.encode("utf-8")),
|
328
|
-
encoding=response.encoding,
|
329
|
-
),
|
330
|
-
)
|
331
|
-
|
332
|
-
config._parse_data()
|
333
|
-
return config
|
334
|
-
|
335
|
-
def to_file(
|
336
|
-
self,
|
337
|
-
path: str | Path,
|
338
|
-
*,
|
339
|
-
overwrite: bool = False,
|
340
|
-
format_type: str | None = None,
|
341
|
-
) -> None:
|
342
|
-
"""Saves the configuration object to a file. This
|
343
|
-
utilizes the following file types:
|
344
|
-
|
345
|
-
- json
|
346
|
-
- toml
|
347
|
-
- yaml
|
348
|
-
- ini
|
349
|
-
- env
|
350
|
-
|
351
|
-
Args:
|
352
|
-
path: The path to the file to save the configuration to.
|
353
|
-
overwrite: Whether to overwrite the file if it already exists.
|
354
|
-
format_type: Override the format type for saving.
|
355
|
-
"""
|
356
|
-
save_path = Path(path)
|
357
|
-
|
358
|
-
if save_path.exists() and not overwrite:
|
359
|
-
raise FileExistsError(f"File already exists: {save_path}")
|
360
|
-
|
361
|
-
# Determine format from path extension if not specified
|
362
|
-
if format_type is None:
|
363
|
-
ext = save_path.suffix.lower()
|
364
|
-
if ext in [".json"]:
|
365
|
-
format_type = "json"
|
366
|
-
elif ext in [".toml"]:
|
367
|
-
format_type = "toml"
|
368
|
-
elif ext in [".yaml", ".yml"]:
|
369
|
-
format_type = "yaml"
|
370
|
-
elif ext in [".ini", ".cfg", ".conf"]:
|
371
|
-
format_type = "ini"
|
372
|
-
elif ext in [".env"]:
|
373
|
-
format_type = "env"
|
374
|
-
else:
|
375
|
-
format_type = self.format_type or "json"
|
376
|
-
|
377
|
-
# Serialize and save
|
378
|
-
content = self._serialize_data(format_type)
|
379
|
-
save_path.parent.mkdir(parents=True, exist_ok=True)
|
380
|
-
save_path.write_text(content, encoding="utf-8")
|
381
|
-
|
382
|
-
def update_file(
|
383
|
-
self,
|
384
|
-
path: str | Path,
|
385
|
-
exclude: list[str] | None = None,
|
386
|
-
exclude_none: bool = True,
|
387
|
-
) -> None:
|
388
|
-
"""Updates a valid configuration file with only the
|
389
|
-
differing values.
|
390
|
-
|
391
|
-
Args:
|
392
|
-
path: The path to the file to update.
|
393
|
-
exclude: A list of keys to exclude from the update.
|
394
|
-
exclude_none: Whether to exclude keys with None values.
|
395
|
-
"""
|
396
|
-
path = Path(path)
|
397
|
-
|
398
|
-
if not path.exists():
|
399
|
-
raise FileNotFoundError(f"Configuration file not found: {path}")
|
400
|
-
|
401
|
-
# Load existing configuration
|
402
|
-
existing_config = Configuration.from_file(path)
|
403
|
-
|
404
|
-
# Prepare data to update
|
405
|
-
update_data = self.config_data.copy()
|
406
|
-
|
407
|
-
if exclude:
|
408
|
-
for key in exclude:
|
409
|
-
update_data.pop(key, None)
|
410
|
-
|
411
|
-
if exclude_none:
|
412
|
-
update_data = {k: v for k, v in update_data.items() if v is not None}
|
413
|
-
|
414
|
-
# Merge with existing data
|
415
|
-
existing_config.config_data.update(update_data)
|
416
|
-
|
417
|
-
# Save back to file
|
418
|
-
existing_config.to_file(path, overwrite=True)
|
419
|
-
|
420
|
-
def to_os(
|
421
|
-
self,
|
422
|
-
prefix: str | None = None,
|
423
|
-
exclude: list[str] | None = None,
|
424
|
-
) -> None:
|
425
|
-
"""Pushes the configuration object's values as active
|
426
|
-
environment variables. This will overwrite any existing
|
427
|
-
values for the session.
|
428
|
-
|
429
|
-
Args:
|
430
|
-
prefix: The prefix to use to filter the variables.
|
431
|
-
exclude: A list of keys to exclude from the update.
|
432
|
-
"""
|
433
|
-
exclude = exclude or []
|
434
|
-
|
435
|
-
for key, value in self.config_data.items():
|
436
|
-
if key in exclude:
|
437
|
-
continue
|
438
|
-
|
439
|
-
# Convert value to string
|
440
|
-
env_value = str(value) if value is not None else ""
|
441
|
-
|
442
|
-
# Apply prefix if specified
|
443
|
-
env_key = f"{prefix}_{key}".upper() if prefix else key.upper()
|
444
|
-
|
445
|
-
# Set environment variable
|
446
|
-
os.environ[env_key] = env_value
|
447
|
-
|
448
|
-
def get(self, key: str, default: Any = None) -> Any:
|
449
|
-
"""Get a configuration value by key.
|
450
|
-
|
451
|
-
Args:
|
452
|
-
key: The configuration key
|
453
|
-
default: Default value if key is not found
|
454
|
-
|
455
|
-
Returns:
|
456
|
-
The configuration value or default
|
457
|
-
"""
|
458
|
-
return self.config_data.get(key, default)
|
459
|
-
|
460
|
-
def set(self, key: str, value: Any) -> None:
|
461
|
-
"""Set a configuration value.
|
462
|
-
|
463
|
-
Args:
|
464
|
-
key: The configuration key
|
465
|
-
value: The value to set
|
466
|
-
"""
|
467
|
-
self.config_data[key] = value
|
468
|
-
|
469
|
-
def __getitem__(self, key: str) -> Any:
|
470
|
-
"""Get configuration value using dict-like access."""
|
471
|
-
return self.config_data[key]
|
472
|
-
|
473
|
-
def __setitem__(self, key: str, value: Any) -> None:
|
474
|
-
"""Set configuration value using dict-like access."""
|
475
|
-
self.config_data[key] = value
|
476
|
-
|
477
|
-
def __contains__(self, key: str) -> bool:
|
478
|
-
"""Check if configuration contains a key."""
|
479
|
-
return key in self.config_data
|
480
|
-
|
481
|
-
def keys(self):
|
482
|
-
"""Return configuration keys."""
|
483
|
-
return self.config_data.keys()
|
484
|
-
|
485
|
-
def values(self):
|
486
|
-
"""Return configuration values."""
|
487
|
-
return self.config_data.values()
|
488
|
-
|
489
|
-
def items(self):
|
490
|
-
"""Return configuration key-value pairs."""
|
491
|
-
return self.config_data.items()
|
492
|
-
|
493
|
-
|
494
|
-
# HELPERS
|
495
|
-
|
496
|
-
|
497
|
-
def read_configuration_from_file(path: str | Path) -> Configuration:
|
498
|
-
"""Parse a filepath into a `Configuration` object.
|
499
|
-
|
500
|
-
Valid file types:
|
501
|
-
- json
|
502
|
-
- toml
|
503
|
-
- yaml
|
504
|
-
- ini
|
505
|
-
- env
|
506
|
-
|
507
|
-
Args:
|
508
|
-
path: The path to the file to parse.
|
509
|
-
|
510
|
-
Returns:
|
511
|
-
A `Configuration` object.
|
512
|
-
"""
|
513
|
-
file_obj = File.from_path(path, lazy=False)
|
514
|
-
return Configuration.from_file(file_obj)
|
515
|
-
|
516
|
-
|
517
|
-
def read_configuration_from_url(url: str) -> Configuration:
|
518
|
-
"""Parse a URL into a `Configuration` object.
|
519
|
-
|
520
|
-
Args:
|
521
|
-
url: The URL to parse.
|
522
|
-
|
523
|
-
Returns:
|
524
|
-
A `Configuration` object.
|
525
|
-
"""
|
526
|
-
return Configuration.from_url(url)
|
527
|
-
|
528
|
-
|
529
|
-
def read_configuration_from_os_vars(vars: list[str]) -> Configuration:
|
530
|
-
"""Parse a list of environment variables into a `Configuration` object.
|
531
|
-
|
532
|
-
Args:
|
533
|
-
vars: The list of environment variables to parse.
|
534
|
-
|
535
|
-
Returns:
|
536
|
-
A `Configuration` object.
|
537
|
-
"""
|
538
|
-
return Configuration.from_os_vars(vars)
|
539
|
-
|
540
|
-
|
541
|
-
def read_configuration_from_os_prefix(prefix: str) -> Configuration:
|
542
|
-
"""Parse a list of environment variables into a `Configuration` object.
|
543
|
-
|
544
|
-
Args:
|
545
|
-
prefix: The prefix to use to filter the variables.
|
546
|
-
|
547
|
-
Returns:
|
548
|
-
A `Configuration` object.
|
549
|
-
"""
|
550
|
-
return Configuration.from_os_prefix(prefix)
|
551
|
-
|
552
|
-
|
553
|
-
def read_configuration_from_dotenv(path: str | Path = ".env") -> Configuration:
|
554
|
-
"""Parse a .env file into a `Configuration` object.
|
555
|
-
|
556
|
-
NOTE: Defaults to `.env` in the current working directory.
|
557
|
-
|
558
|
-
Args:
|
559
|
-
path: The path to the .env file to parse.
|
560
|
-
|
561
|
-
Returns:
|
562
|
-
A `Configuration` object.
|
563
|
-
"""
|
564
|
-
return Configuration.from_dotenv(path)
|
hammad/data/models/__init__.py
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
"""hammad.data.models
|
2
|
-
|
3
|
-
Contains **BOTH** resources contains predefined models or base class like
|
4
|
-
models, as well as modules & utilities specifically for various interfaces
|
5
|
-
of models such as `pydantic`."""
|
6
|
-
|
7
|
-
from typing import TYPE_CHECKING
|
8
|
-
from ..._internal import create_getattr_importer
|
9
|
-
|
10
|
-
if TYPE_CHECKING:
|
11
|
-
from .model import (
|
12
|
-
Model,
|
13
|
-
model_settings,
|
14
|
-
)
|
15
|
-
from .fields import field
|
16
|
-
from .utils import (
|
17
|
-
validator,
|
18
|
-
is_field,
|
19
|
-
is_model,
|
20
|
-
)
|
21
|
-
from .extensions.pydantic.converters import (
|
22
|
-
convert_to_pydantic_model,
|
23
|
-
convert_to_pydantic_field,
|
24
|
-
is_pydantic_model_class,
|
25
|
-
)
|
26
|
-
|
27
|
-
|
28
|
-
__all__ = (
|
29
|
-
# hammad.lib.data.models.model
|
30
|
-
"Model",
|
31
|
-
"model_settings",
|
32
|
-
# hammad.lib.data.models.fields
|
33
|
-
"field",
|
34
|
-
# hammad.lib.data.models.utils
|
35
|
-
"validator",
|
36
|
-
"is_field",
|
37
|
-
"is_model",
|
38
|
-
"model_settings",
|
39
|
-
# hammad.lib.data.models.extensions.pydantic.converters
|
40
|
-
"convert_to_pydantic_model",
|
41
|
-
"convert_to_pydantic_field",
|
42
|
-
"is_pydantic_model_class",
|
43
|
-
)
|
44
|
-
|
45
|
-
|
46
|
-
__getattr__ = create_getattr_importer(__all__)
|
47
|
-
|
48
|
-
|
49
|
-
def __dir__() -> list[str]:
|
50
|
-
return list(__all__)
|
@@ -1,42 +0,0 @@
|
|
1
|
-
"""hammad.data.models.extensions.pydantic
|
2
|
-
|
3
|
-
Contains both models and pydantic **specific** utiltiies / resources
|
4
|
-
meant for general case usage."""
|
5
|
-
|
6
|
-
from typing import TYPE_CHECKING
|
7
|
-
from ....._internal import create_getattr_importer
|
8
|
-
|
9
|
-
if TYPE_CHECKING:
|
10
|
-
from .converters import (
|
11
|
-
convert_to_pydantic_model,
|
12
|
-
convert_to_pydantic_field,
|
13
|
-
convert_dataclass_to_pydantic_model,
|
14
|
-
convert_dict_to_pydantic_model,
|
15
|
-
convert_function_to_pydantic_model,
|
16
|
-
convert_sequence_to_pydantic_model,
|
17
|
-
convert_type_to_pydantic_model,
|
18
|
-
create_confirmation_pydantic_model,
|
19
|
-
create_selection_pydantic_model,
|
20
|
-
)
|
21
|
-
|
22
|
-
|
23
|
-
__all__ = [
|
24
|
-
# hammad.lib.pydantic.converters
|
25
|
-
"convert_to_pydantic_model",
|
26
|
-
"convert_to_pydantic_field",
|
27
|
-
"convert_dataclass_to_pydantic_model",
|
28
|
-
"convert_dict_to_pydantic_model",
|
29
|
-
"convert_function_to_pydantic_model",
|
30
|
-
"convert_sequence_to_pydantic_model",
|
31
|
-
"convert_type_to_pydantic_model",
|
32
|
-
"create_confirmation_pydantic_model",
|
33
|
-
"create_selection_pydantic_model",
|
34
|
-
]
|
35
|
-
|
36
|
-
|
37
|
-
__getattr__ = create_getattr_importer(__all__)
|
38
|
-
|
39
|
-
|
40
|
-
def __dir__() -> list[str]:
|
41
|
-
"""Get the attributes of the models module."""
|
42
|
-
return __all__
|