hammad-python 0.0.13__py3-none-any.whl → 0.0.15__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.
- hammad_python-0.0.15.dist-info/METADATA +184 -0
- hammad_python-0.0.15.dist-info/RECORD +4 -0
- hammad/__init__.py +0 -180
- hammad/_core/__init__.py +0 -1
- hammad/_core/_utils/__init__.py +0 -4
- hammad/_core/_utils/_import_utils.py +0 -182
- hammad/ai/__init__.py +0 -59
- hammad/ai/_utils.py +0 -142
- hammad/ai/completions/__init__.py +0 -44
- hammad/ai/completions/client.py +0 -729
- hammad/ai/completions/create.py +0 -686
- hammad/ai/completions/types.py +0 -711
- hammad/ai/completions/utils.py +0 -374
- hammad/ai/embeddings/__init__.py +0 -35
- hammad/ai/embeddings/client/__init__.py +0 -1
- hammad/ai/embeddings/client/base_embeddings_client.py +0 -26
- hammad/ai/embeddings/client/fastembed_text_embeddings_client.py +0 -200
- hammad/ai/embeddings/client/litellm_embeddings_client.py +0 -288
- hammad/ai/embeddings/create.py +0 -159
- hammad/ai/embeddings/types.py +0 -69
- hammad/base/__init__.py +0 -35
- hammad/base/fields.py +0 -546
- hammad/base/model.py +0 -1078
- hammad/base/utils.py +0 -280
- hammad/cache/__init__.py +0 -48
- 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 -604
- hammad/cli/plugins.py +0 -781
- 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 -480
- hammad/configuration/__init__.py +0 -35
- hammad/configuration/configuration.py +0 -564
- hammad/data/__init__.py +0 -39
- hammad/data/collections/__init__.py +0 -34
- hammad/data/collections/base_collection.py +0 -58
- hammad/data/collections/collection.py +0 -452
- hammad/data/collections/searchable_collection.py +0 -556
- hammad/data/collections/vector_collection.py +0 -603
- hammad/data/databases/__init__.py +0 -21
- hammad/data/databases/database.py +0 -902
- hammad/json/__init__.py +0 -21
- hammad/json/converters.py +0 -152
- hammad/logging/__init__.py +0 -35
- hammad/logging/decorators.py +0 -834
- hammad/logging/logger.py +0 -954
- hammad/multimodal/__init__.py +0 -24
- hammad/multimodal/audio.py +0 -96
- hammad/multimodal/image.py +0 -80
- hammad/multithreading/__init__.py +0 -304
- hammad/py.typed +0 -0
- hammad/pydantic/__init__.py +0 -43
- hammad/pydantic/converters.py +0 -623
- hammad/pydantic/models/__init__.py +0 -28
- hammad/pydantic/models/arbitrary_model.py +0 -46
- hammad/pydantic/models/cacheable_model.py +0 -79
- hammad/pydantic/models/fast_model.py +0 -318
- hammad/pydantic/models/function_model.py +0 -176
- hammad/pydantic/models/subscriptable_model.py +0 -63
- hammad/text/__init__.py +0 -82
- hammad/text/converters.py +0 -723
- hammad/text/markdown.py +0 -131
- hammad/text/text.py +0 -1066
- hammad/types/__init__.py +0 -11
- hammad/types/file.py +0 -358
- hammad/typing/__init__.py +0 -407
- 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 -245
- hammad/web/openapi/__init__.py +0 -0
- hammad/web/openapi/client.py +0 -740
- hammad/web/search/__init__.py +0 -1
- hammad/web/search/client.py +0 -988
- hammad/web/utils.py +0 -472
- hammad/yaml/__init__.py +0 -30
- hammad/yaml/converters.py +0 -19
- hammad_python-0.0.13.dist-info/METADATA +0 -38
- hammad_python-0.0.13.dist-info/RECORD +0 -85
- {hammad_python-0.0.13.dist-info → hammad_python-0.0.15.dist-info}/WHEEL +0 -0
- {hammad_python-0.0.13.dist-info → hammad_python-0.0.15.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,184 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: hammad-python
|
3
|
+
Version: 0.0.15
|
4
|
+
Author-email: Hammad Saeed <hammadaidev@gmail.com>
|
5
|
+
License: MIT License
|
6
|
+
|
7
|
+
Copyright (c) 2025 Hammad Saeed
|
8
|
+
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
11
|
+
in the Software without restriction, including without limitation the rights
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
14
|
+
furnished to do so, subject to the following conditions:
|
15
|
+
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
17
|
+
copies or substantial portions of the Software.
|
18
|
+
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
25
|
+
SOFTWARE.
|
26
|
+
License-File: LICENSE
|
27
|
+
Requires-Python: >=3.11
|
28
|
+
Requires-Dist: ddgs>=9.0.0
|
29
|
+
Requires-Dist: httpx>=0.28.1
|
30
|
+
Requires-Dist: msgspec>=0.19.0
|
31
|
+
Requires-Dist: pydantic>=2.11.7
|
32
|
+
Requires-Dist: rich>=14.0.0
|
33
|
+
Requires-Dist: selectolax>=0.3.31
|
34
|
+
Requires-Dist: sqlalchemy>=2.0.41
|
35
|
+
Requires-Dist: tantivy>=0.24.0
|
36
|
+
Requires-Dist: tenacity>=9.1.2
|
37
|
+
Requires-Dist: typing-inspect>=0.9.0
|
38
|
+
Provides-Extra: ai
|
39
|
+
Requires-Dist: instructor>=1.9.0; extra == 'ai'
|
40
|
+
Requires-Dist: litellm>=1.73.6; extra == 'ai'
|
41
|
+
Requires-Dist: qdrant-client>=1.14.3; extra == 'ai'
|
42
|
+
Provides-Extra: mcp
|
43
|
+
Requires-Dist: mcp>=1.10.1; extra == 'mcp'
|
44
|
+
Provides-Extra: serve
|
45
|
+
Requires-Dist: fastapi>=0.115.6; extra == 'serve'
|
46
|
+
Requires-Dist: uvicorn>=0.34.0; extra == 'serve'
|
47
|
+
Description-Content-Type: text/markdown
|
48
|
+
|
49
|
+
## hammad-python
|
50
|
+
|
51
|
+
> __Happily Accelerated Micro-Modules (_for_) Application Development__
|
52
|
+
|
53
|
+
## Introduction
|
54
|
+
|
55
|
+
The `hammad-python` library, is a mix of a love letter and collection of mixed resources for
|
56
|
+
developing Python applications. This library is meant to be used for rapid prototyping and
|
57
|
+
development, and is focused on providing styled placeholder tools for common patterns, tasks
|
58
|
+
and workflows.
|
59
|
+
|
60
|
+
The package is currently built into the following structures:
|
61
|
+
|
62
|
+
- `hammad-python` : Contains most core functionality and resources.
|
63
|
+
- `hammad-python[ai]` : Contains easy to use resources for Generative AI related tasks such as
|
64
|
+
generating completions with language models, or creating embeddings.
|
65
|
+
- `hammad-python[serve]` : Contains FastAPI / Uvicorn based resources for serving and running applications.
|
66
|
+
|
67
|
+
## Installation
|
68
|
+
|
69
|
+
You can install the package using `pip` or `uv`:
|
70
|
+
|
71
|
+
```bash
|
72
|
+
pip install hammad-python
|
73
|
+
|
74
|
+
# or install the `ai` extension
|
75
|
+
# pip install 'hammad-python[ai]'
|
76
|
+
|
77
|
+
# or install the `serve` extension
|
78
|
+
# pip install 'hammad-python[serve]'
|
79
|
+
```
|
80
|
+
|
81
|
+
```bash
|
82
|
+
uv pip install hammad-python
|
83
|
+
|
84
|
+
# or install the `ai` extension
|
85
|
+
# uv pip install 'hammad-python[ai]'
|
86
|
+
|
87
|
+
# or install the `serve` extension
|
88
|
+
# uv pip install 'hammad-python[serve]'
|
89
|
+
```
|
90
|
+
|
91
|
+
## Basic Usage
|
92
|
+
|
93
|
+
### Data Structures, Databases and Other Data Related Resources
|
94
|
+
|
95
|
+
#### Collections
|
96
|
+
|
97
|
+
Using `hammad.data.collections` is a simple way to create searchable collections of
|
98
|
+
data using both `bm25` and `vector` based search.
|
99
|
+
|
100
|
+
```python
|
101
|
+
from hammad.data.collections import create_collection
|
102
|
+
|
103
|
+
# Create either a `vector` or `searchable` collection
|
104
|
+
col = create_collection(type = "searchable")
|
105
|
+
|
106
|
+
# add anything to the collection
|
107
|
+
col.add("This is some text")
|
108
|
+
col.add(5)
|
109
|
+
col.add({'text' : "this is a dictionary"})
|
110
|
+
|
111
|
+
# search the collection
|
112
|
+
print(col.query("text"))
|
113
|
+
```
|
114
|
+
|
115
|
+
#### Databases
|
116
|
+
|
117
|
+
Any collection can be either used as a standalone database, or can be added as one
|
118
|
+
of the collections within a database. Databases provide a unified interface for handling
|
119
|
+
both `Searchable` and `Vector` based collections.
|
120
|
+
|
121
|
+
```python
|
122
|
+
from hammad.data.collections import create_collection
|
123
|
+
from hammad.data.databases import Database
|
124
|
+
|
125
|
+
# Create either a `vector` or `searchable` collection
|
126
|
+
col = create_collection(type = "searchable")
|
127
|
+
|
128
|
+
col.add("This is some text")
|
129
|
+
|
130
|
+
# Databases can either be created on memory or using a path
|
131
|
+
db = Database(location = "memory")
|
132
|
+
|
133
|
+
db.add_collection(col)
|
134
|
+
|
135
|
+
# search globally or within a single collection
|
136
|
+
print(db.query("text"))
|
137
|
+
```
|
138
|
+
|
139
|
+
### Styling / Introspection Resources
|
140
|
+
|
141
|
+
The `hammad-python` package contains a variety of components that can be used
|
142
|
+
to easily style, or run introspection (logging) on your code.
|
143
|
+
|
144
|
+
```python
|
145
|
+
from hammad.cli import print, input, animate
|
146
|
+
|
147
|
+
# Use extended `rich` styling easily
|
148
|
+
print("Hello, World", bg_settings = {"title" : "This is a title"})
|
149
|
+
|
150
|
+
# Easily collect various forms of input in a single function
|
151
|
+
class User(BaseModel):
|
152
|
+
name : str
|
153
|
+
age : int
|
154
|
+
|
155
|
+
# TIP:
|
156
|
+
# you can style this the same way with `print`
|
157
|
+
user = input("Enter some information about yourself: ", schema = User)
|
158
|
+
|
159
|
+
# easily run a collection of prebuilt animations
|
160
|
+
animate("This is a rainbow!", type = "rainbow", duration = 2, refresh_rate = 20)
|
161
|
+
```
|
162
|
+
|
163
|
+
Using the various `hammad.logging` resources, you can both create custom & styled
|
164
|
+
loggers, as well as easily inspect various aspects of your code during runtime.
|
165
|
+
|
166
|
+
```python
|
167
|
+
from hammad.logging import Logger
|
168
|
+
|
169
|
+
# create standard / file based loggers easily
|
170
|
+
logger = Logger("hammad", level = "info", rich = Trues)
|
171
|
+
|
172
|
+
file_logger = Logger("hammad-file", level = "info", file = "hammad.log")
|
173
|
+
|
174
|
+
# log to the console
|
175
|
+
logger.info("This is an info message")
|
176
|
+
|
177
|
+
# Use the various `trace_` methods to run various introspection tasks
|
178
|
+
from hammad.logging import (
|
179
|
+
trace,
|
180
|
+
trace_cls,
|
181
|
+
trace_function,
|
182
|
+
trace_http
|
183
|
+
)
|
184
|
+
```
|
@@ -0,0 +1,4 @@
|
|
1
|
+
hammad_python-0.0.15.dist-info/METADATA,sha256=76e_P5ZnWxhhfnyhA0B91cnlFtAxepwavtFancGsUuw,5907
|
2
|
+
hammad_python-0.0.15.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
3
|
+
hammad_python-0.0.15.dist-info/licenses/LICENSE,sha256=h74yFUWjbBaodcWG5wNmm30npjl8obVcxD-1nQfUp2I,1069
|
4
|
+
hammad_python-0.0.15.dist-info/RECORD,,
|
hammad/__init__.py
DELETED
@@ -1,180 +0,0 @@
|
|
1
|
-
"""hammad-python
|
2
|
-
|
3
|
-
```markdown
|
4
|
-
## Happliy Accelerated Micro Modules (for) Application Development
|
5
|
-
```
|
6
|
-
"""
|
7
|
-
|
8
|
-
from typing import TYPE_CHECKING
|
9
|
-
from ._core._utils._import_utils import _auto_create_getattr_loader
|
10
|
-
|
11
|
-
|
12
|
-
if TYPE_CHECKING:
|
13
|
-
# hammad.ai
|
14
|
-
# NOTE:
|
15
|
-
# TO USE MODULES FROM THE `hammad.ai` EXTENSION,
|
16
|
-
# REQUIRES INSTALLATION OF THE `hammad-python[ai]` PACKAGE.
|
17
|
-
from .ai import (
|
18
|
-
create_completion,
|
19
|
-
async_create_completion,
|
20
|
-
create_embeddings,
|
21
|
-
async_create_embeddings,
|
22
|
-
)
|
23
|
-
|
24
|
-
# hammad.base
|
25
|
-
from .base import Model, field, create_model, is_field, is_model, validator
|
26
|
-
|
27
|
-
# hammad.cache
|
28
|
-
from .cache import Cache, cached, auto_cached, create_cache
|
29
|
-
|
30
|
-
# hammad.cli
|
31
|
-
from .cli import print, animate, input
|
32
|
-
|
33
|
-
# hammad.configuration
|
34
|
-
from .configuration import (
|
35
|
-
Configuration,
|
36
|
-
read_configuration_from_os_vars,
|
37
|
-
read_configuration_from_dotenv,
|
38
|
-
read_configuration_from_file,
|
39
|
-
read_configuration_from_url,
|
40
|
-
read_configuration_from_os_prefix,
|
41
|
-
)
|
42
|
-
|
43
|
-
# hammad.data
|
44
|
-
from .data import Collection, Database, create_collection, create_database
|
45
|
-
|
46
|
-
# hammad.json
|
47
|
-
from .json import encode_json, decode_json, convert_to_json_schema
|
48
|
-
|
49
|
-
# hammad.logging
|
50
|
-
from .logging import (
|
51
|
-
Logger,
|
52
|
-
create_logger,
|
53
|
-
trace,
|
54
|
-
trace_cls,
|
55
|
-
trace_function,
|
56
|
-
trace_http,
|
57
|
-
install_trace_http,
|
58
|
-
)
|
59
|
-
|
60
|
-
# hammad.multithreading
|
61
|
-
from .multithreading import (
|
62
|
-
run_parallel,
|
63
|
-
run_sequentially,
|
64
|
-
run_with_retry,
|
65
|
-
retry,
|
66
|
-
)
|
67
|
-
|
68
|
-
# hammad.pydantic
|
69
|
-
from .pydantic import (
|
70
|
-
convert_to_pydantic_field,
|
71
|
-
convert_to_pydantic_model,
|
72
|
-
)
|
73
|
-
|
74
|
-
# hammad.text
|
75
|
-
from .text import (
|
76
|
-
Text,
|
77
|
-
OutputText,
|
78
|
-
SimpleText,
|
79
|
-
convert_to_text,
|
80
|
-
convert_type_to_text,
|
81
|
-
convert_docstring_to_text,
|
82
|
-
)
|
83
|
-
|
84
|
-
# hammad.web
|
85
|
-
from .web import (
|
86
|
-
create_http_client,
|
87
|
-
create_openapi_client,
|
88
|
-
create_search_client,
|
89
|
-
search_news,
|
90
|
-
search_web,
|
91
|
-
run_web_request,
|
92
|
-
read_web_page,
|
93
|
-
read_web_pages,
|
94
|
-
extract_page_links,
|
95
|
-
)
|
96
|
-
|
97
|
-
# hammad.yaml
|
98
|
-
from .yaml import encode_yaml, decode_yaml, read_yaml_file
|
99
|
-
|
100
|
-
|
101
|
-
__all__ = (
|
102
|
-
# hammad.ai
|
103
|
-
"create_completion",
|
104
|
-
"async_create_completion",
|
105
|
-
"create_embeddings",
|
106
|
-
"async_create_embeddings",
|
107
|
-
# hammad.base
|
108
|
-
"Model",
|
109
|
-
"field",
|
110
|
-
"create_model",
|
111
|
-
# hammad.cache
|
112
|
-
"Cache",
|
113
|
-
"cached",
|
114
|
-
"auto_cached",
|
115
|
-
"create_cache",
|
116
|
-
# hammad.cli
|
117
|
-
"print",
|
118
|
-
"animate",
|
119
|
-
"input",
|
120
|
-
# hammad.configuration
|
121
|
-
"Configuration",
|
122
|
-
"read_configuration_from_os_vars",
|
123
|
-
"read_configuration_from_dotenv",
|
124
|
-
"read_configuration_from_file",
|
125
|
-
"read_configuration_from_url",
|
126
|
-
"read_configuration_from_os_prefix",
|
127
|
-
# hammad.data
|
128
|
-
"Collection",
|
129
|
-
"Database",
|
130
|
-
"create_collection",
|
131
|
-
"create_database",
|
132
|
-
# hammad.json
|
133
|
-
"encode_json",
|
134
|
-
"decode_json",
|
135
|
-
"convert_to_json_schema",
|
136
|
-
# hammad.logging
|
137
|
-
"Logger",
|
138
|
-
"create_logger",
|
139
|
-
"trace",
|
140
|
-
"trace_cls",
|
141
|
-
"trace_function",
|
142
|
-
"trace_http",
|
143
|
-
"install_trace_http",
|
144
|
-
# hammad.multithreading
|
145
|
-
"run_parallel",
|
146
|
-
"run_sequentially",
|
147
|
-
"run_with_retry",
|
148
|
-
"retry",
|
149
|
-
# hammad.pydantic
|
150
|
-
"convert_to_pydantic_field",
|
151
|
-
"convert_to_pydantic_model",
|
152
|
-
# hammad.text
|
153
|
-
"Text",
|
154
|
-
"OutputText",
|
155
|
-
"SimpleText",
|
156
|
-
"convert_to_text",
|
157
|
-
"convert_type_to_text",
|
158
|
-
"convert_docstring_to_text",
|
159
|
-
# hammad.web
|
160
|
-
"create_http_client",
|
161
|
-
"create_openapi_client",
|
162
|
-
"create_search_client",
|
163
|
-
"search_news",
|
164
|
-
"search_web",
|
165
|
-
"run_web_request",
|
166
|
-
"read_web_page",
|
167
|
-
"read_web_pages",
|
168
|
-
"extract_page_links",
|
169
|
-
# hammad.yaml
|
170
|
-
"encode_yaml",
|
171
|
-
"decode_yaml",
|
172
|
-
"read_yaml_file",
|
173
|
-
)
|
174
|
-
|
175
|
-
|
176
|
-
__getattr__ = _auto_create_getattr_loader(__all__)
|
177
|
-
|
178
|
-
|
179
|
-
def __dir__() -> list[str]:
|
180
|
-
return list(__all__)
|
hammad/_core/__init__.py
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
"""hammad._core"""
|
hammad/_core/_utils/__init__.py
DELETED
@@ -1,182 +0,0 @@
|
|
1
|
-
"""hammad._core._utils._import_utils"""
|
2
|
-
|
3
|
-
from typing import Any, Callable
|
4
|
-
import inspect
|
5
|
-
import ast
|
6
|
-
import hashlib
|
7
|
-
|
8
|
-
__all__ = ("_auto_create_getattr_loader",)
|
9
|
-
|
10
|
-
|
11
|
-
class _ModuleCache:
|
12
|
-
"""Minimal cache implementation for internal use only."""
|
13
|
-
|
14
|
-
def __init__(self, maxsize: int = 128):
|
15
|
-
self.maxsize = maxsize
|
16
|
-
self._cache: dict[str, Any] = {}
|
17
|
-
|
18
|
-
def _make_key(self, data: str) -> str:
|
19
|
-
"""Create a simple hash key from string data."""
|
20
|
-
return hashlib.sha256(data.encode("utf-8")).hexdigest()[:16]
|
21
|
-
|
22
|
-
def get(self, key: str, default: Any = None) -> Any:
|
23
|
-
"""Get value from cache."""
|
24
|
-
return self._cache.get(key, default)
|
25
|
-
|
26
|
-
def set(self, key: str, value: Any) -> None:
|
27
|
-
"""Set value in cache with basic LRU eviction."""
|
28
|
-
if len(self._cache) >= self.maxsize and key not in self._cache:
|
29
|
-
# Simple eviction: remove oldest (first) item
|
30
|
-
oldest_key = next(iter(self._cache))
|
31
|
-
del self._cache[oldest_key]
|
32
|
-
self._cache[key] = value
|
33
|
-
|
34
|
-
def cached_call(self, func: Callable[[str], Any]) -> Callable[[str], Any]:
|
35
|
-
"""Decorator to cache function calls."""
|
36
|
-
|
37
|
-
def wrapper(arg: str) -> Any:
|
38
|
-
key = self._make_key(arg)
|
39
|
-
result = self.get(key)
|
40
|
-
if result is None:
|
41
|
-
result = func(arg)
|
42
|
-
self.set(key, result)
|
43
|
-
return result
|
44
|
-
|
45
|
-
return wrapper
|
46
|
-
|
47
|
-
|
48
|
-
# Global cache instance for parse function
|
49
|
-
_parse_cache = _ModuleCache(maxsize=64)
|
50
|
-
|
51
|
-
|
52
|
-
def _create_getattr_loader(
|
53
|
-
imports_dict: dict[str, tuple[str, str]], package: str
|
54
|
-
) -> Callable[[str], Any]:
|
55
|
-
"""Create a lazy loader function for __getattr__.
|
56
|
-
|
57
|
-
Args:
|
58
|
-
imports_dict: Dictionary mapping attribute names to (module_path, original_name) tuples
|
59
|
-
package: The package name for import_module
|
60
|
-
|
61
|
-
Returns:
|
62
|
-
A __getattr__ function that lazily imports modules
|
63
|
-
"""
|
64
|
-
from importlib import import_module
|
65
|
-
|
66
|
-
_cache = {}
|
67
|
-
|
68
|
-
def __getattr__(name: str) -> Any:
|
69
|
-
if name in _cache:
|
70
|
-
return _cache[name]
|
71
|
-
|
72
|
-
if name in imports_dict:
|
73
|
-
module_path, original_name = imports_dict[name]
|
74
|
-
module = import_module(module_path, package)
|
75
|
-
result = getattr(module, original_name)
|
76
|
-
_cache[name] = result
|
77
|
-
return result
|
78
|
-
raise AttributeError(f"module '{package}' has no attribute '{name}'")
|
79
|
-
|
80
|
-
return __getattr__
|
81
|
-
|
82
|
-
|
83
|
-
_type_checking_cache = {}
|
84
|
-
|
85
|
-
|
86
|
-
def _auto_create_getattr_loader(all_exports: tuple[str, ...]) -> Callable[[str], Any]:
|
87
|
-
"""Automatically create a lazy loader by inspecting the calling module.
|
88
|
-
|
89
|
-
This function inspects the calling module's source code to extract
|
90
|
-
TYPE_CHECKING imports and automatically builds the import map.
|
91
|
-
|
92
|
-
Args:
|
93
|
-
all_exports: The __all__ tuple from the calling module
|
94
|
-
|
95
|
-
Returns:
|
96
|
-
A __getattr__ function that lazily imports modules
|
97
|
-
"""
|
98
|
-
# Get the calling module's frame
|
99
|
-
frame = inspect.currentframe()
|
100
|
-
if frame is None or frame.f_back is None:
|
101
|
-
raise RuntimeError("Cannot determine calling module")
|
102
|
-
|
103
|
-
calling_frame = frame.f_back
|
104
|
-
module_name = calling_frame.f_globals.get("__name__", "")
|
105
|
-
package = calling_frame.f_globals.get("__package__", "")
|
106
|
-
filename = calling_frame.f_globals.get("__file__", "")
|
107
|
-
|
108
|
-
# Check cache first
|
109
|
-
cache_key = (filename, tuple(all_exports))
|
110
|
-
if cache_key in _type_checking_cache:
|
111
|
-
return _type_checking_cache[cache_key]
|
112
|
-
|
113
|
-
# Read the source file
|
114
|
-
try:
|
115
|
-
with open(filename, "r") as f:
|
116
|
-
source_code = f.read()
|
117
|
-
except (IOError, OSError):
|
118
|
-
# Fallback: try to get source from the module
|
119
|
-
import sys
|
120
|
-
|
121
|
-
module = sys.modules.get(module_name)
|
122
|
-
if module:
|
123
|
-
source_code = inspect.getsource(module)
|
124
|
-
else:
|
125
|
-
raise RuntimeError(f"Cannot read source for module {module_name}")
|
126
|
-
|
127
|
-
# Parse the source to extract TYPE_CHECKING imports
|
128
|
-
imports_map = _parse_type_checking_imports(source_code)
|
129
|
-
|
130
|
-
# Filter to only include exports that are in __all__
|
131
|
-
filtered_map = {
|
132
|
-
name: path for name, path in imports_map.items() if name in all_exports
|
133
|
-
}
|
134
|
-
|
135
|
-
loader = _create_getattr_loader(filtered_map, package)
|
136
|
-
_type_checking_cache[cache_key] = loader
|
137
|
-
return loader
|
138
|
-
|
139
|
-
|
140
|
-
def _parse_type_checking_imports(source_code: str) -> dict[str, tuple[str, str]]:
|
141
|
-
"""Parse TYPE_CHECKING imports from source code to build import map.
|
142
|
-
|
143
|
-
Args:
|
144
|
-
source_code: The source code containing TYPE_CHECKING imports
|
145
|
-
|
146
|
-
Returns:
|
147
|
-
Dictionary mapping local names to (module_path, original_name) tuples
|
148
|
-
"""
|
149
|
-
|
150
|
-
@_parse_cache.cached_call
|
151
|
-
def _exec(source_code: str) -> dict[str, tuple[str, str]]:
|
152
|
-
tree = ast.parse(source_code)
|
153
|
-
imports = {}
|
154
|
-
|
155
|
-
for node in ast.walk(tree):
|
156
|
-
if isinstance(node, ast.If):
|
157
|
-
# Check if this is a TYPE_CHECKING block
|
158
|
-
is_type_checking = False
|
159
|
-
|
160
|
-
if isinstance(node.test, ast.Name) and node.test.id == "TYPE_CHECKING":
|
161
|
-
is_type_checking = True
|
162
|
-
elif isinstance(node.test, ast.Attribute):
|
163
|
-
if (
|
164
|
-
isinstance(node.test.value, ast.Name)
|
165
|
-
and node.test.value.id == "typing"
|
166
|
-
and node.test.attr == "TYPE_CHECKING"
|
167
|
-
):
|
168
|
-
is_type_checking = True
|
169
|
-
|
170
|
-
if is_type_checking:
|
171
|
-
# Process imports in this block
|
172
|
-
for stmt in node.body:
|
173
|
-
if isinstance(stmt, ast.ImportFrom) and stmt.module:
|
174
|
-
module_path = f".{stmt.module}"
|
175
|
-
for alias in stmt.names:
|
176
|
-
original_name = alias.name
|
177
|
-
local_name = alias.asname or original_name
|
178
|
-
imports[local_name] = (module_path, original_name)
|
179
|
-
|
180
|
-
return imports
|
181
|
-
|
182
|
-
return _exec(source_code)
|
hammad/ai/__init__.py
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
"""hammad.ai"""
|
2
|
-
|
3
|
-
from typing import TYPE_CHECKING
|
4
|
-
from .._core._utils._import_utils import _auto_create_getattr_loader
|
5
|
-
|
6
|
-
if TYPE_CHECKING:
|
7
|
-
from .completions import (
|
8
|
-
CompletionsClient,
|
9
|
-
Completion,
|
10
|
-
CompletionChunk,
|
11
|
-
CompletionsInputParam,
|
12
|
-
CompletionsModelName,
|
13
|
-
CompletionsOutputType,
|
14
|
-
CompletionStream,
|
15
|
-
AsyncCompletionStream,
|
16
|
-
async_create_completion,
|
17
|
-
create_completion,
|
18
|
-
)
|
19
|
-
from .embeddings import (
|
20
|
-
Embedding,
|
21
|
-
EmbeddingResponse,
|
22
|
-
EmbeddingUsage,
|
23
|
-
BaseEmbeddingsClient,
|
24
|
-
FastEmbedTextEmbeddingsClient,
|
25
|
-
LiteLlmEmbeddingsClient,
|
26
|
-
create_embeddings,
|
27
|
-
async_create_embeddings,
|
28
|
-
)
|
29
|
-
|
30
|
-
|
31
|
-
__all__ = (
|
32
|
-
# hammad.ai.completions
|
33
|
-
"CompletionsClient",
|
34
|
-
"Completion",
|
35
|
-
"CompletionChunk",
|
36
|
-
"CompletionsInputParam",
|
37
|
-
"CompletionsModelName",
|
38
|
-
"CompletionsOutputType",
|
39
|
-
"CompletionStream",
|
40
|
-
"AsyncCompletionStream",
|
41
|
-
"async_create_completion",
|
42
|
-
"create_completion",
|
43
|
-
# hammad.ai.embeddings
|
44
|
-
"Embedding",
|
45
|
-
"EmbeddingResponse",
|
46
|
-
"EmbeddingUsage",
|
47
|
-
"BaseEmbeddingsClient",
|
48
|
-
"FastEmbedTextEmbeddingsClient",
|
49
|
-
"LiteLlmEmbeddingsClient",
|
50
|
-
"create_embeddings",
|
51
|
-
"async_create_embeddings",
|
52
|
-
)
|
53
|
-
|
54
|
-
|
55
|
-
__getattr__ = _auto_create_getattr_loader(__all__)
|
56
|
-
|
57
|
-
|
58
|
-
def __dir__() -> list[str]:
|
59
|
-
return list(__all__)
|