unaiverse 0.1.1__py3-none-any.whl → 0.1.2__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 unaiverse might be problematic. Click here for more details.
- unaiverse/networking/p2p/__init__.py +138 -106
- {unaiverse-0.1.1.dist-info → unaiverse-0.1.2.dist-info}/METADATA +3 -1
- {unaiverse-0.1.1.dist-info → unaiverse-0.1.2.dist-info}/RECORD +6 -6
- {unaiverse-0.1.1.dist-info → unaiverse-0.1.2.dist-info}/WHEEL +0 -0
- {unaiverse-0.1.1.dist-info → unaiverse-0.1.2.dist-info}/licenses/LICENSE +0 -0
- {unaiverse-0.1.1.dist-info → unaiverse-0.1.2.dist-info}/top_level.txt +0 -0
|
@@ -18,6 +18,7 @@ from . import golibp2p
|
|
|
18
18
|
from . import lib_types
|
|
19
19
|
import os
|
|
20
20
|
import sys
|
|
21
|
+
import json
|
|
21
22
|
import ctypes
|
|
22
23
|
import platform
|
|
23
24
|
import requests
|
|
@@ -31,128 +32,159 @@ from .lib_types import TypeInterface # Assuming TypeInterface handles the void*
|
|
|
31
32
|
|
|
32
33
|
# --- Setup and Pre-build Checks ---
|
|
33
34
|
|
|
34
|
-
#
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
# Determine the correct library file extension and URL based on the OS
|
|
36
|
+
os_to_ext = {
|
|
37
|
+
"Windows": ".dll",
|
|
38
|
+
"Darwin": ".dylib",
|
|
39
|
+
"Linux": ".so"
|
|
40
|
+
}
|
|
41
|
+
os_to_url = {
|
|
42
|
+
"Windows": "https://raw.githubusercontent.com/collectionlessai/unaiverse-misc/main/precompiled/lib.dll",
|
|
43
|
+
"Darwin": "https://raw.githubusercontent.com/collectionlessai/unaiverse-misc/main/precompiled/lib.dylib",
|
|
44
|
+
"Linux": "https://raw.githubusercontent.com/collectionlessai/unaiverse-misc/main/precompiled/lib.so"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
current_os = platform.system()
|
|
48
|
+
lib_ext = os_to_ext.get(current_os, ".so")
|
|
49
|
+
lib_url = os_to_url.get(current_os, os_to_url["Linux"])
|
|
50
|
+
|
|
51
|
+
# --- Configuration & Paths ---
|
|
52
|
+
lib_dir = os.path.dirname(os.path.abspath(__file__))
|
|
37
53
|
go_source_file = os.path.join(lib_dir, "lib.go")
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
# Determine the correct library file extension based on the OS
|
|
41
|
-
if platform.system() == "Windows":
|
|
42
|
-
lib_url = "https://github.com/collectionlessai/unaiverse-misc/raw/main/precompiled/lib.dll"
|
|
43
|
-
lib_ext = ".dll"
|
|
44
|
-
elif platform.system() == "Darwin": # MacOS
|
|
45
|
-
lib_url = "https://github.com/collectionlessai/unaiverse-misc/raw/main/precompiled/lib.dylib"
|
|
46
|
-
lib_ext = ".dylib"
|
|
47
|
-
else: # Linux and other Unix-like
|
|
48
|
-
lib_url = "https://github.com/collectionlessai/unaiverse-misc/raw/main/precompiled/lib.so"
|
|
49
|
-
lib_ext = ".so"
|
|
50
|
-
|
|
51
|
-
lib_filename = f"{lib_name}{lib_ext}"
|
|
54
|
+
lib_filename = f"lib{lib_ext}"
|
|
52
55
|
lib_path = os.path.join(lib_dir, lib_filename)
|
|
56
|
+
go_mod_file = os.path.join(lib_dir, "go.mod")
|
|
57
|
+
version_file = os.path.join(lib_dir, "lib.version.json")
|
|
53
58
|
|
|
54
|
-
|
|
55
|
-
print(f"INFO: Found a more recent Go source file, removing the existing library (if any)")
|
|
56
|
-
if os.path.exists(lib_path):
|
|
57
|
-
os.remove(lib_path)
|
|
58
|
-
|
|
59
|
-
# Possible states
|
|
60
|
-
shared_lib_was_downloaded = False
|
|
61
|
-
shared_lib_was_already_there = os.path.exists(lib_path)
|
|
62
|
-
must_recompile = False
|
|
63
|
-
reason_to_recompile = ""
|
|
64
|
-
_shared_lib = None # This is where the loaded library will stay
|
|
65
|
-
|
|
66
|
-
if not shared_lib_was_already_there:
|
|
67
|
-
print(f"INFO: '{lib_filename}' not found. Attempting to automatically download it and save to '{lib_dir}'...")
|
|
68
|
-
download_was_successful = False
|
|
69
|
-
try:
|
|
70
|
-
headers = {
|
|
71
|
-
"User-Agent": "python-requests/2.31.0" # Any browser-like agent also works
|
|
72
|
-
}
|
|
73
|
-
response = requests.get(lib_url, headers=headers, allow_redirects=True)
|
|
74
|
-
with open(lib_path, "wb") as f:
|
|
75
|
-
f.write(response.content)
|
|
76
|
-
download_was_successful = True
|
|
77
|
-
print(f"INFO: Download complete")
|
|
78
|
-
except Exception:
|
|
79
|
-
pass
|
|
59
|
+
# --- Helper Functions ---
|
|
80
60
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
reason_to_recompile = "The downloaded library was not compatible with this platform and was deleted."
|
|
90
|
-
must_recompile = True
|
|
91
|
-
else:
|
|
92
|
-
reason_to_recompile = "Failed to download the library."
|
|
93
|
-
must_recompile = True
|
|
61
|
+
def load_shared_library(path):
|
|
62
|
+
"""Attempt to load the shared library and return the handle."""
|
|
63
|
+
try:
|
|
64
|
+
print(f"INFO: Attempting to load library from '{path}'...")
|
|
65
|
+
return ctypes.CDLL(path)
|
|
66
|
+
except OSError as e:
|
|
67
|
+
print(f"INFO: Failed to load library: {e}")
|
|
68
|
+
return None
|
|
94
69
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
70
|
+
def get_remote_version_info(url):
|
|
71
|
+
"""Performs a HEAD request to get ETag from the remote file."""
|
|
72
|
+
try:
|
|
73
|
+
print(f"INFO: Checking remote version at '{url}'...")
|
|
74
|
+
response = requests.head(url, allow_redirects=True, timeout=10)
|
|
75
|
+
response.raise_for_status()
|
|
76
|
+
etag = response.headers.get("ETag")
|
|
77
|
+
return etag
|
|
78
|
+
except Exception as e:
|
|
79
|
+
print(f"INFO: Failed to get remote version info: {e}")
|
|
80
|
+
return None
|
|
81
|
+
|
|
82
|
+
def download_library(url, path, etag):
|
|
83
|
+
"""Downloads the shared library and saves version info."""
|
|
84
|
+
print(f"INFO: Downloading new library from '{url}'...")
|
|
85
|
+
try:
|
|
86
|
+
headers = {"User-Agent": "python-requests/2.31.0"}
|
|
87
|
+
response = requests.get(url, headers=headers, allow_redirects=True, timeout=30)
|
|
88
|
+
response.raise_for_status()
|
|
89
|
+
with open(path, "wb") as f:
|
|
90
|
+
f.write(response.content)
|
|
91
|
+
|
|
92
|
+
print("INFO: Download complete.")
|
|
93
|
+
return True
|
|
94
|
+
except Exception as e:
|
|
95
|
+
print(f"INFO: Failed to download library: {e}")
|
|
96
|
+
return False
|
|
97
|
+
|
|
98
|
+
def build_go_library():
|
|
99
|
+
"""Build the Go shared library and saves version info."""
|
|
100
|
+
print("INFO: Building library from source...")
|
|
99
101
|
if not os.path.exists(go_mod_file):
|
|
100
|
-
print(f"INFO: 'go.mod' not found. Initializing Go module
|
|
102
|
+
print(f"INFO: 'go.mod' not found. Initializing Go module...")
|
|
103
|
+
module_path = "unaiverse/networking/p2p/lib"
|
|
101
104
|
try:
|
|
102
|
-
|
|
103
|
-
# Define a module path. This can be anything, but a path-like name is conventional.
|
|
104
|
-
module_path = "unaiverse/networking/p2p/lib"
|
|
105
|
-
|
|
106
|
-
# Run 'go mod init'
|
|
107
|
-
subprocess.run(
|
|
108
|
-
["go", "mod", "init", module_path],
|
|
109
|
-
cwd=lib_dir, # Run the command in the directory containing lib.go
|
|
110
|
-
check=True, # Raise an exception if the command fails
|
|
111
|
-
capture_output=True, # Capture stdout/stderr
|
|
112
|
-
text=True
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
# Run 'go mod tidy' to find dependencies and create go.sum
|
|
105
|
+
subprocess.run(["go", "mod", "init", module_path], cwd=lib_dir, check=True, capture_output=True, text=True)
|
|
116
106
|
print("INFO: Go module initialized. Running 'go mod tidy'...")
|
|
117
|
-
subprocess.run(
|
|
118
|
-
["go", "mod", "tidy"],
|
|
119
|
-
cwd=lib_dir,
|
|
120
|
-
check=True,
|
|
121
|
-
capture_output=True,
|
|
122
|
-
text=True
|
|
123
|
-
)
|
|
124
|
-
print("INFO: 'go.mod' and 'go.sum' created successfully.")
|
|
107
|
+
subprocess.run(["go", "mod", "tidy"], cwd=lib_dir, check=True, capture_output=True, text=True)
|
|
125
108
|
except (subprocess.CalledProcessError, FileNotFoundError) as e:
|
|
126
|
-
print("FATAL: Failed to initialize Go module.
|
|
127
|
-
file=sys.stderr)
|
|
109
|
+
print(f"FATAL: Failed to initialize Go module. Is Go installed? Error: {e}", file=sys.stderr)
|
|
128
110
|
raise e
|
|
129
111
|
|
|
130
|
-
# --- Automatically build the shared library if it's missing or outdated ---
|
|
131
112
|
try:
|
|
132
113
|
build_command = ["go", "build", "-buildmode=c-shared", "-ldflags", "-s -w", "-o", lib_filename, "lib.go"]
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
build_command,
|
|
136
|
-
cwd=lib_dir,
|
|
137
|
-
check=True,
|
|
138
|
-
capture_output=True,
|
|
139
|
-
text=True
|
|
140
|
-
)
|
|
141
|
-
if result.stdout:
|
|
142
|
-
print(f"Go build stdout:\n{result.stdout}")
|
|
114
|
+
subprocess.run(build_command, cwd=lib_dir, check=True, capture_output=True, text=True)
|
|
115
|
+
|
|
143
116
|
print(f"INFO: Successfully built '{lib_filename}'.")
|
|
117
|
+
return True
|
|
144
118
|
except (subprocess.CalledProcessError, FileNotFoundError) as e:
|
|
145
|
-
print("FATAL: Failed to
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
119
|
+
print(f"FATAL: Failed to build library. Is Go installed? Error: {e}", file=sys.stderr)
|
|
120
|
+
return False
|
|
121
|
+
|
|
122
|
+
# --- Main Logic Flow ---
|
|
123
|
+
_shared_lib = None
|
|
124
|
+
should_update = False
|
|
125
|
+
go_source_time = os.path.getmtime(go_source_file)
|
|
126
|
+
|
|
127
|
+
# Step 1: Check for existing local binary and version info
|
|
128
|
+
if os.path.exists(lib_path):
|
|
129
|
+
print(f"INFO: Found existing library '{lib_filename}'.")
|
|
130
|
+
if os.path.exists(version_file):
|
|
131
|
+
try:
|
|
132
|
+
with open(version_file, "r") as f:
|
|
133
|
+
version_info = json.load(f)
|
|
134
|
+
|
|
135
|
+
if version_info.get("source") == "remote":
|
|
136
|
+
remote_etag = get_remote_version_info(lib_url)
|
|
137
|
+
if remote_etag and remote_etag != version_info.get("etag"):
|
|
138
|
+
print("INFO: Remote binary is newer (different ETag). An update is required.")
|
|
139
|
+
should_update = True
|
|
140
|
+
else:
|
|
141
|
+
print("INFO: Local binary is up-to-date with remote.")
|
|
142
|
+
elif version_info.get("source") == "local":
|
|
143
|
+
if go_source_time > version_info.get("timestamp", 0):
|
|
144
|
+
print("INFO: Go source file is newer than local binary. Re-compilation is required.")
|
|
145
|
+
should_update = True
|
|
146
|
+
else:
|
|
147
|
+
print("INFO: Local binary is up-to-date with source.")
|
|
148
|
+
|
|
149
|
+
except (IOError, json.JSONDecodeError):
|
|
150
|
+
print("INFO: Could not read version file. Assuming outdated.")
|
|
151
|
+
should_update = True
|
|
152
|
+
else:
|
|
153
|
+
print("INFO: No version file found. Assuming outdated.")
|
|
154
|
+
should_update = True
|
|
155
|
+
|
|
156
|
+
if should_update:
|
|
157
|
+
if os.path.exists(lib_path):
|
|
158
|
+
os.remove(lib_path)
|
|
159
|
+
else:
|
|
160
|
+
# Load if it exists and is up-to-date
|
|
161
|
+
_shared_lib = load_shared_library(lib_path)
|
|
162
|
+
|
|
163
|
+
# Step 2: Try to get a library if none is loaded
|
|
164
|
+
if _shared_lib is None: # same as should_update being True
|
|
165
|
+
# Attempt to download the latest binary
|
|
166
|
+
remote_etag = get_remote_version_info(lib_url)
|
|
167
|
+
if remote_etag and download_library(lib_url, lib_path, remote_etag):
|
|
168
|
+
_shared_lib = load_shared_library(lib_path)
|
|
169
|
+
if _shared_lib is not None:
|
|
170
|
+
with open(version_file, "w") as f:
|
|
171
|
+
json.dump({"source": "remote", "etag": remote_etag}, f)
|
|
172
|
+
|
|
173
|
+
# Step 3: Fallback to local build if download failed or the file is invalid
|
|
174
|
+
if _shared_lib is None: # meaning that the download and load failed
|
|
175
|
+
print("INFO: Download failed or produced an invalid library. Building from source...")
|
|
176
|
+
if build_go_library():
|
|
177
|
+
_shared_lib = load_shared_library(lib_path)
|
|
178
|
+
if _shared_lib is not None:
|
|
179
|
+
with open(version_file, "w") as f:
|
|
180
|
+
json.dump({"source": "local", "timestamp": go_source_time}, f)
|
|
181
|
+
|
|
182
|
+
# Final check
|
|
150
183
|
if _shared_lib is None:
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
raise e
|
|
184
|
+
print("FATAL: Critical failure. Could not obtain or load the shared library.", file=sys.stderr)
|
|
185
|
+
sys.exit(1)
|
|
186
|
+
else:
|
|
187
|
+
print("SUCCESS: Library is ready to use.")
|
|
156
188
|
|
|
157
189
|
# --- Function Prototypes (argtypes and restype) ---
|
|
158
190
|
# Using void* for returned C strings, requiring TypeInterface for conversion/freeing.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: unaiverse
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: UNaIVERSE: A Collectionless AI Project. The new web of humans & AI Agents, built on privacy, control, and reduced energy consumption.
|
|
5
5
|
Author-email: Stefano Melacci <stefano.melacci@unisi.it>, Christian Di Maio <christian.dimaio@phd.unipi.it>, Tommaso Guidi <tommaso.guidi.1998@gmail.com>
|
|
6
6
|
Maintainer-email: Stefano Melacci <stefano.melacci@unisi.it>, Christian Di Maio <christian.dimaio@phd.unipi.it>, Tommaso Guidi <tommaso.guidi.1998@gmail.com>
|
|
@@ -31,9 +31,11 @@ Requires-Dist: Pillow
|
|
|
31
31
|
Requires-Dist: protobuf
|
|
32
32
|
Requires-Dist: psutil
|
|
33
33
|
Requires-Dist: PyJWT
|
|
34
|
+
Requires-Dist: cryptography
|
|
34
35
|
Requires-Dist: Requests
|
|
35
36
|
Requires-Dist: torch
|
|
36
37
|
Requires-Dist: torchvision
|
|
38
|
+
Requires-Dist: transformers
|
|
37
39
|
Dynamic: license-file
|
|
38
40
|
|
|
39
41
|
<div align="center">
|
|
@@ -21,7 +21,7 @@ unaiverse/networking/node/connpool.py,sha256=hctRoYYGZA2D7sy1elIgE7o4umm8B9dZKq-
|
|
|
21
21
|
unaiverse/networking/node/node.py,sha256=q740PylBIqHm6jKN32A1_meYUhbmHdDWmZ9ySJ7sMkY,117733
|
|
22
22
|
unaiverse/networking/node/profile.py,sha256=lbB35MoI20oDxDqb97zH2NNNUCGJs8-8KIGNjjmnTio,20203
|
|
23
23
|
unaiverse/networking/node/tokens.py,sha256=UHyPnl6TDvPitrkP2AYAIegSWq4CpvsjRvmio3T-3nA,5281
|
|
24
|
-
unaiverse/networking/p2p/__init__.py,sha256=
|
|
24
|
+
unaiverse/networking/p2p/__init__.py,sha256=ikRpQyJa2PRIeCLXcMWLWioJyyu1aS5I6twArCkhGhQ,13599
|
|
25
25
|
unaiverse/networking/p2p/golibp2p.py,sha256=ibVCLERzM2JgPP_A5FTooCoxYW5Zm2HBbzX28aQIFzo,2450
|
|
26
26
|
unaiverse/networking/p2p/golibp2p.pyi,sha256=ri7ZL8LQHx2rnwhXmQ9q2RiaTXeU6nitw1lB_L5Bhq4,4079
|
|
27
27
|
unaiverse/networking/p2p/lib.go,sha256=l40IsZEC4a70LfJr8qzl8YDuh-fAcOaqaMPDLNG7IkI,108699
|
|
@@ -38,8 +38,8 @@ unaiverse/utils/lone_wolf.json,sha256=_rHfeqV8gqvPc0h-cZF7mPCG0Z4HuVkV-mKoXXwjbN
|
|
|
38
38
|
unaiverse/utils/misc.py,sha256=4J3HotzosgsnEr9MgeuQmdrrISPuKl85oOAuKAfcz-U,12085
|
|
39
39
|
unaiverse/utils/sandbox.py,sha256=S_eocNIGTyckovYMxmWb56wsCG7M-mxmGHqdLavSWQA,14436
|
|
40
40
|
unaiverse/utils/server.py,sha256=hCxHTNmYGrgGYrwZ5RaQ9kdmmfqWuIVTUdPYLCwpTQU,21974
|
|
41
|
-
unaiverse-0.1.
|
|
42
|
-
unaiverse-0.1.
|
|
43
|
-
unaiverse-0.1.
|
|
44
|
-
unaiverse-0.1.
|
|
45
|
-
unaiverse-0.1.
|
|
41
|
+
unaiverse-0.1.2.dist-info/licenses/LICENSE,sha256=02v7juVPTazXHV7TG9WtaWrtmeC3BAd49itKH_SiHOs,1396
|
|
42
|
+
unaiverse-0.1.2.dist-info/METADATA,sha256=H-V1qkzJhcKhX_tmABnnA1SG2iPHfXY3TlSzyCjMKkI,18268
|
|
43
|
+
unaiverse-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
44
|
+
unaiverse-0.1.2.dist-info/top_level.txt,sha256=0rP09tH9hv17TDQs66OHbJaRSnADpZsDsODy6JVsTtw,10
|
|
45
|
+
unaiverse-0.1.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|