purem 2.0.3__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.
- purem/__init__.py +6 -0
- purem/core.py +235 -0
- purem/env_config.py +71 -0
- purem/file_structure.py +98 -0
- purem/loader.py +43 -0
- purem/logger.py +30 -0
- purem/utils.py +26 -0
- purem-2.0.3.dist-info/METADATA +202 -0
- purem-2.0.3.dist-info/RECORD +12 -0
- purem-2.0.3.dist-info/WHEEL +5 -0
- purem-2.0.3.dist-info/licenses/LICENSE +37 -0
- purem-2.0.3.dist-info/top_level.txt +1 -0
purem/__init__.py
ADDED
purem/core.py
ADDED
@@ -0,0 +1,235 @@
|
|
1
|
+
"""
|
2
|
+
Business Source License 1.1
|
3
|
+
|
4
|
+
Copyright (C) 2025 Raman Marozau, raman@worktif.com
|
5
|
+
Use of this software is governed by the Business Source License included in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
6
|
+
|
7
|
+
Change Date: Never
|
8
|
+
On the date above, in accordance with the Business Source License, use of this software will be governed by the open source license specified in the LICENSE file.
|
9
|
+
Additional Use Grant: Free for personal and non-commercial research use only.
|
10
|
+
|
11
|
+
SPDX-License-Identifier: BUSL-1.1
|
12
|
+
"""
|
13
|
+
|
14
|
+
import base64
|
15
|
+
import ctypes
|
16
|
+
import json
|
17
|
+
import os
|
18
|
+
import shutil
|
19
|
+
import ssl
|
20
|
+
import urllib.request
|
21
|
+
import zipfile
|
22
|
+
from typing import List, Optional, Dict
|
23
|
+
|
24
|
+
import certifi as certifi
|
25
|
+
import numpy as np
|
26
|
+
from numpy import ndarray
|
27
|
+
|
28
|
+
from purem.env_config import load_env_config
|
29
|
+
from purem.file_structure import FileStructure
|
30
|
+
from purem.loader import Loader
|
31
|
+
from purem.logger import Logger
|
32
|
+
from purem.utils import _compute_shifted_jit
|
33
|
+
|
34
|
+
|
35
|
+
class Purem:
|
36
|
+
"""
|
37
|
+
Summary of what the class does.
|
38
|
+
|
39
|
+
The Purem class is used to manage and handle the initialization, configuration, and
|
40
|
+
operation of the Purem environment and its associated runtime, including license management,
|
41
|
+
binary handling, and API configuration. It centralizes the setup of the Purem runtime,
|
42
|
+
ensuring that all necessary binaries, license checks, and configurations are in place.
|
43
|
+
|
44
|
+
The class supports downloading and extracting binaries, setting up runtime libraries, and providing utility
|
45
|
+
methods such as softmax computation, license validation, and URL construction to interact with remote
|
46
|
+
and local systems.
|
47
|
+
|
48
|
+
:ivar _license_key: The license key used for Purem initialization and validation.
|
49
|
+
:type _license_key: Optional[str]
|
50
|
+
:ivar _lib: The dynamically loaded library object for the Purem binary.
|
51
|
+
:type _lib: ctypes.CDLL
|
52
|
+
:ivar _download_binary_url: The URL for downloading the Purem binary.
|
53
|
+
:type _download_binary_url: Optional[str]
|
54
|
+
:ivar _ctx: SSL context used for secure connections, initialized using the system's certificates.
|
55
|
+
:type _ctx: ssl.SSLContext
|
56
|
+
:ivar _file_structure: Manages file paths and structures related to Purem binary and runtime.
|
57
|
+
:type _file_structure: FileStructure
|
58
|
+
:ivar _binary_path: The path to the main Purem binary.
|
59
|
+
:type _binary_path: pathlib.Path
|
60
|
+
:ivar _binary_project_root_path: The path to the project root Purem binary.
|
61
|
+
:type _binary_project_root_path: pathlib.Path
|
62
|
+
:ivar _binary_archive_path: The path where the binary archive is stored.
|
63
|
+
:type _binary_archive_path: pathlib.Path
|
64
|
+
:ivar _binary_archive_path_tmp: The temporary path for binary archive operations.
|
65
|
+
:type _binary_archive_path_tmp: pathlib.Path
|
66
|
+
:ivar _env: Environment configuration used in Purem operations, including URLs.
|
67
|
+
:type _env: Any
|
68
|
+
:ivar _config_url: URL for retrieving Purem configuration, either from an environment variable or a default.
|
69
|
+
:type _config_url: str
|
70
|
+
:ivar _loader: Loader utility for displaying loading messages during lengthy operations.
|
71
|
+
:type _loader: Loader
|
72
|
+
:ivar _log: Logger utility for tracking and managing logging in the Purem operations.
|
73
|
+
:type _log: Logger
|
74
|
+
"""
|
75
|
+
|
76
|
+
def __init__(self, licenced_key: Optional[str] = None):
|
77
|
+
self._license_key = licenced_key or None
|
78
|
+
self._lib = None
|
79
|
+
self._download_binary_url = None
|
80
|
+
self._ctx = ssl.create_default_context(cafile=certifi.where())
|
81
|
+
self._file_structure = FileStructure()
|
82
|
+
self._binary_path = self._file_structure.get_binary_path()
|
83
|
+
self._binary_project_root_path = (
|
84
|
+
self._file_structure.get_binary_project_root_path()
|
85
|
+
)
|
86
|
+
self._binary_archive_path = self._file_structure.get_binary_archive_path()
|
87
|
+
self._binary_archive_path_tmp = (
|
88
|
+
self._file_structure.get_binary_archive_path_tmp()
|
89
|
+
)
|
90
|
+
self._env = load_env_config()
|
91
|
+
self._config_url = (
|
92
|
+
self._env.PUREM_CONFIG_URL
|
93
|
+
or "https://api.worktif.com/v2/portal/products/purem/config"
|
94
|
+
)
|
95
|
+
self._loader = Loader()
|
96
|
+
self._log = Logger()
|
97
|
+
|
98
|
+
def configure(self, license_key: Optional[str] = None) -> None:
|
99
|
+
if self._license_key is None and license_key is not None:
|
100
|
+
self._license_key = license_key
|
101
|
+
if self._license_key is None:
|
102
|
+
raise ValueError(
|
103
|
+
self._log.info(
|
104
|
+
"Purem requires a valid license key to initialize.\n"
|
105
|
+
"You can obtain your key at https://worktif.com or through your enterprise deployment."
|
106
|
+
)
|
107
|
+
)
|
108
|
+
|
109
|
+
self._set_binary()
|
110
|
+
|
111
|
+
def softmax(self, array: ndarray) -> ndarray:
|
112
|
+
array_size = len(array)
|
113
|
+
array = array.astype(np.float32, copy=False)
|
114
|
+
shifted_arr = np.empty(array_size, dtype=np.float32)
|
115
|
+
_compute_shifted_jit(array, shifted_arr)
|
116
|
+
ptr = shifted_arr.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
|
117
|
+
self._lib.purem(ptr, array_size)
|
118
|
+
return shifted_arr
|
119
|
+
|
120
|
+
def clean_softmax(self, arr: [np.float32], size) -> List[any]:
|
121
|
+
return self._lib.purem(arr, size)
|
122
|
+
|
123
|
+
def _build_url(self, config: dict) -> Optional[str]:
|
124
|
+
if config is None:
|
125
|
+
return None
|
126
|
+
base = config.get("base_url", "").rstrip("/")
|
127
|
+
protocol = config.get("protocol", "https")
|
128
|
+
path = config.get("pathname", "").lstrip("/")
|
129
|
+
binary_url = f"{protocol}://{base}/{path}{self._license_key}"
|
130
|
+
return binary_url
|
131
|
+
|
132
|
+
def _tune_binary(self):
|
133
|
+
self._lib = ctypes.CDLL(str(self._binary_path))
|
134
|
+
self._lib.purem.argtypes = [ctypes.POINTER(ctypes.c_float), ctypes.c_size_t]
|
135
|
+
self._lib.purem.restype = None
|
136
|
+
|
137
|
+
def _tune_project_root_binary(self):
|
138
|
+
self._lib = ctypes.CDLL(str(self._binary_project_root_path))
|
139
|
+
self._lib.purem.argtypes = [ctypes.POINTER(ctypes.c_float), ctypes.c_size_t]
|
140
|
+
self._lib.purem.restype = None
|
141
|
+
|
142
|
+
def _load_from_latest_cdn_index(self) -> Optional[Dict]:
|
143
|
+
try:
|
144
|
+
if self._config_url is not None:
|
145
|
+
req = urllib.request.Request(
|
146
|
+
self._config_url,
|
147
|
+
)
|
148
|
+
|
149
|
+
with urllib.request.urlopen(req, context=self._ctx) as response:
|
150
|
+
return json.load(response)
|
151
|
+
else:
|
152
|
+
return None
|
153
|
+
|
154
|
+
except Exception:
|
155
|
+
return None
|
156
|
+
|
157
|
+
def _set_binary(self):
|
158
|
+
if os.path.exists(self._binary_path):
|
159
|
+
self._tune_binary()
|
160
|
+
elif os.path.exists(self._binary_project_root_path):
|
161
|
+
self._tune_project_root_binary()
|
162
|
+
elif not self._license_key:
|
163
|
+
raise ValueError(
|
164
|
+
self._log.info(
|
165
|
+
"Purem requires a valid license key to initialize.\n"
|
166
|
+
"You can obtain your key at https://worktif.com or through your enterprise deployment."
|
167
|
+
)
|
168
|
+
)
|
169
|
+
else:
|
170
|
+
try:
|
171
|
+
self._loader.set_message(
|
172
|
+
"Initializing Purem licensed runtime locally..."
|
173
|
+
)
|
174
|
+
self._loader.start()
|
175
|
+
self._download_binary_url = (
|
176
|
+
self._build_url(self._load_from_latest_cdn_index())
|
177
|
+
or f"{self._env.PUREM_DOWNLOAD_BINARY_URL}{self._license_key}"
|
178
|
+
)
|
179
|
+
self._download_and_extract_binary()
|
180
|
+
self._loader.stop()
|
181
|
+
|
182
|
+
except Exception as e:
|
183
|
+
raise RuntimeError(
|
184
|
+
self._log.info(
|
185
|
+
"We couldn't load your Purem binary at this time.\n"
|
186
|
+
"This may be a local issue or license mismatch.\n"
|
187
|
+
"Please try again โ or contact us at support@worktif.com.\n"
|
188
|
+
"We're here to help you run at full power."
|
189
|
+
)
|
190
|
+
)
|
191
|
+
|
192
|
+
try:
|
193
|
+
self._tune_project_root_binary()
|
194
|
+
except Exception as e:
|
195
|
+
raise RuntimeError(
|
196
|
+
self._log.info(
|
197
|
+
"It appears your Purem licensed binary can not be loaded. Please try again. If the problem "
|
198
|
+
"persists, please contact us at support@worktif.com. Thank you for your patience."
|
199
|
+
)
|
200
|
+
)
|
201
|
+
|
202
|
+
def _download_and_extract_binary(self):
|
203
|
+
req = urllib.request.Request(
|
204
|
+
self._download_binary_url, headers={"User-Agent": "PuremInstance/1.0"}
|
205
|
+
)
|
206
|
+
|
207
|
+
with urllib.request.urlopen(req, context=self._ctx) as response:
|
208
|
+
with open(self._binary_archive_path_tmp, "wb") as out_file:
|
209
|
+
shutil.copyfileobj(response, out_file)
|
210
|
+
|
211
|
+
with open(self._binary_archive_path_tmp, "rb") as f:
|
212
|
+
zip_utf = base64.b64decode(f.read())
|
213
|
+
|
214
|
+
with open(self._binary_archive_path, "wb") as f:
|
215
|
+
f.write(zip_utf)
|
216
|
+
|
217
|
+
try:
|
218
|
+
with zipfile.ZipFile(self._binary_archive_path, "r") as zip_ref:
|
219
|
+
zip_ref.extractall(
|
220
|
+
self._file_structure.dirs.project_root_binary_dir_path
|
221
|
+
)
|
222
|
+
self._log.printr(
|
223
|
+
f"Purem binary extracted to: {self._file_structure.dirs.binary_dir_path}"
|
224
|
+
)
|
225
|
+
except zipfile.BadZipFile as e:
|
226
|
+
raise RuntimeError(
|
227
|
+
self._log.info(
|
228
|
+
f"The Purem archive appears to be corrupted or incomplete.\nDetails: {e}"
|
229
|
+
"Please ensure the package downloaded fully and is unmodified.\n"
|
230
|
+
"Need help? Contact support@worktif.com โ we'll assist right away.\n"
|
231
|
+
)
|
232
|
+
)
|
233
|
+
|
234
|
+
self._binary_archive_path.unlink()
|
235
|
+
self._binary_archive_path_tmp.unlink()
|
purem/env_config.py
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
"""
|
2
|
+
Business Source License 1.1
|
3
|
+
|
4
|
+
Copyright (C) 2025 Raman Marozau, raman@worktif.com
|
5
|
+
Use of this software is governed by the Business Source License included in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
6
|
+
|
7
|
+
Change Date: Never
|
8
|
+
On the date above, in accordance with the Business Source License, use of this software will be governed by the open source license specified in the LICENSE file.
|
9
|
+
Additional Use Grant: Free for personal and non-commercial research use only.
|
10
|
+
|
11
|
+
SPDX-License-Identifier: BUSL-1.1
|
12
|
+
"""
|
13
|
+
|
14
|
+
import os
|
15
|
+
from typing import Optional
|
16
|
+
|
17
|
+
from dotenv import load_dotenv # Import dotenv
|
18
|
+
from pydantic import BaseModel, ValidationError, Field
|
19
|
+
|
20
|
+
|
21
|
+
# Loads environment variables from .env file
|
22
|
+
load_dotenv()
|
23
|
+
|
24
|
+
|
25
|
+
class EnvConfig(BaseModel):
|
26
|
+
"""
|
27
|
+
Configuration class for environment variables validation using Pydantic.
|
28
|
+
Each field represents a required environment variable with validation.
|
29
|
+
"""
|
30
|
+
|
31
|
+
PUREM_LICENSED_KEY: Optional[str] = Field(
|
32
|
+
..., description="Purem Instance Licensed Key."
|
33
|
+
)
|
34
|
+
PUREM_DOWNLOAD_BINARY_URL: Optional[str] = Field(
|
35
|
+
default="https://api.worktif.com/binary/v2/products/purem?token=",
|
36
|
+
description="Purem Instance Download Binary URL.",
|
37
|
+
)
|
38
|
+
PUREM_CONFIG_URL: Optional[str] = Field(
|
39
|
+
..., description="Purem Instance Binary Config URL."
|
40
|
+
)
|
41
|
+
PUREM_VERBOSE: bool = Field(default="1", description="Verbose Purem Mode.")
|
42
|
+
DEBUG: bool = Field(default=False, description="Debug Mode.")
|
43
|
+
|
44
|
+
|
45
|
+
def load_env_config() -> EnvConfig:
|
46
|
+
"""
|
47
|
+
Load and validate environment variables using the AppConfig schema.
|
48
|
+
If validation fails, it prints the errors and raises the exception.
|
49
|
+
|
50
|
+
Returns:
|
51
|
+
EnvConfig: A validated instance of the configuration class.
|
52
|
+
"""
|
53
|
+
licenced_key_default = None
|
54
|
+
try:
|
55
|
+
# Retrieve and validate environment variables
|
56
|
+
return EnvConfig(
|
57
|
+
PUREM_LICENSED_KEY=os.getenv("PUREM_LICENSED_KEY", licenced_key_default),
|
58
|
+
PUREM_DOWNLOAD_BINARY_URL=os.getenv(
|
59
|
+
"PUREM_DOWNLOAD_BINARY_URL",
|
60
|
+
"https://api.worktif.com/binary/v2/products/purem?token=",
|
61
|
+
),
|
62
|
+
PUREM_CONFIG_URL=os.getenv("PUREM_CONFIG_URL"),
|
63
|
+
PUREM_VERBOSE=os.getenv("PUREM_VERBOSE", "0").strip().lower()
|
64
|
+
in {"1", "true", "yes"},
|
65
|
+
DEBUG=os.getenv("DEBUG", "false").strip().lower() in {"1", "true", "yes"},
|
66
|
+
)
|
67
|
+
except ValidationError as e:
|
68
|
+
# Print detailed error messages for missing or invalid environment variables
|
69
|
+
print("Configuration validation error:")
|
70
|
+
print(e.json(indent=2)) # Format errors for better readability
|
71
|
+
raise
|
purem/file_structure.py
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
"""
|
2
|
+
Business Source License 1.1
|
3
|
+
|
4
|
+
Copyright (C) 2025 Raman Marozau, raman@worktif.com
|
5
|
+
Use of this software is governed by the Business Source License included in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
6
|
+
|
7
|
+
Change Date: Never
|
8
|
+
On the date above, in accordance with the Business Source License, use of this software will be governed by the open source license specified in the LICENSE file.
|
9
|
+
Additional Use Grant: Free for personal and non-commercial research use only.
|
10
|
+
|
11
|
+
SPDX-License-Identifier: BUSL-1.1
|
12
|
+
"""
|
13
|
+
|
14
|
+
import os
|
15
|
+
from pathlib import Path
|
16
|
+
|
17
|
+
|
18
|
+
# Directories structure definitions
|
19
|
+
class FileStructureDirs:
|
20
|
+
def __init__(self):
|
21
|
+
"""
|
22
|
+
Initializes directory paths used in the file structure.
|
23
|
+
"""
|
24
|
+
self._current_settings_dir: str = os.path.dirname(__file__)
|
25
|
+
self._base_dir: Path = Path(
|
26
|
+
self._current_settings_dir
|
27
|
+
) # Base directory for service
|
28
|
+
self._lib = Path("lib")
|
29
|
+
|
30
|
+
self.binary_dir_path: Path = (
|
31
|
+
self._base_dir / self._lib
|
32
|
+
) # Base directory for binary storage
|
33
|
+
os.makedirs(self.binary_dir_path, exist_ok=True)
|
34
|
+
|
35
|
+
self.project_root = self._find_project_root()
|
36
|
+
self.project_root_binary_dir_path = self.project_root / self._lib
|
37
|
+
os.makedirs(self.project_root_binary_dir_path, exist_ok=True)
|
38
|
+
|
39
|
+
def _find_project_root(self) -> Path:
|
40
|
+
for parent in [self._base_dir] + list(self._base_dir.parents):
|
41
|
+
if (
|
42
|
+
(parent / "pyproject.toml").exists()
|
43
|
+
or (parent / "requirements.txt").exists()
|
44
|
+
or (parent / ".git").exists()
|
45
|
+
):
|
46
|
+
return parent
|
47
|
+
return self._base_dir
|
48
|
+
|
49
|
+
|
50
|
+
# File names and templates definitions
|
51
|
+
class FileStructureFiles:
|
52
|
+
def __init__(self):
|
53
|
+
"""
|
54
|
+
Initializes file names and templates used in the file structure.
|
55
|
+
"""
|
56
|
+
self.binary_path: Path = Path("libpurem.so")
|
57
|
+
self.binary_archive_path: Path = Path("libpurem.zip")
|
58
|
+
self.binary_archive_path_tmp: Path = Path("libpurem.txt")
|
59
|
+
|
60
|
+
|
61
|
+
# Files and directories internal management
|
62
|
+
class FileStructure:
|
63
|
+
def __init__(self):
|
64
|
+
"""
|
65
|
+
Initializes the file structure with directories and files.
|
66
|
+
"""
|
67
|
+
self.dirs = FileStructureDirs()
|
68
|
+
self.files = FileStructureFiles()
|
69
|
+
|
70
|
+
def get_binary_path(self) -> Path:
|
71
|
+
"""
|
72
|
+
Retrieve the path for the licensed binary file.
|
73
|
+
|
74
|
+
Returns:
|
75
|
+
Path: Full path for the licensed binary file.
|
76
|
+
"""
|
77
|
+
return self.dirs.binary_dir_path / Path(self.files.binary_path)
|
78
|
+
|
79
|
+
def get_binary_archive_path(self) -> Path:
|
80
|
+
"""
|
81
|
+
Retrieve the path for the licensed binary archive file.
|
82
|
+
|
83
|
+
Returns:
|
84
|
+
Path: Full path for the licensed binary archive file.
|
85
|
+
"""
|
86
|
+
return self.dirs.binary_dir_path / Path(self.files.binary_archive_path)
|
87
|
+
|
88
|
+
def get_binary_project_root_path(self) -> Path:
|
89
|
+
"""
|
90
|
+
Retrieve the path for the licensed project root binary file.
|
91
|
+
|
92
|
+
Returns:
|
93
|
+
Path: Full path for the licensed project root binary file.
|
94
|
+
"""
|
95
|
+
return self.dirs.project_root_binary_dir_path / Path(self.files.binary_path)
|
96
|
+
|
97
|
+
def get_binary_archive_path_tmp(self) -> Path:
|
98
|
+
return self.dirs.binary_dir_path / Path(self.files.binary_archive_path_tmp)
|
purem/loader.py
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
"""
|
2
|
+
Business Source License 1.1
|
3
|
+
|
4
|
+
Copyright (C) 2025 Raman Marozau, raman@worktif.com
|
5
|
+
Use of this software is governed by the Business Source License included in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
6
|
+
|
7
|
+
Change Date: Never
|
8
|
+
On the date above, in accordance with the Business Source License, use of this software will be governed by the open source license specified in the LICENSE file.
|
9
|
+
Additional Use Grant: Free for personal and non-commercial research use only.
|
10
|
+
|
11
|
+
SPDX-License-Identifier: BUSL-1.1
|
12
|
+
"""
|
13
|
+
|
14
|
+
import sys
|
15
|
+
import threading
|
16
|
+
import time
|
17
|
+
|
18
|
+
|
19
|
+
class Loader:
|
20
|
+
def __init__(self, message="Downloading"):
|
21
|
+
self._message = message
|
22
|
+
self._thread = threading.Thread(target=self._animate, daemon=True)
|
23
|
+
self.done = False
|
24
|
+
|
25
|
+
def set_message(self, message: str):
|
26
|
+
self._message = message
|
27
|
+
|
28
|
+
def start(self):
|
29
|
+
self._thread.start()
|
30
|
+
|
31
|
+
def stop(self):
|
32
|
+
self.done = True
|
33
|
+
self._thread.join()
|
34
|
+
|
35
|
+
def _animate(self):
|
36
|
+
symbols = ["|", "/", "-", "\\"]
|
37
|
+
i = 0
|
38
|
+
while not self.done:
|
39
|
+
sys.stdout.write(f"\r{self._message}... {symbols[i % len(symbols)]}")
|
40
|
+
sys.stdout.flush()
|
41
|
+
i += 1
|
42
|
+
time.sleep(0.1)
|
43
|
+
sys.stdout.write(f"\r{self._message}... done.\n")
|
purem/logger.py
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
"""
|
2
|
+
Business Source License 1.1
|
3
|
+
|
4
|
+
Copyright (C) 2025 Raman Marozau, raman@worktif.com
|
5
|
+
Use of this software is governed by the Business Source License included in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
6
|
+
|
7
|
+
Change Date: Never
|
8
|
+
On the date above, in accordance with the Business Source License, use of this software will be governed by the open source license specified in the LICENSE file.
|
9
|
+
Additional Use Grant: Free for personal and non-commercial research use only.
|
10
|
+
|
11
|
+
SPDX-License-Identifier: BUSL-1.1
|
12
|
+
"""
|
13
|
+
|
14
|
+
from purem import load_env_config
|
15
|
+
|
16
|
+
|
17
|
+
class Logger:
|
18
|
+
def __init__(self):
|
19
|
+
self._env = load_env_config()
|
20
|
+
self._default_info_message = f"Something went wrong"
|
21
|
+
|
22
|
+
def info(self, message: str) -> str:
|
23
|
+
if self._env.PUREM_VERBOSE is True:
|
24
|
+
return f"[purem]: {message}\n"
|
25
|
+
else:
|
26
|
+
return f"[purem]: {self._default_info_message}\n"
|
27
|
+
|
28
|
+
def printr(self, message: str) -> str or None:
|
29
|
+
if self._env.PUREM_VERBOSE is True:
|
30
|
+
print(self.info(message))
|
purem/utils.py
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
"""
|
2
|
+
Business Source License 1.1
|
3
|
+
|
4
|
+
Copyright (C) 2025 Raman Marozau, raman@worktif.com
|
5
|
+
Use of this software is governed by the Business Source License included in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
6
|
+
|
7
|
+
Change Date: Never
|
8
|
+
On the date above, in accordance with the Business Source License, use of this software will be governed by the open source license specified in the LICENSE file.
|
9
|
+
Additional Use Grant: Free for personal and non-commercial research use only.
|
10
|
+
|
11
|
+
SPDX-License-Identifier: BUSL-1.1
|
12
|
+
"""
|
13
|
+
|
14
|
+
import numpy as np
|
15
|
+
from numba import njit
|
16
|
+
from numpy import ndarray
|
17
|
+
|
18
|
+
|
19
|
+
@njit(parallel=True, fastmath=True)
|
20
|
+
def _compute_shifted_jit(entire_input: ndarray, entire_out: ndarray):
|
21
|
+
x_max = np.float32(-np.inf)
|
22
|
+
for i in range(entire_input.shape[0]):
|
23
|
+
if entire_input[i] > x_max:
|
24
|
+
x_max = entire_input[i]
|
25
|
+
for i in range(entire_input.shape[0]):
|
26
|
+
entire_out[i] = entire_input[i] - x_max
|
@@ -0,0 +1,202 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: purem
|
3
|
+
Version: 2.0.3
|
4
|
+
Summary: High-performance mapping function for mixed-type arrays
|
5
|
+
Author-email: Raman Marozau <raman@worktif.com>
|
6
|
+
License-Expression: BUSL-1.1
|
7
|
+
Project-URL: Homepage, https://github.com/morozow/purem
|
8
|
+
Project-URL: Documentation, https://worktif.com/docs/basic-usage
|
9
|
+
Keywords: mapping,performance,numpy,arrays
|
10
|
+
Classifier: Programming Language :: Python
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
14
|
+
Classifier: Operating System :: MacOS
|
15
|
+
Classifier: Operating System :: Unix
|
16
|
+
Classifier: Operating System :: POSIX
|
17
|
+
Requires-Python: >=3.11
|
18
|
+
Description-Content-Type: text/x-rst
|
19
|
+
License-File: LICENSE
|
20
|
+
Requires-Dist: numpy~=2.1.3
|
21
|
+
Requires-Dist: pytest~=8.3.5
|
22
|
+
Requires-Dist: torch~=2.6.0
|
23
|
+
Requires-Dist: numba~=0.61.0
|
24
|
+
Requires-Dist: certifi~=2025.1.31
|
25
|
+
Requires-Dist: pydantic~=2.10.6
|
26
|
+
Requires-Dist: dotenv~=0.9.9
|
27
|
+
Requires-Dist: python-dotenv~=1.1.0
|
28
|
+
Requires-Dist: setuptools~=65.5.1
|
29
|
+
Requires-Dist: requests~=2.32.3
|
30
|
+
Provides-Extra: dev
|
31
|
+
Requires-Dist: pytest; extra == "dev"
|
32
|
+
Requires-Dist: flake8; extra == "dev"
|
33
|
+
Requires-Dist: black; extra == "dev"
|
34
|
+
Requires-Dist: coverage; extra == "dev"
|
35
|
+
Requires-Dist: pytest-mock; extra == "dev"
|
36
|
+
Dynamic: license-file
|
37
|
+
|
38
|
+
Purem - High-Performance Mapping Operations
|
39
|
+
===========================================
|
40
|
+
|
41
|
+
.. image:: https://badge.fury.io/py/purem.svg
|
42
|
+
:target: https://pypi.org/project/purem/
|
43
|
+
:alt: PyPI version
|
44
|
+
|
45
|
+
.. image:: https://img.shields.io/badge/license-BUSL--1.1-blue.svg
|
46
|
+
:target: https://worktif.com/documents/terms-of-service
|
47
|
+
:alt: License: BUSL-1.1
|
48
|
+
|
49
|
+
Overview
|
50
|
+
--------
|
51
|
+
|
52
|
+
**Purem** is an advanced high-performance computational library optimized for vectorized mathematical operations. This project focuses on efficient execution of element-wise transformations, including ``softmax``, ``exp``, and other mathematical functions, leveraging highly optimized assembly code for modern architectures.
|
53
|
+
|
54
|
+
Key Features
|
55
|
+
------------
|
56
|
+
|
57
|
+
Purem is a blazing-fast AI math engine that turns your Python formulas into native-speed vectorized execution.
|
58
|
+
Achieve up to 80ร faster performance on CPU/GPU/TPU โ no rewrites, no dependencies, just speed.
|
59
|
+
Designed for ML researchers, scientific computing, and production-grade workloads that canโt afford to wait.
|
60
|
+
|
61
|
+
---
|
62
|
+
|
63
|
+
๐ง Installation
|
64
|
+
---------------
|
65
|
+
|
66
|
+
Install the Python wrapper via pip::
|
67
|
+
|
68
|
+
pip install purem
|
69
|
+
|
70
|
+
๐ฆ **Note:** Installation is quick, but ``purem`` must be initialized with a license before use.
|
71
|
+
Setup takes less than a minute โ weโre ready when you are: https://worktif.com/#start
|
72
|
+
|
73
|
+
---
|
74
|
+
|
75
|
+
๐ Quickstart
|
76
|
+
-------------
|
77
|
+
|
78
|
+
1. Import and Initialize::
|
79
|
+
|
80
|
+
from purem import purem
|
81
|
+
|
82
|
+
purem.configure(license_key='your-license-key') # Auto-downloads and configures backend
|
83
|
+
|
84
|
+
Alternatively, if you already have the backend ``.so`` file::
|
85
|
+
|
86
|
+
from purem import purem
|
87
|
+
|
88
|
+
purem.softmax([...]) # Initialized from local ./lib/libpurem.so
|
89
|
+
|
90
|
+
---
|
91
|
+
|
92
|
+
๐ Local Library Structure
|
93
|
+
---------------------------
|
94
|
+
|
95
|
+
If the backend ``.so`` is already downloaded manually, place it here::
|
96
|
+
|
97
|
+
your_project/
|
98
|
+
โโโ main.py
|
99
|
+
โโโ lib/
|
100
|
+
โ โโโ libpurem.so
|
101
|
+
|
102
|
+
---
|
103
|
+
|
104
|
+
๐ License-Based Activation
|
105
|
+
----------------------------
|
106
|
+
|
107
|
+
To automatically download and configure the backend library:
|
108
|
+
|
109
|
+
1. Call ``purem.configure(license_key='<your-license-key>')``
|
110
|
+
2. The system will download the ``.so`` file to ``./lib/``
|
111
|
+
3. All functions will become available instantly after initialization
|
112
|
+
|
113
|
+
Without a valid license key:
|
114
|
+
|
115
|
+
- No ``.so`` will be downloaded
|
116
|
+
- The library won't work unless you provide the ``.so`` manually
|
117
|
+
|
118
|
+
---
|
119
|
+
|
120
|
+
๐ง Available Functions
|
121
|
+
-----------------------
|
122
|
+
|
123
|
+
After initialization, you can call::
|
124
|
+
|
125
|
+
from purem import purem
|
126
|
+
|
127
|
+
purem.softmax([...])
|
128
|
+
...
|
129
|
+
|
130
|
+
Full function list: https://worktif.com/docs/basic-usage
|
131
|
+
|
132
|
+
---
|
133
|
+
|
134
|
+
๐ฆ Packaging Notes
|
135
|
+
-------------------
|
136
|
+
|
137
|
+
This package does **not** bundle the ``.so`` file. You are required to:
|
138
|
+
|
139
|
+
- Use a license key to download it dynamically
|
140
|
+
- Alternatively, place it manually into ``./lib/`` folder before calling ``init()``
|
141
|
+
|
142
|
+
---
|
143
|
+
|
144
|
+
๐งช Benchmark Tutorial
|
145
|
+
----------------------
|
146
|
+
|
147
|
+
Visit the Benchmark Tutorial: https://worktif.com/#benchmarks
|
148
|
+
|
149
|
+
- How ``Purem`` compares to NumPy, PyTorch and Numba
|
150
|
+
- How it reaches low-level performance via native execution
|
151
|
+
- Why it's faster than traditional Python-based computation
|
152
|
+
|
153
|
+
---
|
154
|
+
|
155
|
+
๐ง Distribution and Licensing
|
156
|
+
------------------------------
|
157
|
+
|
158
|
+
We **do not provide direct download links** for the backend.
|
159
|
+
All users must either:
|
160
|
+
|
161
|
+
- Use their license key to install
|
162
|
+
- Or receive ``.so`` file from verified sources
|
163
|
+
|
164
|
+
For access, contact us or visit: https://worktif.com/documents/terms-of-service
|
165
|
+
|
166
|
+
---
|
167
|
+
|
168
|
+
๐ Full Example
|
169
|
+
----------------
|
170
|
+
|
171
|
+
.. code-block:: python
|
172
|
+
|
173
|
+
import numpy as np
|
174
|
+
from purem import purem
|
175
|
+
|
176
|
+
# Automatic setup using license key
|
177
|
+
try:
|
178
|
+
purem.configure(license_key='<your-license-key>')
|
179
|
+
except Exception as e:
|
180
|
+
print(f"Setup failed: {e}")
|
181
|
+
|
182
|
+
data = np.array([1.0, 2.0, 3.0], dtype=float)
|
183
|
+
output = purem.softmax(data)
|
184
|
+
|
185
|
+
print(output)
|
186
|
+
|
187
|
+
---
|
188
|
+
|
189
|
+
๐ง Why Purem?
|
190
|
+
--------------
|
191
|
+
|
192
|
+
- ๐ฅ High level performance with zero Python overhead
|
193
|
+
- ๐งช Built-in benchmarking and scientific accuracy
|
194
|
+
- ๐งฉ Easy plug-and-play design
|
195
|
+
- ๐ Secure and license-aware system
|
196
|
+
|
197
|
+
---
|
198
|
+
|
199
|
+
๐ Advanced Usage & API Docs
|
200
|
+
----------------------------
|
201
|
+
|
202
|
+
Coming soon...
|
@@ -0,0 +1,12 @@
|
|
1
|
+
purem/__init__.py,sha256=-npGtjgo4iHpJHW1DabIA7aUXPDGzgDw8jClOVAg35I,142
|
2
|
+
purem/core.py,sha256=pT_FWD6GHtRs2kWOMfHrGjrIdHAF85kqTl3OBiv_2ng,9761
|
3
|
+
purem/env_config.py,sha256=J5J_zSRzPYUCSUPZGd8m6dz6AmShgG9e0s7ll0BZL4Q,2668
|
4
|
+
purem/file_structure.py,sha256=8PRP9uk6PApOHwKF5Pfyg7CbZfgqTVwzV4NrYLJkTjY,3341
|
5
|
+
purem/loader.py,sha256=F-4dFzBtmxnB8r4Y620WJhJ6-yAiBjmvZYCi8Z1ykkU,1274
|
6
|
+
purem/logger.py,sha256=muhL_QsqKgo-ElSee7SDwwFopGgbPQf6xXB7IlTuC5k,1025
|
7
|
+
purem/utils.py,sha256=Kv0DPvt8SpSfKp4ar03ZP26Aj60dxW5Gf8B9FKKUrDc,927
|
8
|
+
purem-2.0.3.dist-info/licenses/LICENSE,sha256=btmdQkvGxH-SryIGO_D4TpIzD7dZ8Y6z9M33WxCb1rI,1633
|
9
|
+
purem-2.0.3.dist-info/METADATA,sha256=ZHjSCMOEHuN5KKZR2vleLwa2KIHp8TNgrOYrboM905I,5424
|
10
|
+
purem-2.0.3.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
11
|
+
purem-2.0.3.dist-info/top_level.txt,sha256=EjS75KEpZUEKSV2TFGW6w5aLqY9nUyO6Gq2ATz-KeZM,6
|
12
|
+
purem-2.0.3.dist-info/RECORD,,
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Business Source License 1.1
|
2
|
+
|
3
|
+
Parameters
|
4
|
+
Licensor: Raman Marozau, sa.marozau@gmail.com
|
5
|
+
Licensed Work: React Serverless <react-serverless>
|
6
|
+
Change Date: Never
|
7
|
+
Change License: Proprietary License
|
8
|
+
Additional Use Grant: Free for personal and non-commercial research use only.
|
9
|
+
|
10
|
+
Terms
|
11
|
+
The Licensed Work is provided under the Business Source License 1.1 (the "License").
|
12
|
+
|
13
|
+
The Licensor grants you a non-exclusive, worldwide, non-transferable, limited right to use, copy, distribute, and modify the Licensed Work subject to the following terms:
|
14
|
+
|
15
|
+
Commercial Use Restriction
|
16
|
+
You may use the Licensed Work freely for non-commercial purposes.
|
17
|
+
Commercial use requires a separate commercial license from the Licensor.
|
18
|
+
|
19
|
+
Availability of Source Code
|
20
|
+
The source code is provided under this License but may not be used for commercial purposes unless explicitly permitted.
|
21
|
+
|
22
|
+
Change Date and Transition to Open Source
|
23
|
+
On the Change Date, the Licensed Work will automatically transition to the Change License specified above.
|
24
|
+
After the Change Date, the restrictions imposed by this License no longer apply.
|
25
|
+
|
26
|
+
Additional Use Grant
|
27
|
+
The Licensor may grant additional permissions, such as allowing specific non-commercial uses or exceptions.
|
28
|
+
|
29
|
+
Termination
|
30
|
+
Any violation of these terms will result in an immediate termination of your rights under this License.
|
31
|
+
Upon termination, you must cease all use of the Licensed Work and delete any copies.
|
32
|
+
|
33
|
+
Disclaimer of Warranty
|
34
|
+
The Licensed Work is provided "AS IS", without any warranties, express or implied.
|
35
|
+
|
36
|
+
Limitation of Liability
|
37
|
+
The Licensor is not liable for any damages arising from the use of the Licensed Work.
|
@@ -0,0 +1 @@
|
|
1
|
+
purem
|