1
0
Fork 0
mirror of https://github.com/Findus23/PaperLibrary-cli.git synced 2024-09-20 17:03:46 +02:00

use config file

This commit is contained in:
Lukas Winkler 2020-12-29 17:16:16 +01:00
parent 8b483000e2
commit 1fa77dab22
Signed by: lukas
GPG key ID: 54DE4D798D244853
7 changed files with 125 additions and 47 deletions

1
.gitignore vendored
View file

@ -2,4 +2,3 @@
__pycache__/ __pycache__/
library/ library/
!paperlibrary/library !paperlibrary/library
paperlibrary/config.py

View file

@ -47,11 +47,11 @@ class PaperComplete(Paper):
publication: str publication: str
doctype: str doctype: str
arxiv_id: Optional[str] arxiv_id: Optional[str]
bibcode: str bibcode: Optional[str]
year: int year: int
pubdate: str # TODO: to datetime pubdate: str # TODO: to datetime
entry_date: str # TODO: to datetime entry_date: str # TODO: to datetime
citation_count: int citation_count: Optional[int]
citation_key: Optional[str] citation_key: Optional[str]
recommended_by: List[str] recommended_by: List[str]
tags: List[str] tags: List[str]

38
paperlibrary/config.py Normal file
View file

@ -0,0 +1,38 @@
from dataclasses import dataclass
from pathlib import Path
from typing import Optional
import yaml
from dataclasses_json import dataclass_json, DataClassJsonMixin
config_path = Path("~/.config/paperlibrary.yaml").expanduser()
@dataclass_json
@dataclass
class Config(DataClassJsonMixin):
url: str
auth_token: str
basedir: str
@property
def basedir_path(self):
return Path(self.basedir)
def get_config() -> Optional[Config]:
try:
with config_path.open() as f:
data = yaml.safe_load(f)
if not data:
raise ValueError("config file is empty")
return Config.from_dict(data)
except FileNotFoundError:
return
def save_config(config: Config) -> None:
with config_path.open("w") as f:
yaml.safe_dump(config.to_dict(), f)

View file

