Obsidian import: More intelligent time behaviour
Some checks failed
Test Python / Test (push) Failing after 32s
Some checks failed
Test Python / Test (push) Failing after 32s
This commit is contained in:
parent
a64cbc6186
commit
c8c142bd1b
|
@ -119,8 +119,9 @@ def import_watched_series_csv(vault: ObsidianVault, rows: Rows) -> int:
|
||||||
sample.single_label_with_category('episode.index'),
|
sample.single_label_with_category('episode.index'),
|
||||||
sample.single_label_with_category('episode.name'),
|
sample.single_label_with_category('episode.name'),
|
||||||
)
|
)
|
||||||
return Event(sample.start_at.time(),
|
expected_tz = datetime.timezone(datetime.timedelta(hours=2)) # TODO: Determine this in a more intelligent manner
|
||||||
sample.end_at.time(),
|
return Event(sample.start_at.astimezone(expected_tz).replace(second=0,microsecond=0).time(),
|
||||||
|
sample.end_at.astimezone(expected_tz).replace(second=0,microsecond=0).time(),
|
||||||
verb,
|
verb,
|
||||||
sample.single_label_with_category('series.name'),
|
sample.single_label_with_category('series.name'),
|
||||||
comment,
|
comment,
|
||||||
|
@ -162,6 +163,5 @@ def import_data(obsidian_path: Path, dry_run=True):
|
||||||
data_path = Path('output/show_episodes_watched.csv')
|
data_path = Path('output/show_episodes_watched.csv')
|
||||||
rows = load_csv_file(data_path)
|
rows = load_csv_file(data_path)
|
||||||
logger.info('Loaded CSV with %d lines', len(rows))
|
logger.info('Loaded CSV with %d lines', len(rows))
|
||||||
rows = rows[:7]
|
|
||||||
num_updated = import_watched_series_csv(vault, rows)
|
num_updated = import_watched_series_csv(vault, rows)
|
||||||
logger.info('Updated %d files', num_updated)
|
logger.info('Updated %d files', num_updated)
|
||||||
|
|
|
@ -210,25 +210,43 @@ def format_event_string(event: Event) -> str:
|
||||||
):
|
):
|
||||||
return event.comment
|
return event.comment
|
||||||
|
|
||||||
return f'{event.start_time:%H:%M} | {event.verb} [[{event.subject}]]. {event.comment}'.strip()
|
buf = []
|
||||||
|
buf.append(f'{event.start_time:%H:%M}')
|
||||||
|
if event.end_time and event.end_time != event.start_time:
|
||||||
|
buf.append(f'-{event.end_time:%H:%M}')
|
||||||
|
buf.append(' | ')
|
||||||
|
buf.append(event.verb)
|
||||||
|
buf.append(' [[')
|
||||||
|
buf.append(event.subject)
|
||||||
|
buf.append(']]. ')
|
||||||
|
buf.append(event.comment.strip())
|
||||||
|
|
||||||
|
return ''.join(buf)
|
||||||
|
|
||||||
|
|
||||||
RE_TIME = r'(\d\d:\d\d(?::\d\d(?:\.\d+?))?)'
|
RE_TIME = r'(\d\d:\d\d(?::\d\d(?:\.\d+?))?)'
|
||||||
|
RE_VERB = r'(\w+(?:ed|te))'
|
||||||
|
RE_LINK_MD = r'\[([^\]]*)\]\(?:[^)]*\)'
|
||||||
|
RE_LINK_WIKI = r'\[\[([^\]]*)\]\]'
|
||||||
|
|
||||||
|
RE_TIME_FORMAT = RE_TIME + r'(?:\s*\-\s*' + RE_TIME + r')?'
|
||||||
|
|
||||||
|
|
||||||
def parse_event_string(event_str: str) -> Event:
|
def parse_event_string(event_str: str) -> Event:
|
||||||
if m := re.match(
|
if m := re.match(
|
||||||
r'^\s*' + RE_TIME + r'[ :\|-]*(\w+ed)\s+\[([^\]]*)\]\([^)]*\)\.?\s*(.*)$',
|
r'^\s*' + RE_TIME_FORMAT + r'[ :\|-]*'+RE_VERB+r'\s+'+RE_LINK_MD+r'\.?\s*(.*)$',
|
||||||
event_str,
|
event_str,
|
||||||
):
|
):
|
||||||
start = datetime.time.fromisoformat(m.group(1))
|
start = datetime.time.fromisoformat(m.group(1))
|
||||||
return Event(start, start, m.group(2), m.group(3), m.group(4))
|
end = datetime.time.fromisoformat(m.group(2)) if m.group(2) else start
|
||||||
|
return Event(start, end, m.group(3), m.group(4), m.group(5))
|
||||||
if m := re.match(
|
if m := re.match(
|
||||||
r'^\s*' + RE_TIME + '[ :\|-]*(\w+ed)\s+\[\[([^\]]*)\]\]\.?\s*(.*)$',
|
r'^\s*' + RE_TIME_FORMAT + r'[ :\|-]*'+RE_VERB+r'\s+'+RE_LINK_WIKI+r'\.?\s*(.*)$',
|
||||||
event_str,
|
event_str,
|
||||||
):
|
):
|
||||||
start = datetime.time.fromisoformat(m.group(1))
|
start = datetime.time.fromisoformat(m.group(1))
|
||||||
return Event(start, start, m.group(2), m.group(3), m.group(4))
|
end = datetime.time.fromisoformat(m.group(2)) if m.group(2) else start
|
||||||
|
return Event(start, end, m.group(3), m.group(4), m.group(5))
|
||||||
logger.info('Could not parse format: %s', event_str)
|
logger.info('Could not parse format: %s', event_str)
|
||||||
return Event(None, None, None, None, event_str)
|
return Event(None, None, None, None, event_str)
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,10 @@ class ActivitySample:
|
||||||
start_at: datetime.datetime | None
|
start_at: datetime.datetime | None
|
||||||
end_at: datetime.datetime | None
|
end_at: datetime.datetime | None
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
if self.start_at and self.end_at:
|
||||||
|
assert self.start_at <= self.end_at
|
||||||
|
|
||||||
def single_label_with_category(self, category: str) -> str:
|
def single_label_with_category(self, category: str) -> str:
|
||||||
for label in self.labels:
|
for label in self.labels:
|
||||||
if label.category == category:
|
if label.category == category:
|
||||||
|
@ -35,6 +39,11 @@ class RealizedActivitySample(ActivitySample):
|
||||||
start_at: datetime.datetime
|
start_at: datetime.datetime
|
||||||
end_at: datetime.datetime
|
end_at: datetime.datetime
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
assert self.start_at is not None
|
||||||
|
assert self.end_at is not None
|
||||||
|
assert self.start_at <= self.end_at
|
||||||
|
|
||||||
|
|
||||||
def heuristically_realize_samples(
|
def heuristically_realize_samples(
|
||||||
samples: list[ActivitySample],
|
samples: list[ActivitySample],
|
||||||
|
@ -45,6 +54,8 @@ def heuristically_realize_samples(
|
||||||
* No samples overlap.
|
* No samples overlap.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
samples.sort(key = lambda x: x.end_at)
|
||||||
|
|
||||||
previous_sample_end = None
|
previous_sample_end = None
|
||||||
for sample in samples:
|
for sample in samples:
|
||||||
end_at = sample.end_at
|
end_at = sample.end_at
|
||||||
|
|
18
test/test_obsidian_format.py
Normal file
18
test/test_obsidian_format.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import datetime
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from obsidian_import import obsidian
|
||||||
|
|
||||||
|
|
||||||
|
EXAMPLES = [
|
||||||
|
obsidian.Event(datetime.time(12, 0, 0), datetime.time(12, 0, 0), "Ate",
|
||||||
|
"Lunch", "instantly"),
|
||||||
|
obsidian.Event(datetime.time(20, 0, 0), datetime.time(22, 0, 0),
|
||||||
|
"Watched", "Tom and Jerry", "on the *Television*"),
|
||||||
|
obsidian.Event(None, None, None, None, "Took a walk"),
|
||||||
|
]
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("event", EXAMPLES)
|
||||||
|
def test_format_preserves_information(event: obsidian.Event):
|
||||||
|
formatted = obsidian.format_event_string(event)
|
||||||
|
assert obsidian.parse_event_string(formatted) == event
|
Loading…
Reference in New Issue
Block a user