From b1fda1fa8bdc7772186bf03de401b13497f3cf51 Mon Sep 17 00:00:00 2001 From: Daniel Tomlinson Date: Sun, 24 Oct 2021 21:56:04 +0100 Subject: [PATCH] adding latest --- TODO.todo | 4 + tembo/cli.py | 3 +- tembo/journal/pages.py | 164 ++++++++++++++++++++++------------------- 3 files changed, 96 insertions(+), 75 deletions(-) diff --git a/TODO.todo b/TODO.todo index 1287bf5..c956e6e 100644 --- a/TODO.todo +++ b/TODO.todo @@ -2,6 +2,10 @@ Functionality: ☐ Handle case where there are no scopes in the config and command is invoked. ☐ 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. + ☐ When template not found, raise a Tembo error + currently raises jinja2.exceptions.TemplateNotFound on line 62, in _load_template + ☐ Add update notification? + check pypi for latest version and compare to current ✔ `TEMBO_CONFIG` should follow same pattern as other env vars and be a python string when read in @done(21-10-24 05:31) VSCode: diff --git a/tembo/cli.py b/tembo/cli.py index b26acec..1978be1 100644 --- a/tembo/cli.py +++ b/tembo/cli.py @@ -62,5 +62,6 @@ run.add_command(new) if __name__ == "__main__": # BUG: fix this bug where input tokens are mismatched - new(["meeting", "robs presentation", "meeting on gcp"]) + # new(["meeting", "robs presentation", "meeting on gcp"]) + new(["meeting", "a", "b", "c"]) # new(["meeting", "robs presentation"]) diff --git a/tembo/journal/pages.py b/tembo/journal/pages.py index ae5b796..4398af0 100644 --- a/tembo/journal/pages.py +++ b/tembo/journal/pages.py @@ -69,9 +69,9 @@ class ScopedPageCreator(PageCreator): self.page_path = "" self.filename = "" self.extension = "" - self.path_date_tokens: Tuple[int, int] = (0, 0) - self.template_date_tokens: Tuple[int, int] = (0, 0) - + # TODO: rename these to input tokens + more sensible + self.path_input_tokens: Tuple[int, int] = (0, 0) + self.template_input_tokens: Tuple[int, int] = (0, 0) def create_page( self, @@ -92,77 +92,84 @@ class ScopedPageCreator(PageCreator): path = self._convert_to_path( self.base_path, self.page_path, self.filename, self.extension ) + # substitute tokens in the filepath - try: - path = pathlib.Path( - self._substitute_tokens(str(path), user_input, name, "path") - ) - except MismatchedTokenError as mismatched_path_error: - self.path_error = mismatched_path_error + path = pathlib.Path( + self._substitute_tokens(str(path), user_input, name, "path") + ) + if sum(self.path_input_tokens) > 0: + _highest_input_token_in_path = max(self.path_input_tokens) + else: + _highest_input_token_in_path = 0 + # get the template file if template_filename is not None: # load the template file contents and substitute tokens template_contents = self._load_template(self.base_path, template_filename) - try: - template_contents = self._substitute_tokens( - template_contents, user_input, name, "template" - ) - except MismatchedTokenError as mismatched_template_error: - self.template_error = mismatched_template_error + template_contents = self._substitute_tokens( + template_contents, user_input, name, "template" + ) + if sum(self.template_input_tokens) > 0: + _highest_input_token_in_template = max(self.template_input_tokens) + else: + _highest_input_token_in_template = 0 else: template_contents = "" - if self.path_error is not None or self.template_error is not None: - # self.__mismatched_token_error(path_error, template_error) - if self.path_error.args[0] > self.template_error.args[0]: - print("path_token_count > template_token_count") - elif self.template_error.args[0] > self.path_error.args[0]: - print("template_token_count > path_token_count") + + self.__check_input_token_mismatch( + _highest_input_token_in_path, _highest_input_token_in_template + ) return ScopedPage(path, template_contents) - # @staticmethod - # def __mismatched_token_error( - # path_error: MismatchedTokenError | None = None, - # template_error: MismatchedTokenError | None = None, - # ) -> None: - # if isinstance(path_error, MismatchedTokenError): - # path_token_count = path_error.args[0] - # # logger.critical( - # # "Your config specifies %s input tokens, you gave %s " "- exiting", - # # path_error.args[0], - # # path_error.args[1], - # # ) - # # raise SystemExit(1) - # if isinstance(template_error, MismatchedTokenError): - # template_token_count = template_error.args[0] - # # logger.critical( - # # "Your template specifies %s input tokens, you gave %s " "- exiting", - # # template_error.args[0], - # # template_error.args[1], - # # ) - # # raise SystemExit(1) - # if path_token_count > template_token_count: - # print("path_token_count > template_token_count") - # elif template_token_count > path_token_count: - # print("template_token_count > path_token_count") - # raise SystemExit(1) + def __check_input_token_mismatch( + self, _highest_input_token_in_path: int, _highest_input_token_in_template: int + ) -> None: + _highest_input_token_count = max( + _highest_input_token_in_path, _highest_input_token_in_template + ) + if _highest_input_token_in_path < _highest_input_token_count: + logger.critical( + "Your config/template specifies %s input tokens, you gave %s " + "- exiting", + _highest_input_token_count, + self.path_input_tokens[0], + ) + raise SystemExit(1) + if _highest_input_token_in_path > _highest_input_token_count: + logger.warning( + "Your config/template specifies %s input tokens, you gave %s", + _highest_input_token_count, + self.path_input_tokens[0], + ) + if _highest_input_token_in_template < _highest_input_token_count: + logger.critical( + "Your config/template specifies %s input tokens, you gave %s " + "- exiting", + _highest_input_token_count, + self.template_input_tokens[0], + ) + raise SystemExit(1) + if _highest_input_token_in_template > _highest_input_token_count: + logger.warning( + "Your config/template specifies %s input tokens, you gave %s", + _highest_input_token_count, + self.template_input_tokens[0], + ) - # TODO: change the annotation to include the error def _substitute_tokens( self, tokenified_string: str, user_input: Tuple[str, ...] | Tuple[()], name: str, - token_type: Literal["path", "template"], + input_token_type: Literal["path", "template"], ) -> str: - # for a tokened string, substitute input, name and date tokens - try: - tokenified_string = self.__substitute_input_tokens( - tokenified_string, user_input - ) - tokenified_string = self.__substitute_name_tokens(tokenified_string, name) - tokenified_string = self.__substitute_date_tokens(tokenified_string) - except MismatchedTokenError as mismatched_token_error: - raise mismatched_token_error + """For a tokened string, substitute input, name and date tokens.""" + + tokenified_string = self.__substitute_input_tokens( + tokenified_string, user_input, input_token_type + ) + tokenified_string = self.__substitute_name_tokens(tokenified_string, name) + tokenified_string = self.__substitute_date_tokens(tokenified_string) return tokenified_string @staticmethod @@ -175,28 +182,35 @@ class ScopedPageCreator(PageCreator): # @staticmethod def __substitute_input_tokens( - self, tokenified_string: str, user_input: Tuple[str, ...] | Tuple[()] + self, + tokenified_string: str, + user_input: Tuple[str, ...] | Tuple[()], + input_token_type: Literal["path", "template"], ) -> str: - # find {inputN} tokens in string + """Find `{inputN}` tokens in string.""" + input_extraction = re.findall(r"(\{input\d*\})", tokenified_string) + # if there is no user input if len(user_input) == 0: - # if there's no user input, but the regex matches, raise error if len(input_extraction) > 0: - raise MismatchedTokenError(len(input_extraction), 0) + # if the regex matches, save the number of input tokens found + if input_token_type == "path": # noqa: bandit 105 + # TODO: change this to a dict instead of tuple + self.path_input_tokens = (len(input_extraction), 0) + if input_token_type == "template": # noqa: bandit 105 + self.template_input_tokens = (len(input_extraction), 0) # if there aren't any tokens in the string, return the string return tokenified_string - # if there is user input, check the number of tokens match the number passed in - if ( - len(input_extraction) > 0 - and len(input_extraction) != len(user_input) - and len(user_input) > 0 - ): - # if there are input matches and they don't equal the number of input - # tokens, raise error - raise MismatchedTokenError(len(input_extraction), len(user_input)) - # if the length of both the input matches and the number of tokens match then - # substitute each token with the user's input + + # if there is user input if len(user_input) > 0: + # save the number of input tokens, and the number of user inputs + if input_token_type == "path": # noqa: bandit 105 + self.path_input_tokens = (len(input_extraction), len(user_input)) + elif input_token_type == "template": # noqa: bandit 105 + self.template_input_tokens = (len(input_extraction), len(user_input)) + + # sbustitute the input token for the user's input for extracted_input, input_value in zip(input_extraction, user_input): tokenified_string = tokenified_string.replace( extracted_input, input_value @@ -205,7 +219,9 @@ class ScopedPageCreator(PageCreator): @staticmethod def __substitute_date_tokens(tokenified_string: str) -> str: - # find any {d:%d-%M-%Y} tokens + """Find any {d:%d-%M-%Y} tokens.""" + + # extract the full token string date_extraction_token = re.findall(r"(\{d\:[^}]*\})", tokenified_string) for extracted_token in date_extraction_token: # extract the inner %d-%M-%Y only