replacing all calls to self.options

This commit is contained in:
2021-10-30 03:21:21 +01:00
parent 903fbf6b69
commit a6ec5a9f35
2 changed files with 60 additions and 81 deletions

View File

@@ -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)

View File

@@ -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