dataroom-client 1.0.6.post79.dev0__tar.gz → 1.0.6.post200.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.6.post79.dev0 → dataroom_client-1.0.6.post200.dev0}/PKG-INFO +1 -1
- {dataroom_client-1.0.6.post79.dev0 → dataroom_client-1.0.6.post200.dev0}/dataroom_client/client.py +280 -0
- {dataroom_client-1.0.6.post79.dev0 → dataroom_client-1.0.6.post200.dev0}/pyproject.toml +1 -1
- {dataroom_client-1.0.6.post79.dev0 → dataroom_client-1.0.6.post200.dev0}/README.md +0 -0
- {dataroom_client-1.0.6.post79.dev0 → dataroom_client-1.0.6.post200.dev0}/dataroom_client/__init__.py +0 -0
- {dataroom_client-1.0.6.post79.dev0 → dataroom_client-1.0.6.post200.dev0}/dataroom_client/counter.py +0 -0
- {dataroom_client-1.0.6.post79.dev0 → dataroom_client-1.0.6.post200.dev0}/dataroom_client/loader.py +0 -0
- {dataroom_client-1.0.6.post79.dev0 → dataroom_client-1.0.6.post200.dev0}/dataroom_client/print_utils.py +0 -0
{dataroom_client-1.0.6.post79.dev0 → dataroom_client-1.0.6.post200.dev0}/dataroom_client/client.py
RENAMED
|
@@ -353,6 +353,10 @@ class DataRoomClient:
|
|
|
353
353
|
datasets__all: list = None,
|
|
354
354
|
datasets__ne_all: list = None,
|
|
355
355
|
datasets__empty: bool = None,
|
|
356
|
+
query: str = None,
|
|
357
|
+
group_ids: list[str] = None,
|
|
358
|
+
roles: list[str] = None,
|
|
359
|
+
group_type: str = None,
|
|
356
360
|
) -> list[dict]:
|
|
357
361
|
"""
|
|
358
362
|
Retrieves a paginated list of images, with optional filtering and field selection.
|
|
@@ -437,6 +441,10 @@ class DataRoomClient:
|
|
|
437
441
|
"datasets__all": ",".join(datasets__all) if datasets__all else None,
|
|
438
442
|
"datasets__ne_all": ",".join(datasets__ne_all) if datasets__ne_all else None,
|
|
439
443
|
"datasets__empty": datasets__empty,
|
|
444
|
+
"query": query,
|
|
445
|
+
"group_ids": ",".join(group_ids) if group_ids else None,
|
|
446
|
+
"roles": ",".join(roles) if roles else None,
|
|
447
|
+
"group_type": group_type,
|
|
440
448
|
}
|
|
441
449
|
),
|
|
442
450
|
headers=headers,
|
|
@@ -501,6 +509,7 @@ class DataRoomClient:
|
|
|
501
509
|
datasets__all: list = None,
|
|
502
510
|
datasets__ne_all: list = None,
|
|
503
511
|
datasets__empty: bool = None,
|
|
512
|
+
query: str = None,
|
|
504
513
|
) -> AsyncIterable[dict]:
|
|
505
514
|
"""
|
|
506
515
|
Retrieves an iterator of images, with optional filtering and field selection.
|
|
@@ -587,6 +596,7 @@ class DataRoomClient:
|
|
|
587
596
|
"datasets__all": ",".join(datasets__all) if datasets__all else None,
|
|
588
597
|
"datasets__ne_all": ",".join(datasets__ne_all) if datasets__ne_all else None,
|
|
589
598
|
"datasets__empty": datasets__empty,
|
|
599
|
+
"query": query,
|
|
590
600
|
}
|
|
591
601
|
),
|
|
592
602
|
headers=headers,
|
|
@@ -652,6 +662,7 @@ class DataRoomClient:
|
|
|
652
662
|
datasets__all: list = None,
|
|
653
663
|
datasets__ne_all: list = None,
|
|
654
664
|
datasets__empty: bool = None,
|
|
665
|
+
query: str = None,
|
|
655
666
|
) -> list[dict]:
|
|
656
667
|
"""
|
|
657
668
|
Get a list of random images.
|
|
@@ -741,6 +752,7 @@ class DataRoomClient:
|
|
|
741
752
|
"datasets__all": ",".join(datasets__all) if datasets__all else None,
|
|
742
753
|
"datasets__ne_all": ",".join(datasets__ne_all) if datasets__ne_all else None,
|
|
743
754
|
"datasets__empty": datasets__empty,
|
|
755
|
+
"query": query,
|
|
744
756
|
}
|
|
745
757
|
),
|
|
746
758
|
headers=headers,
|
|
@@ -797,6 +809,7 @@ class DataRoomClient:
|
|
|
797
809
|
datasets__all: list = None,
|
|
798
810
|
datasets__ne_all: list = None,
|
|
799
811
|
datasets__empty: bool = None,
|
|
812
|
+
query: str = None,
|
|
800
813
|
) -> int:
|
|
801
814
|
"""
|
|
802
815
|
Returns the total count of images based on the provided filters.
|
|
@@ -862,6 +875,7 @@ class DataRoomClient:
|
|
|
862
875
|
"datasets__all": ",".join(datasets__all) if datasets__all else None,
|
|
863
876
|
"datasets__ne_all": ",".join(datasets__ne_all) if datasets__ne_all else None,
|
|
864
877
|
"datasets__empty": datasets__empty,
|
|
878
|
+
"query": query,
|
|
865
879
|
}
|
|
866
880
|
),
|
|
867
881
|
)
|
|
@@ -1318,6 +1332,7 @@ class DataRoomClient:
|
|
|
1318
1332
|
datasets__all: list = None,
|
|
1319
1333
|
datasets__ne_all: list = None,
|
|
1320
1334
|
datasets__empty: bool = None,
|
|
1335
|
+
query: str = None,
|
|
1321
1336
|
) -> list[dict]:
|
|
1322
1337
|
"""
|
|
1323
1338
|
Finds images similar to a given image, vector, or text query.
|
|
@@ -1396,6 +1411,7 @@ class DataRoomClient:
|
|
|
1396
1411
|
"datasets__all": ",".join(datasets__all) if datasets__all else None,
|
|
1397
1412
|
"datasets__ne_all": ",".join(datasets__ne_all) if datasets__ne_all else None,
|
|
1398
1413
|
"datasets__empty": datasets__empty,
|
|
1414
|
+
"query": query,
|
|
1399
1415
|
})
|
|
1400
1416
|
|
|
1401
1417
|
if image_file:
|
|
@@ -1799,6 +1815,270 @@ class DataRoomClient:
|
|
|
1799
1815
|
method="DELETE",
|
|
1800
1816
|
)
|
|
1801
1817
|
|
|
1818
|
+
# ------------------------------------------------------------------
|
|
1819
|
+
# Roles, GroupTypes, Groups + memberships
|
|
1820
|
+
#
|
|
1821
|
+
# Setup flow when starting from an empty DB:
|
|
1822
|
+
# 1. ``create_role(name)`` for each allowed role
|
|
1823
|
+
# 2. ``create_group_type(name, roles=[{role, is_required}, ...])``
|
|
1824
|
+
# with admin credentials
|
|
1825
|
+
# 3. ``create_group(name, type=...)`` then ``replace_group(...)`` to
|
|
1826
|
+
# attach memberships
|
|
1827
|
+
# All four (Roles, GroupTypes, Groups, Memberships) are open to any
|
|
1828
|
+
# token-authenticated dataroom user.
|
|
1829
|
+
# Group ids are plain UUIDs in Postgres; the type is its own column.
|
|
1830
|
+
# Membership rows carry a canonical role plus free-form metadata.
|
|
1831
|
+
# ------------------------------------------------------------------
|
|
1832
|
+
async def get_roles(self, limit: int = 1000) -> list[dict]:
|
|
1833
|
+
"""Lists all roles."""
|
|
1834
|
+
return await self._make_paginated_request(url="roles/", limit=limit)
|
|
1835
|
+
|
|
1836
|
+
async def create_role(self, name: str, description: str = None) -> dict:
|
|
1837
|
+
"""Creates a role. Roles are referenced by name from GroupTypeRole rows."""
|
|
1838
|
+
payload = self._dict_filter_none({"name": name, "description": description})
|
|
1839
|
+
return await self._make_request(url="roles/", method="POST", json=payload)
|
|
1840
|
+
|
|
1841
|
+
async def delete_role(self, name: str) -> None:
|
|
1842
|
+
"""Deletes a role. Fails if any GroupTypeRole still references it."""
|
|
1843
|
+
return await self._make_request(url=f"roles/{name}/", method="DELETE")
|
|
1844
|
+
|
|
1845
|
+
async def get_group_types(self, limit: int = 1000) -> list[dict]:
|
|
1846
|
+
"""Lists all GroupTypes with their (role, is_required) pairs."""
|
|
1847
|
+
return await self._make_paginated_request(url="group-types/", limit=limit)
|
|
1848
|
+
|
|
1849
|
+
async def get_group_type(self, name: str) -> dict:
|
|
1850
|
+
"""Retrieves a single GroupType by name."""
|
|
1851
|
+
return await self._make_request(url=f"group-types/{name}/", method="GET")
|
|
1852
|
+
|
|
1853
|
+
async def create_group_type(
|
|
1854
|
+
self,
|
|
1855
|
+
name: str,
|
|
1856
|
+
roles: list[dict] = None,
|
|
1857
|
+
description: str = None,
|
|
1858
|
+
metadata_schema: dict = None,
|
|
1859
|
+
) -> dict:
|
|
1860
|
+
"""Creates a GroupType.
|
|
1861
|
+
|
|
1862
|
+
@param name: lowercase alphanumeric/underscore; doubles as the OS-encoding
|
|
1863
|
+
prefix (``<name>::<uuid>``).
|
|
1864
|
+
@param roles: list of ``{"role": <existing role name>, "is_required": bool}``.
|
|
1865
|
+
Roles must already exist — create them with ``create_role`` first.
|
|
1866
|
+
@param description: optional free-form description.
|
|
1867
|
+
@param metadata_schema: JSON Schema applied to ``Group.metadata`` for groups
|
|
1868
|
+
of this type.
|
|
1869
|
+
"""
|
|
1870
|
+
payload = self._dict_filter_none({
|
|
1871
|
+
"name": name,
|
|
1872
|
+
"description": description,
|
|
1873
|
+
"metadata_schema": metadata_schema,
|
|
1874
|
+
"roles": roles,
|
|
1875
|
+
})
|
|
1876
|
+
return await self._make_request(url="group-types/", method="POST", json=payload)
|
|
1877
|
+
|
|
1878
|
+
# No update_group_type: GroupTypes are immutable. A type's name is baked
|
|
1879
|
+
# into the OS encoding of its groups and its schema/roles gate their
|
|
1880
|
+
# validation, so the server rejects PUT/PATCH on group-types. Create a new
|
|
1881
|
+
# type (and migrate) instead.
|
|
1882
|
+
|
|
1883
|
+
async def delete_group_type(self, name: str) -> None:
|
|
1884
|
+
"""Deletes a GroupType. Fails if any Group of this type exists."""
|
|
1885
|
+
return await self._make_request(url=f"group-types/{name}/", method="DELETE")
|
|
1886
|
+
|
|
1887
|
+
async def get_groups(
|
|
1888
|
+
self,
|
|
1889
|
+
type: str = None,
|
|
1890
|
+
search: str = None,
|
|
1891
|
+
limit: int = 1000,
|
|
1892
|
+
) -> list[dict]:
|
|
1893
|
+
"""
|
|
1894
|
+
Lists groups, optionally filtered by type or text search on name/id.
|
|
1895
|
+
|
|
1896
|
+
@param type: Optional group type filter (a GroupType.name).
|
|
1897
|
+
@param search: Optional substring search over name and id.
|
|
1898
|
+
@param limit: Maximum number of groups to return.
|
|
1899
|
+
@return: List of group dicts.
|
|
1900
|
+
"""
|
|
1901
|
+
params = self._dict_filter_none({"type": type, "search": search})
|
|
1902
|
+
return await self._make_paginated_request(url="groups/", params=params, limit=limit)
|
|
1903
|
+
|
|
1904
|
+
async def get_group(self, group_id: str, include_members: bool = False) -> dict:
|
|
1905
|
+
"""
|
|
1906
|
+
Retrieves a single group by id.
|
|
1907
|
+
|
|
1908
|
+
@param group_id: Group UUID.
|
|
1909
|
+
@param include_members: When True, also fetch the group's memberships
|
|
1910
|
+
(a second request to the members endpoint, which is paginated and
|
|
1911
|
+
not part of the group representation) and attach them under a
|
|
1912
|
+
``members`` key as ``[{image_id, role, metadata}, ...]`` — the
|
|
1913
|
+
shape ``upsert_group`` accepts, so a fetched group round-trips
|
|
1914
|
+
without silently dropping members.
|
|
1915
|
+
@return: Group dict (with ``members`` when ``include_members``).
|
|
1916
|
+
"""
|
|
1917
|
+
group = await self._make_request(url=f"groups/{group_id}/", method="GET")
|
|
1918
|
+
if include_members:
|
|
1919
|
+
group["members"] = [
|
|
1920
|
+
{"image_id": m["image_id"], "role": m["role"], "metadata": m.get("metadata", {})}
|
|
1921
|
+
for m in await self.get_group_members(group_id)
|
|
1922
|
+
]
|
|
1923
|
+
return group
|
|
1924
|
+
|
|
1925
|
+
async def update_group(
|
|
1926
|
+
self,
|
|
1927
|
+
group_id: str,
|
|
1928
|
+
name: str = None,
|
|
1929
|
+
description: str = None,
|
|
1930
|
+
metadata: dict = None,
|
|
1931
|
+
cover_image_id: str = None,
|
|
1932
|
+
) -> dict:
|
|
1933
|
+
"""
|
|
1934
|
+
Partially updates a group. The `type` is immutable and cannot be changed.
|
|
1935
|
+
|
|
1936
|
+
@param group_id: Group UUID.
|
|
1937
|
+
@return: Updated group dict.
|
|
1938
|
+
"""
|
|
1939
|
+
payload = self._dict_filter_none({
|
|
1940
|
+
"name": name,
|
|
1941
|
+
"description": description,
|
|
1942
|
+
"metadata": metadata,
|
|
1943
|
+
"cover_image_id": cover_image_id,
|
|
1944
|
+
})
|
|
1945
|
+
return await self._make_request(
|
|
1946
|
+
url=f"groups/{group_id}/",
|
|
1947
|
+
method="PATCH",
|
|
1948
|
+
json=payload,
|
|
1949
|
+
)
|
|
1950
|
+
|
|
1951
|
+
async def delete_group(self, group_id: str) -> None:
|
|
1952
|
+
"""
|
|
1953
|
+
Soft-deletes a group and queues the OS scrub. The Postgres row is
|
|
1954
|
+
finalized by the reconciler once OS is clean.
|
|
1955
|
+
"""
|
|
1956
|
+
return await self._make_request(url=f"groups/{group_id}/", method="DELETE")
|
|
1957
|
+
|
|
1958
|
+
async def get_group_members(self, group_id: str, limit: int = 1000) -> list[dict]:
|
|
1959
|
+
"""
|
|
1960
|
+
Lists memberships of a group.
|
|
1961
|
+
|
|
1962
|
+
@return: List of {id, image_id, role, metadata, ...}.
|
|
1963
|
+
"""
|
|
1964
|
+
return await self._make_paginated_request(url=f"groups/{group_id}/members/", limit=limit)
|
|
1965
|
+
|
|
1966
|
+
async def upsert_group(
|
|
1967
|
+
self,
|
|
1968
|
+
name: str,
|
|
1969
|
+
type: str,
|
|
1970
|
+
metadata: dict = None,
|
|
1971
|
+
members: list[dict] = None,
|
|
1972
|
+
description: str = None,
|
|
1973
|
+
cover_image_id: str = None,
|
|
1974
|
+
group_id: str = None,
|
|
1975
|
+
) -> dict:
|
|
1976
|
+
"""Create-or-replace a group by name. One PUT round-trip in the common case.
|
|
1977
|
+
|
|
1978
|
+
Re-running the same call with the same ``name`` is idempotent: the client
|
|
1979
|
+
looks up an existing group with that name (or uses the explicit ``group_id``
|
|
1980
|
+
when supplied), and PUTs the whole ``{metadata, members}`` payload to its
|
|
1981
|
+
UUID. New groups get a fresh UUID4 generated client-side and committed via
|
|
1982
|
+
the same PUT. The server validates roles + metadata in one transaction.
|
|
1983
|
+
"""
|
|
1984
|
+
import uuid as _uuid
|
|
1985
|
+
|
|
1986
|
+
if group_id is None:
|
|
1987
|
+
matches = [g for g in await self.get_groups(search=name) if g['name'] == name]
|
|
1988
|
+
group_id = matches[0]['id'] if matches else str(_uuid.uuid4())
|
|
1989
|
+
|
|
1990
|
+
payload = self._dict_filter_none({
|
|
1991
|
+
"name": name,
|
|
1992
|
+
"type": type,
|
|
1993
|
+
"metadata": metadata if metadata is not None else {},
|
|
1994
|
+
"members": members if members is not None else [],
|
|
1995
|
+
"description": description,
|
|
1996
|
+
"cover_image_id": cover_image_id,
|
|
1997
|
+
})
|
|
1998
|
+
return await self._make_request(
|
|
1999
|
+
url=f"groups/{group_id}/",
|
|
2000
|
+
method="PUT",
|
|
2001
|
+
json=payload,
|
|
2002
|
+
)
|
|
2003
|
+
|
|
2004
|
+
async def get_image_groups(self, image_id: str) -> list[dict]:
|
|
2005
|
+
"""
|
|
2006
|
+
Lists all (non-deleted) groups this image is a member of, hydrated.
|
|
2007
|
+
|
|
2008
|
+
Each item: {group: {...}, role, metadata}.
|
|
2009
|
+
"""
|
|
2010
|
+
return await self._make_request(url=f"images/{image_id}/groups/", method="GET")
|
|
2011
|
+
|
|
2012
|
+
# -------------------- Query API methods --------------------
|
|
2013
|
+
|
|
2014
|
+
async def get_queries(self, limit: int = 1000) -> list[dict]:
|
|
2015
|
+
"""
|
|
2016
|
+
Retrieves a list of queries.
|
|
2017
|
+
|
|
2018
|
+
@param limit: The maximum number of queries to return.
|
|
2019
|
+
@return: A list of query dictionaries.
|
|
2020
|
+
"""
|
|
2021
|
+
return await self._make_paginated_request(
|
|
2022
|
+
url="queries/",
|
|
2023
|
+
limit=limit,
|
|
2024
|
+
)
|
|
2025
|
+
|
|
2026
|
+
async def get_query(self, slug: str) -> dict:
|
|
2027
|
+
"""
|
|
2028
|
+
Retrieves a single query by its slug.
|
|
2029
|
+
|
|
2030
|
+
@param slug: The identifier for the query (e.g., "my-query").
|
|
2031
|
+
@return: A dictionary representing the query.
|
|
2032
|
+
"""
|
|
2033
|
+
return await self._make_request(
|
|
2034
|
+
url=f"queries/{slug}/",
|
|
2035
|
+
)
|
|
2036
|
+
|
|
2037
|
+
async def create_query(self, slug: str, name: str, filters: dict, description: str | None = None) -> dict:
|
|
2038
|
+
"""
|
|
2039
|
+
Creates a new query.
|
|
2040
|
+
|
|
2041
|
+
@param slug: The identifier for the query (e.g., "my-query").
|
|
2042
|
+
@param name: The display name of the query.
|
|
2043
|
+
@param filters: The filters for the query.
|
|
2044
|
+
@param description: An optional description for the query.
|
|
2045
|
+
@return: A dictionary representing the newly created query.
|
|
2046
|
+
"""
|
|
2047
|
+
return await self._make_request(
|
|
2048
|
+
url="queries/",
|
|
2049
|
+
method="POST",
|
|
2050
|
+
json={
|
|
2051
|
+
"slug": slug,
|
|
2052
|
+
"name": name,
|
|
2053
|
+
"description": description if description else "",
|
|
2054
|
+
"filters": filters,
|
|
2055
|
+
},
|
|
2056
|
+
)
|
|
2057
|
+
|
|
2058
|
+
async def update_query(
|
|
2059
|
+
self, slug: str, name: str | None = None, description: str | None = None, filters: dict | None = None
|
|
2060
|
+
) -> dict:
|
|
2061
|
+
"""
|
|
2062
|
+
Updates a query.
|
|
2063
|
+
|
|
2064
|
+
@param slug: The identifier for the query (e.g., "my-query").
|
|
2065
|
+
@param name: The display name of the query.
|
|
2066
|
+
@param description: An optional description for the query.
|
|
2067
|
+
@param filters: The filters for the query.
|
|
2068
|
+
@return: A dictionary representing the updated query.
|
|
2069
|
+
"""
|
|
2070
|
+
return await self._make_request(
|
|
2071
|
+
url=f"queries/{slug}/",
|
|
2072
|
+
method="PUT",
|
|
2073
|
+
json=self._dict_filter_none(
|
|
2074
|
+
{
|
|
2075
|
+
"slug": slug,
|
|
2076
|
+
"name": name,
|
|
2077
|
+
"description": description,
|
|
2078
|
+
"filters": filters,
|
|
2079
|
+
}
|
|
2080
|
+
),
|
|
2081
|
+
)
|
|
1802
2082
|
|
|
1803
2083
|
|
|
1804
2084
|
class AsyncRunner:
|
|
File without changes
|
{dataroom_client-1.0.6.post79.dev0 → dataroom_client-1.0.6.post200.dev0}/dataroom_client/__init__.py
RENAMED
|
File without changes
|
{dataroom_client-1.0.6.post79.dev0 → dataroom_client-1.0.6.post200.dev0}/dataroom_client/counter.py
RENAMED
|
File without changes
|
{dataroom_client-1.0.6.post79.dev0 → dataroom_client-1.0.6.post200.dev0}/dataroom_client/loader.py
RENAMED
|
File without changes
|
|
File without changes
|