my.goodreads: cleanup, rename from my.reading.goodrads & use proper pip dependency

related:
- https://github.com/karlicoss/HPI/issues/79
- 10d8cc86a1
This commit is contained in:
Dima Gerasimov 2021-03-26 04:48:18 +00:00 committed by karlicoss
parent 1cdef6f40a
commit 29384aef44
5 changed files with 123 additions and 83 deletions

View file

@ -45,6 +45,9 @@ class bluemaestro:
class stackexchange: class stackexchange:
export_path: Paths = '' export_path: Paths = ''
class goodreads:
export_path: Paths = ''
class pinboard: class pinboard:
export_dir: Paths = '' export_dir: Paths = ''

102
my/goodreads.py Normal file
View file

@ -0,0 +1,102 @@
"""
[[https://www.goodreads.com][Goodreads]] statistics
"""
REQUIRES = [
'git+https://github.com/karlicoss/goodrexport',
]
from dataclasses import dataclass
from my.core import Paths
from my.config import goodreads as user_config
@dataclass
class goodreads(user_config):
# paths[s]/glob to the exported JSON data
export_path: Paths
from my.core.cfg import make_config, Attrs
def _migration(attrs: Attrs) -> Attrs:
export_dir = 'export_dir'
if export_dir in attrs: # legacy name
attrs['export_path'] = attrs[export_dir]
from my.core.warnings import high
high(f'"{export_dir}" is deprecated! Please use "export_path" instead."')
return attrs
config = make_config(goodreads, migration=_migration)
#############################3
from my.core import get_files
from typing import Sequence, Iterator
from pathlib import Path
def inputs() -> Sequence[Path]:
return get_files(config.export_path)
from datetime import datetime
import pytz
from goodrexport import dal
def _dal() -> dal.DAL:
return dal.DAL(inputs())
def reviews() -> Iterator[dal.Review]:
return _dal().reviews()
# todo should be in DAL?
def books() -> Iterator[dal.Book]:
for r in reviews():
yield r.book
#######
# todo ok, not sure these really belong here...
from my.core.common import datetime_aware
@dataclass
class Event:
dt: datetime_aware
summary: str
eid: str
def events() -> Iterator[Event]:
for b in books():
yield Event(
dt=b.date_added,
summary=f'Added book "{b.title}"', # todo shelf?
eid=b.id
)
# todo finished? other updates?
def print_read_history() -> None:
def ddate(x):
if x is None:
return datetime.fromtimestamp(0, pytz.utc)
else:
return x
def key(b):
return ddate(b.date_started)
def fmtdt(dt):
if dt is None:
return dt
tz = pytz.timezone('Europe/London')
return dt.astimezone(tz)
for b in sorted(books(), key=key):
print(f"""
{b.title} by {', '.join(b.authors)}
started : {fmtdt(b.date_started)}
finished: {fmtdt(b.date_read)}
""")

86
my/reading/goodreads.py Executable file → Normal file
View file

@ -1,85 +1,5 @@
#!/usr/bin/env python3 from my.core import warnings
from functools import lru_cache
from typing import NamedTuple
from datetime import datetime
import pytz
from my.config.repos.goodrexport import dal as goodrexport warnings.medium('my.reading.goodreads is deprecated! Use my.goodreads instead!')
from my.config import goodreads as config
from ..goodreads import *
def get_model():
sources = list(sorted(config.export_dir.glob('*.xml')))
model = goodrexport.DAL(sources)
return model
def get_books():
model = get_model()
return [r.book for r in model.reviews()]
def test_books():
books = get_books()
assert len(books) > 10
class Event(NamedTuple):
dt: datetime
summary: str
eid: str
def get_events():
events = []
for b in get_books():
events.append(Event(
dt=b.date_added,
summary=f'Added book "{b.title}"', # TODO shelf?
eid=b.id
))
# TODO finished? other updates?
return sorted(events, key=lambda e: e.dt)
def print_read_history():
def ddate(x):
if x is None:
return datetime.fromtimestamp(0, pytz.utc)
else:
return x
def key(b):
return ddate(b.date_started)
def fmtdt(dt):
if dt is None:
return dt
tz = pytz.timezone('Europe/London')
return dt.astimezone(tz)
for b in sorted(get_books(), key=key):
print(f"""
{b.title} by {', '.join(b.authors)}
started : {fmtdt(b.date_started)}
finished: {fmtdt(b.date_read)}
""")
def test():
assert len(get_events()) > 20
# def main():
# import argparse
# p = argparse.ArgumentParser()
# sp = p.add_argument('mode', nargs='?')
# args = p.parse_args()
# if args.mode == 'history':
# print_read_history()
# else:
# assert args.mode is None
# for b in iter_books():
# print(b)
# if __name__ == '__main__':
# main()

13
tests/goodreads.py Normal file
View file

@ -0,0 +1,13 @@
from .common import skip_if_not_karlicoss as pytestmark
from more_itertools import ilen
def test_events() -> None:
from my.goodreads import events
assert ilen(events()) > 20
def test_books() -> None:
from my.goodreads import books
assert ilen(books()) > 10

View file

@ -81,6 +81,7 @@ commands =
hpi module install my.pinboard hpi module install my.pinboard
hpi module install my.arbtt hpi module install my.arbtt
hpi module install my.coding.commits hpi module install my.coding.commits
hpi module install my.goodreads
# todo fuck. -p my.github isn't checking the subpackages?? wtf... # todo fuck. -p my.github isn't checking the subpackages?? wtf...
# guess it wants .pyi file?? # guess it wants .pyi file??
@ -101,6 +102,7 @@ commands =
-p my.calendar.holidays \ -p my.calendar.holidays \
-p my.arbtt \ -p my.arbtt \
-p my.coding.commits \ -p my.coding.commits \
-p my.goodreads \
--txt-report .coverage.mypy-misc \ --txt-report .coverage.mypy-misc \
--html-report .coverage.mypy-misc \ --html-report .coverage.mypy-misc \
{posargs} {posargs}