core/general: move cached_property into compat, use standard implementation from python3.8
This commit is contained in:
parent
711157e0f5
commit
4e59a65f9a
6 changed files with 38 additions and 27 deletions
|
@ -6,8 +6,8 @@ from typing import NamedTuple
|
||||||
import json
|
import json
|
||||||
from typing import Dict, Iterator
|
from typing import Dict, Iterator
|
||||||
|
|
||||||
from ..common import cproperty, get_files
|
from ..core import get_files, Res, unwrap
|
||||||
from ..error import Res, unwrap
|
from ..core.compat import cached_property
|
||||||
from ..core.konsume import ignore, wrap
|
from ..core.konsume import ignore, wrap
|
||||||
|
|
||||||
from kython import fget
|
from kython import fget
|
||||||
|
@ -46,18 +46,18 @@ class Competition(NamedTuple):
|
||||||
contest: str
|
contest: str
|
||||||
cmap: Cmap
|
cmap: Cmap
|
||||||
|
|
||||||
@cproperty
|
@cached_property
|
||||||
def uid(self) -> Cid:
|
def uid(self) -> Cid:
|
||||||
return self.contest_id
|
return self.contest_id
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash(self.contest_id)
|
return hash(self.contest_id)
|
||||||
|
|
||||||
@cproperty
|
@cached_property
|
||||||
def when(self) -> datetime:
|
def when(self) -> datetime:
|
||||||
return self.cmap[self.uid].when
|
return self.cmap[self.uid].when
|
||||||
|
|
||||||
@cproperty
|
@cached_property
|
||||||
def summary(self) -> str:
|
def summary(self) -> str:
|
||||||
return f'participated in {self.contest}' # TODO
|
return f'participated in {self.contest}' # TODO
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,9 @@ from typing import NamedTuple
|
||||||
import json
|
import json
|
||||||
from typing import Dict, Iterator
|
from typing import Dict, Iterator
|
||||||
|
|
||||||
from ..common import cproperty, get_files
|
from ..core import get_files, Res, unwrap
|
||||||
from ..error import Res, unwrap
|
from ..core.compat import cached_property
|
||||||
|
from ..core.error import Res, unwrap
|
||||||
|
|
||||||
# TODO get rid of fget?
|
# TODO get rid of fget?
|
||||||
from kython import fget
|
from kython import fget
|
||||||
|
@ -26,18 +27,18 @@ class Competition(NamedTuple):
|
||||||
percentile: float
|
percentile: float
|
||||||
dates: str
|
dates: str
|
||||||
|
|
||||||
@cproperty
|
@cached_property
|
||||||
def uid(self) -> str:
|
def uid(self) -> str:
|
||||||
return self.contest_id
|
return self.contest_id
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash(self.contest_id)
|
return hash(self.contest_id)
|
||||||
|
|
||||||
@cproperty
|
@cached_property
|
||||||
def when(self) -> datetime:
|
def when(self) -> datetime:
|
||||||
return datetime.strptime(self.dates, '%Y-%m-%dT%H:%M:%S.%fZ')
|
return datetime.strptime(self.dates, '%Y-%m-%dT%H:%M:%S.%fZ')
|
||||||
|
|
||||||
@cproperty
|
@cached_property
|
||||||
def summary(self) -> str:
|
def summary(self) -> str:
|
||||||
return f'participated in {self.contest}: {self.percentile:.0f}'
|
return f'participated in {self.contest}: {self.percentile:.0f}'
|
||||||
|
|
||||||
|
|
|
@ -128,13 +128,6 @@ def test_make_dict() -> None:
|
||||||
assert d == {0: 0, 1: 1, 2: 0, 3: 1, 4: 0}
|
assert d == {0: 0, 1: 1, 2: 0, 3: 1, 4: 0}
|
||||||
|
|
||||||
|
|
||||||
Cl = TypeVar('Cl')
|
|
||||||
R = TypeVar('R')
|
|
||||||
|
|
||||||
def cproperty(f: Callable[[Cl], R]) -> R:
|
|
||||||
return property(functools.lru_cache(maxsize=1)(f)) # type: ignore
|
|
||||||
|
|
||||||
|
|
||||||
# https://stackoverflow.com/a/12377059/706389
|
# https://stackoverflow.com/a/12377059/706389
|
||||||
def listify(fn=None, wrapper=list):
|
def listify(fn=None, wrapper=list):
|
||||||
"""
|
"""
|
||||||
|
@ -638,3 +631,6 @@ class DummyExecutor(Executor):
|
||||||
|
|
||||||
def shutdown(self, wait: bool=True) -> None: # type: ignore[override]
|
def shutdown(self, wait: bool=True) -> None: # type: ignore[override]
|
||||||
self._shutdown = True
|
self._shutdown = True
|
||||||
|
|
||||||
|
# legacy deprecated import
|
||||||
|
from .compat import cached_property as cproperty
|
||||||
|
|
|
@ -90,3 +90,16 @@ def removeprefix(text: str, prefix: str) -> str:
|
||||||
if text.startswith(prefix):
|
if text.startswith(prefix):
|
||||||
return text[len(prefix):]
|
return text[len(prefix):]
|
||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
# can remove after python3.8
|
||||||
|
if sys.version_info[:2] >= (3, 8):
|
||||||
|
from functools import cached_property
|
||||||
|
else:
|
||||||
|
from typing import TypeVar, Callable
|
||||||
|
Cl = TypeVar('Cl')
|
||||||
|
R = TypeVar('R')
|
||||||
|
def cached_property(f: Callable[[Cl], R]) -> R:
|
||||||
|
return property(functools.lru_cache(maxsize=1)(f)) # type: ignore
|
||||||
|
del Cl
|
||||||
|
del R
|
||||||
|
|
13
my/rtm.py
13
my/rtm.py
|
@ -10,7 +10,8 @@ import re
|
||||||
from typing import Dict, List, Iterator
|
from typing import Dict, List, Iterator
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from .common import LazyLogger, get_files, group_by_key, cproperty, make_dict
|
from .core.common import LazyLogger, get_files, group_by_key, make_dict
|
||||||
|
from .core.compat import cached_property
|
||||||
|
|
||||||
from my.config import rtm as config
|
from my.config import rtm as config
|
||||||
|
|
||||||
|
@ -28,14 +29,14 @@ class MyTodo:
|
||||||
self.todo = todo
|
self.todo = todo
|
||||||
self.revision = revision
|
self.revision = revision
|
||||||
|
|
||||||
@cproperty
|
@cached_property
|
||||||
def notes(self) -> List[str]:
|
def notes(self) -> List[str]:
|
||||||
# TODO can there be multiple??
|
# TODO can there be multiple??
|
||||||
desc = self.todo['DESCRIPTION']
|
desc = self.todo['DESCRIPTION']
|
||||||
notes = re.findall(r'---\n\n(.*?)\n\nUpdated:', desc, flags=re.DOTALL)
|
notes = re.findall(r'---\n\n(.*?)\n\nUpdated:', desc, flags=re.DOTALL)
|
||||||
return notes
|
return notes
|
||||||
|
|
||||||
@cproperty
|
@cached_property
|
||||||
def tags(self) -> List[str]:
|
def tags(self) -> List[str]:
|
||||||
desc = self.todo['DESCRIPTION']
|
desc = self.todo['DESCRIPTION']
|
||||||
[tags_str] = re.findall(r'\nTags: (.*?)\n', desc, flags=re.DOTALL)
|
[tags_str] = re.findall(r'\nTags: (.*?)\n', desc, flags=re.DOTALL)
|
||||||
|
@ -44,11 +45,11 @@ class MyTodo:
|
||||||
tags = [t.strip() for t in tags_str.split(',')]
|
tags = [t.strip() for t in tags_str.split(',')]
|
||||||
return tags
|
return tags
|
||||||
|
|
||||||
@cproperty
|
@cached_property
|
||||||
def uid(self) -> str:
|
def uid(self) -> str:
|
||||||
return str(self.todo['UID'])
|
return str(self.todo['UID'])
|
||||||
|
|
||||||
@cproperty
|
@cached_property
|
||||||
def title(self) -> str:
|
def title(self) -> str:
|
||||||
return str(self.todo['SUMMARY'])
|
return str(self.todo['SUMMARY'])
|
||||||
|
|
||||||
|
@ -59,7 +60,7 @@ class MyTodo:
|
||||||
return str(self.todo['STATUS'])
|
return str(self.todo['STATUS'])
|
||||||
|
|
||||||
# TODO tz?
|
# TODO tz?
|
||||||
@cproperty
|
@cached_property
|
||||||
def time(self) -> datetime:
|
def time(self) -> datetime:
|
||||||
t1 = self.todo['DTSTAMP'].dt
|
t1 = self.todo['DTSTAMP'].dt
|
||||||
t2 = self.todo['LAST-MODIFIED'].dt
|
t2 = self.todo['LAST-MODIFIED'].dt
|
||||||
|
|
|
@ -21,9 +21,9 @@ except ImportError as ie:
|
||||||
|
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from functools import lru_cache
|
|
||||||
import html
|
import html
|
||||||
from ..core.common import Paths, datetime_aware
|
from ..core.common import Paths, datetime_aware
|
||||||
|
from ..core.compat import cached_property
|
||||||
from ..core.error import Res
|
from ..core.error import Res
|
||||||
from ..core.kompress import ZipPath
|
from ..core.kompress import ZipPath
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ class ZipExport:
|
||||||
# older format
|
# older format
|
||||||
yield j
|
yield j
|
||||||
|
|
||||||
@lru_cache(1)
|
@cached_property
|
||||||
def screen_name(self) -> str:
|
def screen_name(self) -> str:
|
||||||
[acc] = self.raw('account')
|
[acc] = self.raw('account')
|
||||||
return acc['username']
|
return acc['username']
|
||||||
|
@ -201,14 +201,14 @@ class ZipExport:
|
||||||
# NOTE: for some reason, created_at doesn't seem to be in order
|
# NOTE: for some reason, created_at doesn't seem to be in order
|
||||||
# it mostly is, but there are a bunch of one-off random tweets where the time decreases (typically at the very end)
|
# it mostly is, but there are a bunch of one-off random tweets where the time decreases (typically at the very end)
|
||||||
for r in self.raw('tweet'):
|
for r in self.raw('tweet'):
|
||||||
yield Tweet(r, screen_name=self.screen_name())
|
yield Tweet(r, screen_name=self.screen_name)
|
||||||
|
|
||||||
|
|
||||||
def likes(self) -> Iterator[Like]:
|
def likes(self) -> Iterator[Like]:
|
||||||
# TODO ugh. would be nice to unify Tweet/Like interface
|
# TODO ugh. would be nice to unify Tweet/Like interface
|
||||||
# however, akeout only got tweetId, full text and url
|
# however, akeout only got tweetId, full text and url
|
||||||
for r in self.raw('like'):
|
for r in self.raw('like'):
|
||||||
yield Like(r, screen_name=self.screen_name())
|
yield Like(r, screen_name=self.screen_name)
|
||||||
|
|
||||||
|
|
||||||
# todo not sure about list and sorting? although can't hurt considering json is not iterative?
|
# todo not sure about list and sorting? although can't hurt considering json is not iterative?
|
||||||
|
|
Loading…
Add table
Reference in a new issue