adding options class and tidying up

This commit is contained in:
2021-10-28 20:11:27 +01:00
parent a0afe62879
commit 4077ec1760
4 changed files with 101 additions and 68 deletions

View File

@@ -5,24 +5,41 @@ Priority:
☐ Write the tests ☐ Write the tests
☐ test logs: <https://stackoverflow.com/questions/53125305/testing-logging-output-with-pytest> ☐ test logs: <https://stackoverflow.com/questions/53125305/testing-logging-output-with-pytest>
document this document this
☐ Docstrings ☐ Docstrings
Documentation: Documentation:
Docstrings:
☐ Use Duty to write module docstrings
☐ Use Duty to add Class docstrings
☐ Document these in Trilium and rewrite the docstrings notes
☐ Add the comment on Reddit (artie buco?) about imports in a module
☐ Document using `__main__.py` and `cli.py`
Use Duty as an example
☐ Write documentation using `mkdocs` ☐ Write documentation using `mkdocs`
☐ Look at how to use github actions ☐ Look at how to use github actions
Use <https://github.com/pdm-project/pdm/tree/main/.github/workflows> for an example Use <https://github.com/pdm-project/pdm/tree/main/.github/workflows> for an example
☐ Build the docs using a github action. ☐ Build the docs using a github action.
Functionality: Functionality:
✔ Move any `tembo.CONFIG` calls out of `pages.py` and ensure these are passed in from the cli. @done(21-10-28 19:44)
✔ Make `config scope` a dict in `cli.py`. @done(21-10-28 19:44)
☐ Add the `--example` output to the miscounted token message so the user knows the correct command to use.
✔ Page options dataclass @done(21-10-28 20:09)
☐ Replace loggers with `click.echo` for command outputs. Keep logging messages for actual logging messages? ☐ Replace loggers with `click.echo` for command outputs. Keep logging messages for actual logging messages?
☐ Use the python runner ☐ Use the python runner Duty
<https://github.com/pawamoy/duty> <https://github.com/pawamoy/duty>
☐ Run tests ☐ Run tests
☐ Update poetry ☐ Update poetry
☐ Build docs ☐ Build docs
☐ Document using Duty ☐ Document using Duty
VSCode:
PyInstaller:
☐ Document build error: <https://github.com/pyenv/pyenv/issues/1095>
PYTHON_CONFIGURE_OPTS="--enable-framework" pyenv install 3.8.11
☐ Freeze a click app: <https://stackoverflow.com/questions/45090083/freeze-a-program-created-with-pythons-click-pacage>
Tests: Tests:
☐ Write tests! @2d ☐ Write tests! @2d
Use coverage as going along to make sure all bases are covered in the testing Use coverage as going along to make sure all bases are covered in the testing
@@ -33,8 +50,6 @@ VSCode:
Logging: Logging:
Documentation: Documentation:
☐ a
Tembo: Tembo:
☐ Document creating new Tembo config ☐ Document creating new Tembo config
☐ ~/tembo needs creating ☐ ~/tembo needs creating

View File

@@ -1,9 +1,10 @@
import sys
import click import click
import tembo import tembo
from tembo.journal import pages from tembo.journal import pages
CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"]) CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
@@ -62,18 +63,19 @@ def new(scope, inputs, dry_run, example):
# get the scope information from the tembo config.yml # get the scope information from the tembo config.yml
try: try:
config_scope = [ config_scope = {
( option: str(user_scope[option])
str(user_scope["name"]), for option in [
user_scope.get("example"), "name",
str(user_scope["path"]), "example",
str(user_scope["filename"]), "path",
str(user_scope["extension"]), "filename",
user_scope.get("template_filename"), "extension",
) "template_filename",
]
for user_scope in tembo.CONFIG.scopes for user_scope in tembo.CONFIG.scopes
if user_scope["name"] == scope if user_scope["name"] == scope
] }
except KeyError as key_error: except KeyError as key_error:
# raise error if any non optional keys are missing # raise error if any non optional keys are missing
tembo.logger.critical("Key %s not found in config.yml - exiting", key_error) tembo.logger.critical("Key %s not found in config.yml - exiting", key_error)
@@ -83,24 +85,26 @@ def new(scope, inputs, dry_run, example):
if example: if example:
tembo.logger.info( tembo.logger.info(
"Example for 'tembo new %s': %s", "Example for 'tembo new %s': %s",
config_scope[0][0], config_scope["name"],
config_scope[0][1] config_scope["example"]
if isinstance(config_scope[0][1], str) if isinstance(config_scope[0][1], str)
else "No example in config.yml", else "No example in config.yml",
) )
raise SystemExit(0) raise SystemExit(0)
# if the name is in the config.yml, create the scoped page # if the name is in the config.yml, create the scoped page
if _name_found: page_creator_options = pages.PageCreatorOptions(
scoped_page = pages.ScopedPageCreator().create_page( base_path=tembo.CONFIG.base_path,
base_path=str(tembo.CONFIG.base_path), page_path=config_scope["path"],
page_path=config_scope[0][2], filename=config_scope["filename"],
filename=config_scope[0][3], extension=config_scope["extension"],
extension=config_scope[0][4], name=config_scope["name"],
name=config_scope[0][0],
user_input=inputs, user_input=inputs,
template_filename=config_scope[0][5], template_filename=config_scope["template_filename"],
template_path=tembo.CONFIG.template_path,
) )
if _name_found:
scoped_page = pages.ScopedPageCreator().create_page(page_creator_options)
scoped_page.save_to_disk(dry_run=dry_run) scoped_page.save_to_disk(dry_run=dry_run)
raise SystemExit(0) raise SystemExit(0)
if not _name_found and len(tembo.CONFIG.scopes) > 0: if not _name_found and len(tembo.CONFIG.scopes) > 0:
@@ -121,5 +125,10 @@ run.add_command(list_all)
if __name__ == "__main__": if __name__ == "__main__":
# new(["meeting", "robs presentation", "meeting on gcp"]) # new(["meeting", "robs presentation", "meeting on gcp"])
new(["meeting", "a", "b", "c", "d", "--example"]) new(["meeting", "a", "b", "c", "d"])
# new(["meeting", "robs presentation"]) # new(["meeting", "robs presentation"])
# pyinstaller
# if getattr(sys, "frozen", False):
# run(sys.argv[1:])
# run(sys.argv[1:])

