fxn 0.0.39__py3-none-any.whl → 0.0.41__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/c/__init__.py CHANGED
@@ -5,12 +5,9 @@
5
5
 
6
6
  # https://github.com/fxnai/fxnc
7
7
 
8
- from .status import FXNStatus
9
- from .value import FXNDtype, FXNValueRef, FXNValueFlags
10
- from .map import FXNValueMapRef
11
- from .configuration import FXNConfigurationRef, FXNAcceleration
12
- from .prediction import FXNPredictionRef
13
- from .stream import FXNPredictionStreamRef
14
- from .predictor import FXNPredictorRef
15
-
16
- from .fxnc import load_fxnc
8
+ from .configuration import Configuration
9
+ from .map import ValueMap
10
+ from .prediction import Prediction
11
+ from .predictor import Predictor
12
+ from .stream import PredictionStream
13
+ from .value import Value, ValueFlags
fxn/c/configuration.py CHANGED
@@ -3,58 +3,116 @@
3
3
  # Copyright © 2024 NatML Inc. All Rights Reserved.
4
4
  #
5
5
 
6
- from ctypes import c_char_p, c_int, c_int32, c_void_p, CDLL, POINTER, Structure
7
- from .status import FXNStatus
8
-
9
- class FXNAcceleration(c_int):
10
- FXN_ACCELERATION_DEFAULT = 0
11
- FXN_ACCELERATION_CPU = 1 << 0
12
- FXN_ACCELERATION_GPU = 1 << 1
13
- FXN_ACCELERATION_NPU = 1 << 2
14
-
15
- class FXNConfiguration(Structure): pass
16
-
17
- FXNConfigurationRef = POINTER(FXNConfiguration)
18
-
19
- def _register_fxn_configuration (fxnc: CDLL) -> CDLL:
20
- # FXNConfigurationGetUniqueID
21
- fxnc.FXNConfigurationGetUniqueID.argtypes = [c_char_p, c_int32]
22
- fxnc.FXNConfigurationGetUniqueID.restype = FXNStatus
23
- # FXNConfigurationGetClientID
24
- fxnc.FXNConfigurationGetClientID.argtypes = [c_char_p, c_int32]
25
- fxnc.FXNConfigurationGetClientID.restype = FXNStatus
26
- # FXNConfigurationCreate
27
- fxnc.FXNConfigurationCreate.argtypes = [POINTER(FXNConfigurationRef)]
28
- fxnc.FXNConfigurationCreate.restype = FXNStatus
29
- # FXNConfigurationRelease
30
- fxnc.FXNConfigurationRelease.argtypes = [FXNConfigurationRef]
31
- fxnc.FXNConfigurationRelease.restype = FXNStatus
32
- # FXNConfigurationGetTag
33
- fxnc.FXNConfigurationGetTag.argtypes = [FXNConfigurationRef, c_char_p, c_int32]
34
- fxnc.FXNConfigurationRelease.restype = FXNStatus
35
- # FXNConfigurationSetTag
36
- fxnc.FXNConfigurationSetTag.argtypes = [FXNConfigurationRef, c_char_p]
37
- fxnc.FXNConfigurationSetTag.restype = FXNStatus
38
- # FXNConfigurationGetToken
39
- fxnc.FXNConfigurationGetToken.argtypes = [FXNConfigurationRef, c_char_p, c_int32]
40
- fxnc.FXNConfigurationGetToken.restype = FXNStatus
41
- # FXNConfigurationSetToken
42
- fxnc.FXNConfigurationSetToken.argtypes = [FXNConfigurationRef, c_char_p]
43
- fxnc.FXNConfigurationSetToken.restype = FXNStatus
44
- # FXNConfigurationGetAcceleration
45
- fxnc.FXNConfigurationGetAcceleration.argtypes = [FXNConfigurationRef, POINTER(FXNAcceleration)]
46
- fxnc.FXNConfigurationGetAcceleration.restype = FXNStatus
47
- # FXNConfigurationSetAcceleration
48
- fxnc.FXNConfigurationSetAcceleration.argtypes = [FXNConfigurationRef, FXNAcceleration]
49
- fxnc.FXNConfigurationSetAcceleration.restype = FXNStatus
50
- # FXNConfigurationGetDevice
51
- fxnc.FXNConfigurationGetDevice.argtypes = [FXNConfigurationRef, POINTER(c_void_p)]
52
- fxnc.FXNConfigurationGetDevice.restype = FXNStatus
53
- # FXNConfigurationSetDevice
54
- fxnc.FXNConfigurationSetDevice.argtypes = [FXNConfigurationRef, c_void_p]
55
- fxnc.FXNConfigurationSetDevice.restype = FXNStatus
56
- # FXNConfigurationAddResource
57
- fxnc.FXNConfigurationAddResource.argtypes = [FXNConfigurationRef, c_char_p, c_char_p]
58
- fxnc.FXNConfigurationAddResource.restype = FXNStatus
59
- # Return
60
- return fxnc
6
+ from ctypes import byref, c_int, c_void_p, create_string_buffer
7
+ from pathlib import Path
8
+ from typing import final
9
+
10
+ from ..types import Acceleration
11
+ from .fxnc import get_fxnc, status_to_error, FXNStatus
12
+
13
+ @final
14
+ class Configuration:
15
+
16
+ def __init__ (self):
17
+ configuration = c_void_p()
18
+ status = get_fxnc().FXNConfigurationCreate(byref(configuration))
19
+ if status == FXNStatus.OK:
20
+ self.__configuration = configuration
21
+ else:
22
+ raise RuntimeError(f"Failed to create configuration with error: {status_to_error(status)}")
23
+
24
+ @property
25
+ def tag (self) -> str:
26
+ buffer = create_string_buffer(2048)
27
+ status = get_fxnc().FXNConfigurationGetTag(self.__configuration, buffer, len(buffer))
28
+ if status != FXNStatus.OK:
29
+ raise RuntimeError(f"Failed to get configuration tag with error: {status_to_error(status)}")
30
+ tag = buffer.value.decode("utf-8")
31
+ return tag if tag else None
32
+
33
+ @tag.setter
34
+ def tag (self, tag: str):
35
+ tag = tag.encode() if tag is not None else None
36
+ status = get_fxnc().FXNConfigurationSetTag(self.__configuration, tag)
37
+ if status != FXNStatus.OK:
38
+ raise RuntimeError(f"Failed to set configuration tag with error: {status_to_error(status)}")
39
+
40
+ @property
41
+ def token (self) -> str:
42
+ buffer = create_string_buffer(2048)
43
+ status = get_fxnc().FXNConfigurationGetToken(self.__configuration, buffer, len(buffer))
44
+ if status != FXNStatus.OK:
45
+ raise RuntimeError(f"Failed to get configuration token with error: {status_to_error(status)}")
46
+ token = buffer.value.decode("utf-8")
47
+ return token if token else None
48
+
49
+ @token.setter
50
+ def token (self, token: str):
51
+ token = token.encode() if token is not None else None
52
+ status = get_fxnc().FXNConfigurationSetToken(self.__configuration, token)
53
+ if status != FXNStatus.OK:
54
+ raise RuntimeError(f"Failed to set configuration token with error: {status_to_error(status)}")
55
+
56
+ @property
57
+ def acceleration (self) -> Acceleration:
58
+ acceleration = c_int()
59
+ status = get_fxnc().FXNConfigurationGetAcceleration(self.__configuration, byref(acceleration))
60
+ if status == FXNStatus.OK:
61
+ return Acceleration(acceleration.value)
62
+ else:
63
+ raise RuntimeError(f"Failed to get configuration acceleration with error: {status_to_error(status)}")
64
+
65
+ @acceleration.setter
66
+ def acceleration (self, acceleration: Acceleration):
67
+ status = get_fxnc().FXNConfigurationSetAcceleration(self.__configuration, acceleration.value)
68
+ if status != FXNStatus.OK:
69
+ raise RuntimeError(f"Failed to set configuration acceleration with error: {status_to_error(status)}")
70
+
71
+ @property
72
+ def device (self):
73
+ device = c_void_p()
74
+ status = get_fxnc().FXNConfigurationGetDevice(self.__configuration, byref(device))
75
+ if status == FXNStatus.OK:
76
+ return device if device.value else None
77
+ else:
78
+ raise RuntimeError(f"Failed to get configuration device with error: {status_to_error(status)}")
79
+
80
+ @device.setter
81
+ def device (self, device):
82
+ status = get_fxnc().FXNConfigurationSetDevice(self.__configuration, device)
83
+ if status != FXNStatus.OK:
84
+ raise RuntimeError(f"Failed to set configuration device with error: {status_to_error(status)}")
85
+
86
+ def add_resource (self, type: str, path: Path):
87
+ status = get_fxnc().FXNConfigurationAddResource(self.__configuration, type.encode(), str(path).encode())
88
+ if status != FXNStatus.OK:
89
+ raise RuntimeError(f"Failed to add configuration resource with error: {status_to_error(status)}")
90
+
91
+ def __enter__ (self):
92
+ return self
93
+
94
+ def __exit__ (self, exc_type, exc_value, traceback):
95
+ self.__release()
96
+
97
+ def __release (self):
98
+ if self.__configuration:
99
+ get_fxnc().FXNConfigurationRelease(self.__configuration)
100
+ self.__configuration = None
101
+
102
+ @classmethod
103
+ def get_unique_id (cls) -> str:
104
+ buffer = create_string_buffer(2048)
105
+ status = get_fxnc().FXNConfigurationGetUniqueID(buffer, len(buffer))
106
+ if status == FXNStatus.OK:
107
+ return buffer.value.decode("utf-8")
108
+ else:
109
+ raise RuntimeError(f"Failed to retrieve configuration identifier with error: {status_to_error(status)}")
110
+
111
+ @classmethod
112
+ def get_client_id (cls) -> str:
113
+ buffer = create_string_buffer(64)
114
+ status = get_fxnc().FXNConfigurationGetClientID(buffer, len(buffer))
115
+ if status == FXNStatus.OK:
116
+ return buffer.value.decode("utf-8")
117
+ else:
118
+ raise RuntimeError(f"Failed to retrieve client identifier with error: {status_to_error(status)}")
fxn/c/fxnc.py CHANGED
@@ -4,25 +4,45 @@
4
4
  #
