mirror of
https://github.com/dtomlinson91/tembo.git
synced 2025-12-22 05:55:44 +00:00
adding latest to cli
This commit is contained in:
@@ -3,13 +3,20 @@ Functionality:
|
|||||||
☐ Have an `--example` flag to `new` that prints an example given in the `config.yml`
|
☐ Have an `--example` flag to `new` that prints an example given in the `config.yml`
|
||||||
☐ Should be a `tembo new --list` to list all possible names.
|
☐ Should be a `tembo new --list` to list all possible names.
|
||||||
|
|
||||||
|
VSCode:
|
||||||
|
☐ Look at <https://github.com/CodeWithSwastik/vscode-ext>
|
||||||
|
|
||||||
Logging:
|
Logging:
|
||||||
☐ How to raise + debug an exception?
|
☐ How to raise + debug an exception?
|
||||||
|
☐ Document how to raise a logger.critical instead of exception
|
||||||
|
in a try, except you can just do logger.critical(exec_info=1) to print the stack
|
||||||
|
|
||||||
Documentation:
|
Documentation:
|
||||||
☐ Document usage of Panaetius in a module?
|
☐ Document usage of Panaetius in a module
|
||||||
|
Using the logger, initialising with the config path etc
|
||||||
☐ Uses Pendulum tokens: https://pendulum.eustace.io/docs/#tokens
|
☐ Uses Pendulum tokens: https://pendulum.eustace.io/docs/#tokens
|
||||||
☐ Document latest typing.
|
☐ Document latest typing.
|
||||||
☐ Using from `__future__` with `|`
|
☐ Using from `__future__` with `|`
|
||||||
☐ `using Tuple[str, ...]`
|
☐ `using Tuple[str, ...]`
|
||||||
☐ `Sequence` vs `Collection`
|
☐ `Sequence` vs `Collection`
|
||||||
|
☐ Document using jinja2 briefly and link to Tembo (link to <https://zetcode.com/python/jinja/>)
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ pep257:
|
|||||||
- D102
|
- D102
|
||||||
# Missing docstring in public function
|
# Missing docstring in public function
|
||||||
- D103
|
- D103
|
||||||
|
# Missing docstring in magic method
|
||||||
|
- D105
|
||||||
# One-line docstring should fit on one line with quotes
|
# One-line docstring should fit on one line with quotes
|
||||||
- D200
|
- D200
|
||||||
# No blank lines allowed after function docstring
|
# No blank lines allowed after function docstring
|
||||||
|
|||||||
36
tembo/cli.py
36
tembo/cli.py
@@ -1,6 +1,8 @@
|
|||||||
import click
|
import click
|
||||||
|
|
||||||
import tembo
|
import tembo
|
||||||
|
from tembo.journal import pages
|
||||||
|
|
||||||
|
|
||||||
CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
|
CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
|
||||||
|
|
||||||
@@ -32,27 +34,19 @@ def new(scope, inputs):
|
|||||||
Example: tembo new meeting my_presentation
|
Example: tembo new meeting my_presentation
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# for user_scope in tembo.CONFIG.scopes:
|
for user_scope in tembo.CONFIG.scopes:
|
||||||
# print(f"passed in scope: {scope}")
|
if user_scope["name"] == scope:
|
||||||
# print(f'config scope: {user_scope["name"]}')
|
scoped_page = pages.ScopedPageCreator().create_page(
|
||||||
# if user_scope["name"] == scope:
|
base_path=str(tembo.CONFIG.base_path),
|
||||||
# print(True)
|
page_path=str(user_scope["path"]),
|
||||||
|
filename=str(user_scope["filename"]),
|
||||||
# TODO: if user_scope["template"], check for a template in the templates dir. If it doesn't exist raise MissingTemplateError
|
extension=str(user_scope["extension"]),
|
||||||
|
name=str(user_scope["name"]),
|
||||||
# click.echo(inputs)
|
user_input=inputs,
|
||||||
# click.echo(type(inputs))
|
template_filename=str(user_scope["template_filename"]),
|
||||||
|
)
|
||||||
# if len(inputs) == 0, pass None is as user_input
|
scoped_page.save_to_disk()
|
||||||
|
tembo.logger.info("Saved %s to disk", scoped_page)
|
||||||
|
|
||||||
# TODO: decide on a date format to pass in
|
|
||||||
@click.command(options_metavar="<options>")
|
|
||||||
@click.option("--scope", "-s", help="The name of the scope in the Tembo config.yml.")
|
|
||||||
@click.option("--date", "-d", help="")
|
|
||||||
def archive(scope, date):
|
|
||||||
print(f"{scope}, {date}")
|
|
||||||
|
|
||||||
|
|
||||||
run.add_command(new)
|
run.add_command(new)
|
||||||
run.add_command(archive)
|
|
||||||
|
|||||||
@@ -1,9 +1 @@
|
|||||||
"""Tembo exceptions."""
|
"""Tembo exceptions."""
|
||||||
|
|
||||||
|
|
||||||
class BasePathDoesNotExistError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class MismatchingNumberOfInputTokensError(Exception):
|
|
||||||
pass
|
|
||||||
|
|||||||
@@ -7,10 +7,6 @@ import re
|
|||||||
import jinja2
|
import jinja2
|
||||||
import pendulum
|
import pendulum
|
||||||
|
|
||||||
from tembo.exceptions import (
|
|
||||||
BasePathDoesNotExistError,
|
|
||||||
MismatchingNumberOfInputTokensError,
|
|
||||||
) # noqa
|
|
||||||
from tembo import logger, CONFIG
|
from tembo import logger, CONFIG
|
||||||
|
|
||||||
|
|
||||||
@@ -24,7 +20,7 @@ class PageCreator:
|
|||||||
extension: str,
|
extension: str,
|
||||||
name: str,
|
name: str,
|
||||||
user_input: tuple[str, ...],
|
user_input: tuple[str, ...],
|
||||||
template_file: str | None = None,
|
template_filename: str | None = None,
|
||||||
) -> Page:
|
) -> Page:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -34,10 +30,8 @@ class PageCreator:
|
|||||||
) -> pathlib.Path:
|
) -> pathlib.Path:
|
||||||
# check if Tembo base path exists
|
# check if Tembo base path exists
|
||||||
if not pathlib.Path(base_path).expanduser().exists():
|
if not pathlib.Path(base_path).expanduser().exists():
|
||||||
logger.debug("base path of %s does not exist", base_path)
|
logger.critical("base path of %s does not exist - exiting", base_path)
|
||||||
raise BasePathDoesNotExistError(
|
raise SystemExit(1)
|
||||||
f"Your base path of {base_path} does not exist."
|
|
||||||
)
|
|
||||||
path_to_file = (
|
path_to_file = (
|
||||||
pathlib.Path(base_path).expanduser()
|
pathlib.Path(base_path).expanduser()
|
||||||
/ pathlib.Path(page_path).expanduser()
|
/ pathlib.Path(page_path).expanduser()
|
||||||
@@ -52,19 +46,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_file: str) -> str:
|
def _load_template(self, base_path: str, template_filename: str) -> str:
|
||||||
if CONFIG.template_path is not None:
|
if CONFIG.template_path is not None:
|
||||||
# check for overriden template_path
|
# check for overriden template_path
|
||||||
template_path = self._convert_to_path("", CONFIG.template_path, "", "")
|
template_path = self._convert_to_path("", 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", "", "")
|
template_path = self._convert_to_path(base_path, "templates", "", "")
|
||||||
print(template_path, template_file)
|
print(template_path, template_filename)
|
||||||
# load the template folder
|
# load the template folder
|
||||||
file_loader = jinja2.FileSystemLoader(template_path)
|
file_loader = jinja2.FileSystemLoader(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
|
||||||
loaded_template = env.get_template(template_file)
|
loaded_template = env.get_template(template_filename)
|
||||||
return loaded_template.render()
|
return loaded_template.render()
|
||||||
|
|
||||||
|
|
||||||
@@ -83,7 +77,7 @@ class ScopedPageCreator(PageCreator):
|
|||||||
extension: str,
|
extension: str,
|
||||||
name: str,
|
name: str,
|
||||||
user_input: tuple[str, ...] | None,
|
user_input: tuple[str, ...] | None,
|
||||||
template_file: str | None = None,
|
template_filename: str | None = None,
|
||||||
) -> Page:
|
) -> Page:
|
||||||
self.base_path = base_path
|
self.base_path = base_path
|
||||||
self.page_path = page_path
|
self.page_path = page_path
|
||||||
@@ -96,9 +90,9 @@ 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), user_input, name))
|
||||||
# get the template file
|
# get the template file
|
||||||
if template_file is not None:
|
if template_filename is not None:
|
||||||
# load the template file contents and substitute tokens
|
# load the template file contents and substitute tokens
|
||||||
template_contents = self._load_template(self.base_path, template_file)
|
template_contents = self._load_template(self.base_path, template_filename)
|
||||||
template_contents = self._substitute_tokens(
|
template_contents = self._substitute_tokens(
|
||||||
template_contents, user_input, name
|
template_contents, user_input, name
|
||||||
)
|
)
|
||||||
@@ -135,23 +129,26 @@ class ScopedPageCreator(PageCreator):
|
|||||||
if user_input is None:
|
if user_input is None:
|
||||||
# if there's no user input, but the regex matches, raise error
|
# if there's no user input, but the regex matches, raise error
|
||||||
if len(input_extraction) > 0:
|
if len(input_extraction) > 0:
|
||||||
raise MismatchingNumberOfInputTokensError(
|
logger.critical(
|
||||||
f"Your config specifies {len(input_extraction)} input tokens, "
|
"Your config/template specifies %s input tokens, you gave 0 "
|
||||||
f"you gave 0",
|
"- exiting",
|
||||||
|
len(input_extraction),
|
||||||
)
|
)
|
||||||
# if there aren't any tokens in the string, return it
|
raise SystemExit(1)
|
||||||
|
# if there aren't any tokens in the string, return the string
|
||||||
return tokenified_string
|
return tokenified_string
|
||||||
# if there is user input, check the number of tokens matches what's passed in
|
# if there is user input, check the number of tokens match what's passed in
|
||||||
if len(input_extraction) != len(user_input) and len(input_extraction) > 0:
|
if len(input_extraction) != len(user_input) and len(input_extraction) > 0:
|
||||||
# if there are input matches and they don't equal the number of input
|
# if there are input matches and they don't equal the number of input
|
||||||
# tokens, raise error
|
# tokens, raise error
|
||||||
logger.debug("MismatchingNumberOfInputTokensError")
|
logger.critical(
|
||||||
raise MismatchingNumberOfInputTokensError(
|
"Your config specifies %s input tokens, you gave %s - exiting",
|
||||||
f"Your config specifies {len(input_extraction)} input tokens, "
|
len(input_extraction),
|
||||||
f"you gave {len(user_input)}",
|
len(user_input),
|
||||||
)
|
)
|
||||||
# if the length of both matches and tokens match, or there arent any input
|
raise SystemExit(1)
|
||||||
# matches, then substitute each token with the user's input
|
# if the length of user input matches and number of tokens match, or there are
|
||||||
|
# no input matches, then substitute each token with the user's input
|
||||||
for extracted_input, input_value in zip(input_extraction, user_input):
|
for extracted_input, input_value in zip(input_extraction, user_input):
|
||||||
tokenified_string = tokenified_string.replace(extracted_input, input_value)
|
tokenified_string = tokenified_string.replace(extracted_input, input_value)
|
||||||
return tokenified_string
|
return tokenified_string
|
||||||
@@ -165,7 +162,7 @@ class ScopedPageCreator(PageCreator):
|
|||||||
strftime_value = re.match(r"\{d\:([^\}]*)\}", extracted_token)
|
strftime_value = re.match(r"\{d\:([^\}]*)\}", extracted_token)
|
||||||
if strftime_value:
|
if strftime_value:
|
||||||
strftime_value = strftime_value.group(1)
|
strftime_value = strftime_value.group(1)
|
||||||
# replace {d:DD-MM-YYYY} with todays format of DD-MM-YYYY
|
# replace {d:DD-MM-YYYY} with todays date formatted as DD-MM-YYYY
|
||||||
tokenified_string = tokenified_string.replace(
|
tokenified_string = tokenified_string.replace(
|
||||||
extracted_token, pendulum.now().format(strftime_value)
|
extracted_token, pendulum.now().format(strftime_value)
|
||||||
)
|
)
|
||||||
@@ -189,6 +186,9 @@ class ScopedPage(Page):
|
|||||||
self.path = path
|
self.path = path
|
||||||
self.page_content = page_content
|
self.page_content = page_content
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"ScopedPage({self.path})"
|
||||||
|
|
||||||
def save_to_disk(self) -> None:
|
def save_to_disk(self) -> None:
|
||||||
scoped_note_file = pathlib.Path(self.path)
|
scoped_note_file = pathlib.Path(self.path)
|
||||||
# create the parent directories
|
# create the parent directories
|
||||||
@@ -197,7 +197,8 @@ class ScopedPage(Page):
|
|||||||
if not scoped_note_file.exists():
|
if not scoped_note_file.exists():
|
||||||
with scoped_note_file.open("w", encoding="utf-8") as scoped_page:
|
with scoped_note_file.open("w", encoding="utf-8") as scoped_page:
|
||||||
scoped_page.write(self.page_content)
|
scoped_page.write(self.page_content)
|
||||||
logger.info("The file %s already exists - skipping.", str(scoped_note_file))
|
else:
|
||||||
|
logger.info("The file %s already exists - skipping.", str(scoped_note_file))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
@@ -260,6 +261,7 @@ if __name__ == "__main__":
|
|||||||
("last",),
|
("last",),
|
||||||
"scratchpad.md.tpl",
|
"scratchpad.md.tpl",
|
||||||
)
|
)
|
||||||
|
print(test_page_with_template)
|
||||||
test_page_with_template.save_to_disk()
|
test_page_with_template.save_to_disk()
|
||||||
# print(
|
# print(
|
||||||
# c.create_page(
|
# c.create_page(
|
||||||
|
|||||||
Reference in New Issue
Block a user