inferencesh 0.1.11__py3-none-any.whl → 0.1.14__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.
Potentially problematic release.
This version of inferencesh might be problematic. Click here for more details.
- inferencesh/sdk.py +84 -9
- {inferencesh-0.1.11.dist-info → inferencesh-0.1.14.dist-info}/METADATA +1 -1
- inferencesh-0.1.14.dist-info/RECORD +8 -0
- {inferencesh-0.1.11.dist-info → inferencesh-0.1.14.dist-info}/WHEEL +1 -1
- inferencesh-0.1.11.dist-info/RECORD +0 -8
- {inferencesh-0.1.11.dist-info → inferencesh-0.1.14.dist-info}/LICENSE +0 -0
- {inferencesh-0.1.11.dist-info → inferencesh-0.1.14.dist-info}/entry_points.txt +0 -0
- {inferencesh-0.1.11.dist-info → inferencesh-0.1.14.dist-info}/top_level.txt +0 -0
inferencesh/sdk.py
CHANGED
|
@@ -6,10 +6,81 @@ import urllib.request
|
|
|
6
6
|
import urllib.parse
|
|
7
7
|
import tempfile
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
from typing import Any, Dict, List
|
|
10
|
+
import inspect
|
|
11
|
+
import ast
|
|
12
|
+
import textwrap
|
|
13
|
+
from collections import OrderedDict
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# inspired by https://github.com/pydantic/pydantic/issues/7580
|
|
17
|
+
class OrderedSchemaModel(BaseModel):
|
|
18
|
+
"""A base model that ensures the JSON schema properties and required fields are in the order of field definition."""
|
|
19
|
+
|
|
20
|
+
@classmethod
|
|
21
|
+
def model_json_schema(cls, by_alias: bool = True, **kwargs: Any) -> Dict[str, Any]:
|
|
22
|
+
schema = super().model_json_schema(by_alias=by_alias, **kwargs)
|
|
23
|
+
|
|
24
|
+
field_order = cls._get_field_order()
|
|
25
|
+
|
|
26
|
+
if field_order:
|
|
27
|
+
# Order properties
|
|
28
|
+
ordered_properties = OrderedDict()
|
|
29
|
+
for field_name in field_order:
|
|
30
|
+
if field_name in schema['properties']:
|
|
31
|
+
ordered_properties[field_name] = schema['properties'][field_name]
|
|
32
|
+
|
|
33
|
+
# Add any remaining properties that weren't in field_order
|
|
34
|
+
for field_name, field_schema in schema['properties'].items():
|
|
35
|
+
if field_name not in ordered_properties:
|
|
36
|
+
ordered_properties[field_name] = field_schema
|
|
37
|
+
|
|
38
|
+
schema['properties'] = ordered_properties
|
|
39
|
+
|
|
40
|
+
# Order required fields
|
|
41
|
+
if 'required' in schema:
|
|
42
|
+
ordered_required = [field for field in field_order if field in schema['required']]
|
|
43
|
+
# Add any remaining required fields that weren't in field_order
|
|
44
|
+
ordered_required.extend([field for field in schema['required'] if field not in ordered_required])
|
|
45
|
+
schema['required'] = ordered_required
|
|
46
|
+
|
|
47
|
+
return schema
|
|
48
|
+
|
|
49
|
+
@classmethod
|
|
50
|
+
def _get_field_order(cls) -> List[str]:
|
|
51
|
+
"""Get the order of fields as they were defined in the class."""
|
|
52
|
+
source = inspect.getsource(cls)
|
|
53
|
+
|
|
54
|
+
# Unindent the entire source code
|
|
55
|
+
source = textwrap.dedent(source)
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
module = ast.parse(source)
|
|
59
|
+
except IndentationError:
|
|
60
|
+
# If we still get an IndentationError, wrap the class in a dummy module
|
|
61
|
+
source = f"class DummyModule:\n{textwrap.indent(source, ' ')}"
|
|
62
|
+
module = ast.parse(source)
|
|
63
|
+
# Adjust to look at the first class def inside DummyModule
|
|
64
|
+
# noinspection PyUnresolvedReferences
|
|
65
|
+
class_def = module.body[0].body[0]
|
|
66
|
+
else:
|
|
67
|
+
# Find the class definition
|
|
68
|
+
class_def = next(
|
|
69
|
+
node for node in module.body if isinstance(node, ast.ClassDef) and node.name == cls.__name__
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# Extract field names in the order they were defined
|
|
73
|
+
field_order = []
|
|
74
|
+
for node in class_def.body:
|
|
75
|
+
if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name):
|
|
76
|
+
field_order.append(node.target.id)
|
|
77
|
+
|
|
78
|
+
return field_order
|
|
79
|
+
|
|
80
|
+
class BaseAppInput(OrderedSchemaModel):
|
|
10
81
|
pass
|
|
11
82
|
|
|
12
|
-
class BaseAppOutput(
|
|
83
|
+
class BaseAppOutput(OrderedSchemaModel):
|
|
13
84
|
pass
|
|
14
85
|
|
|
15
86
|
class BaseApp(BaseModel):
|
|
@@ -30,27 +101,31 @@ class BaseApp(BaseModel):
|
|
|
30
101
|
|
|
31
102
|
class File(BaseModel):
|
|
32
103
|
"""A class representing a file in the inference.sh ecosystem."""
|
|
33
|
-
|
|
104
|
+
uri: str # Original location (URL or file path)
|
|
105
|
+
path: Optional[str] = None # Resolved local file path
|
|
34
106
|
mime_type: Optional[str] = None # MIME type of the file
|
|
35
107
|
size: Optional[int] = None # File size in bytes
|
|
36
108
|
filename: Optional[str] = None # Original filename if available
|
|
37
|
-
_tmp_path: Optional[str] = None # Internal storage for temporary file path
|
|
109
|
+
_tmp_path: Optional[str] = PrivateAttr(default=None) # Internal storage for temporary file path
|
|
38
110
|
|
|
39
111
|
def __init__(self, **data):
|
|
40
112
|
super().__init__(**data)
|
|
41
|
-
if self._is_url(self.
|
|
113
|
+
if self._is_url(self.uri):
|
|
42
114
|
self._download_url()
|
|
43
|
-
elif not os.path.isabs(self.
|
|
44
|
-
self.path = os.path.abspath(self.
|
|
115
|
+
elif not os.path.isabs(self.uri):
|
|
116
|
+
self.path = os.path.abspath(self.uri)
|
|
117
|
+
else:
|
|
118
|
+
self.path = self.uri
|
|
45
119
|
self._populate_metadata()
|
|
46
120
|
|
|
47
121
|
def _is_url(self, path: str) -> bool:
|
|
48
122
|
"""Check if the path is a URL."""
|
|
49
123
|
parsed = urllib.parse.urlparse(path)
|
|
50
124
|
return parsed.scheme in ('http', 'https')
|
|
125
|
+
|
|
51
126
|
def _download_url(self) -> None:
|
|
52
127
|
"""Download the URL to a temporary file and update the path."""
|
|
53
|
-
original_url = self.
|
|
128
|
+
original_url = self.uri
|
|
54
129
|
tmp_file = None
|
|
55
130
|
try:
|
|
56
131
|
# Create a temporary file with a suffix based on the URL path
|
|
@@ -108,7 +183,7 @@ class File(BaseModel):
|
|
|
108
183
|
@classmethod
|
|
109
184
|
def from_path(cls, path: Union[str, os.PathLike]) -> 'File':
|
|
110
185
|
"""Create a File instance from a file path."""
|
|
111
|
-
return cls(
|
|
186
|
+
return cls(uri=str(path))
|
|
112
187
|
|
|
113
188
|
def _guess_mime_type(self) -> Optional[str]:
|
|
114
189
|
"""Guess the MIME type of the file."""
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
inferencesh/__init__.py,sha256=pR0MXSJe41LgJkjGK-jhZR7LjqCFdRZtNTV6qcjYSTI,123
|
|
2
|
+
inferencesh/sdk.py,sha256=hfdaQs-ojHStDOqgBpNEXsqF8VmutbT-0mgQMm3PSVQ,7843
|
|
3
|
+
inferencesh-0.1.14.dist-info/LICENSE,sha256=OsgqEWIh2el_QMj0y8O1A5Q5Dl-dxqqYbFE6fszuR4s,1086
|
|
4
|
+
inferencesh-0.1.14.dist-info/METADATA,sha256=_e4fr2uefeABHk6hwnWnHDddL8QT-mFYrE7dRaIp9gA,2584
|
|
5
|
+
inferencesh-0.1.14.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
|
6
|
+
inferencesh-0.1.14.dist-info/entry_points.txt,sha256=6IC-fyozAqW3ljsMLGCXxJ0_ui2Jb-2fLHtoH1RTnEE,45
|
|
7
|
+
inferencesh-0.1.14.dist-info/top_level.txt,sha256=TSMHg3T1ThMl1HGAWmzBClwOYH1ump5neof9BfHIwaA,12
|
|
8
|
+
inferencesh-0.1.14.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
inferencesh/__init__.py,sha256=pR0MXSJe41LgJkjGK-jhZR7LjqCFdRZtNTV6qcjYSTI,123
|
|
2
|
-
inferencesh/sdk.py,sha256=Czs31xNdlm9LB_PdCo5Vnknn46c98votVsRbv9gHezU,4870
|
|
3
|
-
inferencesh-0.1.11.dist-info/LICENSE,sha256=OsgqEWIh2el_QMj0y8O1A5Q5Dl-dxqqYbFE6fszuR4s,1086
|
|
4
|
-
inferencesh-0.1.11.dist-info/METADATA,sha256=RbW4TasZukB7XGe7wZsk6rR8pwuTs_fCiaMLvecmL-k,2584
|
|
5
|
-
inferencesh-0.1.11.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
6
|
-
inferencesh-0.1.11.dist-info/entry_points.txt,sha256=6IC-fyozAqW3ljsMLGCXxJ0_ui2Jb-2fLHtoH1RTnEE,45
|
|
7
|
-
inferencesh-0.1.11.dist-info/top_level.txt,sha256=TSMHg3T1ThMl1HGAWmzBClwOYH1ump5neof9BfHIwaA,12
|
|
8
|
-
inferencesh-0.1.11.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|