Skip to content

Commit aae2b74

Browse files
chore: new tls-client version
1 parent e1f1dac commit aae2b74

File tree

2 files changed

+145
-139
lines changed

2 files changed

+145
-139
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,4 @@ cython_debug/
160160
# and can be added to the global gitignore or merged into this file. For a more nuclear
161161
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
162162
.idea/
163-
tls_requests/bin/*xgo*
163+
tls_requests/bin/*

tls_requests/models/libraries.py

Lines changed: 144 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import ctypes
22
import glob
3+
import json
34
import os
45
import platform
56
import re
67
import sys
8+
import urllib.error
9+
import urllib.request
710
from dataclasses import dataclass, field, fields
811
from pathlib import Path
912
from platform import machine
10-
from typing import List, Optional
11-
12-
import requests
13-
from tqdm import tqdm
13+
from typing import List, Optional, Tuple
1414

1515
__all__ = ["TLSLibrary"]
1616

17+
LATEST_VERSION_TAG_NAME = "v1.11.2"
1718
BIN_DIR = os.path.join(Path(__file__).resolve(strict=True).parent.parent / "bin")
1819
GITHUB_API_URL = "https://api.github.com/repos/bogdanfinn/tls-client/releases"
1920
PLATFORM = sys.platform
@@ -73,7 +74,7 @@ def model_fields_set(cls) -> set:
7374
@classmethod
7475
def from_kwargs(cls, **kwargs):
7576
model_fields_set = cls.model_fields_set()
76-
return cls(**{k: v for k, v in kwargs.items() if k in model_fields_set})
77+
return cls(**{k: v for k, v in kwargs.items() if k in model_fields_set}) # noqa
7778

7879

7980
@dataclass
@@ -133,92 +134,64 @@ class TLSLibrary:
133134

134135
_PATH: str = None
135136
_STATIC_API_DATA = {
136-
"name": "v1.7.10",
137-
"tag_name": "v1.7.10",
137+
"name": "v1.11.2",
138+
"tag_name": "v1.11.2",
138139
"assets": [
139-
{
140-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-darwin-amd64-1.7.10.dylib",
141-
"name": "tls-client-darwin-amd64-1.7.10.dylib",
142-
},
143-
{
144-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-darwin-arm64-1.7.10.dylib",
145-
"name": "tls-client-darwin-arm64-1.7.10.dylib",
146-
},
147-
{
148-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-linux-arm64-1.7.10.so",
149-
"name": "tls-client-linux-arm64-1.7.10.so",
150-
},
151-
{
152-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-linux-armv7-1.7.10.so",
153-
"name": "tls-client-linux-armv7-1.7.10.so",
154-
},
155-
{
156-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-linux-ubuntu-amd64-1.7.10.so",
157-
"name": "tls-client-linux-ubuntu-amd64-1.7.10.so",
158-
},
159-
{
160-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-windows-32-1.7.10.dll",
161-
"name": "tls-client-windows-32-1.7.10.dll",
162-
},
163-
{
164-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-windows-64-1.7.10.dll",
165-
"name": "tls-client-windows-64-1.7.10.dll",
166-
},
167-
{
168-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-xgo-1.7.10-darwin-amd64.dylib",
169-
"name": "tls-client-xgo-1.7.10-darwin-amd64.dylib",
170-
},
171-
{
172-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-xgo-1.7.10-darwin-arm64.dylib",
173-
"name": "tls-client-xgo-1.7.10-darwin-arm64.dylib",
174-
},
175-
{
176-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-xgo-1.7.10-linux-386.so",
177-
"name": "tls-client-xgo-1.7.10-linux-386.so",
178-
},
179-
{
180-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-xgo-1.7.10-linux-amd64.so",
181-
"name": "tls-client-xgo-1.7.10-linux-amd64.so",
182-
},
183-
{
184-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-xgo-1.7.10-linux-arm-5.so",
185-
"name": "tls-client-xgo-1.7.10-linux-arm-5.so",
186-
},
187-
{
188-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-xgo-1.7.10-linux-arm-6.so",
189-
"name": "tls-client-xgo-1.7.10-linux-arm-6.so",
190-
},
191-
{
192-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-xgo-1.7.10-linux-arm-7.so",
193-
"name": "tls-client-xgo-1.7.10-linux-arm-7.so",
194-
},
195-
{
196-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-xgo-1.7.10-linux-arm64.so",
197-
"name": "tls-client-xgo-1.7.10-linux-arm64.so",
198-
},
199-
{
200-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-xgo-1.7.10-linux-ppc64le.so",
201-
"name": "tls-client-xgo-1.7.10-linux-ppc64le.so",
202-
},
203-
{
204-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-xgo-1.7.10-linux-riscv64.so",
205-
"name": "tls-client-xgo-1.7.10-linux-riscv64.so",
206-
},
207-
{
208-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-xgo-1.7.10-linux-s390x.so",
209-
"name": "tls-client-xgo-1.7.10-linux-s390x.so",
210-
},
211-
{
212-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-xgo-1.7.10-windows-386.dll",
213-
"name": "tls-client-xgo-1.7.10-windows-386.dll",
214-
},
215-
{
216-
"browser_download_url": "https://github.com/bogdanfinn/tls-client/releases/download/v1.7.10/tls-client-xgo-1.7.10-windows-amd64.dll",
217-
"name": "tls-client-xgo-1.7.10-windows-amd64.dll",
218-
},
219-
],
140+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-darwin-amd64-1.11.2.dylib', 'name': 'tls-client-darwin-amd64-1.11.2.dylib'},
141+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-darwin-arm64-1.11.2.dylib', 'name': 'tls-client-darwin-arm64-1.11.2.dylib'},
142+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-linux-alpine-amd64-1.11.2.so', 'name': 'tls-client-linux-alpine-amd64-1.11.2.so'},
143+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-linux-arm64-1.11.2.so', 'name': 'tls-client-linux-arm64-1.11.2.so'},
144+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-linux-armv7-1.11.2.so', 'name': 'tls-client-linux-armv7-1.11.2.so'},
145+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-linux-ubuntu-amd64-1.11.2.so', 'name': 'tls-client-linux-ubuntu-amd64-1.11.2.so'},
146+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-windows-32-1.11.2.dll', 'name': 'tls-client-windows-32-1.11.2.dll'},
147+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-windows-64-1.11.2.dll', 'name': 'tls-client-windows-64-1.11.2.dll'},
148+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-xgo-1.11.2-darwin-amd64.dylib', 'name': 'tls-client-xgo-1.11.2-darwin-amd64.dylib'},
149+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-xgo-1.11.2-darwin-arm64.dylib', 'name': 'tls-client-xgo-1.11.2-darwin-arm64.dylib'},
150+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-xgo-1.11.2-linux-386.so', 'name': 'tls-client-xgo-1.11.2-linux-386.so'},
151+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-xgo-1.11.2-linux-amd64.so', 'name': 'tls-client-xgo-1.11.2-linux-amd64.so'},
152+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-xgo-1.11.2-linux-arm-5.so', 'name': 'tls-client-xgo-1.11.2-linux-arm-5.so'},
153+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-xgo-1.11.2-linux-arm-6.so', 'name': 'tls-client-xgo-1.11.2-linux-arm-6.so'},
154+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-xgo-1.11.2-linux-arm-7.so', 'name': 'tls-client-xgo-1.11.2-linux-arm-7.so'},
155+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-xgo-1.11.2-linux-arm64.so', 'name': 'tls-client-xgo-1.11.2-linux-arm64.so'},
156+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-xgo-1.11.2-linux-ppc64le.so', 'name': 'tls-client-xgo-1.11.2-linux-ppc64le.so'},
157+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-xgo-1.11.2-linux-riscv64.so', 'name': 'tls-client-xgo-1.11.2-linux-riscv64.so'},
158+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-xgo-1.11.2-linux-s390x.so', 'name': 'tls-client-xgo-1.11.2-linux-s390x.so'},
159+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-xgo-1.11.2-windows-386.dll', 'name': 'tls-client-xgo-1.11.2-windows-386.dll'},
160+
{'browser_download_url': 'https://github.com/bogdanfinn/tls-client/releases/download/v1.11.2/tls-client-xgo-1.11.2-windows-amd64.dll', 'name': 'tls-client-xgo-1.11.2-windows-amd64.dll'}],
220161
}
221162

163+
@staticmethod
164+
def _parse_version(version_string: str) -> Tuple[int, ...]:
165+
"""Converts a version string (e.g., "v1.11.2") to a comparable tuple (1, 11, 2)."""
166+
try:
167+
parts = version_string.lstrip('v').split('.')
168+
return tuple(map(int, parts))
169+
except (ValueError, AttributeError):
170+
return 0, 0, 0
171+
172+
@staticmethod
173+
def _parse_version_from_filename(filename: str) -> Tuple[int, ...]:
174+
"""Extracts and parses the version from a library filename."""
175+
match = re.search(r'v?(\d+\.\d+\.\d+)', Path(filename).name)
176+
if match:
177+
return TLSLibrary._parse_version(match.group(1))
178+
return 0, 0, 0
179+
180+
@classmethod
181+
def cleanup_files(cls, keep_file: str = None):
182+
"""Removes all library files in the BIN_DIR except for the one to keep."""
183+
for file_path in cls.find_all():
184+
is_remove = True
185+
if keep_file and Path(file_path).name == Path(keep_file).name:
186+
is_remove = False
187+
188+
if is_remove:
189+
try:
190+
os.remove(file_path)
191+
print(f"Removed old library file: {file_path}")
192+
except OSError as e:
193+
print(f"Error removing old library file {file_path}: {e}")
194+
222195
@classmethod
223196
def fetch_api(cls, version: str = None, retries: int = 3):
224197
def _find_release(data, version_: str = None):
@@ -250,11 +223,12 @@ def _find_release(data, version_: str = None):
250223
asset_urls, ubuntu_urls = [], []
251224
for _ in range(retries):
252225
try:
253-
response = requests.get(GITHUB_API_URL)
254-
if response.ok:
255-
_find_release(response.json())
256-
break
257-
226+
# Use standard library's urllib to fetch API data
227+
with urllib.request.urlopen(GITHUB_API_URL, timeout=10) as response:
228+
if response.status == 200:
229+
content = response.read().decode('utf-8')
230+
_find_release(json.loads(content))
231+
break
258232
except Exception as ex:
259233
print("Unable to fetch GitHub API: %s" % ex)
260234

@@ -272,6 +246,7 @@ def find(cls) -> str:
272246
for fp in cls.find_all():
273247
if PATTERN_RE.search(fp):
274248
return fp
249+
return None
275250

276251
@classmethod
277252
def find_all(cls) -> List[str]:
@@ -293,80 +268,111 @@ def download(cls, version: str = None) -> str:
293268
)
294269
)
295270
download_url = None
296-
for download_url in cls.fetch_api(version):
297-
if download_url:
271+
for url in cls.fetch_api(version):
272+
if url:
273+
download_url = url
298274
break
299275

300276
print("Library Download URL: %s" % download_url)
301277
if download_url:
302-
destination = os.path.join(BIN_DIR, download_url.split("/")[-1])
303-
with requests.get(download_url, stream=True) as response:
304-
response.raise_for_status()
278+
destination_name = download_url.split("/")[-1]
279+
destination = os.path.join(BIN_DIR, destination_name)
280+
281+
# Use standard library's urllib to download the file
282+
with urllib.request.urlopen(download_url, timeout=10) as response:
283+
if response.status != 200:
284+
raise urllib.error.URLError(f"Failed to download file: HTTP {response.status}")
285+
305286
os.makedirs(BIN_DIR, exist_ok=True)
306287
total_size = int(response.headers.get("content-length", 0))
307-
chunk_size = 1024
308-
with open(
309-
os.path.join(BIN_DIR, download_url.split("/")[-1]), "wb"
310-
) as file, tqdm(
311-
desc=destination,
312-
total=total_size,
313-
unit="iB",
314-
unit_scale=True,
315-
unit_divisor=chunk_size,
316-
) as progress_bar:
317-
for chunk in response.iter_content(chunk_size):
318-
size = file.write(chunk)
319-
progress_bar.update(size)
320-
288+
chunk_size = 8192 # 8KB
289+
290+
with open(destination, "wb") as file:
291+
downloaded = 0
292+
while True:
293+
chunk = response.read(chunk_size)
294+
if not chunk:
295+
break
296+
297+
file.write(chunk)
298+
downloaded += len(chunk)
299+
300+
# Simple text-based progress bar
301+
if total_size > 0:
302+
percent = downloaded / total_size * 100
303+
bar_length = 50
304+
filled_length = int(bar_length * downloaded // total_size)
305+
bar = "=" * filled_length + '-' * (bar_length - filled_length)
306+
sys.stdout.write(f'\rDownloading {destination_name}: [{bar}] {percent:.1f}%')
307+
sys.stdout.flush()
308+
309+
print() # Newline after download completes
321310
return destination
322311

323-
except requests.exceptions.HTTPError as ex:
312+
except (urllib.error.URLError, urllib.error.HTTPError) as ex:
324313
print("Unable to download file: %s" % ex)
314+
except Exception as e:
315+
print("An unexpected error occurred during download: %s" % e)
325316

326317
@classmethod
327318
def set_path(cls, fp: str):
328319
cls._PATH = fp
329320

330321
@classmethod
331322
def load(cls):
332-
"""Load libraries"""
323+
"""
324+
Loads the TLS library. It checks for the correct version, downloads it if
325+
the local version is outdated or missing, and then loads it into memory.
326+
"""
333327

334-
def _load_libraries(fp_):
328+
def _load_library(fp_):
335329
try:
336330
lib = ctypes.cdll.LoadLibrary(fp_)
337331
cls.set_path(fp_)
332+
print(f"Successfully loaded TLS library: {fp_}")
338333
return lib
339334
except Exception as ex:
340-
print("Unable to load TLS Library, details: %s" % ex)
335+
print(f"Unable to load TLS library '{fp_}', details: {ex}")
341336
try:
342337
os.remove(fp_)
343-
except FileNotFoundError:
338+
except (FileNotFoundError, PermissionError):
344339
pass
345340

346-
if cls._PATH is not None:
347-
library = _load_libraries(cls._PATH)
348-
if library:
349-
return library
350-
351-
if TLS_LIBRARY_PATH:
352-
library = _load_libraries(TLS_LIBRARY_PATH)
353-
if library:
354-
return library
355-
356-
for fp in cls.find_all():
357-
if IS_UBUNTU and PATTERN_UBUNTU_RE.search(fp):
358-
library = _load_libraries(fp)
359-
if library:
360-
return library
361-
if PATTERN_RE.search(fp):
362-
library = _load_libraries(fp)
341+
target_version = cls._parse_version(LATEST_VERSION_TAG_NAME)
342+
print(f"Required library version: {LATEST_VERSION_TAG_NAME}")
343+
local_files = cls.find_all()
344+
newest_local_version = (0, 0, 0)
345+
newest_local_file = None
346+
347+
if local_files:
348+
for file_path in local_files:
349+
file_version = cls._parse_version_from_filename(file_path)
350+
if file_version > newest_local_version:
351+
newest_local_version = file_version
352+
newest_local_file = file_path
353+
print(
354+
f"Found newest local library: {newest_local_file} (version {'.'.join(map(str, newest_local_version))})")
355+
else:
356+
print("No local library found.")
357+
358+
if newest_local_version < target_version:
359+
if newest_local_file:
360+
print(f"Local library is outdated. Upgrading to {LATEST_VERSION_TAG_NAME}...")
361+
else:
362+
print(f"Downloading required library version {LATEST_VERSION_TAG_NAME}...")
363+
364+
downloaded_fp = cls.download(version=LATEST_VERSION_TAG_NAME)
365+
if downloaded_fp:
366+
cls.cleanup_files(keep_file=downloaded_fp)
367+
library = _load_library(downloaded_fp)
363368
if library:
364369
return library
370+
raise OSError("Failed to download the required TLS library.")
365371

366-
download_fp = cls.download()
367-
if download_fp:
368-
library = _load_libraries(download_fp)
372+
if newest_local_file:
373+
library = _load_library(newest_local_file)
369374
if library:
375+
cls.cleanup_files(keep_file=newest_local_file)
370376
return library
371377

372-
raise OSError("Your system does not support TLS Library.")
378+
raise OSError("Could not find or load a compatible TLS library.")

0 commit comments

Comments
 (0)