diff --git a/TODO.todo b/TODO.todo index e3f56b2..831fb56 100644 --- a/TODO.todo +++ b/TODO.todo @@ -5,24 +5,41 @@ Priority: ☐ Write the tests ☐ test logs: document this - ☐ ☐ Docstrings 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` ☐ Look at how to use github actions Use for an example ☐ Build the docs using a github action. 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? - ☐ Use the python runner + ☐ Use the python runner Duty ☐ Run tests ☐ Update poetry ☐ Build docs ☐ Document using Duty +VSCode: + PyInstaller: + ☐ Document build error: + PYTHON_CONFIGURE_OPTS="--enable-framework" pyenv install 3.8.11 + ☐ Freeze a click app: + Tests: ☐ Write tests! @2d Use coverage as going along to make sure all bases are covered in the testing @@ -33,8 +50,6 @@ VSCode: Logging: Documentation: - ☐ a - Tembo: ☐ Document creating new Tembo config ☐ ~/tembo needs creating diff --git a/tembo/cli.py b/tembo/cli.py index 8740d44..3a9b071 100644 --- a/tembo/cli.py +++ b/tembo/cli.py @@ -1,9 +1,10 @@ +import sys + import click import tembo from tembo.journal import pages - 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 try: - config_scope = [ - ( - str(user_scope["name"]), - user_scope.get("example"), - str(user_scope["path"]), - str(user_scope["filename"]), - str(user_scope["extension"]), - user_scope.get("template_filename"), - ) + config_scope = { + option: str(user_scope[option]) + for option in [ + "name", + "example", + "path", + "filename", + "extension", + "template_filename", + ] for user_scope in tembo.CONFIG.scopes if user_scope["name"] == scope - ] + } except KeyError as key_error: # raise error if any non optional keys are missing 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: tembo.logger.info( "Example for 'tembo new %s': %s", - config_scope[0][0], - config_scope[0][1] + config_scope["name"], + config_scope["example"] if isinstance(config_scope[0][1], str) else "No example in config.yml", ) raise SystemExit(0) # if the name is in the config.yml, create the scoped page + page_creator_options = pages.PageCreatorOptions( + base_path=tembo.CONFIG.base_path, + page_path=config_scope["path"], + filename=config_scope["filename"], + extension=config_scope["extension"], + name=config_scope["name"], + user_input=inputs, + template_filename=config_scope["template_filename"], + template_path=tembo.CONFIG.template_path, + ) if _name_found: - scoped_page = pages.ScopedPageCreator().create_page( - base_path=str(tembo.CONFIG.base_path), - page_path=config_scope[0][2], - filename=config_scope[0][3], - extension=config_scope[0][4], - name=config_scope[0][0], - user_input=inputs, - template_filename=config_scope[0][5], - ) + scoped_page = pages.ScopedPageCreator().create_page(page_creator_options) scoped_page.save_to_disk(dry_run=dry_run) raise SystemExit(0) if not _name_found and len(tembo.CONFIG.scopes) > 0: @@ -121,5 +125,10 @@ run.add_command(list_all) if __name__ == "__main__": # new(["meeting", "robs presentation", "meeting on gcp"]) - new(["meeting", "a", "b", "c", "d", "--example"]) + new(["meeting", "a", "b", "c", "d"]) # new(["meeting", "robs presentation"]) + + # pyinstaller + # if getattr(sys, "frozen", False): + # run(sys.argv[1:]) + # run(sys.argv[1:]) diff --git a/tembo/journal/pages.py b/tembo/journal/pages.py index 96f5a4a..20bb3e6 100644 --- a/tembo/journal/pages.py +++ b/tembo/journal/pages.py @@ -1,6 +1,7 @@ from __future__ import annotations from abc import ABCMeta, abstractmethod +from dataclasses import dataclass import pathlib import re from typing import Collection @@ -12,18 +13,21 @@ import pendulum 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: @abstractmethod - def create_page( - self, - base_path: str, - page_path: str, - filename: str, - extension: str, - name: str, - user_input: Collection[str], - template_filename: str | None = None, - ) -> Page: + def create_page(self, options: PageCreatorOptions) -> Page: raise NotImplementedError @staticmethod @@ -50,17 +54,19 @@ class PageCreator: # return path with a file 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 - if tembo.CONFIG.template_path is not None: - template_path = self._convert_to_path( - "", tembo.CONFIG.template_path, "", "" - ) + if template_path is not None: + converted_template_path = self._convert_to_path("", template_path, "", "") else: # 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 - file_loader = jinja2.FileSystemLoader(template_path) + file_loader = jinja2.FileSystemLoader(converted_template_path) env = jinja2.Environment(loader=file_loader, autoescape=True) # load the template contents try: @@ -91,25 +97,18 @@ class ScopedPageCreator(PageCreator): self.extension = "" self._all_input_tokens: list[str] = [] - def create_page( - self, - base_path: str, - page_path: str, - filename: str, - 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 + def create_page(self, options: PageCreatorOptions) -> Page: + self.base_path = options.base_path + self.page_path = options.page_path + self.filename = options.filename + self.extension = options.extension # verify the user input length matches the number of input tokens in the # tembo config/templates - self._all_input_tokens = self._get_input_tokens(template_filename) - self._verify_input_tokens(user_input) + self._all_input_tokens = self._get_input_tokens( + options.template_filename, options.template_path + ) + self._verify_input_tokens(options.user_input) # get the path of the scoped page path = self._convert_to_path( @@ -117,24 +116,32 @@ class ScopedPageCreator(PageCreator): ) # 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 - 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 - if template_filename is not None: + if options.template_filename is not None: template_contents = self._substitute_tokens( - template_contents, user_input, name + template_contents, options.user_input, options.name ) 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( pathlib.Path( self.base_path, self.page_path, self.filename, self.extension ).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 all_input_tokens = [] for tokenified_string in (path, template_contents): @@ -150,9 +157,11 @@ class ScopedPageCreator(PageCreator): ) 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 ( - self._load_template(self.base_path, template_filename) + self._load_template(self.base_path, template_filename, template_path) if template_filename is not None else "" ) diff --git a/tests/test_journal/test_pages.py b/tests/test_journal/test_pages.py new file mode 100644 index 0000000..e69de29