From 6faf6ce2a611cda77db924b013ea2fc4adad0f3f Mon Sep 17 00:00:00 2001 From: Jon Michael Aanes Date: Thu, 26 Sep 2024 16:43:30 +0200 Subject: [PATCH] Standard project structure --- README.md | 3 ++ favro_sync/__init__.py | 1 + favro_sync/__main__.py | 35 ++++++++++++++++++ favro_sync/favro_client.py | 58 +++++++++++++++++++++++++++++ test.py | 75 -------------------------------------- 5 files changed, 97 insertions(+), 75 deletions(-) create mode 100644 README.md create mode 100644 favro_sync/__init__.py create mode 100644 favro_sync/__main__.py create mode 100644 favro_sync/favro_client.py delete mode 100644 test.py diff --git a/README.md b/README.md new file mode 100644 index 0000000..918847d --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ + +TODO: Hook into repo-manager. + diff --git a/favro_sync/__init__.py b/favro_sync/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/favro_sync/__init__.py @@ -0,0 +1 @@ + diff --git a/favro_sync/__main__.py b/favro_sync/__main__.py new file mode 100644 index 0000000..deb8c16 --- /dev/null +++ b/favro_sync/__main__.py @@ -0,0 +1,35 @@ +import secret_loader + +from .favro_client import FavroClient + +# Authentication + + +description = ''' +I cannot remember what this card involved + +# Tasks + +- [ ] Why doesn't task work? +- [ ] Task 2 + +# Quotes + + I love this card. +''' + +def main(card_id: CardId): + + +def main(): + secrets = secret_loader.SecretLoader() + FAVRO_ORG_ID = secrets.load_or_fail('FAVRO_ORGANIZATION_ID') + FAVRO_USERNAME = secrets.load_or_fail('FAVRO_USERNAME') + FAVRO_PASSWORD = secrets.load_or_fail('FAVRO_PASSWORD') + + client = FavroClient(FAVRO_ORG_ID, FAVRO_USERNAME, FAVRO_PASSWORD) + card_id = client.get_card_id(SeqId(4714)) + client.update_card_description(card_id, description) + +if __name__ == '__main__': + main() diff --git a/favro_sync/favro_client.py b/favro_sync/favro_client.py new file mode 100644 index 0000000..be7cd8e --- /dev/null +++ b/favro_sync/favro_client.py @@ -0,0 +1,58 @@ +import requests +import dataclasses +from typing import Any +import functools + +# Types + +@dataclasses.dataclass(frozen=True) +class SeqId: + raw_id: int + +@dataclasses.dataclass(frozen=True) +class CardId: + raw_id: str + +# Endpoints +URL_API_ROOT = 'https://favro.com/api/v1' +URL_GET_ALL_CARDS = URL_API_ROOT+'/cards' +URL_UPDATE_CARD = URL_API_ROOT+'/cards/{card_id}' + +class FavroClient: + + def __init__(*, favro_org_id: str, favro_username: str, favro_password: str, + session: requests.Session | None = None): + # Setup session + self.session = session or requests.Session() + self.session.auth = (favro_username, favro_username) + self.session.headers.update({ + 'organizationId': favro_org_id, + 'content-type': 'application/json', + }) + + + def get_card_json(seqid: SeqId) -> dict[str, Any]: + # TODO: Return structured? + + params = {'cardSequentialId': seqid.raw_id} + response = self.session.get(URL_GET_ALL_CARDS, params = params) + response.raise_for_status() + json = response.json() + assert json['pages'] == 1 + assert len(json['entities']) == 1 + return json['entities'][0] + + @functools.cache + def get_card_id(seqid: SeqId) -> CardId: + json = get_card_json(seqid) + return CardId(json['cardId']) + + def update_card_description(card_id: CardId, description: str): + json_body = { + 'detailedDescription': description, + 'descriptionFormat': 'markdown', + } + + response = SESSION.put(URL_UPDATE_CARD.format(card_id=card_id.raw_id), json=json_body) + response.raise_for_status() + # TODO: Return updated? diff --git a/test.py b/test.py deleted file mode 100644 index a9fc6a6..0000000 --- a/test.py +++ /dev/null @@ -1,75 +0,0 @@ -import requests -import secret_loader -from typing import Any -import functools -import dataclasses - -URL_API_ROOT = 'https://favro.com/api/v1' -URL_GET_ALL_CARDS = URL_API_ROOT+'/cards' -URL_UPDATE_CARD = URL_API_ROOT+'/cards/{card_id}' - -# Types - -@dataclasses.dataclass(frozen=True) -class SeqId: - raw_id: int - -@dataclasses.dataclass(frozen=True) -class CardId: - raw_id: str - - -# Authentication - -secrets = secret_loader.SecretLoader() -FAVRO_ORG_ID = secrets.load_or_fail('FAVRO_ORGANIZATION_ID') -FAVRO_USERNAME = secrets.load_or_fail('FAVRO_USERNAME') -FAVRO_PASSWORD = secrets.load_or_fail('FAVRO_PASSWORD') - -headers = { - 'organizationId': FAVRO_ORG_ID, - 'content-type': 'application/json', -} - -SESSION = requests.Session() - -def get_card_json(seqid: SeqId) -> dict[str, Any]: - params = {'cardSequentialId': seqid.raw_id} - response = SESSION.get(URL_GET_ALL_CARDS, headers=headers, auth=(FAVRO_USERNAME, FAVRO_PASSWORD), params = params) - response.raise_for_status() - json = response.json() - assert json['pages'] == 1 - assert len(json['entities']) == 1 - return json['entities'][0] - -@functools.cache -def get_card_id(seqid: SeqId) -> CardId: - json = get_card_json(seqid) - return CardId(json['cardId']) - -description = ''' -I cannot remember what this card involved - -# Tasks - -- [ ] Why doesn't task work? -- [ ] Task 2 - -# Quotes - - I love this card. -''' - -def main(card_id: CardId): - - json_body = { - 'detailedDescription': description, - 'descriptionFormat': 'markdown', - } - - response = SESSION.put(URL_UPDATE_CARD.format(card_id=card_id.raw_id), - json=json_body, headers=headers, auth=(FAVRO_USERNAME, FAVRO_PASSWORD)) - response.raise_for_status() - -if __name__ == '__main__': - main(get_card_id(SeqId(4714)))