my.orgmode: cache entries

This commit is contained in:
Dima Gerasimov 2020-10-11 10:55:30 +01:00 committed by karlicoss
parent 1ded99c61c
commit d8ed780e36
2 changed files with 48 additions and 32 deletions

View file

@ -25,10 +25,11 @@ class Entry(NamedTuple):
Result = Res[Entry] Result = Res[Entry]
# TODO cachew? but in order for that to work, would need timestamps for input org-mode files..
def from_orgmode() -> Iterator[Result]: def from_orgmode() -> Iterator[Result]:
orgs = orgmode.query() orgs = orgmode.query()
for o in orgs.query_all(lambda o: o.with_tag('weight')): for o in orgmode.query().all():
if 'weight' not in o.tags:
continue
try: try:
# TODO can it throw? not sure # TODO can it throw? not sure
created = o.created created = o.created

View file

@ -1,59 +1,74 @@
''' '''
Programmatic access and queries to org-mode files on the filesystem Programmatic access and queries to org-mode files on the filesystem
''' '''
from datetime import datetime
from glob import glob
from typing import List, Sequence, Iterator
from pathlib import Path from pathlib import Path
from typing import List, Sequence, Iterable, NamedTuple, Optional
from .core import PathIsh from .core import PathIsh
from .core.common import mcachew
from .core.cachew import cache_dir
from my.config import orgmode as user_config from my.config import orgmode as user_config
from porg import Org from porg import Org
# TODO not sure about symlinks? # temporary? hack to cache org-mode notes
def _org_files_in(ppp: Path, archived: bool=False) -> Iterator[Path]: class OrgNote(NamedTuple):
assert ppp.exists(), ppp created: Optional[datetime]
# TODO reuse get_files somehow? heading: str
if ppp.is_file(): tags: List[str]
return [ppp]
yield from ppp.rglob('*.org')
if archived:
yield from ppp.rglob('*.org_archive')
def org_files(roots=user_config.roots, archived: bool=False) -> Iterator[Path]: # todo move to common?
# TODO rename to 'paths'? use get_files? import re
for p in roots: def _sanitize(p: Path) -> str:
yield from _org_files_in(Path(p), archived=archived) return re.sub(r'\W', '_', str(p))
# TODO move to porg? # todo move to porg?
class PorgAll: class Query:
# TODO *roots? def __init__(self, files: Sequence[Path]) -> None:
def __init__(self, roots: Sequence[PathIsh]) -> None: self.files = files
self.roots = roots
@property # TODO yield errors?
def files(self): @mcachew(
yield from org_files(roots=self.roots) cache_path=lambda _, f: cache_dir() / 'orgmode' / _sanitize(f), force_file=True,
depends_on=lambda _, f: (f, f.stat().st_mtime),
)
def _iterate(self, f: Path) -> Iterable[OrgNote]:
o = Org.from_file(f)
for x in o.iterate():
try:
# TODO(porg) not sure if created should ever throw... maybe warning/log?
created = x.created
except Exception as e:
created = None
yield OrgNote(
created=created,
heading=x.heading, # todo include the rest?
tags=list(x.tags),
)
def xpath_all(self, query: str): def all(self) -> Iterable[OrgNote]:
return self.query_all(lambda x: x.xpath_all(query)) for f in self.files:
yield from self._iterate(f)
# TODO very confusing names... # TODO very confusing names...
# TODO careful... maybe use orgparse iterate instead?? ugh. # TODO careful... maybe use orgparse iterate instead?? ugh.
def get_all(self): def get_all(self):
return self.xpath_all('//org') return self._xpath_all('//org')
def query_all(self, query): def query_all(self, query):
for of in self.files: for of in self.files:
org = Org.from_file(str(of)) org = Org.from_file(str(of))
yield from query(org) yield from query(org)
def _xpath_all(self, query: str):
return self.query_all(lambda x: x.xpath_all(query))
def query():
return PorgAll(roots=user_config.roots) def query() -> Query:
return Query(files=list(user_config.files))