parent
3e5b4cd7b8
commit
f448ee5eb8
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
Implements methods for interacting with the [Favro API](https://favro.com/developer/).
|
Implements methods for interacting with the [Favro API](https://favro.com/developer/).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import dataclasses
|
import dataclasses
|
||||||
from collections.abc import Iterator
|
from collections.abc import Iterator
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
@ -156,22 +157,26 @@ class FavroClient:
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_card_contents_locally(
|
def update_card_contents_locally(
|
||||||
self, card_id: CardId, card_contents: CardContents,
|
self,
|
||||||
|
card_id: CardId,
|
||||||
|
card_contents: CardContents,
|
||||||
) -> Card | None:
|
) -> Card | None:
|
||||||
if card := self.cache.remove(card_id):
|
if card := self.cache.remove(card_id):
|
||||||
card = dataclasses.replace(
|
card = dataclasses.replace(
|
||||||
card,
|
card,
|
||||||
detailed_description=card_contents.description,
|
detailed_description=card_contents.description,
|
||||||
name=card_contents.name,
|
name=card_contents.name,
|
||||||
tags=[], # TODO?
|
tags=[], # TODO?
|
||||||
assignments=[], # TODO?
|
assignments=[], # TODO?
|
||||||
dependencies=[], # TODO
|
dependencies=[], # TODO
|
||||||
)
|
)
|
||||||
self.cache.add_card(card)
|
self.cache.add_card(card)
|
||||||
return card
|
return card
|
||||||
|
|
||||||
def update_card_contents(
|
def update_card_contents(
|
||||||
self, card_id: CardId, card_contents: CardContents,
|
self,
|
||||||
|
card_id: CardId,
|
||||||
|
card_contents: CardContents,
|
||||||
) -> Card | None:
|
) -> Card | None:
|
||||||
"""Returns updated Card."""
|
"""Returns updated Card."""
|
||||||
if self.read_only == 'silent':
|
if self.read_only == 'silent':
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
Based on the descriptions on the [Favro API Specification
|
Based on the descriptions on the [Favro API Specification
|
||||||
Page](https://favro.com/developer/), and observed behaviour.
|
Page](https://favro.com/developer/), and observed behaviour.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import datetime
|
import datetime
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
@ -93,13 +94,13 @@ class TagInfo:
|
||||||
@dataclasses.dataclass(frozen=True)
|
@dataclasses.dataclass(frozen=True)
|
||||||
class CustomField:
|
class CustomField:
|
||||||
custom_field_id: CustomFieldId
|
custom_field_id: CustomFieldId
|
||||||
value: list[str] # TODO
|
value: list[str] # TODO
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(json: dict[str, Any]) -> 'CustomField':
|
def from_json(json: dict[str, Any]) -> 'CustomField':
|
||||||
return CustomField(
|
return CustomField(
|
||||||
CustomFieldId(json['customFieldId']),
|
CustomFieldId(json['customFieldId']),
|
||||||
json['value'], # TODO
|
json['value'], # TODO
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -154,11 +155,15 @@ class Card:
|
||||||
name=json['name'],
|
name=json['name'],
|
||||||
todo_list_user_id=todo_list_user_id,
|
todo_list_user_id=todo_list_user_id,
|
||||||
todo_list_completed=json.get('todoListCompleted'),
|
todo_list_completed=json.get('todoListCompleted'),
|
||||||
dependencies=[CardDependency.from_json(dep) for dep in json['dependencies']],
|
dependencies=[
|
||||||
|
CardDependency.from_json(dep) for dep in json['dependencies']
|
||||||
|
],
|
||||||
tags=[TagId(tag) for tag in json['tags']],
|
tags=[TagId(tag) for tag in json['tags']],
|
||||||
creator_user_id=UserId(json['createdByUserId']),
|
creator_user_id=UserId(json['createdByUserId']),
|
||||||
creation_date=datetime.datetime.fromisoformat(json['createdAt']),
|
creation_date=datetime.datetime.fromisoformat(json['createdAt']),
|
||||||
assignments=[CardAssignment.from_json(ass) for ass in json['assignments']],
|
assignments=[CardAssignment.from_json(ass) for ass in json['assignments']],
|
||||||
custom_fields=[CustomField.from_json(field) for field in json['customFields']],
|
custom_fields=[
|
||||||
attachments=json['attachments'], # TODO
|
CustomField.from_json(field) for field in json['customFields']
|
||||||
|
],
|
||||||
|
attachments=json['attachments'], # TODO
|
||||||
)
|
)
|
||||||
|
|
|
@ -59,7 +59,10 @@ class FavroFuse(fuse.Fuse):
|
||||||
"""Favro Filesystem in Userspace."""
|
"""Favro Filesystem in Userspace."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, favro_client: FavroClient, formatter: CardFileFormatter, **kwargs,
|
self,
|
||||||
|
favro_client: FavroClient,
|
||||||
|
formatter: CardFileFormatter,
|
||||||
|
**kwargs,
|
||||||
):
|
):
|
||||||
self.favro_client = favro_client
|
self.favro_client = favro_client
|
||||||
self.formatter = formatter
|
self.formatter = formatter
|
||||||
|
@ -169,8 +172,11 @@ class FavroFuse(fuse.Fuse):
|
||||||
for assignment in card.assignments
|
for assignment in card.assignments
|
||||||
]
|
]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
CARD_FILENAME_FORMAT.format(seq_id=self.favro_client.get_card_by_card_id(dep.card_id).seq_id.raw_id)
|
CARD_FILENAME_FORMAT.format(
|
||||||
for dep in card.dependencies if dep.is_before
|
seq_id=self.favro_client.get_card_by_card_id(dep.card_id).seq_id.raw_id
|
||||||
|
)
|
||||||
|
for dep in card.dependencies
|
||||||
|
if dep.is_before
|
||||||
]
|
]
|
||||||
card_contents = CardContents(
|
card_contents = CardContents(
|
||||||
card.name,
|
card.name,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import dataclasses
|
import dataclasses
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
import frontmatter
|
import frontmatter
|
||||||
import marko
|
import marko
|
||||||
import marko.md_renderer
|
import marko.md_renderer
|
||||||
|
@ -18,6 +18,7 @@ class CardContents:
|
||||||
def format_obsidian_link(text: str) -> str:
|
def format_obsidian_link(text: str) -> str:
|
||||||
return f'"[[{text}]]"'
|
return f'"[[{text}]]"'
|
||||||
|
|
||||||
|
|
||||||
def parse_obsidian_link(text: str) -> str:
|
def parse_obsidian_link(text: str) -> str:
|
||||||
if m := re.match(r'^\[\[(.*)\]\]$', text):
|
if m := re.match(r'^\[\[(.*)\]\]$', text):
|
||||||
return m.group(1)
|
return m.group(1)
|
||||||
|
@ -45,13 +46,15 @@ class CardFileFormatter:
|
||||||
frontmatter_data['assignments'] = card.assignments
|
frontmatter_data['assignments'] = card.assignments
|
||||||
if self.obsidian_mode:
|
if self.obsidian_mode:
|
||||||
frontmatter_data['assignments'] = [
|
frontmatter_data['assignments'] = [
|
||||||
format_obsidian_link(name) for name in frontmatter_data['assignments']
|
format_obsidian_link(name)
|
||||||
|
for name in frontmatter_data['assignments']
|
||||||
]
|
]
|
||||||
if card.card_dependencies:
|
if card.card_dependencies:
|
||||||
frontmatter_data['dependencies'] = card.card_dependencies
|
frontmatter_data['dependencies'] = card.card_dependencies
|
||||||
if self.obsidian_mode:
|
if self.obsidian_mode:
|
||||||
frontmatter_data['dependencies'] = [
|
frontmatter_data['dependencies'] = [
|
||||||
format_obsidian_link(name) for name in frontmatter_data['dependencies']
|
format_obsidian_link(name)
|
||||||
|
for name in frontmatter_data['dependencies']
|
||||||
]
|
]
|
||||||
|
|
||||||
# Frontmatter
|
# Frontmatter
|
||||||
|
@ -100,7 +103,7 @@ class CardFileFormatter:
|
||||||
assignments = [parse_obsidian_link(text) for text in assignments]
|
assignments = [parse_obsidian_link(text) for text in assignments]
|
||||||
|
|
||||||
card_dependencies: list[str] = fm.metadata.get('dependencies', [])
|
card_dependencies: list[str] = fm.metadata.get('dependencies', [])
|
||||||
card_dependencies=[parse_obsidian_link(text) for text in card_dependencies]
|
card_dependencies = [parse_obsidian_link(text) for text in card_dependencies]
|
||||||
|
|
||||||
description = self.renderer.render_children(document).strip()
|
description = self.renderer.render_children(document).strip()
|
||||||
return CardContents(
|
return CardContents(
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
def test_import():
|
def test_import():
|
||||||
import favro_sync.favro_data_model
|
import favro_sync.favro_data_model # noqa
|
||||||
import favro_sync.favro_client
|
import favro_sync.favro_client # noqa
|
||||||
import favro_sync.favro_fuse
|
import favro_sync.favro_fuse # noqa
|
||||||
import favro_sync.favro_markdown
|
import favro_sync.favro_markdown # noqa
|
||||||
import favro_sync
|
import favro_sync # noqa
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ Great news everyone! My weird program actually works!
|
||||||
|
|
||||||
FORMATTER = CardFileFormatter()
|
FORMATTER = CardFileFormatter()
|
||||||
|
|
||||||
|
|
||||||
def test_parse_and_render():
|
def test_parse_and_render():
|
||||||
card_contents = FORMATTER.parse_card_contents(EXAMPLE_TEXT_1)
|
card_contents = FORMATTER.parse_card_contents(EXAMPLE_TEXT_1)
|
||||||
|
|
||||||
|
@ -45,6 +46,7 @@ def test_parse_and_render():
|
||||||
assert '---' not in card_contents.description
|
assert '---' not in card_contents.description
|
||||||
assert FORMATTER.format_card_contents(card_contents) == EXAMPLE_TEXT_1
|
assert FORMATTER.format_card_contents(card_contents) == EXAMPLE_TEXT_1
|
||||||
|
|
||||||
|
|
||||||
def test_parse_and_render_2():
|
def test_parse_and_render_2():
|
||||||
card_contents = FORMATTER.parse_card_contents(EXAMPLE_TEXT_2)
|
card_contents = FORMATTER.parse_card_contents(EXAMPLE_TEXT_2)
|
||||||
print(card_contents)
|
print(card_contents)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user