0
# Utility Functions
1
2
File operations, platform compatibility checks, and system integration utilities. Provides comprehensive support for downloading, extracting, and installing software releases with platform-aware compatibility filtering.
3
4
## Capabilities
5
6
### File Download and Extraction
7
8
Core utilities for downloading and extracting software releases from URLs, supporting multiple archive formats and providing progress feedback.
9
10
```python { .api }
11
def download_file(url: str, local_filename: str = None) -> str:
12
"""
13
Download a file from URL to local filesystem with progress tracking.
14
15
Parameters:
16
- url: URL to download from
17
- local_filename: Optional local filename (derived from URL if None)
18
19
Returns:
20
- Local filename of downloaded file
21
22
Features:
23
- Progress bar display using tqdm
24
- Automatic filename detection from Content-Disposition header
25
- Resume support for partial downloads
26
- Proper handling of redirects and authentication
27
"""
28
29
def extract_file(url: str, to_dir: str = ".") -> Any:
30
"""
31
Download and extract compressed files (tar, zip, 7z) in one operation.
32
33
Parameters:
34
- url: URL of compressed file to download and extract
35
- to_dir: Target directory for extraction (default: current directory)
36
37
Returns:
38
- Extraction results and file list
39
40
Supported formats:
41
- TAR archives (.tar, .tar.gz, .tar.bz2, .tar.xz)
42
- ZIP archives (.zip)
43
- 7-Zip archives (.7z)
44
45
Security:
46
- Path traversal protection for all archive types
47
- Safe extraction with directory bounds checking
48
"""
49
```
50
51
### Archive Format Handlers
52
53
Specialized functions for handling different archive formats with security protections.
54
55
```python { .api }
56
def extract_tar(buffer: io.BytesIO, to_dir: str) -> None:
57
"""
58
Extract TAR archive from BytesIO buffer with safety checks.
59
60
Parameters:
61
- buffer: BytesIO buffer containing TAR data
62
- to_dir: Target extraction directory
63
64
Security features:
65
- Path traversal attack prevention
66
- Symbolic link attack protection
67
- Size bomb protection
68
"""
69
70
def extract_zip(buffer: io.BytesIO, to_dir: str) -> None:
71
"""
72
Extract ZIP archive from BytesIO buffer.
73
74
Parameters:
75
- buffer: BytesIO buffer containing ZIP data
76
- to_dir: Target extraction directory
77
78
Features:
79
- Unicode filename support
80
- Directory structure preservation
81
- Executable permission handling on Unix systems
82
"""
83
84
def extract_7z(buffer: io.BytesIO, to_dir: str) -> None:
85
"""
86
Extract 7-Zip archive from BytesIO buffer.
87
88
Parameters:
89
- buffer: BytesIO buffer containing 7z data
90
- to_dir: Target extraction directory
91
92
Requires:
93
- py7zr library for 7-Zip support
94
"""
95
96
def check_if_tar_safe(tar_file: tarfile.TarFile) -> bool:
97
"""
98
Verify TAR file safety against path traversal attacks.
99
100
Parameters:
101
- tar_file: Open TarFile object to check
102
103
Returns:
104
- True if archive is safe to extract, False otherwise
105
106
Checks for:
107
- Path traversal attempts (../ sequences)
108
- Absolute path entries
109
- Symbolic link attacks
110
"""
111
```
112
113
### Platform Compatibility Utilities
114
115
Functions for determining platform compatibility of software assets and packages.
116
117
```python { .api }
118
def is_file_ext_not_compatible_with_os(file_ext: str) -> bool:
119
"""
120
Check if file extension is incompatible with current operating system.
121
122
Parameters:
123
- file_ext: File extension to check (with or without leading dot)
124
125
Returns:
126
- True if extension is incompatible with current OS
127
"""
128
129
def is_asset_name_compatible_with_platform(asset_name: str) -> bool:
130
"""
131
Determine if asset name indicates compatibility with current platform.
132
133
Parameters:
134
- asset_name: Asset or filename to analyze
135
136
Returns:
137
- True if asset appears compatible with current platform
138
139
Analyzes:
140
- Operating system indicators (windows, linux, macos, darwin)
141
- Architecture indicators (x86, x64, arm, aarch64)
142
- Package format compatibility
143
"""
144
145
def is_not_compatible_to_distro(asset_ext: str) -> bool:
146
"""
147
Check if asset extension is incompatible with current Linux distribution.
148
149
Parameters:
150
- asset_ext: Asset file extension
151
152
Returns:
153
- True if incompatible with current distribution
154
155
Considers:
156
- RPM vs DEB package formats
157
- Distribution-specific package types
158
- Current system's package manager
159
"""
160
161
def is_not_compatible_bitness(asset_name: str) -> bool:
162
"""
163
Check if asset bitness (32/64-bit) is incompatible with current system.
164
165
Parameters:
166
- asset_name: Asset filename to analyze
167
168
Returns:
169
- True if bitness is incompatible
170
"""
171
172
def asset_does_not_belong_to_machine(asset_name: str) -> bool:
173
"""
174
Comprehensive compatibility check for asset against current machine.
175
176
Parameters:
177
- asset_name: Asset filename to analyze
178
179
Returns:
180
- True if asset is incompatible with current machine
181
182
Combines all compatibility checks:
183
- Operating system compatibility
184
- Architecture compatibility
185
- Distribution compatibility
186
- Bitness compatibility
187
"""
188
```
189
190
### System Integration Utilities
191
192
Functions for integrating with system package managers and application installation.
193
194
```python { .api }
195
def rpm_installed_version(name: str) -> str:
196
"""
197
Get installed version of an RPM package.
198
199
Parameters:
200
- name: RPM package name
201
202
Returns:
203
- Version string of installed package or None if not installed
204
205
Uses:
206
- rpm command-line tool for version queries
207
- Handles package name variations and provides
208
"""
209
210
def extract_appimage_desktop_file(appimage_path: str) -> str:
211
"""
212
Extract desktop file from AppImage for system integration.
213
214
Parameters:
215
- appimage_path: Path to AppImage file
216
217
Returns:
218
- Desktop file content as string
219
220
Features:
221
- Mounts AppImage temporarily
222
- Extracts .desktop file content
223
- Handles AppImage format variations
224
- Provides metadata for system integration
225
"""
226
227
def ensure_directory_exists(directory_path: str) -> None:
228
"""
229
Ensure directory exists, creating parent directories as needed.
230
231
Parameters:
232
- directory_path: Directory path to create
233
234
Features:
235
- Creates parent directories recursively
236
- Handles existing directories gracefully
237
- Proper error handling for permission issues
238
"""
239
```
240
241
### HTTP Response Utilities
242
243
Helper functions for processing HTTP responses and extracting metadata.
244
245
```python { .api }
246
def get_content_disposition_filename(response: requests.Response) -> str:
247
"""
248
Extract filename from HTTP Content-Disposition header.
249
250
Parameters:
251
- response: requests.Response object
252
253
Returns:
254
- Extracted filename or None if not found
255
256
Handles:
257
- Various Content-Disposition header formats
258
- Unicode filename encoding
259
- Fallback to URL-based filename extraction
260
"""
261
```
262
263
## Usage Examples
264
265
### File Download Operations
266
267
```python
268
from lastversion.utils import download_file, extract_file
269
270
# Simple file download
271
local_file = download_file("https://example.com/software.tar.gz")
272
print(f"Downloaded to: {local_file}")
273
274
# Download with custom filename
275
download_file("https://example.com/file.zip", "custom-name.zip")
276
277
# Download and extract in one operation
278
extract_file("https://example.com/archive.tar.gz", to_dir="/tmp/extracted")
279
```
280
281
### Platform Compatibility Checking
282
283
```python
284
from lastversion.utils import (
285
is_asset_name_compatible_with_platform,
286
asset_does_not_belong_to_machine
287
)
288
289
# Check individual assets for compatibility
290
assets = [
291
"software-1.0-linux-x86_64.tar.gz",
292
"software-1.0-windows-x64.exe",
293
"software-1.0-macos-arm64.dmg",
294
]
295
296
compatible_assets = []
297
for asset in assets:
298
if is_asset_name_compatible_with_platform(asset):
299
compatible_assets.append(asset)
300
301
print(f"Compatible assets: {compatible_assets}")
302
303
# Comprehensive compatibility check
304
for asset in assets:
305
if not asset_does_not_belong_to_machine(asset):
306
print(f"Asset {asset} is compatible with this machine")
307
```
308
309
### Archive Extraction with Safety
310
311
```python
312
import io
313
from lastversion.utils import extract_tar, check_if_tar_safe
314
import tarfile
315
316
# Safe TAR extraction
317
with open("archive.tar.gz", "rb") as f:
318
buffer = io.BytesIO(f.read())
319
320
# Verify archive safety before extraction
321
with tarfile.open(fileobj=buffer, mode="r:gz") as tar:
322
if check_if_tar_safe(tar):
323
buffer.seek(0) # Reset buffer position
324
extract_tar(buffer, "/safe/extraction/path")
325
else:
326
print("Archive contains unsafe paths - extraction blocked")
327
```
328
329
### System Package Integration
330
331
```python
332
from lastversion.utils import rpm_installed_version
333
334
# Check installed RPM version
335
current_version = rpm_installed_version("nginx")
336
if current_version:
337
print(f"Nginx version {current_version} is installed")
338
else:
339
print("Nginx is not installed")
340
341
# Use with version comparison
342
from lastversion import has_update
343
from lastversion.version import Version
344
345
if current_version:
346
update_available = has_update("nginx/nginx", current_version)
347
if update_available:
348
print(f"Update available: {current_version} → {update_available}")
349
```
350
351
### AppImage Integration
352
353
```python
354
from lastversion.utils import extract_appimage_desktop_file
355
import os
356
357
# Extract desktop file for system integration
358
appimage_path = "/path/to/application.AppImage"
359
if os.path.exists(appimage_path):
360
desktop_content = extract_appimage_desktop_file(appimage_path)
361
362
# Save desktop file for system integration
363
desktop_file = "/home/user/.local/share/applications/application.desktop"
364
with open(desktop_file, "w") as f:
365
f.write(desktop_content)
366
```
367
368
### HTTP Response Processing
369
370
```python
371
import requests
372
from lastversion.utils import get_content_disposition_filename
373
374
# Download with automatic filename detection
375
response = requests.get("https://example.com/download", stream=True)
376
filename = get_content_disposition_filename(response)
377
378
if filename:
379
print(f"Server suggested filename: {filename}")
380
else:
381
# Fallback to URL-based filename
382
filename = "download.bin"
383
384
# Save file with detected name
385
with open(filename, "wb") as f:
386
for chunk in response.iter_content(chunk_size=8192):
387
f.write(chunk)
388
```