fxn 0.0.41__py3-none-any.whl → 0.0.42__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.
- fxn/__init__.py +3 -1
- fxn/beta/__init__.py +6 -0
- fxn/beta/client.py +16 -0
- fxn/beta/prediction.py +16 -0
- fxn/beta/remote.py +207 -0
- fxn/c/__init__.py +1 -1
- fxn/c/configuration.py +1 -1
- fxn/c/fxnc.py +1 -1
- fxn/c/map.py +1 -1
- fxn/c/prediction.py +2 -2
- fxn/c/predictor.py +2 -3
- fxn/c/stream.py +2 -3
- fxn/c/value.py +1 -1
- fxn/cli/__init__.py +8 -10
- fxn/cli/auth.py +1 -1
- fxn/cli/misc.py +1 -1
- fxn/cli/predictions.py +1 -1
- fxn/cli/predictors.py +3 -51
- fxn/client.py +23 -11
- fxn/compile/__init__.py +7 -0
- fxn/compile/compile.py +80 -0
- fxn/compile/sandbox.py +177 -0
- fxn/compile/signature.py +183 -0
- fxn/function.py +6 -2
- fxn/lib/__init__.py +1 -1
- fxn/lib/linux/arm64/libFunction.so +0 -0
- fxn/lib/linux/x86_64/libFunction.so +0 -0
- fxn/lib/macos/arm64/Function.dylib +0 -0
- fxn/lib/macos/x86_64/Function.dylib +0 -0
- fxn/lib/windows/arm64/Function.dll +0 -0
- fxn/lib/windows/x86_64/Function.dll +0 -0
- fxn/services/__init__.py +1 -1
- fxn/services/prediction.py +5 -4
- fxn/services/predictor.py +6 -3
- fxn/services/user.py +6 -3
- fxn/types/__init__.py +3 -3
- fxn/types/dtype.py +1 -1
- fxn/types/prediction.py +12 -2
- fxn/types/predictor.py +2 -13
- fxn/types/user.py +1 -1
- fxn/version.py +2 -2
- {fxn-0.0.41.dist-info → fxn-0.0.42.dist-info}/METADATA +3 -3
- fxn-0.0.42.dist-info/RECORD +47 -0
- {fxn-0.0.41.dist-info → fxn-0.0.42.dist-info}/WHEEL +1 -1
- fxn/cli/env.py +0 -40
- fxn-0.0.41.dist-info/RECORD +0 -40
- {fxn-0.0.41.dist-info → fxn-0.0.42.dist-info}/LICENSE +0 -0
- {fxn-0.0.41.dist-info → fxn-0.0.42.dist-info}/entry_points.txt +0 -0
- {fxn-0.0.41.dist-info → fxn-0.0.42.dist-info}/top_level.txt +0 -0
fxn/compile/sandbox.py
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
#
|
2
|
+
# Function
|
3
|
+
# Copyright © 2025 NatML Inc. All Rights Reserved.
|
4
|
+
#
|
5
|
+
|
6
|
+
from __future__ import annotations
|
7
|
+
from hashlib import sha256
|
8
|
+
from pathlib import Path
|
9
|
+
from pydantic import BaseModel
|
10
|
+
from requests import put
|
11
|
+
from typing import Literal
|
12
|
+
|
13
|
+
from ..function import Function
|
14
|
+
|
15
|
+
class WorkdirCommand (BaseModel):
|
16
|
+
kind: Literal["workdir"] = "workdir"
|
17
|
+
path: str
|
18
|
+
|
19
|
+
class EnvCommand (BaseModel):
|
20
|
+
kind: Literal["env"] = "env"
|
21
|
+
env: dict[str, str]
|
22
|
+
|
23
|
+
class UploadFileCommand (BaseModel):
|
24
|
+
kind: Literal["upload_file"] = "upload_file"
|
25
|
+
from_path: str
|
26
|
+
to_path: str
|
27
|
+
manifest: dict[str, str] | None = None
|
28
|
+
|
29
|
+
class UploadDirectoryCommand (BaseModel):
|
30
|
+
kind: Literal["upload_dir"] = "upload_dir"
|
31
|
+
from_path: str
|
32
|
+
to_path: str
|
33
|
+
manifest: dict[str, str] | None = None
|
34
|
+
|
35
|
+
class PipInstallCommand (BaseModel):
|
36
|
+
kind: Literal["pip_install"] = "pip_install"
|
37
|
+
packages: list[str]
|
38
|
+
|
39
|
+
class AptInstallCommand (BaseModel):
|
40
|
+
kind: Literal["apt_install"] = "apt_install"
|
41
|
+
packages: list[str]
|
42
|
+
|
43
|
+
class EntrypointCommand (BaseModel):
|
44
|
+
kind: Literal["entrypoint"] = "entrypoint"
|
45
|
+
path: str
|
46
|
+
|
47
|
+
Command = (
|
48
|
+
WorkdirCommand |
|
49
|
+
EnvCommand |
|
50
|
+
UploadFileCommand |
|
51
|
+
UploadDirectoryCommand |
|
52
|
+
PipInstallCommand |
|
53
|
+
AptInstallCommand |
|
54
|
+
EntrypointCommand
|
55
|
+
)
|
56
|
+
|
57
|
+
class Sandbox (BaseModel):
|
58
|
+
"""
|
59
|
+
Sandbox which defines a containerized environment for compiling your Python function.
|
60
|
+
"""
|
61
|
+
commands: list[Command] = []
|
62
|
+
|
63
|
+
def workdir (self, path: str | Path) -> Sandbox:
|
64
|
+
"""
|
65
|
+
Change the current working directory for subsequent commands.
|
66
|
+
|
67
|
+
Parameters:
|
68
|
+
path (str | Path): Path to change to.
|
69
|
+
"""
|
70
|
+
command = WorkdirCommand(path=str(path))
|
71
|
+
self.commands.append(command)
|
72
|
+
return self
|
73
|
+
|
74
|
+
def env (self, **env: str) -> Sandbox:
|
75
|
+
"""
|
76
|
+
Set environment variables in the sandbox.
|
77
|
+
"""
|
78
|
+
command = EnvCommand(env=env)
|
79
|
+
self.commands.append(command)
|
80
|
+
return self
|
81
|
+
|
82
|
+
def upload_file (
|
83
|
+
self,
|
84
|
+
from_path: str | Path,
|
85
|
+
to_path: str | Path = "./"
|
86
|
+
) -> Sandbox:
|
87
|
+
"""
|
88
|
+
Upload a file to the sandbox.
|
89
|
+
|
90
|
+
Parameters:
|
91
|
+
from_path (str | Path): File path on the local file system.
|
92
|
+
to_path (str | Path): Remote path to upload file to.
|
93
|
+
"""
|
94
|
+
command = UploadFileCommand(from_path=str(from_path), to_path=str(to_path))
|
95
|
+
self.commands.append(command)
|
96
|
+
return self
|
97
|
+
|
98
|
+
def upload_directory (
|
99
|
+
self,
|
100
|
+
from_path: str | Path,
|
101
|
+
to_path: str | Path = "."
|
102
|
+
) -> Sandbox:
|
103
|
+
"""
|
104
|
+
Upload a directory to the sandbox.
|
105
|
+
|
106
|
+
Parameters:
|
107
|
+
from_path (str | Path): Directory path on the local file system.
|
108
|
+
to_path (str | Path): Remote path to upload directory to.
|
109
|
+
"""
|
110
|
+
command = UploadDirectoryCommand(from_path=str(from_path), to_path=str(to_path))
|
111
|
+
self.commands.append(command)
|
112
|
+
return self
|
113
|
+
|
114
|
+
def pip_install (self, *packages: str) -> Sandbox:
|
115
|
+
"""
|
116
|
+
Install Python packages in the sandbox.
|
117
|
+
|
118
|
+
Parameters:
|
119
|
+
packages (list): Packages to install.
|
120
|
+
"""
|
121
|
+
command = PipInstallCommand(packages=packages)
|
122
|
+
self.commands.append(command)
|
123
|
+
return self
|
124
|
+
|
125
|
+
def apt_install (self, *packages: str) -> Sandbox:
|
126
|
+
"""
|
127
|
+
Install Debian packages in the sandbox.
|
128
|
+
|
129
|
+
Parameters:
|
130
|
+
packages (list): Packages to install.
|
131
|
+
"""
|
132
|
+
command = AptInstallCommand(packages=packages)
|
133
|
+
self.commands.append(command)
|
134
|
+
return self
|
135
|
+
|
136
|
+
def populate (self, fxn: Function=None) -> Sandbox:
|
137
|
+
"""
|
138
|
+
Populate all metadata.
|
139
|
+
"""
|
140
|
+
fxn = fxn if fxn is not None else Function()
|
141
|
+
for command in self.commands:
|
142
|
+
if isinstance(command, UploadFileCommand):
|
143
|
+
from_path = Path(command.from_path)
|
144
|
+
to_path = Path(command.to_path)
|
145
|
+
command.manifest = { str(to_path / from_path.name): self.__upload_file(from_path, fxn=fxn) }
|
146
|
+
elif isinstance(command, UploadDirectoryCommand):
|
147
|
+
from_path = Path(command.from_path)
|
148
|
+
to_path = Path(command.to_path)
|
149
|
+
files = [file for file in from_path.rglob("*") if file.is_file()]
|
150
|
+
command.manifest = { str(to_path / file.relative_to(from_path)): self.__upload_file(file, fxn=fxn) for file in files }
|
151
|
+
return self
|
152
|
+
|
153
|
+
def __upload_file (self, path: Path, fxn: Function) -> str:
|
154
|
+
assert path.is_file(), "Cannot upload file at path {path} because it is not a file"
|
155
|
+
hash = self.__compute_hash(path)
|
156
|
+
try:
|
157
|
+
fxn.client.request(method="HEAD", path=f"/resources/{hash}")
|
158
|
+
except:
|
159
|
+
resource = fxn.client.request(
|
160
|
+
method="POST",
|
161
|
+
path="/resources",
|
162
|
+
body={ "name": hash },
|
163
|
+
response_type=_Resource
|
164
|
+
)
|
165
|
+
with path.open("rb") as f:
|
166
|
+
put(resource.url, data=f).raise_for_status()
|
167
|
+
return hash
|
168
|
+
|
169
|
+
def __compute_hash (self, path: Path) -> str:
|
170
|
+
hash = sha256()
|
171
|
+
with path.open("rb") as f:
|
172
|
+
for chunk in iter(lambda: f.read(4096), b""):
|
173
|
+
hash.update(chunk)
|
174
|
+
return hash.hexdigest()
|
175
|
+
|
176
|
+
class _Resource (BaseModel):
|
177
|
+
url: str
|
fxn/compile/signature.py
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
#
|
2
|
+
# Function
|
3
|
+
# Copyright © 2025 NatML Inc. All Rights Reserved.
|
4
|
+
#
|
5
|
+
|
6
|
+
from collections.abc import Mapping, Sequence
|
7
|
+
from enum import Enum
|
8
|
+
from inspect import isasyncgenfunction, iscoroutinefunction, isgeneratorfunction, signature
|
9
|
+
from io import BytesIO
|
10
|
+
import numpy as np
|
11
|
+
from PIL import Image
|
12
|
+
from pydantic import BaseModel, TypeAdapter
|
13
|
+
from typing import get_type_hints, get_origin, get_args, Any, Dict, List, Union
|
14
|
+
|
15
|
+
from ..types import Dtype, EnumerationMember, Parameter, Signature
|
16
|
+
|
17
|
+
class FunctionType (str, Enum):
|
18
|
+
Coroutine = "ASYNC_FUNCTION"
|
19
|
+
Function = "FUNCTION"
|
20
|
+
Generator = "GENERATOR"
|
21
|
+
AsyncGenerator = "ASYNC_GENERATOR"
|
22
|
+
|
23
|
+
def get_function_type (func) -> FunctionType:
|
24
|
+
if isasyncgenfunction(func):
|
25
|
+
return FunctionType.AsyncGenerator
|
26
|
+
elif iscoroutinefunction(func):
|
27
|
+
return FunctionType.Coroutine
|
28
|
+
elif isgeneratorfunction(func):
|
29
|
+
return FunctionType.Generator
|
30
|
+
else:
|
31
|
+
return FunctionType.Function
|
32
|
+
|
33
|
+
def infer_function_signature (func) -> Signature:
|
34
|
+
inputs = _get_input_parameters(func)
|
35
|
+
outputs = _get_output_parameters(func)
|
36
|
+
signature = Signature(inputs=inputs, outputs=outputs)
|
37
|
+
return signature
|
38
|
+
|
39
|
+
def _get_input_parameters (func) -> list[Parameter]:
|
40
|
+
sig = signature(func)
|
41
|
+
type_hints = get_type_hints(func)
|
42
|
+
parameters = []
|
43
|
+
for name, param in sig.parameters.items():
|
44
|
+
param_type = type_hints.get(name)
|
45
|
+
if param_type is None:
|
46
|
+
raise TypeError(f"Missing type annotation for parameter '{name}' in function '{func.__name__}'")
|
47
|
+
dtype = _infer_dtype(param_type)
|
48
|
+
enumeration = [EnumerationMember(
|
49
|
+
name=member.name,
|
50
|
+
value=member.value
|
51
|
+
) for member in param_type] if _is_enum_subclass(param_type) else None
|
52
|
+
value_schema = _get_type_schema(param_type) if dtype in { Dtype.list, Dtype.dict } else None
|
53
|
+
input_param = Parameter(
|
54
|
+
name=name,
|
55
|
+
type=dtype,
|
56
|
+
description=None,
|
57
|
+
optional=param.default != param.empty,
|
58
|
+
range=None,
|
59
|
+
enumeration=enumeration,
|
60
|
+
value_schema=value_schema
|
61
|
+
)
|
62
|
+
parameters.append(input_param)
|
63
|
+
return parameters
|
64
|
+
|
65
|
+
def _get_output_parameters (func) -> list[Parameter]:
|
66
|
+
# Check for return annotation
|
67
|
+
sig = signature(func)
|
68
|
+
if sig.return_annotation is sig.empty:
|
69
|
+
raise TypeError(f"Missing return type annotation for function '{func.__name__}'")
|
70
|
+
# Gather return types
|
71
|
+
return_types = []
|
72
|
+
if _is_tuple_type(sig.return_annotation):
|
73
|
+
return_types = get_args(sig.return_annotation)
|
74
|
+
if not return_types or Ellipsis in return_types:
|
75
|
+
raise TypeError(f"Return type of function '{func.__name__}' must be fully typed with generic type arguments.")
|
76
|
+
else:
|
77
|
+
return_types = [sig.return_annotation]
|
78
|
+
# Create parameters
|
79
|
+
parameters = [_get_output_parameter(f"output{idx}", output_type) for idx, output_type in enumerate(return_types)]
|
80
|
+
return parameters
|
81
|
+
|
82
|
+
def _get_output_parameter (name: str, return_type) -> Parameter:
|
83
|
+
dtype = _infer_dtype(return_type)
|
84
|
+
enumeration = [EnumerationMember(
|
85
|
+
name=member.name,
|
86
|
+
value=member.value
|
87
|
+
) for member in return_type] if _is_enum_subclass(return_type) else None
|
88
|
+
value_schema = _get_type_schema(return_type) if dtype in { Dtype.list, Dtype.dict } else None
|
89
|
+
parameter = Parameter(
|
90
|
+
name=name,
|
91
|
+
type=dtype,
|
92
|
+
description=None,
|
93
|
+
optional=False,
|
94
|
+
range=None,
|
95
|
+
enumeration=enumeration,
|
96
|
+
value_schema=value_schema
|
97
|
+
)
|
98
|
+
return parameter
|
99
|
+
|
100
|
+
def _infer_dtype (param_type) -> Dtype:
|
101
|
+
param_type = _strip_optional(param_type)
|
102
|
+
origin = get_origin(param_type)
|
103
|
+
args = get_args(param_type)
|
104
|
+
if origin is None:
|
105
|
+
if param_type is np.ndarray:
|
106
|
+
return Dtype.float32
|
107
|
+
elif param_type is Image.Image:
|
108
|
+
return Dtype.image
|
109
|
+
elif param_type in { bytes, bytearray, memoryview, BytesIO }:
|
110
|
+
return Dtype.binary
|
111
|
+
elif param_type is int:
|
112
|
+
return Dtype.int32
|
113
|
+
elif param_type is float:
|
114
|
+
return Dtype.float32
|
115
|
+
elif param_type is bool:
|
116
|
+
return Dtype.bool
|
117
|
+
elif param_type is str:
|
118
|
+
return Dtype.string
|
119
|
+
elif _is_enum_subclass(param_type):
|
120
|
+
return Dtype.string
|
121
|
+
elif param_type is list:
|
122
|
+
return Dtype.list
|
123
|
+
elif param_type is dict:
|
124
|
+
return Dtype.dict
|
125
|
+
elif _is_pydantic_model(param_type):
|
126
|
+
return Dtype.dict
|
127
|
+
else:
|
128
|
+
raise TypeError(f"Unsupported parameter type: {param_type}")
|
129
|
+
else:
|
130
|
+
if origin in { list, List, Sequence }:
|
131
|
+
return Dtype.list
|
132
|
+
elif origin in { dict, Dict, Mapping }:
|
133
|
+
return Dtype.dict
|
134
|
+
elif origin is np.ndarray:
|
135
|
+
if args:
|
136
|
+
dtype_arg = args[0]
|
137
|
+
dtype = _numpy_to_fxn_dtype(dtype_arg)
|
138
|
+
if dtype is not None:
|
139
|
+
return dtype
|
140
|
+
return Dtype.float32
|
141
|
+
else:
|
142
|
+
raise TypeError(f"Unsupported parameter type: {param_type}")
|
143
|
+
|
144
|
+
def _is_enum_subclass (cls) -> bool:
|
145
|
+
return isinstance(cls, type) and issubclass(cls, Enum)
|
146
|
+
|
147
|
+
def _is_pydantic_model (cls) -> bool:
|
148
|
+
return isinstance(cls, type) and issubclass(cls, BaseModel)
|
149
|
+
|
150
|
+
def _is_tuple_type (param_type) -> bool:
|
151
|
+
origin = get_origin(param_type)
|
152
|
+
return origin is tuple
|
153
|
+
|
154
|
+
def _strip_optional (param_type):
|
155
|
+
if get_origin(param_type) is Union:
|
156
|
+
args = get_args(param_type)
|
157
|
+
non_none_args = [arg for arg in args if arg is not type(None)]
|
158
|
+
if len(non_none_args) == 1:
|
159
|
+
return non_none_args[0]
|
160
|
+
return param_type
|
161
|
+
|
162
|
+
def _numpy_to_fxn_dtype (dtype) -> Dtype | None:
|
163
|
+
dtype_mapping = {
|
164
|
+
np.int8: Dtype.int8,
|
165
|
+
np.int16: Dtype.int16,
|
166
|
+
np.int32: Dtype.int32,
|
167
|
+
np.int64: Dtype.int64,
|
168
|
+
np.uint8: Dtype.uint8,
|
169
|
+
np.uint16: Dtype.uint16,
|
170
|
+
np.uint32: Dtype.uint32,
|
171
|
+
np.uint64: Dtype.uint64,
|
172
|
+
np.float16: Dtype.float16,
|
173
|
+
np.float32: Dtype.float32,
|
174
|
+
np.float64: Dtype.float64,
|
175
|
+
np.bool_: Dtype.bool,
|
176
|
+
}
|
177
|
+
return dtype_mapping.get(dtype, None)
|
178
|
+
|
179
|
+
def _get_type_schema (param_type) -> dict[str, Any] | None:
|
180
|
+
try:
|
181
|
+
return TypeAdapter(param_type).json_schema(mode="serialization")
|
182
|
+
except Exception:
|
183
|
+
return None
|
fxn/function.py
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
#
|
2
2
|
# Function
|
3
|
-
# Copyright ©
|
3
|
+
# Copyright © 2025 NatML Inc. All Rights Reserved.
|
4
4
|
#
|
5
5
|
|
6
6
|
from os import environ
|
7
7
|
|
8
|
+
from .beta.client import BetaClient
|
8
9
|
from .client import FunctionClient
|
9
10
|
from .services import PredictionService, PredictorService, UserService
|
10
11
|
|
@@ -17,6 +18,7 @@ class Function:
|
|
17
18
|
users (UserService): Manage users.
|
18
19
|
predictors (PredictorService): Manage predictors.
|
19
20
|
predictions (PredictionService): Manage predictions.
|
21
|
+
beta (BetaClient): Beta client for incubating features.
|
20
22
|
|
21
23
|
Constructor:
|
22
24
|
access_key (str): Function access key.
|
@@ -26,6 +28,7 @@ class Function:
|
|
26
28
|
users: UserService
|
27
29
|
predictors: PredictorService
|
28
30
|
predictions: PredictionService
|
31
|
+
beta: BetaClient
|
29
32
|
|
30
33
|
def __init__ (self, access_key: str=None, api_url: str=None):
|
31
34
|
access_key = access_key or environ.get("FXN_ACCESS_KEY", None)
|
@@ -33,4 +36,5 @@ class Function:
|
|
33
36
|
self.client = FunctionClient(access_key, api_url)
|
34
37
|
self.users = UserService(self.client)
|
35
38
|
self.predictors = PredictorService(self.client)
|
36
|
-
self.predictions = PredictionService(self.client)
|
39
|
+
self.predictions = PredictionService(self.client)
|
40
|
+
self.beta = BetaClient(self.client)
|
fxn/lib/__init__.py
CHANGED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
fxn/services/__init__.py
CHANGED
fxn/services/prediction.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Function
|
3
|
-
# Copyright ©
|
3
|
+
# Copyright © 2025 NatML Inc. All Rights Reserved.
|
4
4
|
#
|
5
5
|
|
6
6
|
from dataclasses import asdict, is_dataclass
|
@@ -16,8 +16,8 @@ from tempfile import gettempdir
|
|
16
16
|
from typing import Any, AsyncIterator
|
17
17
|
from urllib.parse import urlparse
|
18
18
|
|
19
|
-
from ..client import FunctionClient
|
20
19
|
from ..c import Configuration, Predictor, Prediction as CPrediction, Value as CValue, ValueFlags, ValueMap
|
20
|
+
from ..client import FunctionClient
|
21
21
|
from ..types import Acceleration, Prediction, PredictionResource
|
22
22
|
|
23
23
|
Value = ndarray | str | float | int | bool | list[Any] | dict[str, Any] | Image.Image | BytesIO | memoryview
|
@@ -134,9 +134,10 @@ class PredictionService:
|
|
134
134
|
"tag": tag,
|
135
135
|
"clientId": client_id,
|
136
136
|
"configurationId": configuration_id,
|
137
|
-
}
|
137
|
+
},
|
138
|
+
response_type=Prediction
|
138
139
|
)
|
139
|
-
return
|
140
|
+
return prediction
|
140
141
|
|
141
142
|
def __get_predictor (
|
142
143
|
self,
|
fxn/services/predictor.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Function
|
3
|
-
# Copyright ©
|
3
|
+
# Copyright © 2025 NatML Inc. All Rights Reserved.
|
4
4
|
#
|
5
5
|
|
6
6
|
from ..client import FunctionClient, FunctionAPIError
|
@@ -22,8 +22,11 @@ class PredictorService:
|
|
22
22
|
Predictor: Predictor.
|
23
23
|
"""
|
24
24
|
try:
|
25
|
-
|
26
|
-
|
25
|
+
return self.client.request(
|
26
|
+
method="GET",
|
27
|
+
path=f"/predictors/{tag}",
|
28
|
+
response_type=Predictor
|
29
|
+
)
|
27
30
|
except FunctionAPIError as error:
|
28
31
|
if error.status_code == 404:
|
29
32
|
return None
|
fxn/services/user.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Function
|
3
|
-
# Copyright ©
|
3
|
+
# Copyright © 2025 NatML Inc. All Rights Reserved.
|
4
4
|
#
|
5
5
|
|
6
6
|
from ..client import FunctionClient, FunctionAPIError
|
@@ -19,8 +19,11 @@ class UserService:
|
|
19
19
|
User: User.
|
20
20
|
"""
|
21
21
|
try:
|
22
|
-
|
23
|
-
|
22
|
+
return self.client.request(
|
23
|
+
method="GET",
|
24
|
+
path="/users",
|
25
|
+
response_type=User
|
26
|
+
)
|
24
27
|
except FunctionAPIError as error:
|
25
28
|
if error.status_code == 401:
|
26
29
|
return None
|
fxn/types/__init__.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
#
|
2
2
|
# Function
|
3
|
-
# Copyright ©
|
3
|
+
# Copyright © 2025 NatML Inc. All Rights Reserved.
|
4
4
|
#
|
5
5
|
|
6
6
|
from .dtype import Dtype
|
7
|
-
from .prediction import Prediction, PredictionResource
|
8
|
-
from .predictor import
|
7
|
+
from .prediction import Acceleration, Prediction, PredictionResource
|
8
|
+
from .predictor import AccessMode, EnumerationMember, Parameter, Predictor, PredictorStatus, Signature
|
9
9
|
from .user import User
|
fxn/types/dtype.py
CHANGED
fxn/types/prediction.py
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
#
|
2
2
|
# Function
|
3
|
-
# Copyright ©
|
3
|
+
# Copyright © 2025 NatML Inc. All Rights Reserved.
|
4
4
|
#
|
5
5
|
|
6
|
+
from enum import IntFlag
|
6
7
|
from pydantic import BaseModel, Field
|
7
8
|
from typing import Any
|
8
9
|
|
@@ -42,4 +43,13 @@ class Prediction (BaseModel):
|
|
42
43
|
latency: float | None = Field(default=None, description="Prediction latency in milliseconds.")
|
43
44
|
error: str | None = Field(default=None, description="Prediction error. This is `None` if the prediction completed successfully.")
|
44
45
|
logs: str | None = Field(default=None, description="Prediction logs.")
|
45
|
-
created: str = Field(description="Date created.")
|
46
|
+
created: str = Field(description="Date created.")
|
47
|
+
|
48
|
+
class Acceleration (IntFlag):
|
49
|
+
"""
|
50
|
+
Predictor acceleration.
|
51
|
+
"""
|
52
|
+
Auto = 0,
|
53
|
+
CPU = 1 << 0,
|
54
|
+
GPU = 1 << 1,
|
55
|
+
NPU = 1 << 2
|
fxn/types/predictor.py
CHANGED
@@ -1,24 +1,15 @@
|
|
1
1
|
#
|
2
2
|
# Function
|
3
|
-
# Copyright ©
|
3
|
+
# Copyright © 2025 NatML Inc. All Rights Reserved.
|
4
4
|
#
|
5
5
|
|
6
|
-
from enum import Enum
|
6
|
+
from enum import Enum
|
7
7
|
from pydantic import AliasChoices, BaseModel, ConfigDict, Field
|
8
8
|
from typing import Any
|
9
9
|
|
10
10
|
from .dtype import Dtype
|
11
11
|
from .user import User
|
12
12
|
|
13
|
-
class Acceleration (IntFlag):
|
14
|
-
"""
|
15
|
-
Predictor acceleration.
|
16
|
-
"""
|
17
|
-
Auto = 0,
|
18
|
-
CPU = 1 << 0,
|
19
|
-
GPU = 1 << 1,
|
20
|
-
NPU = 1 << 2
|
21
|
-
|
22
13
|
class AccessMode (str, Enum):
|
23
14
|
"""
|
24
15
|
Predictor access mode.
|
@@ -57,7 +48,6 @@ class Parameter (BaseModel):
|
|
57
48
|
optional (bool): Whether the parameter is optional.
|
58
49
|
range (tuple): Parameter value range for numeric parameters.
|
59
50
|
enumeration (list): Parameter value choices for enumeration parameters.
|
60
|
-
default_value (str | float | int | bool | ndarray | list | dict | PIL.Image | BytesIO): Parameter default value.
|
61
51
|
value_schema (dict): Parameter JSON schema. This is only populated for `list` and `dict` parameters.
|
62
52
|
"""
|
63
53
|
name: str = Field(description="Parameter name.")
|
@@ -66,7 +56,6 @@ class Parameter (BaseModel):
|
|
66
56
|
optional: bool | None = Field(default=None, description="Whether the parameter is optional.")
|
67
57
|
range: tuple[float, float] | None = Field(default=None, description="Parameter value range for numeric parameters.")
|
68
58
|
enumeration: list[EnumerationMember] | None = Field(default=None, description="Parameter value choices for enumeration parameters.")
|
69
|
-
default_value: str | float | int | bool | list[Any] | dict[str, Any] | None = Field(default=None, description="Parameter default value.", serialization_alias="defaultValue", validation_alias=AliasChoices("default_value", "defaultValue"))
|
70
59
|
value_schema: dict[str, Any] | None = Field(default=None, description="Parameter JSON schema. This is only populated for `list` and `dict` parameters.", serialization_alias="schema", validation_alias=AliasChoices("schema", "value_schema"))
|
71
60
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
72
61
|
|
fxn/types/user.py
CHANGED
fxn/version.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.2
|
2
2
|
Name: fxn
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.42
|
4
4
|
Summary: Run prediction functions locally in Python. Register at https://fxn.ai.
|
5
5
|
Author-email: "NatML Inc." <hi@fxn.ai>
|
6
|
-
License:
|
6
|
+
License: Apache License
|
7
7
|
Version 2.0, January 2004
|
8
8
|
http://www.apache.org/licenses/
|
9
9
|
|
@@ -0,0 +1,47 @@
|
|
1
|
+
fxn/__init__.py,sha256=co_h8b85Oz3gyrT8T30RbwFQZ8Zf0i57ynGC2H44VZs,207
|
2
|
+
fxn/client.py,sha256=i56oIr4f4ODjKhnD2EugBWQULVubIIFHqqBsoix23xw,1666
|
3
|
+
fxn/function.py,sha256=JBZnGaLedgoY-wV5Tg-Rxwpd3tK_ADkD0Qve45NBaA0,1342
|
4
|
+
fxn/version.py,sha256=-M_EgT0O4ScSm10y5QibgzW8y3KbHfvkosDKMCfirOQ,95
|
5
|
+
fxn/beta/__init__.py,sha256=gKoDhuXtXCjdhUYUqmF0gDPMhJfg3UwFgbvMtRB5ipo,111
|
6
|
+
fxn/beta/client.py,sha256=x1AVAz0PlX0Wnemi7KXk5XfC8R6HC7vOQaGUviPJLN8,363
|
7
|
+
fxn/beta/prediction.py,sha256=9DTBahNF6m0TicLab2o9e8IKpiSV6K7cUSTYaFju0ZU,356
|
8
|
+
fxn/beta/remote.py,sha256=MMFM6QYyxNkpf2czql_JZz9dVbuWHIzhC4mq7pcyPdo,7778
|
9
|
+
fxn/c/__init__.py,sha256=NMIduqO_MYtI9jVCu6ZxvbBtYQXoQyNEWblNy3m2UPY,313
|
10
|
+
fxn/c/configuration.py,sha256=Jq4kWLu3xb1MWjkfNA4xPr_TykABppbHctUEOHBFdRM,4887
|
11
|
+
fxn/c/fxnc.py,sha256=YrvwOlzPmTlSDuz2zmKZfws2WK5BY4YZ62edoplcMJU,1381
|
12
|
+
fxn/c/map.py,sha256=47fBJ0Q6uB_xeW3sn9aCLYJ539edg8ff9DU-EIfWRGA,2352
|
13
|
+
fxn/c/prediction.py,sha256=-d-5yreFAaRS-nDHzhfabRNtgYcmJGiY_N2dt09gk84,2689
|
14
|
+
fxn/c/predictor.py,sha256=48poLj1AthzCgU9n6Wv9gL8o4gFucIlOnBO2wdor6r0,1925
|
15
|
+
fxn/c/stream.py,sha256=Y1Xv1Bt3_qlnWg9rCn7NWESpouF1eKMzDiQjhZWbXTg,1105
|
16
|
+
fxn/c/value.py,sha256=zkmuKb153UUEnenPO560gXFzxJ_ATvs8_HM-j3OLrJU,7362
|
17
|
+
fxn/cli/__init__.py,sha256=OBwaKLyHBqUUqwJD6waGzRRosMwbisLxCPgki0Ye_lU,1126
|
18
|
+
fxn/cli/auth.py,sha256=6iGbNbjxfCr8OZT3_neLThXdWeKRBZATwru8vU0XmRw,1688
|
19
|
+
fxn/cli/misc.py,sha256=LcJbCj_GAgtGraTRva2zHHOPpNwI6SOFntRksxwlqvM,843
|
20
|
+
fxn/cli/predictions.py,sha256=HN7-2BLTgwSn_4LYJQ7Ez9TpTKAZfiEGB62eMF_USaA,3084
|
21
|
+
fxn/cli/predictors.py,sha256=t4DYwGTw_3z0dNDSqLmGmWeksPExGVPHyhHsxmVZk48,447
|
22
|
+
fxn/compile/__init__.py,sha256=BXIcV2Ghp8YkfYZyhHuZjjV3BCLSuaoiTgu9YeFb-w0,130
|
23
|
+
fxn/compile/compile.py,sha256=7PzPEjmHu_mQMoLcRrFOe1TJ11iZMgxcGt4rESqk6fg,3040
|
24
|
+
fxn/compile/sandbox.py,sha256=3ewg1C3lST0KETxkx1qmqMuqcj6YJHBMdCVq4ne-2l8,5425
|
25
|
+
fxn/compile/signature.py,sha256=QiB546g5p_MfiGt8hRi5BZ-_cmGaZm8vuYs47m2W-XM,6436
|
26
|
+
fxn/lib/__init__.py,sha256=-w1ikmmki5NMpzJjERW-O4SwOfBNkimej_0jL8ujYRk,71
|
27
|
+
fxn/lib/linux/arm64/libFunction.so,sha256=NU9PEuQNObqtWPr5vXrWeQuYhzBfmX_Z4guaregFjrI,207632
|
28
|
+
fxn/lib/linux/x86_64/libFunction.so,sha256=qZNlczayaaHIP_tJ9eeZ1TVpV1Os-ztvSWOoBuY9yWE,236272
|
29
|
+
fxn/lib/macos/arm64/Function.dylib,sha256=ODM3zDbI4Tomx7_QSvnqOE42OBYYblntkSq6gftBP4c,263664
|
30
|
+
fxn/lib/macos/x86_64/Function.dylib,sha256=qIu4dhx0Xk5dQHgTnZTcm2IpoMYJwRPmKRi9J-UnkAY,263680
|
31
|
+
fxn/lib/windows/arm64/Function.dll,sha256=FyL-oipK9wSxXdbD9frc8QFbUKTPMCdtmCkCT8ooIIM,419328
|
32
|
+
fxn/lib/windows/x86_64/Function.dll,sha256=iL6w1FwDgBkHlNhQmhE7XgfoeHsiYQgpVGzeGDdHGUw,454656
|
33
|
+
fxn/services/__init__.py,sha256=Bif8IttwJ089mSRsd3MFdob7z2eF-MKigKu4ZQFZBCQ,190
|
34
|
+
fxn/services/prediction.py,sha256=IKudi7n3bm-RAW26dg188ItDgGnJcW4rcN48LD37CEg,10185
|
35
|
+
fxn/services/predictor.py,sha256=Wl_7YKiD5mTpC5x2Zaq4BpatRjwRUX8Th9GIrwd38MA,791
|
36
|
+
fxn/services/user.py,sha256=ADl5MFLsk4K0altgKHnI-i64E3g1wU3e56Noq_ciRuk,685
|
37
|
+
fxn/types/__init__.py,sha256=MEg71rzbGgoWfgB4Yi5QvxbnovHTZRIzCUZLtWtWP1E,292
|
38
|
+
fxn/types/dtype.py,sha256=b0V91aknED2Ql0_BOG_vEg__YJVJByxsgB0cR4rtotE,617
|
39
|
+
fxn/types/prediction.py,sha256=YVnRcqm6IPEx0796OuT3dqn_jOPjhWblzuM2lkk-Vzo,2173
|
40
|
+
fxn/types/predictor.py,sha256=51hhb1rCYFt_r86pbOIVeV_tXYE6BVhcNP27_xmQG1Q,4006
|
41
|
+
fxn/types/user.py,sha256=Z44TwEocyxSrfKyzcNfmAXUrpX_Ry8fJ7MffSxRn4oU,1071
|
42
|
+
fxn-0.0.42.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
|
43
|
+
fxn-0.0.42.dist-info/METADATA,sha256=RM5c7vePEj9cP3OSysoHclvklaV5-byVneeQnhVSKuU,16122
|
44
|
+
fxn-0.0.42.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
45
|
+
fxn-0.0.42.dist-info/entry_points.txt,sha256=O_AwD5dYaeB-YT1F9hPAPuDYCkw_W0tdNGYbc5RVR2k,45
|
46
|
+
fxn-0.0.42.dist-info/top_level.txt,sha256=1ULIEGrnMlhId8nYAkjmRn9g3KEFuHKboq193SEKQkA,4
|
47
|
+
fxn-0.0.42.dist-info/RECORD,,
|