From 9b7a95d6e4e7f1bfc1b275652c212fdbfd234e83 Mon Sep 17 00:00:00 2001 From: Jon Michael Aanes Date: Wed, 2 Oct 2024 13:54:30 +0200 Subject: [PATCH] Support more custom field types --- favro_sync/favro_data_model.py | 16 +++++++++++----- favro_sync/favro_fuse.py | 13 ++++++++----- favro_sync/favro_markdown.py | 3 +++ test/test_client.py | 13 ++++++++++--- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/favro_sync/favro_data_model.py b/favro_sync/favro_data_model.py index 85c6874..e74e04d 100644 --- a/favro_sync/favro_data_model.py +++ b/favro_sync/favro_data_model.py @@ -173,7 +173,7 @@ class CustomFieldInfo: type=json['type'], name=json['name'], enabled=json['enabled'], - custom_field_items=[CustomFieldItem.from_json(f) for f in json['customFieldItems']], + custom_field_items=[CustomFieldItem.from_json(f) for f in json.get('customFieldItems', [])], ) @@ -181,17 +181,21 @@ class CustomFieldInfo: class CustomField: custom_field_id: CustomFieldId value: list[CustomFieldItemId] | CustomFieldItemId + color: str @staticmethod def from_json(json: dict[str, Any]) -> 'CustomField': - value = json['value'] - if isinstance(value, str): + value = json.get('value') + if value is None: + typed_value = [] + elif isinstance(value, str): typed_value = CustomFieldItemId(value) else: typed_value = [CustomFieldItemId(v) for v in value] return CustomField( custom_field_id = CustomFieldId(json['customFieldId']), value = typed_value, + color = json.get('color'), ) @@ -258,9 +262,11 @@ class Card: @staticmethod def from_json(json: dict[str, Any]) -> 'Card': + card_id = CardId(json['cardId']) + seq_id = SeqId(json['sequentialId']) return Card( - card_id=CardId(json['cardId']), - seq_id=SeqId(json['sequentialId']), + card_id=card_id, + seq_id=seq_id, common_id=CardCommonId(json['cardCommonId']), detailed_description=json.get('detailedDescription'), is_archived=json['archived'], diff --git a/favro_sync/favro_fuse.py b/favro_sync/favro_fuse.py index 05e83d2..96f0931 100644 --- a/favro_sync/favro_fuse.py +++ b/favro_sync/favro_fuse.py @@ -8,7 +8,7 @@ from logging import getLogger import fuse from .favro_client import FavroClient -from .favro_data_model import Card, SeqId, CustomFieldInfo, CustomFieldItemId +from .favro_data_model import Card, SeqId, CustomFieldInfo, CustomFieldItemId, CustomField from .favro_markdown import CardContents, CardFileFormatter logger = getLogger(__name__) @@ -58,18 +58,21 @@ class CardFileSystemItem(FileSystemItem): seq_id: SeqId -def to_custom_field_value(value: CustomFieldItemId | list[CustomFieldItemId], field_def: CustomFieldInfo) -> str: - if field_def.type == 'Single select': +def to_custom_field_value(custom_field: CustomField, field_def: CustomFieldInfo) -> str: + value: CustomFieldItemId | list[CustomFieldItemId] = custom_field.value + if field_def.type in {'Single select','Multiple select'}: items = [field_def.get_field_item(item_id) for item_id in value] items = [i for i in items if i] return items[0].name + if field_def.type in {'Color'}: + return custom_field.color assert False, 'Unknown type: ' + field_def.type def to_custom_fields(card: Card, favro_client: FavroClient) -> dict[str,str]: custom_fields = {} for field_assignment in card.custom_fields: field_def = favro_client.get_custom_field(field_assignment.custom_field_id) - custom_fields[field_def.name] = to_custom_field_value(field_assignment.value, field_def) + custom_fields[field_def.name] = to_custom_field_value(field_assignment, field_def) del field_assignment return custom_fields @@ -100,7 +103,7 @@ def to_card_contents(card: Card, favro_client: FavroClient) -> str: is_archived=card.is_archived, start_date=card.start_date, due_date=card.due_date, - custom_fields=to_custom_fields(card, favro_client) + custom_fields=to_custom_fields(card, favro_client), ) diff --git a/favro_sync/favro_markdown.py b/favro_sync/favro_markdown.py index 2974b4e..4b464ea 100644 --- a/favro_sync/favro_markdown.py +++ b/favro_sync/favro_markdown.py @@ -102,6 +102,8 @@ class CardFileFormatter: frontmatter_data[FM_KEY_DUE_DATE] = card.due_date if card.start_date is not None: frontmatter_data[FM_KEY_DUE_DATE] = card.start_date + if len(card.custom_fields) > 0: + frontmatter_data |= card.custom_fields # Card name ls = [] @@ -171,4 +173,5 @@ class CardFileFormatter: is_archived=is_archived, start_date=start_date, due_date=due_date, + custom_fields={}, # TODO ) diff --git a/test/test_client.py b/test/test_client.py index 2423842..0f2d034 100644 --- a/test/test_client.py +++ b/test/test_client.py @@ -1,5 +1,6 @@ import pytest +import requests_cache from favro_sync import secrets from favro_sync.favro_client import FavroClient, OrganizationId, SeqId @@ -36,22 +37,28 @@ def test_get_archived_card(): assert card.is_archived +@needs_secrets +def test_get_card_with_color_custom_field(): + client = create_client() + card = client.get_card(SeqId(8779)) + assert len(card.custom_fields) > 0 + + @needs_secrets def test_get_cards(): client = create_client() for card in client.get_cards(todo_list=True): assert_valid_card(card) - if card.seq_id == SeqId(8723): - assert card.is_archived - def create_client(): + session = requests_cache.CachedSession('output/test-http-cache.sqlite') return FavroClient( favro_org_id=OrganizationId(secrets.favro_org_id()), favro_username=secrets.favro_username(), favro_password=secrets.favro_password(), read_only=True, + session=session, )