View File

@@ -1,6 +1,7 @@
from __future__ import annotations from __future__ import annotations
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
from dataclasses import dataclass
import pathlib import pathlib
import re import re
from typing import Collection from typing import Collection
@@ -12,18 +13,21 @@ import pendulum
import tembo import tembo
@dataclass
class PageCreatorOptions:
base_path: str
page_path: str
filename: str
extension: str
name: str
user_input: Collection[str]
template_filename: str | None = None
template_path: str | None = None
class PageCreator: class PageCreator:
@abstractmethod @abstractmethod
def create_page( def create_page(self, options: PageCreatorOptions) -> Page:
self,
base_path: str,
page_path: str,
filename: str,
extension: str,
name: str,
user_input: Collection[str],
template_filename: str | None = None,
) -> Page:
raise NotImplementedError raise NotImplementedError
@staticmethod @staticmethod
@@ -50,17 +54,19 @@ class PageCreator:
# return path with a file # return path with a file
return path_to_file.with_suffix(f".{extension}") return path_to_file.with_suffix(f".{extension}")
def _load_template(self, base_path: str, template_filename: str) -> str: def _load_template(
self, base_path: str, template_filename: str, template_path: str | None
) -> str:
# check for overriden template_path # check for overriden template_path
if tembo.CONFIG.template_path is not None: if template_path is not None:
template_path = self._convert_to_path( converted_template_path = self._convert_to_path("", template_path, "", "")
"", tembo.CONFIG.template_path, "", ""
)
else: else:
# default template_path is base_path / .templates # default template_path is base_path / .templates
template_path = self._convert_to_path(base_path, ".templates", "", "") converted_template_path = self._convert_to_path(
base_path, ".templates", "", ""
)
# load the template folder # load the template folder
file_loader = jinja2.FileSystemLoader(template_path) file_loader = jinja2.FileSystemLoader(converted_template_path)
env = jinja2.Environment(loader=file_loader, autoescape=True) env = jinja2.Environment(loader=file_loader, autoescape=True)
# load the template contents # load the template contents
try: try:
@@ -91,25 +97,18 @@ class ScopedPageCreator(PageCreator):
self.extension = "" self.extension = ""
self._all_input_tokens: list[str] = [] self._all_input_tokens: list[str] = []
def create_page( def create_page(self, options: PageCreatorOptions) -> Page:
self, self.base_path = options.base_path
base_path: str, self.page_path = options.page_path
page_path: str, self.filename = options.filename
filename: str, self.extension = options.extension
extension: str,
name: str,
user_input: Collection[str],
template_filename: str | None = None,
) -> Page:
self.base_path = base_path
self.page_path = page_path
self.filename = filename
self.extension = extension
# verify the user input length matches the number of input tokens in the # verify the user input length matches the number of input tokens in the
# tembo config/templates # tembo config/templates
self._all_input_tokens = self._get_input_tokens(template_filename) self._all_input_tokens = self._get_input_tokens(
self._verify_input_tokens(user_input) options.template_filename, options.template_path
)
self._verify_input_tokens(options.user_input)
# get the path of the scoped page # get the path of the scoped page
path = self._convert_to_path( path = self._convert_to_path(
@@ -117,24 +116,32 @@ class ScopedPageCreator(PageCreator):
) )
# substitute tokens in the filepath # substitute tokens in the filepath
path = pathlib.Path(self._substitute_tokens(str(path), user_input, name)) path = pathlib.Path(
self._substitute_tokens(str(path), options.user_input, options.name)
)
# get the template file # get the template file
template_contents = self._get_template_contents(template_filename) template_contents = self._get_template_contents(
options.template_filename, options.template_path
)
# substitute tokens in template_contents # substitute tokens in template_contents
if template_filename is not None: if options.template_filename is not None:
template_contents = self._substitute_tokens( template_contents = self._substitute_tokens(
template_contents, user_input, name template_contents, options.user_input, options.name
) )
return ScopedPage(path, template_contents) return ScopedPage(path, template_contents)
def _get_input_tokens(self, template_filename: str | None) -> list[str]: def _get_input_tokens(
self, template_filename: str | None, template_path: str | None
) -> list[str]:
path = str( path = str(
pathlib.Path( pathlib.Path(
self.base_path, self.page_path, self.filename, self.extension self.base_path, self.page_path, self.filename, self.extension
).expanduser() ).expanduser()
) )
template_contents = self._get_template_contents(template_filename) template_contents = self._get_template_contents(
template_filename, template_path
)
# get the input tokens from both the path and the template # get the input tokens from both the path and the template
all_input_tokens = [] all_input_tokens = []
for tokenified_string in (path, template_contents): for tokenified_string in (path, template_contents):
@@ -150,9 +157,11 @@ class ScopedPageCreator(PageCreator):
) )
raise SystemExit(1) raise SystemExit(1)
def _get_template_contents(self, template_filename: str | None) -> str: def _get_template_contents(
self, template_filename: str | None, template_path: str | None
) -> str:
return ( return (
self._load_template(self.base_path, template_filename) self._load_template(self.base_path, template_filename, template_path)
if template_filename is not None if template_filename is not None
else "" else ""
) )

View File