5
5
 
6
6
  from ctypes import CDLL
7
- from pathlib import Path
8
- from .configuration import _register_fxn_configuration
9
- from .prediction import _register_fxn_prediction
10
- from .stream import _register_fxn_prediction_stream
11
- from .predictor import _register_fxn_predictor
12
- from .value import _register_fxn_value
13
- from .map import _register_fxn_value_map
14
- from .version import _register_fxn_version
7
+ from enum import IntEnum
8
+ from importlib import resources
9
+ from platform import machine, system
15
10
 
16
- def load_fxnc (path: Path) -> CDLL:
17
- # Open
18
- fxnc = CDLL(str(path))
19
- # Register
20
- fxnc = _register_fxn_value(fxnc)
21
- fxnc = _register_fxn_value_map(fxnc)
22
- fxnc = _register_fxn_configuration(fxnc)
23
- fxnc = _register_fxn_prediction(fxnc)
24
- fxnc = _register_fxn_prediction_stream(fxnc)
25
- fxnc = _register_fxn_predictor(fxnc)
26
- fxnc = _register_fxn_version(fxnc)
27
- # Return
28
- return fxnc
11
+ _fxnc: CDLL = None
12
+
13
+ class FXNStatus(IntEnum):
14
+ OK = 0
15
+ ERROR_INVALID_ARGUMENT = 1
16
+ ERROR_INVALID_OPERATION = 2
17
+ ERROR_NOT_IMPLEMENTED = 3
18
+
19
+ def get_fxnc () -> CDLL:
20
+ global _fxnc
21
+ _fxnc = _fxnc if _fxnc is not None else _load_fxnc()
22
+ return _fxnc
23
+
24
+ def set_fxnc (fxnc: CDLL):
25
+ global _fxnc
26
+ _fxnc = fxnc
27
+
28
+ def _load_fxnc () -> CDLL:
29
+ os = system().lower()
30
+ os = "macos" if os == "darwin" else os
31
+ arch = machine().lower()
32
+ arch = "arm64" if arch == "aarch64" else arch
33
+ arch = "x86_64" if arch in ["x64", "amd64"] else arch
34
+ package = f"fxn.lib.{os}.{arch}"
35
+ resource = "libFunction.so"
36
+ resource = "Function.dylib" if os == "macos" else resource
37
+ resource = "Function.dll" if os == "windows" else resource
38
+ with resources.path(package, resource) as path:
39
+ return CDLL(str(path))
40
+
41
+ def status_to_error (status: int) -> str:
42
+ if status == FXNStatus.ERROR_INVALID_ARGUMENT:
43
+ return "FXN_ERROR_INVALID_ARGUMENT"
44
+ elif status == FXNStatus.ERROR_INVALID_OPERATION:
45
+ return "FXN_ERROR_INVALID_OPERATION"
46
+ elif status == FXNStatus.ERROR_NOT_IMPLEMENTED:
47
+ return "FXN_ERROR_NOT_IMPLEMENTED"
48
+ return ""
fxn/c/map.py CHANGED
@@ -3,32 +3,62 @@
3
3
  # Copyright © 2024 NatML Inc. All Rights Reserved.
