mirror of
https://github.com/dtomlinson91/tembo.git
synced 2025-12-22 07:55:45 +00:00
replacing all calls to self.options
This commit is contained in:
23
TODO.todo
23
TODO.todo
@@ -1,7 +1,4 @@
|
|||||||
Priority:
|
Priority:
|
||||||
✔ Document the python/logging/typing in Trilium @done(21-10-25 14:33)
|
|
||||||
✔ Update typing annotations to include generics instead @done(21-10-25 22:38)
|
|
||||||
https://docs.python.org/3/library/collections.abc.html#collections-abstract-base-classes
|
|
||||||
☐ 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
|
||||||
@@ -28,15 +25,8 @@ Documentation:
|
|||||||
☐ Can prospector ignore tests dir? document this in the gist if so
|
☐ Can prospector ignore tests dir? document this in the gist if so
|
||||||
|
|
||||||
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)
|
|
||||||
✔ Make example optional @done(21-10-29 00:15)
|
|
||||||
✔ Add the `--example` output to the miscounted token message so the user knows the correct command to use. @done(21-10-29 00:15)
|
|
||||||
✔ Page options dataclass @done(21-10-28 20:09)
|
|
||||||
☐ Make user_input optional @important
|
|
||||||
☐ 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?
|
||||||
✔ Look at `_convert_to_path()` and see if it can be rewritten to make it clearer when there isn't a base path. @done(21-10-30 02:14)
|
☐ Make options a property on the class, add to abstract
|
||||||
☐ Replace scoped page creator inputs so that the whole class uses the options dict rather than the variables passed around.
|
|
||||||
☐ Use the python runner Duty
|
☐ Use the python runner Duty
|
||||||
<https://github.com/pawamoy/duty>
|
<https://github.com/pawamoy/duty>
|
||||||
☐ Run tests
|
☐ Run tests
|
||||||
@@ -75,6 +65,17 @@ Logging:
|
|||||||
clone the repo, delete .git, git init, configure and add git origin
|
clone the repo, delete .git, git init, configure and add git origin
|
||||||
|
|
||||||
Archive:
|
Archive:
|
||||||
|
✔ Document the python/logging/typing in Trilium @done(21-10-25 14:33) @project(Priority)
|
||||||
|
✔ Update typing annotations to include generics instead @done(21-10-25 22:38) @project(Priority)
|
||||||
|
https://docs.python.org/3/library/collections.abc.html#collections-abstract-base-classes
|
||||||
|
✔ Move any `tembo.CONFIG` calls out of `pages.py` and ensure these are passed in from the cli. @done(21-10-28 19:44) @project(Functionality)
|
||||||
|
✔ Make `config scope` a dict in `cli.py`. @done(21-10-28 19:44) @project(Functionality)
|
||||||
|
✔ Make example optional @done(21-10-29 00:15) @project(Functionality)
|
||||||
|
✔ Add the `--example` output to the miscounted token message so the user knows the correct command to use. @done(21-10-29 00:15) @project(Functionality)
|
||||||
|
✔ Page options dataclass @done(21-10-28 20:09) @project(Functionality)
|
||||||
|
✔ Make user_input optional @important @done(21-10-30 03:20) @project(Functionality)
|
||||||
|
✔ Look at `_convert_to_path()` and see if it can be rewritten to make it clearer when there isn't a base path. @done(21-10-30 02:14) @project(Functionality)
|
||||||
|
✔ Replace scoped page creator inputs so that the whole class uses the options dict rather than the variables passed around. @done(21-10-30 03:20) @project(Functionality)
|
||||||
✔ Go through code TODOs @done(21-10-25 05:52) @project(Priority)
|
✔ Go through code TODOs @done(21-10-25 05:52) @project(Priority)
|
||||||
✔ Check code order and make sure things are where they should be @done(21-10-25 13:31) @project(Priority)
|
✔ Check code order and make sure things are where they should be @done(21-10-25 13:31) @project(Priority)
|
||||||
✔ Add version option @done(21-10-25 13:40) @project(Functionality)
|
✔ Add version option @done(21-10-25 13:40) @project(Functionality)
|
||||||
|
|||||||
@@ -42,28 +42,32 @@ class PageCreatorOptions:
|
|||||||
|
|
||||||
|
|
||||||
class PageCreator:
|
class PageCreator:
|
||||||
|
def __init__(self, options: PageCreatorOptions) -> None:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def create_page(self, options: PageCreatorOptions) -> Page:
|
def create_page(self, options: PageCreatorOptions) -> Page:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@staticmethod
|
def _convert_to_path(self) -> pathlib.Path:
|
||||||
def _convert_to_path(
|
|
||||||
base_path: str, page_path: str, filename: str, extension: str
|
|
||||||
) -> 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(self.options.base_path).expanduser().exists():
|
||||||
tembo.logger.critical(
|
tembo.logger.critical(
|
||||||
"Tembo base path of %s does not exist - exiting", base_path
|
"Tembo base path of %s does not exist - exiting", self.options.base_path
|
||||||
)
|
)
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
path_to_file = (
|
path_to_file = (
|
||||||
pathlib.Path(base_path).expanduser()
|
pathlib.Path(self.options.base_path).expanduser()
|
||||||
/ pathlib.Path(page_path.replace(" ", "_")).expanduser()
|
/ pathlib.Path(self.options.page_path.replace(" ", "_")).expanduser()
|
||||||
/ filename.replace(" ", "_")
|
/ self.options.filename.replace(" ", "_")
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
# check for existing `.` in the extension
|
# check for existing `.` in the extension
|
||||||
extension = extension[1:] if extension[0] == "." else extension
|
extension = (
|
||||||
|
self.options.extension[1:]
|
||||||
|
if self.options.extension[0] == "."
|
||||||
|
else self.options.extension
|
||||||
|
)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
# IndexError means the path is not a file, just a path
|
# IndexError means the path is not a file, just a path
|
||||||
return path_to_file
|
return path_to_file
|
||||||
@@ -107,20 +111,14 @@ class ScopedPageCreator(PageCreator):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
# self.base_path = ""
|
|
||||||
# self.page_path = ""
|
|
||||||
# self.filename = ""
|
|
||||||
# self.extension = ""
|
|
||||||
self._all_input_tokens: list[str] = []
|
self._all_input_tokens: list[str] = []
|
||||||
self.options: PageCreatorOptions
|
self.options: PageCreatorOptions
|
||||||
|
|
||||||
def create_page(self, options: PageCreatorOptions) -> Page:
|
def create_page(self, options: PageCreatorOptions) -> Page:
|
||||||
self.options = options
|
self.options = options
|
||||||
|
|
||||||
self._all_input_tokens = self._get_input_tokens(
|
self._all_input_tokens = self._get_input_tokens()
|
||||||
options.template_filename, options.template_path
|
self._verify_input_tokens()
|
||||||
)
|
|
||||||
self._verify_input_tokens(options.user_input, options.example)
|
|
||||||
|
|
||||||
path = self._convert_to_path(
|
path = self._convert_to_path(
|
||||||
self.options.base_path,
|
self.options.base_path,
|
||||||
@@ -128,34 +126,26 @@ class ScopedPageCreator(PageCreator):
|
|||||||
self.options.filename,
|
self.options.filename,
|
||||||
self.options.extension,
|
self.options.extension,
|
||||||
)
|
)
|
||||||
path = pathlib.Path(
|
path = pathlib.Path(self._substitute_tokens(str(path)))
|
||||||
self._substitute_tokens(str(path), options.user_input, options.name)
|
|
||||||
)
|
|
||||||
|
|
||||||
template_contents = self._get_template_contents(
|
template_contents = self._get_template_contents()
|
||||||
options.template_filename, options.template_path
|
|
||||||
)
|
|
||||||
if options.template_filename is not None:
|
if options.template_filename is not None:
|
||||||
template_contents = self._substitute_tokens(
|
template_contents = self._substitute_tokens(template_contents)
|
||||||
template_contents, options.user_input, options.name
|
|
||||||
)
|
|
||||||
|
|
||||||
return ScopedPage(path, template_contents)
|
return ScopedPage(path, template_contents)
|
||||||
|
|
||||||
def _get_template_contents(
|
def _get_template_contents(self) -> str:
|
||||||
self, template_filename: str | None, template_path: str | None
|
|
||||||
) -> str:
|
|
||||||
return (
|
return (
|
||||||
self._load_template(
|
self._load_template(
|
||||||
self.options.base_path, template_filename, template_path
|
self.options.base_path,
|
||||||
|
self.options.template_filename,
|
||||||
|
self.options.template_path,
|
||||||
)
|
)
|
||||||
if template_filename is not None
|
if self.options.template_filename is not None
|
||||||
else ""
|
else ""
|
||||||
)
|
)
|
||||||
|
|
||||||
def _get_input_tokens(
|
def _get_input_tokens(self) -> list[str]:
|
||||||
self, template_filename: str | None, template_path: str | None
|
|
||||||
) -> list[str]:
|
|
||||||
path = str(
|
path = str(
|
||||||
pathlib.Path(
|
pathlib.Path(
|
||||||
self.options.base_path,
|
self.options.base_path,
|
||||||
@@ -164,24 +154,20 @@ class ScopedPageCreator(PageCreator):
|
|||||||
self.options.extension,
|
self.options.extension,
|
||||||
).expanduser()
|
).expanduser()
|
||||||
)
|
)
|
||||||
template_contents = self._get_template_contents(
|
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):
|
||||||
all_input_tokens.extend(re.findall(r"(\{input\d*\})", tokenified_string))
|
all_input_tokens.extend(re.findall(r"(\{input\d*\})", tokenified_string))
|
||||||
return sorted(all_input_tokens)
|
return sorted(all_input_tokens)
|
||||||
|
|
||||||
def _verify_input_tokens(
|
def _verify_input_tokens(self) -> None:
|
||||||
self, user_input: Collection[str] | None, example: str | None
|
if len(self._all_input_tokens) > 0 and self.options.user_input is None:
|
||||||
) -> None:
|
if self.options.example is not None:
|
||||||
if len(self._all_input_tokens) > 0 and user_input is None:
|
|
||||||
if example is not None:
|
|
||||||
tembo.logger.critical(
|
tembo.logger.critical(
|
||||||
"Your tembo.config/template specifies %s input tokens, you gave 0. Example command: %s",
|
"Your tembo.config/template specifies %s input tokens, you gave 0. Example command: %s",
|
||||||
len(self._all_input_tokens),
|
len(self._all_input_tokens),
|
||||||
example,
|
self.options.example,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
tembo.logger.critical(
|
tembo.logger.critical(
|
||||||
@@ -189,58 +175,50 @@ class ScopedPageCreator(PageCreator):
|
|||||||
len(self._all_input_tokens),
|
len(self._all_input_tokens),
|
||||||
)
|
)
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
if user_input is None:
|
if self.options.user_input is None:
|
||||||
return
|
return
|
||||||
if len(self._all_input_tokens) != len(user_input):
|
if len(self._all_input_tokens) != len(self.options.user_input):
|
||||||
if example is not None:
|
if self.options.example is not None:
|
||||||
tembo.logger.critical(
|
tembo.logger.critical(
|
||||||
"Your tembo.config/template specifies %s input tokens, you gave %s. Example command: %s",
|
"Your tembo.config/template specifies %s input tokens, you gave %s. Example command: %s",
|
||||||
len(self._all_input_tokens),
|
len(self._all_input_tokens),
|
||||||
len(user_input),
|
len(self.options.user_input),
|
||||||
example,
|
self.options.example,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
tembo.logger.critical(
|
tembo.logger.critical(
|
||||||
"Your tembo.config/template specifies %s input tokens, you gave %s.",
|
"Your tembo.config/template specifies %s input tokens, you gave %s.",
|
||||||
len(self._all_input_tokens),
|
len(self._all_input_tokens),
|
||||||
len(user_input),
|
len(self.options.user_input),
|
||||||
)
|
)
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
return
|
return
|
||||||
|
|
||||||
def _substitute_tokens(
|
def _substitute_tokens(self, tokenified_string: str) -> str:
|
||||||
self,
|
|
||||||
tokenified_string: str,
|
|
||||||
user_input: Collection[str] | None,
|
|
||||||
name: str,
|
|
||||||
) -> str:
|
|
||||||
"""For a tokened string, substitute input, name and date tokens."""
|
"""For a tokened string, substitute input, name and date tokens."""
|
||||||
tokenified_string = self.__substitute_input_tokens(
|
tokenified_string = self.__substitute_input_tokens(tokenified_string)
|
||||||
tokenified_string, user_input
|
tokenified_string = self.__substitute_name_tokens(tokenified_string)
|
||||||
)
|
|
||||||
tokenified_string = self.__substitute_name_tokens(tokenified_string, name)
|
|
||||||
tokenified_string = self.__substitute_date_tokens(tokenified_string)
|
tokenified_string = self.__substitute_date_tokens(tokenified_string)
|
||||||
return tokenified_string
|
return tokenified_string
|
||||||
|
|
||||||
def __substitute_input_tokens(
|
def __substitute_input_tokens(self, tokenified_string: str) -> str:
|
||||||
self,
|
if self.options.user_input is not None:
|
||||||
tokenified_string: str,
|
for input_value, extracted_token in zip(
|
||||||
user_input: Collection[str] | None,
|
self.options.user_input, self._all_input_tokens
|
||||||
) -> str:
|
):
|
||||||
if user_input is not None:
|
|
||||||
for input_value, extracted_token in zip(user_input, self._all_input_tokens):
|
|
||||||
tokenified_string = tokenified_string.replace(
|
tokenified_string = tokenified_string.replace(
|
||||||
extracted_token, input_value.replace(" ", "_")
|
extracted_token, input_value.replace(" ", "_")
|
||||||
)
|
)
|
||||||
return tokenified_string
|
return tokenified_string
|
||||||
|
|
||||||
@staticmethod
|
def __substitute_name_tokens(self, tokenified_string: str) -> str:
|
||||||
def __substitute_name_tokens(tokenified_string: str, name: str) -> str:
|
|
||||||
"""Find any `{name}` tokens and substitute for the name value."""
|
"""Find any `{name}` tokens and substitute for the name value."""
|
||||||
|
|
||||||
name_extraction = re.findall(r"(\{name\})", tokenified_string)
|
name_extraction = re.findall(r"(\{name\})", tokenified_string)
|
||||||
for extracted_input in name_extraction:
|
for extracted_input in name_extraction:
|
||||||
tokenified_string = tokenified_string.replace(extracted_input, name)
|
tokenified_string = tokenified_string.replace(
|
||||||
|
extracted_input, self.options.name
|
||||||
|
)
|
||||||
return tokenified_string
|
return tokenified_string
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
Reference in New Issue
Block a user