banks 2.1.2__py3-none-any.whl → 2.2.0__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.
- banks/__about__.py +1 -1
- banks/env.py +2 -1
- banks/filters/__init__.py +2 -1
- banks/filters/image.py +11 -1
- banks/filters/xml.py +62 -0
- banks/registries/directory.py +6 -2
- {banks-2.1.2.dist-info → banks-2.2.0.dist-info}/METADATA +1 -1
- {banks-2.1.2.dist-info → banks-2.2.0.dist-info}/RECORD +10 -9
- {banks-2.1.2.dist-info → banks-2.2.0.dist-info}/WHEEL +0 -0
- {banks-2.1.2.dist-info → banks-2.2.0.dist-info}/licenses/LICENSE.txt +0 -0
banks/__about__.py
CHANGED
banks/env.py
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
from jinja2 import Environment, select_autoescape
|
|
5
5
|
|
|
6
6
|
from .config import config
|
|
7
|
-
from .filters import audio, cache_control, image, lemmatize, tool
|
|
7
|
+
from .filters import audio, cache_control, image, lemmatize, tool, xml
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def _add_extensions(_env):
|
|
@@ -38,5 +38,6 @@ env.filters["image"] = image
|
|
|
38
38
|
env.filters["lemmatize"] = lemmatize
|
|
39
39
|
env.filters["tool"] = tool
|
|
40
40
|
env.filters["audio"] = audio
|
|
41
|
+
env.filters["to_xml"] = xml
|
|
41
42
|
|
|
42
43
|
_add_extensions(env)
|
banks/filters/__init__.py
CHANGED
|
@@ -6,5 +6,6 @@ from .cache_control import cache_control
|
|
|
6
6
|
from .image import image
|
|
7
7
|
from .lemmatize import lemmatize
|
|
8
8
|
from .tool import tool
|
|
9
|
+
from .xml import xml
|
|
9
10
|
|
|
10
|
-
__all__ = ("cache_control", "image", "lemmatize", "tool", "audio")
|
|
11
|
+
__all__ = ("cache_control", "image", "lemmatize", "tool", "audio", "xml")
|
banks/filters/image.py
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
# SPDX-FileCopyrightText: 2023-present Massimiliano Pippi <mpippi@gmail.com>
|
|
2
2
|
#
|
|
3
3
|
# SPDX-License-Identifier: MIT
|
|
4
|
+
import re
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
from urllib.parse import urlparse
|
|
6
7
|
|
|
7
8
|
from banks.types import ContentBlock, ImageUrl
|
|
8
9
|
|
|
10
|
+
BASE64_PATH_REGEX = re.compile(r"image\/.*;base64,.*")
|
|
11
|
+
|
|
9
12
|
|
|
10
13
|
def _is_url(string: str) -> bool:
|
|
11
14
|
result = urlparse(string)
|
|
12
|
-
|
|
15
|
+
if not result.scheme:
|
|
16
|
+
return False
|
|
17
|
+
|
|
18
|
+
if not result.netloc:
|
|
19
|
+
# The only valid format when netloc is empty is base64 data urls
|
|
20
|
+
return all([result.scheme == "data", BASE64_PATH_REGEX.match(result.path)])
|
|
21
|
+
|
|
22
|
+
return True
|
|
13
23
|
|
|
14
24
|
|
|
15
25
|
def image(value: str) -> str:
|
banks/filters/xml.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import xml.etree.ElementTree as ET
|
|
3
|
+
from typing import Any, Optional, Union
|
|
4
|
+
from xml.dom.minidom import parseString
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _deserialize(string: str) -> Optional[dict]:
|
|
10
|
+
try:
|
|
11
|
+
return json.loads(string)
|
|
12
|
+
except json.JSONDecodeError:
|
|
13
|
+
return None
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _prepare_dictionary(value: Union[str, BaseModel, dict[str, Any]]):
|
|
17
|
+
root_tag = "input"
|
|
18
|
+
if isinstance(value, str):
|
|
19
|
+
model: Optional[dict[str, Any]] = _deserialize(value)
|
|
20
|
+
if model is None:
|
|
21
|
+
msg = f"{value} is not deserializable"
|
|
22
|
+
raise ValueError(msg)
|
|
23
|
+
elif isinstance(value, BaseModel):
|
|
24
|
+
model = value.model_dump()
|
|
25
|
+
root_tag = value.__class__.__name__.lower()
|
|
26
|
+
elif isinstance(value, dict):
|
|
27
|
+
model = value.copy()
|
|
28
|
+
for k in value.keys():
|
|
29
|
+
if not isinstance(k, str):
|
|
30
|
+
key = str(k)
|
|
31
|
+
if isinstance(k, (int, float)):
|
|
32
|
+
key = "_" + key
|
|
33
|
+
v = model.pop(k)
|
|
34
|
+
model[key.lower()] = v
|
|
35
|
+
else:
|
|
36
|
+
msg = f"Input can only be of type BaseModel, dictionary or deserializable string. Got {type(value)}"
|
|
37
|
+
raise ValueError(msg)
|
|
38
|
+
return model, root_tag
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def xml(value: Union[str, BaseModel, dict[str, Any]]) -> str:
|
|
42
|
+
"""
|
|
43
|
+
Convert a Pydantic model, a deserializable string or a dictionary into an XML string.
|
|
44
|
+
|
|
45
|
+
Example:
|
|
46
|
+
```jinja
|
|
47
|
+
{{'{"username": "user", "email": "example@email.com"}' | to_xml}}
|
|
48
|
+
"
|
|
49
|
+
<input>
|
|
50
|
+
<username>user</username>
|
|
51
|
+
<email>example@email.com</email>
|
|
52
|
+
</input>
|
|
53
|
+
"
|
|
54
|
+
```
|
|
55
|
+
"""
|
|
56
|
+
model, root_tag = _prepare_dictionary(value)
|
|
57
|
+
xml_model = ET.Element(root_tag)
|
|
58
|
+
for k, v in model.items():
|
|
59
|
+
sub = ET.SubElement(xml_model, k)
|
|
60
|
+
sub.text = str(v)
|
|
61
|
+
xml_str = ET.tostring(xml_model, encoding="unicode")
|
|
62
|
+
return parseString(xml_str).toprettyxml().replace('<?xml version="1.0" ?>\n', "") # noqa: S318
|
banks/registries/directory.py
CHANGED
|
@@ -27,7 +27,7 @@ DEFAULT_INDEX_NAME = "index.json"
|
|
|
27
27
|
class PromptFile(PromptModel):
|
|
28
28
|
"""Model representing a prompt file stored on disk."""
|
|
29
29
|
|
|
30
|
-
path: Path = Field(exclude=True)
|
|
30
|
+
path: Path | None = Field(default=None, exclude=True)
|
|
31
31
|
|
|
32
32
|
@classmethod
|
|
33
33
|
def from_prompt_path(cls: type[Self], prompt: Prompt, path: Path) -> Self:
|
|
@@ -101,7 +101,7 @@ class DirectoryPromptRegistry:
|
|
|
101
101
|
"""
|
|
102
102
|
version = version or DEFAULT_VERSION
|
|
103
103
|
for pf in self._index.files:
|
|
104
|
-
if pf.name == name and pf.version == version and pf.path.exists():
|
|
104
|
+
if pf.name == name and pf.version == version and pf.path and pf.path.exists():
|
|
105
105
|
return Prompt(**pf.model_dump())
|
|
106
106
|
raise PromptNotFoundError
|
|
107
107
|
|
|
@@ -135,6 +135,10 @@ class DirectoryPromptRegistry:
|
|
|
135
135
|
def _load(self):
|
|
136
136
|
"""Load the prompt index from disk."""
|
|
137
137
|
self._index = PromptFileIndex.model_validate_json(self._index_path.read_text())
|
|
138
|
+
# Reconstruct the file paths since they're excluded from serialization
|
|
139
|
+
for pf in self._index.files:
|
|
140
|
+
if pf.path is None:
|
|
141
|
+
pf.path = self._path / f"{pf.name}.{pf.version}.jinja"
|
|
138
142
|
|
|
139
143
|
def _save(self):
|
|
140
144
|
"""Save the prompt index to disk."""
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
banks/__about__.py,sha256=
|
|
1
|
+
banks/__about__.py,sha256=77xoXWQ484-a4X30IBRswGGTfRx8t_BwItzAm7NTXwI,132
|
|
2
2
|
banks/__init__.py,sha256=4IBopxXstFZliCvSjOuTurSQb32Vy26EXOPhmNZ4Hus,334
|
|
3
3
|
banks/cache.py,sha256=uUGAu82-mfrscc2q24x19ZMZBkoQzf3hh7_V300J-Ik,1069
|
|
4
4
|
banks/config.py,sha256=c6B1cXUZ-NN0XmJvfezXeHPXHP7knk8TfbmcZL7gCzk,1082
|
|
5
|
-
banks/env.py,sha256=
|
|
5
|
+
banks/env.py,sha256=XOSz6QGNSRaqnIdKWhH5U-ci8Tfi1mDyJHit_aE27Ro,1266
|
|
6
6
|
banks/errors.py,sha256=I5cgsa7wtolRVKBSq_aH5xs27yVcErBlMyUswCnM-es,580
|
|
7
7
|
banks/prompt.py,sha256=RhPq3wpE-AiCfCftZpPFj2HXGdazwYD502Pr1e-j7FY,8162
|
|
8
8
|
banks/types.py,sha256=03x7E7FPVfuN39xY--c0fKumnyVUVzNrq9pgG5R-pAU,5520
|
|
@@ -11,17 +11,18 @@ banks/extensions/__init__.py,sha256=Lx4UrOzywYQY7a8qvIqvc3ql54nwK0lNP7x3jYdbREY,
|
|
|
11
11
|
banks/extensions/chat.py,sha256=VV6UV1wQZcJ0KbIFHSFmDeptWtww4o2IXF5pXB6TpTM,2478
|
|
12
12
|
banks/extensions/completion.py,sha256=kF55PiNxjqpslUTAd46H4jOy0eFiLLm5hEcwxS4_oxs,7356
|
|
13
13
|
banks/extensions/docs.py,sha256=vWOZvu2JoS4LwUG-BR3jPqThirYvu3Fdba331UxooYM,1098
|
|
14
|
-
banks/filters/__init__.py,sha256=
|
|
14
|
+
banks/filters/__init__.py,sha256=MMNxopwecFHW4LA76NwL2JQkdddIAGbKOaHUHG1JQs8,353
|
|
15
15
|
banks/filters/audio.py,sha256=2vTPdpDo8FVQsl0WiPlXskwMCGnF8zKwWXfq1fYQzws,726
|
|
16
16
|
banks/filters/cache_control.py,sha256=aOGOIzuqasV_TcuFaaXbaoGhA2W9YTFuz7wkatyjXRU,962
|
|
17
|
-
banks/filters/image.py,sha256=
|
|
17
|
+
banks/filters/image.py,sha256=Ls1fWCgRx0YLGIFx7hdKtR1skY575jDWlCESP0zV1Bs,1407
|
|
18
18
|
banks/filters/lemmatize.py,sha256=Yvp8M4HCx6C0nrcu3UEMtjJUwsyVYI6GQDYOG4S6EEw,887
|
|
19
19
|
banks/filters/tool.py,sha256=i8ukSDYw54ksShVJ2abfRQAiKzKrqUtmgBB1H04cig0,475
|
|
20
|
+
banks/filters/xml.py,sha256=uQ_2zfCf8NhpdbF8F5HS7URXvDzsxfg-TEIVGufZbM0,1991
|
|
20
21
|
banks/registries/__init__.py,sha256=iRK-8420cKBckOTd5KcIFQyV66EsF0Mc7UHCkzf8qZU,255
|
|
21
|
-
banks/registries/directory.py,sha256=
|
|
22
|
+
banks/registries/directory.py,sha256=gRFO7fl9yXHt2NJ1pDA2wPSQtlORhSw1GKWxSTyFzE8,6055
|
|
22
23
|
banks/registries/file.py,sha256=8ayvFrcM8Tk0DWgGXmKD2DRBfGXr5CmgtdQaQ5cXhow,4054
|
|
23
24
|
banks/registries/redis.py,sha256=eBL92URJa-NegOxRLS4b2xrDRDxz6iiaz_7Ddi32Rtc,2756
|
|
24
|
-
banks-2.
|
|
25
|
-
banks-2.
|
|
26
|
-
banks-2.
|
|
27
|
-
banks-2.
|
|
25
|
+
banks-2.2.0.dist-info/METADATA,sha256=m2W5swzWGUFGr0uNCFAgOqFtxv4A7fMyjsC34GDBTsk,12098
|
|
26
|
+
banks-2.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
27
|
+
banks-2.2.0.dist-info/licenses/LICENSE.txt,sha256=NZJne_JTwMFwq_g-kq-sm4PuaeVOgu1l3NUGOgBHX-g,1102
|
|
28
|
+
banks-2.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|