4
4
  #
5
5
 
6
- from ctypes import c_char_p, c_int32, CDLL, POINTER, Structure
7
- from .status import FXNStatus
8
- from .value import FXNValueRef
9
-
10
- class FXNValueMap(Structure): pass
11
-
12
- FXNValueMapRef = POINTER(FXNValueMap)
13
-
14
- def _register_fxn_value_map (fxnc: CDLL) -> CDLL:
15
- # FXNValueMapCreate
16
- fxnc.FXNValueMapCreate.argtypes = [POINTER(FXNValueMapRef)]
17
- fxnc.FXNValueMapCreate.restype = FXNStatus
18
- # FXNValueMapRelease
19
- fxnc.FXNValueMapRelease.argtypes = [FXNValueMapRef]
20
- fxnc.FXNValueMapRelease.restype = FXNStatus
21
- # FXNValueMapGetSize
22
- fxnc.FXNValueMapGetSize.argtypes = [FXNValueMapRef, POINTER(c_int32)]
23
- fxnc.FXNValueMapGetSize.restype = FXNStatus
24
- # FXNValueMapGetKey
25
- fxnc.FXNValueMapGetKey.argtypes = [FXNValueMapRef, c_int32, c_char_p, c_int32]
26
- fxnc.FXNValueMapGetKey.restype = FXNStatus
27
- # FXNValueMapGetValue
28
- fxnc.FXNValueMapGetValue.argtypes = [FXNValueMapRef, c_char_p, POINTER(FXNValueRef)]
29
- fxnc.FXNValueMapGetValue.restype = FXNStatus
30
- # FXNValueMapSetValue
31
- fxnc.FXNValueMapSetValue.argtypes = [FXNValueMapRef, c_char_p, FXNValueRef]
32
- fxnc.FXNValueMapSetValue.restype = FXNStatus
33
- # Return
34
- return fxnc
6
+ from ctypes import byref, c_int, c_int32, c_void_p, create_string_buffer
7
+ from pathlib import Path
8
+ from typing import final
9
+
10
+ from .fxnc import get_fxnc, status_to_error, FXNStatus
11
+ from .value import Value
12
+
13
+ @final
14
+ class ValueMap:
15
+
16
+ def __init__ (self, map=None, *, owner: bool=True):
17
+ if map is None:
18
+ map = c_void_p()
19
+ owner = True
20
+ status = get_fxnc().FXNValueMapCreate(byref(map))
21
+ if status != FXNStatus.OK:
22
+ raise RuntimeError(f"Failed to create value map with error: {status_to_error(status)}")
23
+ self.__map = map
24
+ self.__owner = owner
25
+
26
+ def key (self, index: int) -> str:
27
+ buffer = create_string_buffer(256)
28
+ status = get_fxnc().FXNValueMapGetKey(self.__map, index, buffer, len(buffer))
29
+ if status == FXNStatus.OK:
30
+ return buffer.value.decode("utf-8")
31
+ else:
32
+ raise RuntimeError(f"Failed to get value map key at index {index} with error: {status_to_error(status)}")
33
+
34
+ def __getitem__ (self, key: str) -> Value | None:
35
+ value = c_void_p()
36
+ status = get_fxnc().FXNValueMapGetValue(self.__map, key.encode(), byref(value))
37
+ if status == FXNStatus.OK:
38
+ return Value(value, owner=False)
39
+ else:
40
+ raise RuntimeError(f"Failed to get value map value for key '{key}' with error: {status_to_error(status)}")
41
+
42
+ def __setitem__ (self, key: str, value: Value):
43
+ status = get_fxnc().FXNValueMapSetValue(self.__map, key.encode(), value._Value__value)
44
+ if status != FXNStatus.OK:
45
+ raise RuntimeError(f"Failed to set value map value for key '{key}' with error: {status_to_error(status)}")
46
+
47
+ def __len__ (self) -> int:
48
+ count = c_int32()
49
+ status = get_fxnc().FXNValueMapGetSize(self.__map, byref(count))
50
+ if status == FXNStatus.OK:
51
+ return count.value
52
+ else:
53
+ raise RuntimeError(f"Failed to get value map size with error: {status_to_error(status)}")
54
+
55
+ def __enter__ (self):
56
+ return self
57
+
58
+ def __exit__ (self, exc_type, exc_value, traceback):
59
+ self.__release()
60
+
61
+ def __release (self):
62
+ if self.__map and self.__owner:
63
+ get_fxnc().FXNValueMapRelease(self.__map)
64
+ self.__map = None
fxn/c/prediction.py CHANGED
@@ -3,35 +3,74 @@
3
3
  # Copyright © 2024 NatML Inc. All Rights Reserved.
