Standard project structure
This commit is contained in:
parent
e1952c3f66
commit
6faf6ce2a6
1
favro_sync/__init__.py
Normal file
1
favro_sync/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
|
35
favro_sync/__main__.py
Normal file
35
favro_sync/__main__.py
Normal file
|
@ -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()
|
58
favro_sync/favro_client.py
Normal file
58
favro_sync/favro_client.py
Normal file
|
@ -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?
|
75
test.py
75
test.py
|
@ -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)))
|
Loading…
Reference in New Issue
Block a user