dataroom-client 1.0.4.post12.dev0__tar.gz → 1.0.5.post2.dev0__tar.gz
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.
- {dataroom_client-1.0.4.post12.dev0 → dataroom_client-1.0.5.post2.dev0}/PKG-INFO +3 -2
- {dataroom_client-1.0.4.post12.dev0 → dataroom_client-1.0.5.post2.dev0}/dataroom_client/client.py +81 -1
- {dataroom_client-1.0.4.post12.dev0 → dataroom_client-1.0.5.post2.dev0}/pyproject.toml +1 -1
- {dataroom_client-1.0.4.post12.dev0 → dataroom_client-1.0.5.post2.dev0}/README.md +0 -0
- {dataroom_client-1.0.4.post12.dev0 → dataroom_client-1.0.5.post2.dev0}/dataroom_client/__init__.py +0 -0
- {dataroom_client-1.0.4.post12.dev0 → dataroom_client-1.0.5.post2.dev0}/dataroom_client/counter.py +0 -0
- {dataroom_client-1.0.4.post12.dev0 → dataroom_client-1.0.5.post2.dev0}/dataroom_client/loader.py +0 -0
- {dataroom_client-1.0.4.post12.dev0 → dataroom_client-1.0.5.post2.dev0}/dataroom_client/print_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: dataroom-client
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.5.post2.dev0
|
|
4
4
|
Summary: A python client to interface with the Dataroom backend API
|
|
5
5
|
Author: Ales Kocjancic
|
|
6
6
|
Author-email: hi@ales.io
|
|
@@ -10,6 +10,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.11
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.12
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
13
14
|
Requires-Dist: httpx (>=0.28.0,<1)
|
|
14
15
|
Description-Content-Type: text/markdown
|
|
15
16
|
|
{dataroom_client-1.0.4.post12.dev0 → dataroom_client-1.0.5.post2.dev0}/dataroom_client/client.py
RENAMED
|
@@ -3,6 +3,7 @@ import functools
|
|
|
3
3
|
import inspect
|
|
4
4
|
import threading
|
|
5
5
|
import atexit
|
|
6
|
+
import queue
|
|
6
7
|
from datetime import datetime
|
|
7
8
|
import json as json_module
|
|
8
9
|
import logging
|
|
@@ -1814,6 +1815,17 @@ class AsyncRunner:
|
|
|
1814
1815
|
future = asyncio.run_coroutine_threadsafe(coro, cls._loop)
|
|
1815
1816
|
return future.result()
|
|
1816
1817
|
|
|
1818
|
+
@classmethod
|
|
1819
|
+
def submit(cls, coro):
|
|
1820
|
+
"""
|
|
1821
|
+
Schedule a coroutine on the shared background event loop and return the Future.
|
|
1822
|
+
|
|
1823
|
+
Unlike run(), this does not wait for the result; useful for producers feeding queues.
|
|
1824
|
+
"""
|
|
1825
|
+
if cls._thread is None:
|
|
1826
|
+
cls._initialize()
|
|
1827
|
+
return asyncio.run_coroutine_threadsafe(coro, cls._loop)
|
|
1828
|
+
|
|
1817
1829
|
@classmethod
|
|
1818
1830
|
def shutdown(cls) -> None:
|
|
1819
1831
|
"""
|
|
@@ -1866,6 +1878,9 @@ class DataRoomClientSync:
|
|
|
1866
1878
|
result = attr(*args, **kwargs)
|
|
1867
1879
|
if inspect.isawaitable(result):
|
|
1868
1880
|
return AsyncRunner.run(result)
|
|
1881
|
+
# If the result is an async generator or async iterable, wrap it into a blocking iterator
|
|
1882
|
+
if inspect.isasyncgen(result) or hasattr(result, "__aiter__"):
|
|
1883
|
+
return self._wrap_async_iterable(result)
|
|
1869
1884
|
return result
|
|
1870
1885
|
|
|
1871
1886
|
return sync_wrapper
|
|
@@ -1886,4 +1901,69 @@ class DataRoomClientSync:
|
|
|
1886
1901
|
@return: A DataRoomFile instance containing the downloaded image.
|
|
1887
1902
|
"""
|
|
1888
1903
|
# Class methods are not covered by the automatic wrapping of async methods in __getattr__.
|
|
1889
|
-
return AsyncRunner.run(DataRoomClient.download_image_from_url(*args, **kwargs))
|
|
1904
|
+
return AsyncRunner.run(DataRoomClient.download_image_from_url(*args, **kwargs))
|
|
1905
|
+
|
|
1906
|
+
@staticmethod
|
|
1907
|
+
def _wrap_async_iterable(async_iterable):
|
|
1908
|
+
"""
|
|
1909
|
+
Convert an AsyncIterable into a synchronous, blocking Python iterator.
|
|
1910
|
+
Items are streamed via a thread-safe queue from a background task.
|
|
1911
|
+
"""
|
|
1912
|
+
sentinel = object()
|
|
1913
|
+
q: queue.Queue = queue.Queue(maxsize=10)
|
|
1914
|
+
stop_flag = {"stop": False}
|
|
1915
|
+
|
|
1916
|
+
async def aclose_safe(ait):
|
|
1917
|
+
aclose = getattr(ait, "aclose", None)
|
|
1918
|
+
if aclose is not None:
|
|
1919
|
+
try:
|
|
1920
|
+
await aclose()
|
|
1921
|
+
except Exception: # pragma: no cover - best effort cleanup
|
|
1922
|
+
pass
|
|
1923
|
+
|
|
1924
|
+
async def producer():
|
|
1925
|
+
try:
|
|
1926
|
+
async for item in async_iterable:
|
|
1927
|
+
if stop_flag["stop"]:
|
|
1928
|
+
await aclose_safe(async_iterable)
|
|
1929
|
+
break
|
|
1930
|
+
while True:
|
|
1931
|
+
try:
|
|
1932
|
+
q.put_nowait(item)
|
|
1933
|
+
break
|
|
1934
|
+
except queue.Full:
|
|
1935
|
+
if stop_flag["stop"]:
|
|
1936
|
+
await aclose_safe(async_iterable)
|
|
1937
|
+
return
|
|
1938
|
+
await asyncio.sleep(0.01)
|
|
1939
|
+
except Exception as e:
|
|
1940
|
+
# pass exception to consumer then terminate
|
|
1941
|
+
try:
|
|
1942
|
+
q.put_nowait(e)
|
|
1943
|
+
except queue.Full:
|
|
1944
|
+
# If full, block briefly in thread to ensure delivery
|
|
1945
|
+
q.put(e)
|
|
1946
|
+
finally:
|
|
1947
|
+
# Signal completion
|
|
1948
|
+
try:
|
|
1949
|
+
q.put_nowait(sentinel)
|
|
1950
|
+
except queue.Full:
|
|
1951
|
+
q.put(sentinel)
|
|
1952
|
+
|
|
1953
|
+
# Start the producer without blocking
|
|
1954
|
+
AsyncRunner.submit(producer())
|
|
1955
|
+
|
|
1956
|
+
def iterator():
|
|
1957
|
+
try:
|
|
1958
|
+
while True:
|
|
1959
|
+
item = q.get()
|
|
1960
|
+
if item is sentinel:
|
|
1961
|
+
break
|
|
1962
|
+
if isinstance(item, Exception):
|
|
1963
|
+
raise item
|
|
1964
|
+
yield item
|
|
1965
|
+
finally:
|
|
1966
|
+
# Signal producer to stop; it will close the async generator promptly
|
|
1967
|
+
stop_flag["stop"] = True
|
|
1968
|
+
|
|
1969
|
+
return iterator()
|
|
File without changes
|
{dataroom_client-1.0.4.post12.dev0 → dataroom_client-1.0.5.post2.dev0}/dataroom_client/__init__.py
RENAMED
|
File without changes
|
{dataroom_client-1.0.4.post12.dev0 → dataroom_client-1.0.5.post2.dev0}/dataroom_client/counter.py
RENAMED
|
File without changes
|
{dataroom_client-1.0.4.post12.dev0 → dataroom_client-1.0.5.post2.dev0}/dataroom_client/loader.py
RENAMED
|
File without changes
|
|
File without changes
|