fastls 0.1.3__py3-none-win_amd64.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.
fastls/__init__.py ADDED
@@ -0,0 +1,11 @@
1
+ from ._native import FastlsError, FastlsTimeoutError, FastlsDecodeError
2
+ from .client import Session, AsyncSession, Response, AsyncResponse, FastlsHTTPError
3
+ from .headers import Headers
4
+ from .cookies import Cookies
5
+ from .timeout import Timeout
6
+ from .sse import ServerSentEvent, SSEStream, AsyncSSEStream
7
+
8
+ __all__ = ["Session", "AsyncSession", "Response", "AsyncResponse", "FastlsError", "Headers", "Cookies", "Timeout", "FastlsTimeoutError", "FastlsDecodeError", "ServerSentEvent", "SSEStream", "AsyncSSEStream"]
9
+ __all__.append("FastlsHTTPError")
10
+ from .websocket import WebSocket, AsyncWebSocket, WebSocketClosed
11
+ __all__ += ["WebSocket", "AsyncWebSocket", "WebSocketClosed"]
@@ -0,0 +1,21 @@
1
+ {
2
+ "platform": "Windows-10-10.0.20348-SP0",
3
+ "machine": "AMD64",
4
+ "local_dependencies": true,
5
+ "package_version": "0.1.3",
6
+ "go": "go version go1.26.10 windows/amd64",
7
+ "cc": "gcc",
8
+ "abi": 1,
9
+ "workspace_source": {
10
+ "sha256": "36962eb4a11e9bd292ef4fc30f3901e6d863d10aecec9b61fe54265881eb8bbd",
11
+ "input_count": 126
12
+ },
13
+ "sources": {
14
+ "fastls-ffi": "f87f44148b79c7f60d92d0d3bf98ab7a29800f90",
15
+ "fastls": "a57a7c51852b80976a07d7ce50ab758c22d44434",
16
+ "ftransport": "2e1d66a7983b4fe730d18c3b8b90831ae6e93db5",
17
+ "imitate": "1ef806aec3fca9607c083e375a72e84ae542d6bd"
18
+ },
19
+ "library_sha256": "058562dfecad02a58bfdd02517322af304efdb676ac89741947ab8730feb019b",
20
+ "note": "Native build metadata. Consult the release manifest for publication and certification status."
21
+ }
fastls/_lib/fastls.dll ADDED
Binary file
@@ -0,0 +1,14 @@
1
+ {
2
+ "format": "PE",
3
+ "machine": "0x8664",
4
+ "imports": [
5
+ "KERNEL32.dll",
6
+ "api-ms-win-crt-environment-l1-1-0.dll",
7
+ "api-ms-win-crt-heap-l1-1-0.dll",
8
+ "api-ms-win-crt-runtime-l1-1-0.dll",
9
+ "api-ms-win-crt-stdio-l1-1-0.dll",
10
+ "api-ms-win-crt-string-l1-1-0.dll",
11
+ "api-ms-win-crt-time-l1-1-0.dll"
12
+ ],
13
+ "note": "Static import table only; does not enumerate runtime LoadLibrary calls."
14
+ }
fastls/_native.py ADDED
@@ -0,0 +1,145 @@
1
+ """ctypes binding to C ABI v1. No native callbacks or Python worker threads."""
2
+ import ctypes as C
3
+ import json
4
+ import os
5
+ from pathlib import Path
6
+ import sys
7
+ import threading
8
+
9
+
10
+ class FastlsError(Exception):
11
+ pass
12
+
13
+
14
+ class FastlsTimeoutError(FastlsError):
15
+ def __init__(self, message, phase):
16
+ super().__init__(message)
17
+ self.phase = phase
18
+
19
+
20
+ class FastlsDecodeError(FastlsError):
21
+ pass
22
+
23
+
24
+ def raise_response_error(info):
25
+ message = info.get("error") or "native request failed"
26
+ if info.get("error_code") == "timeout":
27
+ raise FastlsTimeoutError(message, info.get("timeout_phase", "total"))
28
+ if info.get("error_code") == "decode_error":
29
+ raise FastlsDecodeError(message)
30
+ raise FastlsError(message)
31
+
32
+
33
+ _libraries = {}
34
+ _load_lock = threading.Lock()
35
+
36
+
37
+ class Native:
38
+ def __init__(self, library=None):
39
+ name = "fastls.dll" if sys.platform == "win32" else "libfastls.dylib" if sys.platform == "darwin" else "libfastls.so"
40
+ selected = library if library is not None else os.environ.get("FASTLS_LIBRARY")
41
+ if selected is None:
42
+ bundled = Path(__file__).resolve().parent / "_lib" / name
43
+ development = Path(__file__).resolve().parents[2]
44
+ if bundled.is_file():
45
+ selected = bundled
46
+ elif (development / "python" / "pyproject.toml").is_file():
47
+ selected = development / "dist" / name
48
+ else:
49
+ raise FastlsError("Fastls native library is missing; install a platform wheel or set FASTLS_LIBRARY")
50
+ path = Path(selected).resolve()
51
+ with _load_lock:
52
+ if path not in _libraries:
53
+ try:
54
+ _libraries[path] = C.CDLL(str(path))
55
+ except OSError as error:
56
+ raise FastlsError(f"Cannot load Fastls native library at {path}; check its architecture and system dependencies") from error
57
+ self.lib = _libraries[path] # Retain the library for the process lifetime.
58
+ if not hasattr(self.lib, "fastls_abi_version"):
59
+ raise FastlsError("Selected library does not provide the Fastls C ABI")
60
+ self.lib.fastls_abi_version.argtypes = []
61
+ self.lib.fastls_abi_version.restype = C.c_uint32
62
+ if self.lib.fastls_abi_version() != 1:
63
+ raise FastlsError("unsupported Fastls ABI version")
64
+ signatures = {
65
+ "fastls_profiles": [],
66
+ "fastls_start": [C.c_char_p, C.c_size_t],
67
+ "fastls_info": [C.c_uint64],
68
+ "fastls_cancel": [C.c_uint64],
69
+ "fastls_close": [C.c_uint64],
70
+ }
71
+ if hasattr(self.lib, "fastls_stats"):
72
+ signatures["fastls_stats"] = []
73
+ if hasattr(self.lib, "fastls_features"):
74
+ signatures["fastls_features"] = []
75
+ if hasattr(self.lib, "fastls_ws_start"):
76
+ signatures["fastls_ws_start"] = [C.c_char_p, C.c_size_t]
77
+ self.lib.fastls_ws_send.argtypes = [C.c_uint64, C.c_int, C.c_void_p, C.c_size_t]
78
+ self.lib.fastls_ws_send.restype = C.c_int
79
+ self.lib.fastls_ws_read.argtypes = [C.c_uint64, C.c_void_p, C.c_size_t, C.POINTER(C.c_size_t), C.POINTER(C.c_int), C.POINTER(C.c_int)]
80
+ self.lib.fastls_ws_read.restype = C.c_int
81
+ for name, args in {"fastls_session_create": [], "fastls_session_close": [C.c_uint64], "fastls_session_close_idle": [C.c_uint64]}.items():
82
+ if hasattr(self.lib, name):
83
+ signatures[name] = args
84
+ if hasattr(self.lib, "fastls_session_cookies"):
85
+ signatures["fastls_session_cookies"] = [C.c_uint64, C.c_char_p, C.c_size_t]
86
+ for name, args in {"fastls_session_watch": [C.c_uint64, C.c_uint16, C.c_void_p, C.c_size_t],
87
+ "fastls_session_events": [C.c_uint64], "fastls_session_unwatch": [C.c_uint64]}.items():
88
+ if hasattr(self.lib, name):
89
+ signatures[name] = args
90
+ for name, args in signatures.items():
91
+ fn = getattr(self.lib, name)
92
+ fn.argtypes, fn.restype = args, C.c_void_p
93
+ self.lib.fastls_free.argtypes = [C.c_void_p]
94
+ self.lib.fastls_free.restype = None
95
+ self.lib.fastls_read.argtypes = [C.c_uint64, C.c_void_p, C.c_size_t, C.POINTER(C.c_size_t)]
96
+ self.lib.fastls_read.restype = C.c_int
97
+
98
+ if hasattr(self.lib, "fastls_write"):
99
+ self.lib.fastls_write.argtypes = [C.c_uint64, C.c_void_p, C.c_size_t, C.c_int]
100
+ self.lib.fastls_write.restype = C.c_int
101
+
102
+ if hasattr(self.lib, "fastls_wait"):
103
+ self.lib.fastls_wait.argtypes = [C.c_uint64, C.c_uint32, C.c_uint32]
104
+ self.lib.fastls_wait.restype = C.c_int
105
+
106
+ def wait(self, handle, events, timeout_ms=1000):
107
+ code = self.lib.fastls_wait(handle, events, timeout_ms)
108
+ if code < 0:
109
+ raise FastlsError("native wait failed or request is closed")
110
+ return code
111
+
112
+ def write(self, handle, data, end=False):
113
+ code = self.lib.fastls_write(handle, data, len(data), int(end))
114
+ if code < 0:
115
+ info = self.call("fastls_info", handle)
116
+ if info["state"] == "error":
117
+ raise_response_error(info)
118
+ if info["state"] in ("headers", "eof"):
119
+ return 2 # Server finished the upload early.
120
+ raise FastlsError("upload is closed or invalid")
121
+ return code
122
+
123
+ def call(self, name, *args):
124
+ ptr = getattr(self.lib, name)(*args)
125
+ if not ptr:
126
+ raise FastlsError("native library returned a null result")
127
+ try:
128
+ envelope = json.loads(C.string_at(ptr).decode("utf-8"))
129
+ finally:
130
+ self.lib.fastls_free(ptr)
131
+ if not envelope["ok"]:
132
+ raise FastlsError(envelope["error"])
133
+ return envelope["result"]
134
+
135
+ def start(self, request):
136
+ raw = json.dumps(request, ensure_ascii=False).encode("utf-8")
137
+ return self.call("fastls_start", raw, len(raw))
138
+
139
+ def read(self, handle, buffer):
140
+ length = C.c_size_t()
141
+ code = self.lib.fastls_read(handle, buffer, len(buffer), C.byref(length))
142
+ if code < 0:
143
+ info = self.call("fastls_info", handle)
144
+ raise_response_error(info)
145
+ return code, buffer.raw[:length.value]