From cca4dd575b24bcf4b824c6e6e27b53cd65af87a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Slettvold?= Date: Wed, 8 Mar 2023 18:00:10 +0100 Subject: [PATCH 01/11] Add return types to client functions. --- src/onepasswordconnectsdk/client.py | 43 +++++++++++++++-------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/src/onepasswordconnectsdk/client.py b/src/onepasswordconnectsdk/client.py index 4202ccf..bc381da 100644 --- a/src/onepasswordconnectsdk/client.py +++ b/src/onepasswordconnectsdk/client.py @@ -1,4 +1,5 @@ """Python Client for connecting to 1Password Connect""" +from typing import Dict, List, Union import httpx from httpx import HTTPError import json @@ -13,7 +14,7 @@ EnvironmentHostNotSetException, EnvironmentTokenNotSetException, ) -from onepasswordconnectsdk.models import Item, ItemVault +from onepasswordconnectsdk.models import File, Item, ItemVault, SummaryItem, Vault from onepasswordconnectsdk.models.constants import CONNECT_HOST_ENV_VARIABLE ENV_SERVICE_ACCOUNT_JWT_VARIABLE = "OP_CONNECT_TOKEN" @@ -23,23 +24,23 @@ class Client: """Python Client Class""" - def __init__(self, url: str, token: str): + def __init__(self, url: str, token: str) -> None: """Initialize client""" self.url = url self.token = token self.session = self.create_session(url, token) self.serializer = Serializer() - def create_session(self, url: str, token: str): + def create_session(self, url: str, token: str) -> httpx.Client: return httpx.Client(base_url=url, headers=self.build_headers(token)) - def build_headers(self, token: str): + def build_headers(self, token: str) -> Dict[str, str]: return build_headers(token) def __del__(self): self.session.close() - def get_file(self, file_id: str, item_id: str, vault_id: str): + def get_file(self, file_id: str, item_id: str, vault_id: str) -> File: url = PathBuilder().vaults(vault_id).items(item_id).files(file_id).build() response = self.build_request("GET", url) try: @@ -51,7 +52,7 @@ def get_file(self, file_id: str, item_id: str, vault_id: str): ) return self.serializer.deserialize(response.content, "File") - def get_files(self, item_id: str, vault_id: str): + def get_files(self, item_id: str, vault_id: str) -> List[File]: url = PathBuilder().vaults(vault_id).items(item_id).files().build() response = self.build_request("GET", url) try: @@ -63,7 +64,7 @@ def get_files(self, item_id: str, vault_id: str): ) return self.serializer.deserialize(response.content, "list[File]") - def get_file_content(self, file_id: str, item_id: str, vault_id: str, content_path: str = None): + def get_file_content(self, file_id: str, item_id: str, vault_id: str, content_path: str = None) -> Union[bytes, str]: url = content_path if content_path is None: url = PathBuilder().vaults(vault_id).items(item_id).files(file_id).content().build() @@ -77,7 +78,7 @@ def get_file_content(self, file_id: str, item_id: str, vault_id: str, content_pa ) return response.content - def download_file(self, file_id: str, item_id: str, vault_id: str, path: str): + def download_file(self, file_id: str, item_id: str, vault_id: str, path: str) -> None: file_object = self.get_file(file_id, item_id, vault_id) filename = file_object.name or "1password_item_file.txt" content = self.get_file_content(file_id, item_id, vault_id, file_object.content_path) @@ -87,7 +88,7 @@ def download_file(self, file_id: str, item_id: str, vault_id: str, path: str): file.write(content) file.close() - def get_item(self, item: str, vault: str): + def get_item(self, item: str, vault: str) -> Item: """Get a specific item Args: @@ -111,7 +112,7 @@ def get_item(self, item: str, vault: str): else: return self.get_item_by_title(item, vault_id) - def get_item_by_id(self, item_id: str, vault_id: str): + def get_item_by_id(self, item_id: str, vault_id: str) -> Item: """Get a specific item by uuid Args: @@ -136,7 +137,7 @@ def get_item_by_id(self, item_id: str, vault_id: str): ) return self.serializer.deserialize(response.content, "Item") - def get_item_by_title(self, title: str, vault_id: str): + def get_item_by_title(self, title: str, vault_id: str) -> Item: """Get a specific item by title Args: @@ -170,7 +171,7 @@ def get_item_by_title(self, title: str, vault_id: str): item_summary = self.serializer.deserialize(response.content, "list[SummaryItem]")[0] return self.get_item_by_id(item_summary.id, vault_id) - def get_items(self, vault_id: str, filter_query: str = None): + def get_items(self, vault_id: str, filter_query: str = None) -> list[SummaryItem]: """Returns a list of item summaries for the specified vault Args: @@ -200,7 +201,7 @@ def get_items(self, vault_id: str, filter_query: str = None): return self.serializer.deserialize(response.content, "list[SummaryItem]") - def delete_item(self, item_id: str, vault_id: str): + def delete_item(self, item_id: str, vault_id: str) -> None: """Deletes a specified item from a specified vault Args: @@ -221,7 +222,7 @@ def delete_item(self, item_id: str, vault_id: str): for {url} with message: {response.json().get('message')}" ) - def create_item(self, vault_id: str, item: Item): + def create_item(self, vault_id: str, item: Item) -> Item: """Creates an item at the specified vault Args: @@ -247,7 +248,7 @@ def create_item(self, vault_id: str, item: Item): ) return self.serializer.deserialize(response.content, "Item") - def update_item(self, item_uuid: str, vault_id: str, item: Item): + def update_item(self, item_uuid: str, vault_id: str, item: Item) -> Item: """Update the specified item at the specified vault. Args: @@ -276,7 +277,7 @@ def update_item(self, item_uuid: str, vault_id: str, item: Item): ) return self.serializer.deserialize(response.content, "Item") - def get_vault(self, vault_id: str): + def get_vault(self, vault_id: str) -> Vault: """Returns the vault with the given vault_id Args: @@ -301,7 +302,7 @@ def get_vault(self, vault_id: str): return self.serializer.deserialize(response.content, "Vault") - def get_vault_by_title(self, name: str): + def get_vault_by_title(self, name: str) -> Vault: """Returns the vault with the given name Args: @@ -333,7 +334,7 @@ def get_vault_by_title(self, name: str): return self.serializer.deserialize(response.content, "list[Vault]")[0] - def get_vaults(self): + def get_vaults(self) -> list[Vault]: """Returns all vaults for service account set in client Raises: @@ -355,7 +356,7 @@ def get_vaults(self): return self.serializer.deserialize(response.content, "list[Vault]") - def build_request(self, method: str, path: str, body=None): + def build_request(self, method: str, path: str, body=None) -> httpx.Response: """Builds a http request Parameters: method (str): The rest method to be used @@ -380,7 +381,7 @@ def sanitize_for_serialization(self, obj): return self.serializer.sanitize_for_serialization(obj) -def new_client(url: str, token: str, is_async: bool = False): +def new_client(url: str, token: str, is_async: bool = False) -> Union[AsyncClient, Client]: """Builds a new client for interacting with 1Password Connect Parameters: url: The url of the 1Password Connect API @@ -395,7 +396,7 @@ def new_client(url: str, token: str, is_async: bool = False): return Client(url, token) -def new_client_from_environment(url: str = None): +def new_client_from_environment(url: str = None) -> Union[AsyncClient, Client]: """Builds a new client for interacting with 1Password Connect using the OP_TOKEN environment variable From 487401c9c6cafc0cb496f506da6323393687d2bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Svae=20Slettvold?= Date: Sun, 8 Oct 2023 15:12:04 +0200 Subject: [PATCH 02/11] Deserialize requires string type. --- src/onepasswordconnectsdk/client.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/onepasswordconnectsdk/client.py b/src/onepasswordconnectsdk/client.py index bc381da..51d09c2 100644 --- a/src/onepasswordconnectsdk/client.py +++ b/src/onepasswordconnectsdk/client.py @@ -50,7 +50,7 @@ def get_file(self, file_id: str, item_id: str, vault_id: str) -> File: f"Unable to retrieve item. Received {response.status_code}\ for {url} with message: {response.json().get('message')}" ) - return self.serializer.deserialize(response.content, "File") + return self.deserialize(response.content, "File") def get_files(self, item_id: str, vault_id: str) -> List[File]: url = PathBuilder().vaults(vault_id).items(item_id).files().build() @@ -62,7 +62,10 @@ def get_files(self, item_id: str, vault_id: str) -> List[File]: f"Unable to retrieve item. Received {response.status_code}\ for {url} with message: {response.json().get('message')}" ) - return self.serializer.deserialize(response.content, "list[File]") + return self.deserialize(response.content, "list[File]") + + def get_file_content(self, file_id: str, item_id: str, vault_id: str, content_path: str = None) -> str: + url = content_path if content_path is not None else f"/v1/vaults/{vault_id}/items/{item_id}/files/{file_id}/content" def get_file_content(self, file_id: str, item_id: str, vault_id: str, content_path: str = None) -> Union[bytes, str]: url = content_path @@ -135,7 +138,7 @@ def get_item_by_id(self, item_id: str, vault_id: str) -> Item: f"Unable to retrieve item. Received {response.status_code}\ for {url} with message: {response.json().get('message')}" ) - return self.serializer.deserialize(response.content, "Item") + return self.deserialize(response.content, "Item") def get_item_by_title(self, title: str, vault_id: str) -> Item: """Get a specific item by title @@ -199,7 +202,7 @@ def get_items(self, vault_id: str, filter_query: str = None) -> list[SummaryItem for {url} with message: {response.json().get('message')}" ) - return self.serializer.deserialize(response.content, "list[SummaryItem]") + return self.deserialize(response.content, "list[SummaryItem]") def delete_item(self, item_id: str, vault_id: str) -> None: """Deletes a specified item from a specified vault @@ -246,7 +249,7 @@ def create_item(self, vault_id: str, item: Item) -> Item: f"Unable to post item. Received {response.status_code}\ for {url} with message: {response.json().get('message')}" ) - return self.serializer.deserialize(response.content, "Item") + return self.deserialize(response.content, "Item") def update_item(self, item_uuid: str, vault_id: str, item: Item) -> Item: """Update the specified item at the specified vault. @@ -275,7 +278,7 @@ def update_item(self, item_uuid: str, vault_id: str, item: Item) -> Item: f"Unable to post item. Received {response.status_code}\ for {url} with message: {response.json().get('message')}" ) - return self.serializer.deserialize(response.content, "Item") + return self.deserialize(response.content, "Item") def get_vault(self, vault_id: str) -> Vault: """Returns the vault with the given vault_id @@ -300,7 +303,7 @@ def get_vault(self, vault_id: str) -> Vault: for {url} with message {response.json().get('message')}" ) - return self.serializer.deserialize(response.content, "Vault") + return self.deserialize(response.content, "Vault") def get_vault_by_title(self, name: str) -> Vault: """Returns the vault with the given name @@ -354,7 +357,7 @@ def get_vaults(self) -> list[Vault]: for {url} with message {response.json().get('message')}" ) - return self.serializer.deserialize(response.content, "list[Vault]") + return self.deserialize(response.content, "list[Vault]") def build_request(self, method: str, path: str, body=None) -> httpx.Response: """Builds a http request From 9b7818d0ab3cfa74b63e795e37db9c31f1eae35d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Svae=20Slettvold?= Date: Sun, 8 Oct 2023 16:36:36 +0200 Subject: [PATCH 03/11] Some new functions to add return types for. A few changed types. --- src/onepasswordconnectsdk/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/onepasswordconnectsdk/client.py b/src/onepasswordconnectsdk/client.py index 51d09c2..e64908c 100644 --- a/src/onepasswordconnectsdk/client.py +++ b/src/onepasswordconnectsdk/client.py @@ -37,7 +37,7 @@ def create_session(self, url: str, token: str) -> httpx.Client: def build_headers(self, token: str) -> Dict[str, str]: return build_headers(token) - def __del__(self): + def __del__(self) -> None: self.session.close() def get_file(self, file_id: str, item_id: str, vault_id: str) -> File: From c4bbcb6771168a0a2be05109ef3d2741365062b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Svae=20Slettvold?= Date: Sun, 8 Oct 2023 16:41:01 +0200 Subject: [PATCH 04/11] Clean up the file a bit, import all models from the models module. --- src/onepasswordconnectsdk/client.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/onepasswordconnectsdk/client.py b/src/onepasswordconnectsdk/client.py index e64908c..7f83e94 100644 --- a/src/onepasswordconnectsdk/client.py +++ b/src/onepasswordconnectsdk/client.py @@ -117,7 +117,7 @@ def get_item(self, item: str, vault: str) -> Item: def get_item_by_id(self, item_id: str, vault_id: str) -> Item: """Get a specific item by uuid - + Args: item_id (str): The id of the item to be fetched vault_id (str): The id of the vault in which to get the item from @@ -142,7 +142,7 @@ def get_item_by_id(self, item_id: str, vault_id: str) -> Item: def get_item_by_title(self, title: str, vault_id: str) -> Item: """Get a specific item by title - + Args: title (str): The title of the item to be fetched vault_id (str): The id of the vault in which to get the item from @@ -307,10 +307,10 @@ def get_vault(self, vault_id: str) -> Vault: def get_vault_by_title(self, name: str) -> Vault: """Returns the vault with the given name - + Args: name (str): The name of the vault in which to fetch - + Raises: FailedToRetrieveVaultException: Thrown when a HTTP error is returned from the 1Password Connect API From 34bec97fa833d34b1156d2c4351808c5730b03f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Slettvold?= Date: Mon, 23 Oct 2023 19:53:30 +0200 Subject: [PATCH 05/11] After merge it can also return AsyncClient. Annotate init. Add bytes to get_file_content return types. --- src/onepasswordconnectsdk/client.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/onepasswordconnectsdk/client.py b/src/onepasswordconnectsdk/client.py index 7f83e94..97ba494 100644 --- a/src/onepasswordconnectsdk/client.py +++ b/src/onepasswordconnectsdk/client.py @@ -64,9 +64,6 @@ def get_files(self, item_id: str, vault_id: str) -> List[File]: ) return self.deserialize(response.content, "list[File]") - def get_file_content(self, file_id: str, item_id: str, vault_id: str, content_path: str = None) -> str: - url = content_path if content_path is not None else f"/v1/vaults/{vault_id}/items/{item_id}/files/{file_id}/content" - def get_file_content(self, file_id: str, item_id: str, vault_id: str, content_path: str = None) -> Union[bytes, str]: url = content_path if content_path is None: From 758f6fac74998bd832f9cec8c80748333aea8c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Slettvold?= Date: Mon, 23 Oct 2023 20:01:56 +0200 Subject: [PATCH 06/11] Add return types to AsyncClient. --- src/onepasswordconnectsdk/async_client.py | 38 +++++++++++------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/onepasswordconnectsdk/async_client.py b/src/onepasswordconnectsdk/async_client.py index 415924c..0f1cb81 100644 --- a/src/onepasswordconnectsdk/async_client.py +++ b/src/onepasswordconnectsdk/async_client.py @@ -10,29 +10,29 @@ FailedToRetrieveItemException, FailedToRetrieveVaultException, ) -from onepasswordconnectsdk.models import Item, ItemVault +from onepasswordconnectsdk.models import File, Item, ItemVault, SummaryItem, Vault class AsyncClient: """Python Async Client Class""" - def __init__(self, url: str, token: str): + def __init__(self, url: str, token: str) -> None: """Initialize async client""" self.url = url self.token = token self.session = self.create_session(url, token) self.serializer = Serializer() - def create_session(self, url: str, token: str): + def create_session(self, url: str, token: str) -> httpx.AsyncClient: return httpx.AsyncClient(base_url=url, headers=self.build_headers(token)) - def build_headers(self, token: str): + def build_headers(self, token: str) -> dict[str, str]: return build_headers(token) async def __aexit__(self): await self.session.aclose() - async def get_file(self, file_id: str, item_id: str, vault_id: str): + async def get_file(self, file_id: str, item_id: str, vault_id: str) -> File: url = PathBuilder().vaults(vault_id).items(item_id).files(file_id).build() response = await self.build_request("GET", url) try: @@ -44,7 +44,7 @@ async def get_file(self, file_id: str, item_id: str, vault_id: str): ) return self.serializer.deserialize(response.content, "File") - async def get_files(self, item_id: str, vault_id: str): + async def get_files(self, item_id: str, vault_id: str) -> list[File]: url = PathBuilder().vaults(vault_id).items(item_id).files().build() response = await self.build_request("GET", url) try: @@ -56,7 +56,7 @@ async def get_files(self, item_id: str, vault_id: str): ) return self.serializer.deserialize(response.content, "list[File]") - async def get_file_content(self, file_id: str, item_id: str, vault_id: str, content_path: str = None): + async def get_file_content(self, file_id: str, item_id: str, vault_id: str, content_path: str = None) -> bytes | str: url = content_path if content_path is None: url = PathBuilder().vaults(vault_id).items(item_id).files(file_id).content().build() @@ -71,7 +71,7 @@ async def get_file_content(self, file_id: str, item_id: str, vault_id: str, cont return response.content async def download_file(self, file_id: str, item_id: str, vault_id: str, path: str): - file_object = await self.get_file(file_id, item_id, vault_id) + file_object = await self.get_file(file_id, item_id, vault_id) filename = file_object.name or "1password_item_file.txt" content = await self.get_file_content(file_id, item_id, vault_id, file_object.content_path) global_path = os.path.join(path, filename) @@ -80,7 +80,7 @@ async def download_file(self, file_id: str, item_id: str, vault_id: str, path: s file.write(content) file.close() - async def get_item(self, item: str, vault: str): + async def get_item(self, item: str, vault: str) -> Item: """Get a specific item Args: @@ -105,7 +105,7 @@ async def get_item(self, item: str, vault: str): else: return await self.get_item_by_title(item, vault_id) - async def get_item_by_id(self, item_id: str, vault_id: str): + async def get_item_by_id(self, item_id: str, vault_id: str) -> Item: """Get a specific item by uuid Args: @@ -130,7 +130,7 @@ async def get_item_by_id(self, item_id: str, vault_id: str): ) return self.serializer.deserialize(response.content, "Item") - async def get_item_by_title(self, title: str, vault_id: str): + async def get_item_by_title(self, title: str, vault_id: str) -> Item: """Get a specific item by title Args: @@ -164,7 +164,7 @@ async def get_item_by_title(self, title: str, vault_id: str): item_summary = self.serializer.deserialize(response.content, "list[SummaryItem]")[0] return await self.get_item_by_id(item_summary.id, vault_id) - async def get_items(self, vault_id: str, filter_query: str = None): + async def get_items(self, vault_id: str, filter_query: str = None) -> list[SummaryItem]: """Returns a list of item summaries for the specified vault Args: @@ -192,7 +192,7 @@ async def get_items(self, vault_id: str, filter_query: str = None): return self.serializer.deserialize(response.content, "list[SummaryItem]") - async def delete_item(self, item_id: str, vault_id: str): + async def delete_item(self, item_id: str, vault_id: str) -> None: """Deletes a specified item from a specified vault Args: @@ -214,7 +214,7 @@ async def delete_item(self, item_id: str, vault_id: str): for {url} with message: {response.json().get('message')}" ) - async def create_item(self, vault_id: str, item: Item): + async def create_item(self, vault_id: str, item: Item) -> Item: """Creates an item at the specified vault Args: @@ -240,7 +240,7 @@ async def create_item(self, vault_id: str, item: Item): ) return self.serializer.deserialize(response.content, "Item") - async def update_item(self, item_uuid: str, vault_id: str, item: Item): + async def update_item(self, item_uuid: str, vault_id: str, item: Item) -> Item: """Update the specified item at the specified vault. Args: @@ -269,7 +269,7 @@ async def update_item(self, item_uuid: str, vault_id: str, item: Item): ) return self.serializer.deserialize(response.content, "Item") - async def get_vault(self, vault_id: str): + async def get_vault(self, vault_id: str) -> Vault: """Returns the vault with the given vault_id Args: @@ -294,7 +294,7 @@ async def get_vault(self, vault_id: str): return self.serializer.deserialize(response.content, "Vault") - async def get_vault_by_title(self, name: str): + async def get_vault_by_title(self, name: str) -> Vault: """Returns the vault with the given name Args: @@ -326,7 +326,7 @@ async def get_vault_by_title(self, name: str): return self.serializer.deserialize(response.content, "list[Vault]")[0] - async def get_vaults(self): + async def get_vaults(self) -> list[Vault]: """Returns all vaults for service account set in client Raises: @@ -348,7 +348,7 @@ async def get_vaults(self): return self.serializer.deserialize(response.content, "list[Vault]") - def build_request(self, method: str, path: str, body=None): + def build_request(self, method: str, path: str, body=None) -> httpx.Response: """Builds a http request Parameters: method (str): The rest method to be used From add71cb8b5ef7c8c8fe6469648f6cb6208058db4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Slettvold?= Date: Mon, 23 Oct 2023 22:30:45 +0200 Subject: [PATCH 07/11] Add return type none to downliad_file. --- src/onepasswordconnectsdk/async_client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/onepasswordconnectsdk/async_client.py b/src/onepasswordconnectsdk/async_client.py index 0f1cb81..a44e154 100644 --- a/src/onepasswordconnectsdk/async_client.py +++ b/src/onepasswordconnectsdk/async_client.py @@ -70,8 +70,8 @@ async def get_file_content(self, file_id: str, item_id: str, vault_id: str, cont ) return response.content - async def download_file(self, file_id: str, item_id: str, vault_id: str, path: str): - file_object = await self.get_file(file_id, item_id, vault_id) + async def download_file(self, file_id: str, item_id: str, vault_id: str, path: str) -> None: + file_object = await self.get_file(file_id, item_id, vault_id) filename = file_object.name or "1password_item_file.txt" content = await self.get_file_content(file_id, item_id, vault_id, file_object.content_path) global_path = os.path.join(path, filename) From e737fab5613c60fdf7b274a3f8d6826d4659f202 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Slettvold?= Date: Tue, 24 Oct 2023 01:23:09 +0200 Subject: [PATCH 08/11] Use older style type annotations for lists and dicts. --- src/onepasswordconnectsdk/async_client.py | 9 +++++---- src/onepasswordconnectsdk/client.py | 5 +++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/onepasswordconnectsdk/async_client.py b/src/onepasswordconnectsdk/async_client.py index a44e154..4dd5467 100644 --- a/src/onepasswordconnectsdk/async_client.py +++ b/src/onepasswordconnectsdk/async_client.py @@ -2,6 +2,7 @@ import httpx from httpx import HTTPError import json +from typing import Dict, List import os from onepasswordconnectsdk.serializer import Serializer @@ -26,7 +27,7 @@ def __init__(self, url: str, token: str) -> None: def create_session(self, url: str, token: str) -> httpx.AsyncClient: return httpx.AsyncClient(base_url=url, headers=self.build_headers(token)) - def build_headers(self, token: str) -> dict[str, str]: + def build_headers(self, token: str) -> Dict[str, str]: return build_headers(token) async def __aexit__(self): @@ -44,7 +45,7 @@ async def get_file(self, file_id: str, item_id: str, vault_id: str) -> File: ) return self.serializer.deserialize(response.content, "File") - async def get_files(self, item_id: str, vault_id: str) -> list[File]: + async def get_files(self, item_id: str, vault_id: str) -> List[File]: url = PathBuilder().vaults(vault_id).items(item_id).files().build() response = await self.build_request("GET", url) try: @@ -164,7 +165,7 @@ async def get_item_by_title(self, title: str, vault_id: str) -> Item: item_summary = self.serializer.deserialize(response.content, "list[SummaryItem]")[0] return await self.get_item_by_id(item_summary.id, vault_id) - async def get_items(self, vault_id: str, filter_query: str = None) -> list[SummaryItem]: + async def get_items(self, vault_id: str, filter_query: str = None) -> List[SummaryItem]: """Returns a list of item summaries for the specified vault Args: @@ -326,7 +327,7 @@ async def get_vault_by_title(self, name: str) -> Vault: return self.serializer.deserialize(response.content, "list[Vault]")[0] - async def get_vaults(self) -> list[Vault]: + async def get_vaults(self) -> List[Vault]: """Returns all vaults for service account set in client Raises: diff --git a/src/onepasswordconnectsdk/client.py b/src/onepasswordconnectsdk/client.py index 97ba494..ea2cbba 100644 --- a/src/onepasswordconnectsdk/client.py +++ b/src/onepasswordconnectsdk/client.py @@ -3,6 +3,7 @@ import httpx from httpx import HTTPError import json +from typing import Dict, List import os from onepasswordconnectsdk.async_client import AsyncClient @@ -171,7 +172,7 @@ def get_item_by_title(self, title: str, vault_id: str) -> Item: item_summary = self.serializer.deserialize(response.content, "list[SummaryItem]")[0] return self.get_item_by_id(item_summary.id, vault_id) - def get_items(self, vault_id: str, filter_query: str = None) -> list[SummaryItem]: + def get_items(self, vault_id: str, filter_query: str = None) -> List[SummaryItem]: """Returns a list of item summaries for the specified vault Args: @@ -334,7 +335,7 @@ def get_vault_by_title(self, name: str) -> Vault: return self.serializer.deserialize(response.content, "list[Vault]")[0] - def get_vaults(self) -> list[Vault]: + def get_vaults(self) -> List[Vault]: """Returns all vaults for service account set in client Raises: From 15a8f05e4c2198dba8a345564175d242e8060a4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Slettvold?= Date: Tue, 24 Oct 2023 16:38:38 +0200 Subject: [PATCH 09/11] Need to use Union for mixed return types. --- src/onepasswordconnectsdk/async_client.py | 4 ++-- src/onepasswordconnectsdk/client.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/onepasswordconnectsdk/async_client.py b/src/onepasswordconnectsdk/async_client.py index 4dd5467..7df6ad1 100644 --- a/src/onepasswordconnectsdk/async_client.py +++ b/src/onepasswordconnectsdk/async_client.py @@ -2,7 +2,7 @@ import httpx from httpx import HTTPError import json -from typing import Dict, List +from typing import Dict, List, Union import os from onepasswordconnectsdk.serializer import Serializer @@ -57,7 +57,7 @@ async def get_files(self, item_id: str, vault_id: str) -> List[File]: ) return self.serializer.deserialize(response.content, "list[File]") - async def get_file_content(self, file_id: str, item_id: str, vault_id: str, content_path: str = None) -> bytes | str: + async def get_file_content(self, file_id: str, item_id: str, vault_id: str, content_path: str = None) -> Union[bytes, str]: url = content_path if content_path is None: url = PathBuilder().vaults(vault_id).items(item_id).files(file_id).content().build() diff --git a/src/onepasswordconnectsdk/client.py b/src/onepasswordconnectsdk/client.py index ea2cbba..1f83de8 100644 --- a/src/onepasswordconnectsdk/client.py +++ b/src/onepasswordconnectsdk/client.py @@ -3,7 +3,7 @@ import httpx from httpx import HTTPError import json -from typing import Dict, List +from typing import Dict, List, Union import os from onepasswordconnectsdk.async_client import AsyncClient From 094116e1ded4814c1bb98e31431f9fc56bae8ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Slettvold?= Date: Tue, 24 Oct 2023 19:09:59 +0200 Subject: [PATCH 10/11] An import had snuck in twice in rebase. --- src/onepasswordconnectsdk/client.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/onepasswordconnectsdk/client.py b/src/onepasswordconnectsdk/client.py index 1f83de8..140ccca 100644 --- a/src/onepasswordconnectsdk/client.py +++ b/src/onepasswordconnectsdk/client.py @@ -1,5 +1,4 @@ """Python Client for connecting to 1Password Connect""" -from typing import Dict, List, Union import httpx from httpx import HTTPError import json From 1390c2324ac51ff82e16a88388a4b5614c6ed989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Slettvold?= Date: Tue, 24 Oct 2023 23:47:52 +0200 Subject: [PATCH 11/11] Use self.serializer.deserialize instead of self.deserialize. --- src/onepasswordconnectsdk/client.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/onepasswordconnectsdk/client.py b/src/onepasswordconnectsdk/client.py index 140ccca..a62bae1 100644 --- a/src/onepasswordconnectsdk/client.py +++ b/src/onepasswordconnectsdk/client.py @@ -50,7 +50,7 @@ def get_file(self, file_id: str, item_id: str, vault_id: str) -> File: f"Unable to retrieve item. Received {response.status_code}\ for {url} with message: {response.json().get('message')}" ) - return self.deserialize(response.content, "File") + return self.serializer.deserialize(response.content, "File") def get_files(self, item_id: str, vault_id: str) -> List[File]: url = PathBuilder().vaults(vault_id).items(item_id).files().build() @@ -62,7 +62,7 @@ def get_files(self, item_id: str, vault_id: str) -> List[File]: f"Unable to retrieve item. Received {response.status_code}\ for {url} with message: {response.json().get('message')}" ) - return self.deserialize(response.content, "list[File]") + return self.serializer.deserialize(response.content, "list[File]") def get_file_content(self, file_id: str, item_id: str, vault_id: str, content_path: str = None) -> Union[bytes, str]: url = content_path @@ -135,7 +135,7 @@ def get_item_by_id(self, item_id: str, vault_id: str) -> Item: f"Unable to retrieve item. Received {response.status_code}\ for {url} with message: {response.json().get('message')}" ) - return self.deserialize(response.content, "Item") + return self.serializer.deserialize(response.content, "Item") def get_item_by_title(self, title: str, vault_id: str) -> Item: """Get a specific item by title @@ -199,7 +199,7 @@ def get_items(self, vault_id: str, filter_query: str = None) -> List[SummaryItem for {url} with message: {response.json().get('message')}" ) - return self.deserialize(response.content, "list[SummaryItem]") + return self.serializer.deserialize(response.content, "list[SummaryItem]") def delete_item(self, item_id: str, vault_id: str) -> None: """Deletes a specified item from a specified vault @@ -246,7 +246,7 @@ def create_item(self, vault_id: str, item: Item) -> Item: f"Unable to post item. Received {response.status_code}\ for {url} with message: {response.json().get('message')}" ) - return self.deserialize(response.content, "Item") + return self.serializer.deserialize(response.content, "Item") def update_item(self, item_uuid: str, vault_id: str, item: Item) -> Item: """Update the specified item at the specified vault. @@ -275,7 +275,7 @@ def update_item(self, item_uuid: str, vault_id: str, item: Item) -> Item: f"Unable to post item. Received {response.status_code}\ for {url} with message: {response.json().get('message')}" ) - return self.deserialize(response.content, "Item") + return self.serializer.deserialize(response.content, "Item") def get_vault(self, vault_id: str) -> Vault: """Returns the vault with the given vault_id @@ -300,7 +300,7 @@ def get_vault(self, vault_id: str) -> Vault: for {url} with message {response.json().get('message')}" ) - return self.deserialize(response.content, "Vault") + return self.serializer.deserialize(response.content, "Vault") def get_vault_by_title(self, name: str) -> Vault: """Returns the vault with the given name @@ -354,7 +354,7 @@ def get_vaults(self) -> List[Vault]: for {url} with message {response.json().get('message')}" ) - return self.deserialize(response.content, "list[Vault]") + return self.serializer.deserialize(response.content, "list[Vault]") def build_request(self, method: str, path: str, body=None) -> httpx.Response: """Builds a http request