4
4
  #
5
5
 
6
- from ctypes import c_char_p, c_double, c_int32, CDLL, POINTER, Structure
7
- from .status import FXNStatus
8
- from .map import FXNValueMapRef
9
-
10
- class FXNPrediction(Structure): pass
11
-
12
- FXNPredictionRef = POINTER(FXNPrediction)
13
-
14
- def _register_fxn_prediction (fxnc: CDLL) -> CDLL:
15
- # FXNPredictionRelease
16
- fxnc.FXNPredictionRelease.argtypes = [FXNPredictionRef]
17
- fxnc.FXNPredictionRelease.restype = FXNStatus
18
- # FXNPredictionGetID
19
- fxnc.FXNPredictionGetID.argtypes = [FXNPredictionRef, c_char_p, c_int32]
20
- fxnc.FXNPredictionGetID.restype = FXNStatus
21
- # FXNPredictionGetLatency
22
- fxnc.FXNPredictionGetLatency.argtypes = [FXNPredictionRef, POINTER(c_double)]
23
- fxnc.FXNPredictionGetLatency.restype = FXNStatus
24
- # FXNPredictionGetResults
25
- fxnc.FXNPredictionGetResults.argtypes = [FXNPredictionRef, POINTER(FXNValueMapRef)]
26
- fxnc.FXNPredictionGetResults.restype = FXNStatus
27
- # FXNPredictionGetError
28
- fxnc.FXNPredictionGetError.argtypes = [FXNPredictionRef, c_char_p, c_int32]
29
- fxnc.FXNPredictionGetError.restype = FXNStatus
30
- # FXNPredictionGetLogs
31
- fxnc.FXNPredictionGetLogs.argtypes = [FXNPredictionRef, c_char_p, c_int32]
32
- fxnc.FXNPredictionGetLogs.restype = FXNStatus
33
- # FXNPredictionGetLogLength
34
- fxnc.FXNPredictionGetLogLength.argtypes = [FXNPredictionRef, POINTER(c_int32)]
35
- fxnc.FXNPredictionGetLogLength.restype = FXNStatus
36
- # Return
37
- return fxnc
6
+ from ctypes import byref, c_double, c_int, c_int32, c_void_p, create_string_buffer
7
+ from pathlib import Path
8
+ from typing import final
9
+
10
+ from .fxnc import get_fxnc, status_to_error, FXNStatus
11
+ from .map import ValueMap
12
+
13
+ @final
14
+ class Prediction:
15
+
16
+ def __init__ (self, prediction):
17
+ self.__prediction = prediction
18
+
19
+ @property
20
+ def id (self) -> str:
21
+ id = create_string_buffer(256)
22
+ status = get_fxnc().FXNPredictionGetID(self.__prediction, id, len(id))
23
+ if status == FXNStatus.OK:
24
+ return id.value.decode("utf-8")
25
+ else:
26
+ raise RuntimeError(f"Failed to get prediction id with error: {status_to_error(status)}")
27
+
28
+ @property
29
+ def latency (self) -> float:
30
+ latency = c_double()
31
+ status = get_fxnc().FXNPredictionGetLatency(self.__prediction, byref(latency))
32
+ if status == FXNStatus.OK:
33
+ return latency.value
34
+ else:
35
+ raise RuntimeError(f"Failed to get prediction latency with error: {status_to_error(status)}")
36
+
37
+ @property
38
+ def results (self) -> ValueMap | None:
39
+ map = c_void_p()
40
+ status = get_fxnc().FXNPredictionGetResults(self.__prediction, byref(map))
41
+ if status != FXNStatus.OK:
42
+ raise RuntimeError(f"Failed to get prediction results with error: {status_to_error(status)}")
43
+ map = ValueMap(map, owner=False)
44
+ return map if len(map) > 0 else None
45
+
46
+ @property
47
+ def error (self) -> str | None:
48
+ error = create_string_buffer(2048)
49
+ get_fxnc().FXNPredictionGetError(self.__prediction, error, len(error))
50
+ error = error.value.decode("utf-8")
51
+ return error if error else None
52
+
53
+ @property
54
+ def logs (self) -> str:
55
+ fxnc = get_fxnc()
56
+ log_length = c_int32()
57
+ status = fxnc.FXNPredictionGetLogLength(self.__prediction, byref(log_length))
58
+ if status != FXNStatus.OK:
59
+ raise RuntimeError(f"Failed to get prediction log length with error: {status_to_error(status)}")
60
+ logs = create_string_buffer(log_length.value + 1)
61
+ status = fxnc.FXNPredictionGetLogs(self.__prediction, logs, len(logs))
62
+ if status == FXNStatus.OK:
63
+ return logs.value.decode("utf-8")
64
+ else:
65
+ raise RuntimeError(f"Failed to get prediction logs with error: {status_to_error(status)}")
66
+
67
+ def __enter__ (self):
68
+ return self
69
+
70
+ def __exit__ (self, exc_type, exc_value, traceback):
71
+ self.__release()
72
+
73
+ def __release (self):
74
+ if self.__prediction:
75
+ get_fxnc().FXNPredictionRelease(self.__prediction)
76
+ self.__prediction = None
fxn/c/predictor.py CHANGED
@@ -3,29 +3,58 @@
3
3
  # Copyright © 2024 NatML Inc. All Rights Reserved.
