Skip to content

Commit 47f94ef

Browse files
committed
Improve: SQLite download process
1 parent aff6293 commit 47f94ef

File tree

3 files changed

+38
-27
lines changed

3 files changed

+38
-27
lines changed

python/scripts/test_sqlite.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@
99
import usearch
1010

1111

12-
found_sqlite_path = usearch.sqlite
12+
try:
13+
found_sqlite_path = usearch.sqlite_path()
14+
except FileNotFoundError:
15+
found_sqlite_path = None
16+
1317
if found_sqlite_path is None:
1418
pytest.skip(reason="Can't find an SQLite installation", allow_module_level=True)
1519

python/usearch/__init__.py

+32-25
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,23 @@ class BinaryManager:
2020
def __init__(self, version: Optional[str] = None):
2121
if version is None:
2222
version = __version__
23-
self.version = version
24-
25-
def sqlite_download_url(self) -> str:
26-
"""
27-
Constructs a download URL for the `usearch_sqlite` binary based on the operating system, architecture, and version.
28-
29-
Args:
30-
version (str): The version of the binary to download.
23+
self.version = version or __version__
24+
self.download_dir = self.determine_download_dir()
25+
26+
@staticmethod
27+
def determine_download_dir():
28+
# Check if running within a virtual environment
29+
virtual_env = os.getenv("VIRTUAL_ENV")
30+
if virtual_env:
31+
# Use a subdirectory within the virtual environment for binaries
32+
return os.path.join(virtual_env, "bin", "usearch_binaries")
33+
else:
34+
# Fallback to a directory in the user's home folder
35+
home_dir = os.path.expanduser("~")
36+
return os.path.join(home_dir, ".usearch", "binaries")
3137

32-
Returns:
33-
A string representing the download URL.
34-
"""
38+
def sqlite_file_name(self) -> str:
3539
version = self.version
36-
base_url = "https://github.com/unum-cloud/usearch/releases/download"
3740
os_map = {"Linux": "linux", "Windows": "windows", "Darwin": "macos"}
3841
arch_map = {
3942
"x86_64": "amd64" if platform.system() != "Darwin" else "x86_64",
@@ -47,6 +50,12 @@ def sqlite_download_url(self) -> str:
4750
arch_part = arch_map.get(arch, "")
4851
extension = {"Linux": "so", "Windows": "dll", "Darwin": "dylib"}.get(platform.system(), "")
4952
filename = f"usearch_sqlite_{os_part}_{arch_part}_{version}.{extension}"
53+
return filename
54+
55+
def sqlite_download_url(self) -> str:
56+
version = self.version
57+
filename = self.sqlite_file_name()
58+
base_url = "https://github.com/unum-cloud/usearch/releases/download"
5059
url = f"{base_url}/v{version}/{filename}"
5160
return url
5261

@@ -66,7 +75,6 @@ def download_binary(self, url: str, dest_folder: str) -> str:
6675
urllib.request.urlretrieve(url, dest_path)
6776
return dest_path
6877

69-
@property
7078
def sqlite_found_or_downloaded(self) -> Optional[str]:
7179
"""
7280
Attempts to locate the pre-installed `usearch_sqlite` binary.
@@ -89,20 +97,16 @@ def sqlite_found_or_downloaded(self) -> Optional[str]:
8997
return os.path.join(root, file).removesuffix(file_extension)
9098

9199
# Check a temporary directory (assuming the binary might be downloaded from a GitHub release)
92-
temp_dir = tempfile.gettempdir()
93-
for root, _, files in os.walk(temp_dir):
94-
for file in files:
95-
if file.endswith(file_extension) and "usearch_sqlite" in file:
96-
return os.path.join(root, file).removesuffix(file_extension)
100+
local_path = os.path.join(self.download_dir, self.sqlite_file_name())
101+
if os.path.exists(local_path):
102+
return local_path.removesuffix(file_extension)
97103

98104
# If not found locally, warn the user and download from GitHub
99-
temp_dir = tempfile.gettempdir()
100105
warnings.warn("Will download `usearch_sqlite` binary from GitHub.", UserWarning)
101-
102-
# If the download fails due to HTTPError (e.g., 404 Not Found), like a missing lib version
103106
try:
104-
binary_path = self.download_binary(self.sqlite_download_url(), temp_dir)
107+
binary_path = self.download_binary(self.sqlite_download_url(), self.download_dir)
105108
except HTTPError as e:
109+
# If the download fails due to HTTPError (e.g., 404 Not Found), like a missing lib version
106110
if e.code == 404:
107111
warnings.warn(f"Download failed: {e.url} could not be found.", UserWarning)
108112
else:
@@ -117,6 +121,9 @@ def sqlite_found_or_downloaded(self) -> Optional[str]:
117121
return None
118122

119123

120-
# Use the function to set the `sqlite` computed property
121-
binary_manager = BinaryManager()
122-
sqlite = binary_manager.sqlite_found_or_downloaded
124+
def sqlite_path(version: str = None) -> str:
125+
manager = BinaryManager(version=version)
126+
result = manager.sqlite_found_or_downloaded()
127+
if result is None:
128+
raise FileNotFoundError("Failed to find or download `usearch_sqlite` binary.")
129+
return result

sqlite/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import usearch
3030

3131
conn = sqlite3.connect(":memory:")
3232
conn.enable_load_extension(True)
33-
conn.load_extension(usearch.sqlite)
33+
conn.load_extension(usearch.sqlite_path())
3434
```
3535

3636
Afterwards, the following script should work fine.

0 commit comments

Comments
 (0)