@ -9,7 +9,7 @@ from tzlocal import get_localzone
from paperlibrary.api import PaperLibraryAPI from paperlibrary.api import PaperLibraryAPI
from paperlibrary.api.models import Paper from paperlibrary.api.models import Paper
from paperlibrary.config import basedir from paperlibrary.config import Config
def format_filename(s: str) -> str: def format_filename(s: str) -> str:
@ -32,8 +32,8 @@ def link_file(pdf_dir: Path, directory: Path, paper: Paper, filename: str = None
targetfile.symlink_to(sourcefile) targetfile.symlink_to(sourcefile)
def write_symlinks(api: PaperLibraryAPI): def write_symlinks(api: PaperLibraryAPI, config: Config):
... basedir = config.basedir_path
pdf_dir = basedir / "pdfs" pdf_dir = basedir / "pdfs"
pdf_dir.mkdir(exist_ok=True) pdf_dir.mkdir(exist_ok=True)
@ -49,12 +49,16 @@ def write_symlinks(api: PaperLibraryAPI):
directory.mkdir() directory.mkdir()
for author in api.fetch_authors(): for author in api.fetch_authors():
if not author.papers:
continue
author_subdir = author_dir / format_filename(author.display_name) author_subdir = author_dir / format_filename(author.display_name)
author_subdir.mkdir() author_subdir.mkdir()
for paper in author.papers: for paper in author.papers:
link_file(pdf_dir, author_subdir, paper) link_file(pdf_dir, author_subdir, paper)
for keyword in api.fetch_keywords(): for keyword in api.fetch_keywords():
if not keyword.papers:
continue
keyword_subdir = keyword_dir / format_filename(keyword.name) keyword_subdir = keyword_dir / format_filename(keyword.name)
keyword_subdir.mkdir() keyword_subdir.mkdir()
for paper in keyword.papers: for paper in keyword.papers:
@ -100,8 +104,8 @@ def hash_file(file: Path, buffer_size=65536) -> str:
return sha256.hexdigest() return sha256.hexdigest()
def update_pdfs(api: PaperLibraryAPI): def update_pdfs(api: PaperLibraryAPI, config: Config):
pdf_dir = basedir / "pdfs" pdf_dir = config.basedir_path / "pdfs"
pdf_dir.mkdir(exist_ok=True) pdf_dir.mkdir(exist_ok=True)
for pdf in api.fetch_pdfs(): for pdf in api.fetch_pdfs():
@ -122,8 +126,8 @@ def update_pdfs(api: PaperLibraryAPI):
download_file(api, pdf.file, pdf_file) download_file(api, pdf.file, pdf_file)
def write_bibliography(api: PaperLibraryAPI): def write_bibliography(api: PaperLibraryAPI, config: Config):
bib = api.fetch_bibliography() bib = api.fetch_bibliography()
target_file = basedir / "bibliography.bib" target_file = config.basedir_path / "bibliography.bib"
with target_file.open("w") as f: with target_file.open("w") as f:
f.write(bib) f.write(bib)

View file

@ -1,29 +1,44 @@
import click import click
from paperlibrary.api import PaperLibraryAPI from paperlibrary.api import PaperLibraryAPI
from paperlibrary.config import url, auth_token from paperlibrary.config import get_config, Config, save_config
from paperlibrary.library import write_symlinks, update_pdfs, write_bibliography from paperlibrary.library import write_symlinks, update_pdfs, write_bibliography
@click.group() @click.group()
def cli(): @click.pass_context
def cli(ctx):
ctx.obj = get_config()
pass pass
@cli.command() @cli.command()
def update(): @click.pass_obj
api = PaperLibraryAPI(url, auth_token=auth_token) def update(config: Config):
write_bibliography(api) api = PaperLibraryAPI(config.url, auth_token=config.auth_token)
write_symlinks(api) write_bibliography(api, config)
update_pdfs(api) write_symlinks(api, config)
update_pdfs(api, config)
@cli.command() @cli.command()
def test(): @click.pass_obj
api = PaperLibraryAPI(url, auth_token=auth_token) def test(config: Config):
api = PaperLibraryAPI(config.url, auth_token=config.auth_token)
print(api.fetch_papers()) print(api.fetch_papers())
@cli.command()
def init():
url = click.prompt("URL", type=str)
auth_token = click.prompt("auth_token", type=str)
basedir = click.prompt("basedir", type=str)
config = Config(url=url, auth_token=auth_token, basedir=basedir)
save_config(config)
if __name__ == '__main__': if __name__ == '__main__':
cli() cli()

77
poetry.lock generated
View file

@ -8,7 +8,7 @@ python-versions = ">=2.7, <4"
[[package]] [[package]]
name = "certifi" name = "certifi"
version = "2020.6.20" version = "2020.12.5"
description = "Python package for providing Mozilla's CA Bundle." description = "Python package for providing Mozilla's CA Bundle."
category = "main" category = "main"
optional = false optional = false
@ -16,11 +16,11 @@ python-versions = "*"
[[package]] [[package]]
name = "chardet" name = "chardet"
version = "3.0.4" version = "4.0.0"
description = "Universal encoding detector for Python 2 and 3" description = "Universal encoding detector for Python 2 and 3"
category = "main" category = "main"
optional = false optional = false
python-versions = "*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]] [[package]]
name = "click" name = "click"
@ -57,16 +57,16 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]] [[package]]
name = "marshmallow" name = "marshmallow"
version = "3.8.0" version = "3.10.0"
description = "A lightweight library for converting complex datatypes to and from native Python datatypes." description = "A lightweight library for converting complex datatypes to and from native Python datatypes."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.5" python-versions = ">=3.5"
[package.extras] [package.extras]
dev = ["pytest", "pytz", "simplejson", "mypy (0.782)", "flake8 (3.8.3)", "flake8-bugbear (20.1.4)", "pre-commit (>=2.4,<3.0)", "tox"] dev = ["pytest", "pytz", "simplejson", "mypy (==0.790)", "flake8 (==3.8.4)", "flake8-bugbear (==20.11.1)", "pre-commit (>=2.4,<3.0)", "tox"]
docs = ["sphinx (3.2.1)", "sphinx-issues (1.2.0)", "alabaster (0.7.12)", "sphinx-version-warning (1.1.2)", "autodocsumm (0.2.0)"] docs = ["sphinx (==3.3.1)", "sphinx-issues (==1.2.0)", "alabaster (==0.7.12)", "sphinx-version-warning (==1.1.2)", "autodocsumm (==0.2.2)"]
lint = ["mypy (0.782)", "flake8 (3.8.3)", "flake8-bugbear (20.1.4)", "pre-commit (>=2.4,<3.0)"] lint = ["mypy (==0.790)", "flake8 (==3.8.4)", "flake8-bugbear (==20.11.1)", "pre-commit (>=2.4,<3.0)"]
tests = ["pytest", "pytz", "simplejson"] tests = ["pytest", "pytz", "simplejson"]
[[package]] [[package]]
@ -90,15 +90,23 @@ python-versions = "*"
[[package]] [[package]]
name = "pytz" name = "pytz"
version = "2020.1" version = "2020.5"
description = "World timezone definitions, modern and historical" description = "World timezone definitions, modern and historical"
category = "main" category = "main"
optional = false optional = false
python-versions = "*" python-versions = "*"
[[package]]
name = "pyyaml"
version = "5.3.1"
description = "YAML parser and emitter for Python"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]] [[package]]
name = "requests" name = "requests"
version = "2.24.0" version = "2.25.1"
description = "Python HTTP for Humans." description = "Python HTTP for Humans."
category = "main" category = "main"
optional = false optional = false
@ -106,13 +114,13 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[package.dependencies] [package.dependencies]
certifi = ">=2017.4.17" certifi = ">=2017.4.17"
chardet = ">=3.0.2,<4" chardet = ">=3.0.2,<5"
idna = ">=2.5,<3" idna = ">=2.5,<3"
urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" urllib3 = ">=1.21.1,<1.27"
[package.extras] [package.extras]
security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"]
socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"]
[[package]] [[package]]
name = "stringcase" name = "stringcase"
@ -155,7 +163,7 @@ pytz = "*"
[[package]] [[package]]
name = "urllib3" name = "urllib3"
version = "1.25.10" version = "1.26.2"
description = "HTTP library with thread-safe connection pooling, file post, and more." description = "HTTP library with thread-safe connection pooling, file post, and more."
category = "main" category = "main"
optional = false optional = false
@ -163,13 +171,13 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
[package.extras] [package.extras]
brotli = ["brotlipy (>=0.6.0)"] brotli = ["brotlipy (>=0.6.0)"]
secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)", "ipaddress"] secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = "^3.8" python-versions = "^3.8"
content-hash = "8bb7dbfcc0d218d22ff3dcafae140daff4799bfeb988731a3759412a256d0e29" content-hash = "f28e815cebaa07fe26370dea5e304b5b63e3e9ea12221161c05c94c158191a91"
[metadata.files] [metadata.files]
alive-progress = [ alive-progress = [
@ -177,12 +185,12 @@ alive-progress = [
{file = "alive_progress-1.6.1-py3-none-any.whl", hash = "sha256:9a0fae6b94fb4e4bcd9fb51760506d29a33358ebbfef2c6516dce3e359a661b5"}, {file = "alive_progress-1.6.1-py3-none-any.whl", hash = "sha256:9a0fae6b94fb4e4bcd9fb51760506d29a33358ebbfef2c6516dce3e359a661b5"},
] ]
certifi = [ certifi = [
{file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, {file = "certifi-2020.12.5-py2.py3-none-any.whl", hash = "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"},
{file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"}, {file = "certifi-2020.12.5.tar.gz", hash = "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c"},
] ]
chardet = [ chardet = [
{file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, {file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"},
{file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, {file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"},
] ]
click = [ click = [
{file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"},
@ -197,8 +205,8 @@ idna = [
{file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"},
] ]
marshmallow = [ marshmallow = [
{file = "marshmallow-3.8.0-py2.py3-none-any.whl", hash = "sha256:2272273505f1644580fbc66c6b220cc78f893eb31f1ecde2af98ad28011e9811"}, {file = "marshmallow-3.10.0-py2.py3-none-any.whl", hash = "sha256:eca81d53aa4aafbc0e20566973d0d2e50ce8bf0ee15165bb799bec0df1e50177"},
{file = "marshmallow-3.8.0.tar.gz", hash = "sha256:47911dd7c641a27160f0df5fd0fe94667160ffe97f70a42c3cc18388d86098cc"}, {file = "marshmallow-3.10.0.tar.gz", hash = "sha256:4ab2fdb7f36eb61c3665da67a7ce281c8900db08d72ba6bf0e695828253581f7"},
] ]
marshmallow-enum = [ marshmallow-enum = [
{file = "marshmallow-enum-1.5.1.tar.gz", hash = "sha256:38e697e11f45a8e64b4a1e664000897c659b60aa57bfa18d44e226a9920b6e58"}, {file = "marshmallow-enum-1.5.1.tar.gz", hash = "sha256:38e697e11f45a8e64b4a1e664000897c659b60aa57bfa18d44e226a9920b6e58"},
@ -209,12 +217,25 @@ mypy-extensions = [
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
] ]
pytz = [ pytz = [
{file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"}, {file = "pytz-2020.5-py2.py3-none-any.whl", hash = "sha256:16962c5fb8db4a8f63a26646d8886e9d769b6c511543557bc84e9569fb9a9cb4"},
{file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"}, {file = "pytz-2020.5.tar.gz", hash = "sha256:180befebb1927b16f6b57101720075a984c019ac16b1b7575673bea42c6c3da5"},
]
pyyaml = [
{file = "PyYAML-5.3.1-cp27-cp27m-win32.whl", hash = "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f"},
{file = "PyYAML-5.3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76"},
{file = "PyYAML-5.3.1-cp35-cp35m-win32.whl", hash = "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2"},
{file = "PyYAML-5.3.1-cp35-cp35m-win_amd64.whl", hash = "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c"},
{file = "PyYAML-5.3.1-cp36-cp36m-win32.whl", hash = "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2"},
{file = "PyYAML-5.3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648"},
{file = "PyYAML-5.3.1-cp37-cp37m-win32.whl", hash = "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"},
{file = "PyYAML-5.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf"},
{file = "PyYAML-5.3.1-cp38-cp38-win32.whl", hash = "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97"},
{file = "PyYAML-5.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee"},
{file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"},
] ]
requests = [ requests = [
{file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"}, {file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"},
{file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"}, {file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"},
] ]
stringcase = [ stringcase = [
{file = "stringcase-1.2.0.tar.gz", hash = "sha256:48a06980661908efe8d9d34eab2b6c13aefa2163b3ced26972902e3bdfd87008"}, {file = "stringcase-1.2.0.tar.gz", hash = "sha256:48a06980661908efe8d9d34eab2b6c13aefa2163b3ced26972902e3bdfd87008"},
@ -234,6 +255,6 @@ tzlocal = [
{file = "tzlocal-2.1.tar.gz", hash = "sha256:643c97c5294aedc737780a49d9df30889321cbe1204eac2c2ec6134035a92e44"}, {file = "tzlocal-2.1.tar.gz", hash = "sha256:643c97c5294aedc737780a49d9df30889321cbe1204eac2c2ec6134035a92e44"},
] ]
urllib3 = [ urllib3 = [
{file = "urllib3-1.25.10-py2.py3-none-any.whl", hash = "sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461"}, {file = "urllib3-1.26.2-py2.py3-none-any.whl", hash = "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473"},
{file = "urllib3-1.25.10.tar.gz", hash = "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a"}, {file = "urllib3-1.26.2.tar.gz", hash = "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08"},
] ]

View file

@ -11,6 +11,7 @@ click = "^7.1.2"
dataclasses-json = "^0.5.2" dataclasses-json = "^0.5.2"
tzlocal = "^2.1" tzlocal = "^2.1"
alive-progress = "^1.6.1" alive-progress = "^1.6.1"
PyYAML = "^5.3.1"
[build-system] [build-system]
requires = ["poetry-core>=1.0.0"] requires = ["poetry-core>=1.0.0"]