4
4
  #
5
5
 
6
- from ctypes import CDLL, POINTER, Structure
7
- from .configuration import FXNConfigurationRef
8
- from .prediction import FXNPredictionRef
9
- from .stream import FXNPredictionStreamRef
10
- from .status import FXNStatus
11
- from .map import FXNValueMapRef
12
-
13
- class FXNPredictor(Structure): pass
14
-
15
- FXNPredictorRef = POINTER(FXNPredictor)
16
-
17
- def _register_fxn_predictor (fxnc: CDLL) -> CDLL:
18
- # FXNPredictorCreate
19
- fxnc.FXNPredictorCreate.argtypes = [FXNConfigurationRef, POINTER(FXNPredictorRef)]
20
- fxnc.FXNPredictorCreate.restype = FXNStatus
21
- # FXNPredictorRelease
22
- fxnc.FXNPredictorRelease.argtypes = [FXNPredictorRef]
23
- fxnc.FXNPredictorRelease.restype = FXNStatus
24
- # FXNPredictorCreatePrediction
25
- fxnc.FXNPredictorCreatePrediction.argtypes = [FXNPredictorRef, FXNValueMapRef, POINTER(FXNPredictionRef)]
26
- fxnc.FXNPredictorCreatePrediction.restype = FXNStatus
27
- # FXNPredictorStreamPrediction
28
- fxnc.FXNPredictorStreamPrediction.argtypes = [FXNPredictionRef, FXNValueMapRef, POINTER(FXNPredictionStreamRef)]
29
- fxnc.FXNPredictorStreamPrediction.restype = FXNStatus
30
- # Return
31
- return fxnc
6
+ from ctypes import byref, c_int, c_int32, c_void_p, create_string_buffer
7
+ from pathlib import Path
8
+ from typing import final
9
+
10
+ from .configuration import Configuration
11
+ from .fxnc import get_fxnc, status_to_error, FXNStatus
12
+ from .map import ValueMap
13
+ from .prediction import Prediction
14
+ from .stream import PredictionStream
15
+
16
+ @final
17
+ class Predictor:
18
+
19
+ def __init__ (self, configuration: Configuration):
20
+ predictor = c_void_p()
21
+ status = get_fxnc().FXNPredictorCreate(configuration._Configuration__configuration, byref(predictor))
22
+ if status == FXNStatus.OK:
23
+ self.__predictor = predictor
24
+ else:
25
+ raise RuntimeError(f"Failed to create predictor with error: {status_to_error(status)}")
26
+
27
+ def create_prediction (self, inputs: ValueMap) -> Prediction:
28
+ prediction = c_void_p()
29
+ status = get_fxnc().FXNPredictorCreatePrediction(
30
+ self.__predictor,
31
+ inputs._ValueMap__map,
32
+ byref(prediction)
33
+ )
34
+ if status == FXNStatus.OK:
35
+ return Prediction(prediction)
36
+ else:
37
+ raise RuntimeError(f"Failed to create prediction with error: {status_to_error(status)}")
38
+
39
+ def stream_prediction (self, inputs: ValueMap) -> PredictionStream:
40
+ stream = c_void_p()
41
+ status = get_fxnc().FXNPredictorStreamPrediction(
42
+ self.__predictor,
43
+ inputs._ValueMap__map,
44
+ byref(stream)
45
+ )
46
+ if status == FXNStatus.OK:
47
+ return PredictionStream(stream)
48
+ else:
49
+ raise RuntimeError(f"Failed to stream prediction with error: {status_to_error(status)}")
50
+
51
+ def __enter__ (self):
52
+ return self
53
+
54
+ def __exit__ (self, exc_type, exc_value, traceback):
55
+ self.__release()
56
+
57
+ def __release (self):
58
+ if self.__predictor:
59
+ get_fxnc().FXNPredictorRelease(self.__predictor)
60
+ self.__predictor = None
fxn/c/stream.py CHANGED
@@ -3,20 +3,39 @@
3
3
  # Copyright © 2024 NatML Inc. All Rights Reserved.
4
4
  #
5
5
 
6
- from ctypes import CDLL, POINTER, Structure
7
- from .prediction import FXNPredictionRef
8
- from .status import FXNStatus
9
-
10
- class FXNPredictionStream(Structure): pass
11
-
12
- FXNPredictionStreamRef = POINTER(FXNPredictionStream)
13
-
14
- def _register_fxn_prediction_stream (fxnc: CDLL) -> CDLL:
15
- # FXNPredictionStreamRelease
16
- fxnc.FXNPredictionStreamRelease.argtypes = [FXNPredictionStreamRef]
17
- fxnc.FXNPredictionStreamRelease.restype = FXNStatus
18
- # FXNPredictionStreamReadNext
19
- fxnc.FXNPredictionStreamReadNext.argtypes = [FXNPredictionStreamRef, POINTER(FXNPredictionRef)]
20
- fxnc.FXNPredictionStreamReadNext.restype = FXNStatus
21
- # Return
22
- return fxnc
6
+ from ctypes import byref, c_int, c_int32, c_void_p, create_string_buffer
7
+ from pathlib import Path
8
+ from typing import final
9
+
10
+ from .fxnc import get_fxnc, status_to_error, FXNStatus
11
+ from .prediction import Prediction
12
+
13
+ @final
14
+ class PredictionStream:
15
+
16
+ def __init__ (self, stream):
17
+ self.__stream = stream
18
+
19
+ def __iter__ (self):
20
+ return self
21
+
22
+ def __next__ (self) -> Prediction:
23
+ prediction = c_void_p()
24
+ status = get_fxnc().FXNPredictionStreamReadNext(self.__stream, byref(prediction))
25
+ if status == FXNStatus.ERROR_INVALID_OPERATION:
26
+ raise StopIteration()
27
+ elif status != FXNStatus.OK:
28
+ raise RuntimeError(f"Failed to read next prediction in stream with error: {status_to_error(status)}")
29
+ else:
30
+ return Prediction(prediction)
31
+
32
+ def __enter__ (self):
33
+ return self
34
+
35
+ def __exit__ (self, exc_type, exc_value, traceback):
36
+ self.__release()
37
+
38
+ def __release (self):
39
+ if self.__stream:
40
+ get_fxnc().FXNPredictionStreamRelease(self.__stream)
41
+ self.__stream = None