Merge branch 'refactor/create_exceptions' into develop

This commit is contained in:
2021-11-01 14:11:24 +00:00
13 changed files with 512 additions and 191 deletions

View File

@@ -13,22 +13,47 @@ Documentation:
☐ Document using `__main__.py` and `cli.py`
Use Duty as an example
☐ Document regex usage
☐ Write documentation using `mkdocs`
☐ Create a boilerplate `duties.py` for common tasks for future projects. Put in a gist.
☐ Look at how to use github actions
Use <https://github.com/pdm-project/pdm/tree/main/.github/workflows> for an example
☐ Build the docs using a github action.
☐ Document how to use pytest to read a logging message
<https://stackoverflow.com/questions/53125305/testing-logging-output-with-pytest>
- caplog as fixture
- reading `caplog.records[0].message`
see `_old_test_pages.py`
☐ Document testing value of an exception raised
When you use `with pytest.raises` you can use `.value` to access the attributes
reading `.value.code`
reading `str(.value)`
☐ Document working with exceptions
☐ General pattern - raise exceptions in codebase, catch them in the CLI.
Allows people to use via an API and handle the exceptions themselves.
You can use python builtins but custom exceptions are better for internal control
☐ Capturing exceptions in the CLI.
Access the message of the exception with `.args[0]`.
use `raise SystemExit(1) from exception` in order to gracefully exit
☐ Adding custom args to an exception
Overwrite `__init__`, access them in pytest with `.value.$args`
Access them in a try,except with `raise $excpetion as $name; $name.$arg`
☐ Document using datadir with a module rather than a shared one. Link to tembo as an example.
☐ Can prospector ignore tests dir? document this in the gist if so
☐ Redo the documentation on a CLI, reorganise and inocropoate all the new tembo layouts
Functionality:
☐ Replace loggers with `click.echo` for command outputs. Keep logging messages for actual logging messages?
Define a format: [TEMBO:$datetime] $message 🐘 - document this in general python for CLI
☐ Refactor the tembo new command so the cli is split out into manageable methods
☐ Use the complicated CLI example so the tembo new has its own module to define functions in
☐ Replace all logger errors with exceptions, move logger messages to the cli.
☐ How to pass a successful save notification back to the CLI? Return a bool? Or is there some other way?
☐ Replace pendulum with datetime
✔ Make options a property on the class, add to abstract @done(21-10-30 19:31)
☐ Use the python runner Duty
<https://github.com/pawamoy/duty>
@@ -37,6 +62,10 @@ Functionality:
☐ Build docs
☐ Document using Duty
Logging:
☐ Make all internal tembo logs be debug
☐ User can enable them with the config
VSCode:
PyInstaller:
☐ Document build error: <https://github.com/pyenv/pyenv/issues/1095>

View File

@@ -1,57 +1,39 @@
# testing notes
## options
optional:
- user_input
- example
- template_filename
- template_path
required:
- base_path
- page_path
- filename
- extension
- name
## tests to write
- page with/without a template
- user input is None
- the given base path does not exist
- page using/not using input tokens
- user input does not match number of input tokens
- no user input
- mismatched user input
- with/without example
- page using/not using date tokens
- page using/not using name tokens
- dry run
## tests done
- path/page filenames can contain spaces and they are converted
@dataclass
class PageCreatorOptions:
"""Options dataclass to create a Page.
Attributes:
base_path (str):
page_path (str):
filename (str):
extension (str):
name (str):
user_input (Collection[str] | None, optional):
example (str | None, optional):
template_filename (str | None, optional):
template_path (str | None, optional):
"""
base_path: str
page_path: str
filename: str
extension: str
name: str
user_input: Collection[str] | None = None
example: str | None = None
template_filename: str | None = None
template_path: str | None = None
- user input is None
- page using/not using input tokens
- page using/not using date tokens
- page using/not using name tokens
- page with/without a template
- the given base path does not exist
- the given template file does not exist
- page already exists

View File

@@ -2,6 +2,7 @@ import click
import tembo
from tembo.journal import pages
from tembo import exceptions
CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
@@ -112,9 +113,40 @@ def new(scope, inputs, dry_run, example):
template_path=tembo.CONFIG.template_path,
)
if _name_found:
scoped_page = pages.ScopedPageCreator().create_page(page_creator_options)
scoped_page.save_to_disk(dry_run=dry_run)
raise SystemExit(0)
try:
scoped_page = pages.ScopedPageCreator(page_creator_options).create_page()
except exceptions.BasePathDoesNotExistError as base_path_does_not_exist_error:
tembo.logger.critical(base_path_does_not_exist_error)
raise SystemExit(1) from base_path_does_not_exist_error
except exceptions.TemplateFileNotFoundError as template_file_not_found_error:
tembo.logger.critical(template_file_not_found_error.args[0])
raise SystemExit(1) from template_file_not_found_error
except exceptions.MismatchedTokenError as mismatched_token_error:
if config_scope["example"] is not None:
tembo.logger.critical(
"Your tembo config.yml/template specifies %s input tokens, you gave %s. Example: %s",
mismatched_token_error.expected,
mismatched_token_error.given,
config_scope["example"],
)
raise SystemExit(1) from mismatched_token_error
tembo.logger.critical(
"Your tembo config.yml/template specifies %s input tokens, you gave %s",
mismatched_token_error.expected,
mismatched_token_error.given,
)
raise SystemExit(1) from mismatched_token_error
if dry_run:
click.echo(cli_message(f"{scoped_page.path} will be created"))
raise SystemExit(0)
try:
scoped_page.save_to_disk()
raise SystemExit(0)
except exceptions.ScopedPageAlreadyExists as scoped_page_already_exists:
cli_message(f"File {scoped_page_already_exists}")
raise SystemExit(0) from scoped_page_already_exists
if not _name_found and len(tembo.CONFIG.scopes) > 0:
# if the name is missing in the config.yml, raise error
tembo.logger.warning("Command %s not found in config.yml - exiting", scope)
@@ -127,13 +159,17 @@ def new(scope, inputs, dry_run, example):
raise SystemExit(1)
def cli_message(message: str) -> None:
click.echo(f"[TEMBO] {message} 🐘")
run.add_command(new)
run.add_command(list_all)
if __name__ == "__main__":
# new(["meeting", "robs presentation", "meeting on gcp"])
new(["meeting", "a", "b", "c", "d"])
new(["meeting", "a", "b", "c", "d", "e"])
# new(["meeting", "robs presentation"])
# pyinstaller

View File

@@ -2,8 +2,19 @@
class MismatchedTokenError(Exception):
pass
def __init__(self, expected: int, given: int) -> None:
self.expected = expected
self.given = given
super().__init__()
class BasePathDoesNotExistError(Exception):
pass
"""Raised if the base path does not exist."""
class TemplateFileNotFoundError(Exception):
"""Raised if the template file does not exist."""
class ScopedPageAlreadyExists(Exception):
"""Raised if the scoped page file already exists."""

View File

@@ -11,6 +11,7 @@ import jinja2
from jinja2.exceptions import TemplateNotFound
import tembo
from tembo import exceptions
# TODO: flesh this out with details for the optional args
@@ -42,6 +43,7 @@ class PageCreatorOptions:
class PageCreator:
@abstractmethod
def __init__(self, options: PageCreatorOptions) -> None:
raise NotImplementedError
@@ -51,31 +53,27 @@ class PageCreator:
raise NotImplementedError
@abstractmethod
def create_page(self, options: PageCreatorOptions) -> Page:
def create_page(self) -> Page:
raise NotImplementedError
def _convert_base_path_to_path(self) -> pathlib.Path:
# check if Tembo base path exists
def _check_base_path_exists(self) -> None:
if not pathlib.Path(self.options.base_path).expanduser().exists():
tembo.logger.critical(
"Tembo base path of %s does not exist - exiting", self.options.base_path
raise exceptions.BasePathDoesNotExistError(
f"Tembo base path of {self.options.base_path} does not exist."
)
raise SystemExit(1)
def _convert_base_path_to_path(self) -> pathlib.Path:
path_to_file = (
pathlib.Path(self.options.base_path).expanduser()
/ pathlib.Path(self.options.page_path.replace(" ", "_")).expanduser()
/ self.options.filename.replace(" ", "_")
)
try:
# check for existing `.` in the extension
extension = (
self.options.extension[1:]
if self.options.extension[0] == "."
else self.options.extension
)
except IndexError:
# IndexError means the path is not a file, just a path
return path_to_file
# check for existing `.` in the extension
extension = (
self.options.extension[1:]
if self.options.extension[0] == "."
else self.options.extension
)
# return path with a file
return path_to_file.with_suffix(f".{extension}")
@@ -87,18 +85,20 @@ class PageCreator:
self.options.template_path
).expanduser()
else:
converted_template_path = pathlib.Path()
converted_template_path = (
pathlib.Path(self.options.base_path).expanduser() / ".templates"
)
file_loader = jinja2.FileSystemLoader(converted_template_path)
env = jinja2.Environment(loader=file_loader, autoescape=True)
try:
loaded_template = env.get_template(self.options.template_filename)
except TemplateNotFound as template_not_found:
tembo.logger.critical(
"Template file %s not found - exiting",
str(self.options.template_path) + "/" + str(template_not_found.message),
)
raise SystemExit(1) from template_not_found
_template_file = f"{converted_template_path}/{template_not_found.args[0]}"
raise exceptions.TemplateFileNotFoundError(
f"Template file {_template_file} does not exist."
) from template_not_found
return loaded_template.render()
@@ -112,16 +112,16 @@ class ScopedPageCreator(PageCreator):
extension (str): extension of file.
"""
def __init__(self) -> None:
def __init__(self, options: PageCreatorOptions) -> None:
self._all_input_tokens: list[str] = []
self._options: PageCreatorOptions
self._options = options
@property
def options(self) -> PageCreatorOptions:
return self._options
def create_page(self, options: PageCreatorOptions) -> Page:
self._options = options
def create_page(self) -> Page:
self._check_base_path_exists()
self._all_input_tokens = self._get_input_tokens()
self._verify_input_tokens()
@@ -130,7 +130,7 @@ class ScopedPageCreator(PageCreator):
path = pathlib.Path(self._substitute_tokens(str(path)))
template_contents = self._load_template()
if options.template_filename is not None:
if self.options.template_filename is not None:
template_contents = self._substitute_tokens(template_contents)
return ScopedPage(path, template_contents)
@@ -141,8 +141,9 @@ class ScopedPageCreator(PageCreator):
self.options.base_path,
self.options.page_path,
self.options.filename,
self.options.extension,
).expanduser()
)
.expanduser()
.with_suffix(f".{self.options.extension}")
)
template_contents = self._load_template()
# get the input tokens from both the path and the template
@@ -153,35 +154,16 @@ class ScopedPageCreator(PageCreator):
def _verify_input_tokens(self) -> None:
if len(self._all_input_tokens) > 0 and self.options.user_input is None:
if self.options.example is not None:
tembo.logger.critical(
"Your tembo.config/template specifies %s input tokens, you gave 0. Example command: %s",
len(self._all_input_tokens),
self.options.example,
)
else:
tembo.logger.critical(
"Your tembo.config/template specifies %s input tokens, you gave 0.",
len(self._all_input_tokens),
)
raise SystemExit(1)
raise exceptions.MismatchedTokenError(
expected=len(self._all_input_tokens), given=0
)
if self.options.user_input is None:
return
if len(self._all_input_tokens) != len(self.options.user_input):
if self.options.example is not None:
tembo.logger.critical(
"Your tembo.config/template specifies %s input tokens, you gave %s. Example command: %s",
len(self._all_input_tokens),
len(self.options.user_input),
self.options.example,
)
else:
tembo.logger.critical(
"Your tembo.config/template specifies %s input tokens, you gave %s.",
len(self._all_input_tokens),
len(self.options.user_input),
)
raise SystemExit(1)
raise exceptions.MismatchedTokenError(
expected=len(self._all_input_tokens),
given=len(self.options.user_input),
)
return
def _substitute_tokens(self, tokenified_string: str) -> str:
@@ -235,7 +217,7 @@ class Page(metaclass=ABCMeta):
raise NotImplementedError
@abstractmethod
def save_to_disk(self, dry_run: bool) -> None:
def save_to_disk(self) -> None:
raise NotImplementedError
@@ -260,7 +242,7 @@ class ScopedPage(Page):
def __str__(self) -> str:
return f"ScopedPage({self.path})"
def save_to_disk(self, dry_run: bool = False) -> None:
def save_to_disk(self) -> None:
"""Save the scoped page to disk and write the `page_content`.
If the page already exists a message will be logged to stdout and no file
@@ -276,91 +258,15 @@ class ScopedPage(Page):
SystemExit: Exit code 0 if dry run is `True`, page is successfully saved
or if page already exists.
"""
if dry_run:
tembo.logger.info("%s will be created", self.path)
raise SystemExit(0)
# TODO: move this functionality to the CLI so the page is created and the message
# returned to the user from the CLI.
# create the parent directories
scoped_note_file = pathlib.Path(self.path)
scoped_note_file.parents[0].mkdir(parents=True, exist_ok=True)
if not scoped_note_file.exists():
with scoped_note_file.open("w", encoding="utf-8") as scoped_page:
scoped_page.write(self.page_content)
tembo.logger.info("Saved %s to disk", self.path)
else:
tembo.logger.info("%s already exists - skipping.", self.path)
raise SystemExit(0)
scoped_page_file = pathlib.Path(self.path)
scoped_page_file.parents[0].mkdir(parents=True, exist_ok=True)
if scoped_page_file.exists():
raise exceptions.ScopedPageAlreadyExists(f"{self.path} already exists")
if __name__ == "__main__":
c = ScopedPageCreator()
# # raises error
# # print(c._substitute_tokens("scratchpad/{input0}-{d:DD-MM-YYYY}-{d:dddd}-{d:A}-file.md", None))
# print(
# c._substitute_tokens(
# "scratchpad/{d:A}/{d:DD-MM-YYYY}-{d:dddd}-{d:A}-file-{input0}.md", ("last",)
# )
# )
# print(
# c.create_page(
# "~/tembo",
# "{name}",
# "{input0}-{input1}-file",
# "md",
# "scratchpad",
# ("first", "second"),
# )
# )
# print(
# c.create_page(
# "~/tembo",
# "{name}/{d:MMMM-YY}",
# "{input0}-{d:DD-MM-YYYY}-{d:dddd}-{d:A}-file",
# "md",
# "scratchpad",
# ("first",),
# )
# )
# print(
# c.create_page(
# "~/tembo",
# "{name}/{d:DD-MM-YYYY}-{d:dddd}-{d:A}",
# "file",
# "md",
# "scratchpad",
# None,
# )
# )
# print(
# c.create_page(
# "~/tembo",
# "{name}/{d:A}/{d:DD-MM-YYYY}-{d:dddd}-{d:A}",
# "file-{input0}-{name}",
# ".md",
# "meeting",
# ("last",),
# "scratchpad.md.tpl",
# )
# )
# test_page_with_template = c.create_page(
# "~/tembo",
# "{name}/{d:A}/{d:DD-MM-YYYY}-{d:dddd}-{d:A}",
# "file-{input0}-{name}",
# ".md",
# "meeting",
# ("last",),
# "scratchpad.md.tpl",
# )
# print(test_page_with_template)
# test_page_with_template.save_to_disk(False)
# print(
# c.create_page(
# "~/tembo",
# "{name}/{d:A}/{d:DD-MM-YYYY}-{d:dddd}-{d:A}",
# "file-{input0}-{name}",
# ".md",
# "meeting",
# ("last",),
# "scratchpad_templates/scratchpad.md.tpl",
# )
# )
with scoped_page_file.open("w", encoding="utf-8") as scoped_page:
scoped_page.write(self.page_content)
# TODO: pass this back somehow
tembo.logger.info("Saved %s to disk", self.path)

View File

@@ -1,9 +1,16 @@
from datetime import date
import pathlib
import pytest
from tembo.journal.pages import PageCreatorOptions, ScopedPageCreator
from tembo import exceptions
def test_create_page_base_path_does_not_exist(tmpdir, caplog):
DATE_TODAY = date.today().strftime("%d-%m-%Y")
def test_create_page_base_path_does_not_exist(tmpdir):
# arrange
base_path = str(tmpdir / "nonexistent" / "path")
options = PageCreatorOptions(
@@ -19,13 +26,356 @@ def test_create_page_base_path_does_not_exist(tmpdir, caplog):
)
# act
with pytest.raises(SystemExit) as system_exit:
scoped_page_creator = ScopedPageCreator().create_page(options)
with pytest.raises(
exceptions.BasePathDoesNotExistError
) as base_path_does_not_exist_error:
scoped_page = ScopedPageCreator(options).create_page()
# assert
assert system_exit.value.code == 1
assert (
caplog.records[0].message
== f"Tembo base path of {base_path} does not exist - exiting"
str(base_path_does_not_exist_error.value)
== f"Tembo base path of {base_path} does not exist."
)
assert caplog.records[0].levelname == "CRITICAL"
@pytest.mark.parametrize("template_path", [(None), ("/nonexistent/path")])
def test_create_page_template_file_does_not_exist(template_path, tmpdir):
# arrange
options = PageCreatorOptions(
base_path=str(tmpdir),
page_path="some_path",
filename="some_filename",
extension="some_extension",
name="some_name",
user_input=None,
example=None,
template_filename="template.md.tpl",
template_path=template_path,
)
# act
with pytest.raises(
exceptions.TemplateFileNotFoundError
) as template_file_not_found_error:
scoped_page = ScopedPageCreator(options).create_page()
# assert
if template_path is None:
assert str(template_file_not_found_error.value) == (
f"Template file {options.base_path}/.templates/{options.template_filename} does not exist."
)
else:
assert str(template_file_not_found_error.value) == (
f"Template file {template_path}/{options.template_filename} does not exist."
)
def test_create_page_already_exists(datadir):
# arrange
options = PageCreatorOptions(
base_path=str(datadir),
page_path="does_exist",
filename="some_note",
extension="md",
name="some_name",
user_input=None,
example=None,
template_filename=None,
template_path=None,
)
scoped_page_file = (
pathlib.Path(options.base_path) / options.page_path / options.filename
).with_suffix(f".{options.extension}")
# act
scoped_page = ScopedPageCreator(options).create_page()
with pytest.raises(exceptions.ScopedPageAlreadyExists) as page_already_exists:
scoped_page.save_to_disk()
# assert
assert scoped_page_file.exists()
assert str(page_already_exists.value) == f"{scoped_page_file} already exists"
with scoped_page_file.open("r", encoding="utf-8") as scoped_page_contents:
assert scoped_page_contents.readlines() == ["this file already exists\n"]
def test_create_page_without_template(tmpdir, caplog):
# arrange
options = PageCreatorOptions(
base_path=str(tmpdir),
page_path="some_path",
filename="some_filename",
extension="some_extension",
name="some_name",
user_input=None,
example=None,
template_filename=None,
template_path=None,
)
# TODO: copy this pattern creation into the other tests
scoped_page_file = (
pathlib.Path(options.base_path) / options.page_path / options.filename
).with_suffix(f".{options.extension}")
# act
scoped_page = ScopedPageCreator(options).create_page()
scoped_page.save_to_disk()
# assert
assert scoped_page_file.exists()
assert caplog.records[0].message == f"Saved {scoped_page_file} to disk"
with scoped_page_file.open("r", encoding="utf-8") as scoped_page_contents:
assert scoped_page_contents.readlines() == []
def test_create_page_with_template(datadir, caplog):
# arrange
options = PageCreatorOptions(
base_path=str(datadir),
page_path="some_path",
filename="some_note",
extension="md",
name="some_name",
user_input=None,
example=None,
template_filename="some_template_no_tokens.md.tpl",
template_path=None,
)
scoped_page_file = (
pathlib.Path(options.base_path) / options.page_path / options.filename
).with_suffix(f".{options.extension}")
# act
scoped_page = ScopedPageCreator(options).create_page()
scoped_page.save_to_disk()
# assert
assert scoped_page_file.exists()
assert caplog.records[0].message == f"Saved {scoped_page_file} to disk"
with scoped_page_file.open("r", encoding="utf-8") as scoped_page_contents:
assert scoped_page_contents.readlines() == [
"scoped page file\n",
"\n",
"no tokens",
]
@pytest.mark.parametrize(
"user_input,template_filename,page_contents",
[
(None, "some_template_date_tokens.md.tpl", f"some date token: {DATE_TODAY}"),
(
("first_input", "second_input"),
"some_template_input_tokens.md.tpl",
"some input tokens second_input first_input",
),
(None, "some_template_name_tokens.md.tpl", "some name token some_name"),
],
)
def test_create_tokened_page_tokens_in_template(
datadir, caplog, user_input, template_filename, page_contents
):
# arrange
options = PageCreatorOptions(
base_path=str(datadir),
page_path="some_path",
filename="some_note",
extension="md",
name="some_name",
user_input=user_input,
example=None,
template_filename=template_filename,
template_path=None,
)
scoped_page_file = (
pathlib.Path(options.base_path) / options.page_path / options.filename
).with_suffix(f".{options.extension}")
# act
scoped_page = ScopedPageCreator(options).create_page()
scoped_page.save_to_disk()
# assert
assert scoped_page_file.exists()
assert caplog.records[0].message == f"Saved {scoped_page_file} to disk"
with scoped_page_file.open("r", encoding="utf-8") as scoped_page_contents:
assert scoped_page_contents.readline() == page_contents
@pytest.mark.parametrize(
"user_input,filename,tokened_filename",
[
(None, "date_token_{d:%d-%m-%Y}", f"date_token_{DATE_TODAY}"),
(None, "name_token_{name}", "name_token_some_name"),
(
("first_input", "second input"),
"input_token_{input1}_{input0}",
"input_token_second_input_first_input",
),
],
)
def test_create_tokened_page_tokens_in_filename(
datadir, caplog, user_input, filename, tokened_filename
):
# arrange
options = PageCreatorOptions(
base_path=str(datadir),
page_path="some_path",
filename=filename,
extension="md",
name="some_name",
user_input=user_input,
example=None,
template_filename=None,
template_path=None,
)
scoped_page_file = (
pathlib.Path(options.base_path) / options.page_path / tokened_filename
).with_suffix(f".{options.extension}")
# act
scoped_page = ScopedPageCreator(options).create_page()
scoped_page.save_to_disk()
# assert
assert scoped_page_file.exists()
assert caplog.records[0].message == f"Saved {scoped_page_file} to disk"
def test_create_tokened_page_input_tokens_preserve_order(datadir, caplog):
# arrange
tokened_filename = "input_token_fourth_input_first_input"
options = PageCreatorOptions(
base_path=str(datadir),
page_path="some_path",
filename="input_token_{input3}_{input0}",
extension="md",
name="some_name",
user_input=("first_input", "second_input", "third_input", "fourth_input"),
example=None,
template_filename="some_template_input_tokens_preserve_order.md.tpl",
template_path=None,
)
scoped_page_file = (
pathlib.Path(options.base_path) / options.page_path / tokened_filename
).with_suffix(f".{options.extension}")
# act
scoped_page = ScopedPageCreator(options).create_page()
scoped_page.save_to_disk()
# assert
assert scoped_page_file.exists()
assert caplog.records[0].message == f"Saved {scoped_page_file} to disk"
with scoped_page_file.open(mode="r", encoding="utf-8") as scoped_page_contents:
assert scoped_page_contents.readline() == "third_input second_input"
@pytest.mark.parametrize(
"user_input,expected,given",
[
(None, 3, 0),
(("first_input", "second_input"), 3, 2),
(("first_input", "second_input", "third_input", "fourth_input"), 3, 4),
],
)
def test_create_page_mismatched_tokens(tmpdir, user_input, expected, given):
# arrange
options = PageCreatorOptions(
base_path=str(tmpdir),
page_path="some_path",
filename="input_token_{input0}_{input1}_{input2}",
extension="md",
name="some_name",
user_input=user_input,
example=None,
template_filename=None,
template_path=None,
)
# act
with pytest.raises(exceptions.MismatchedTokenError) as mismatched_token_error:
scoped_page = ScopedPageCreator(options).create_page()
# assert
assert mismatched_token_error.value.expected == expected
assert mismatched_token_error.value.given == given
def test_create_page_spaces_in_path(tmpdir, caplog):
# arrange
options = PageCreatorOptions(
base_path=str(tmpdir),
page_path="some path with a space",
filename="some filename with a space",
extension="md",
name="some_name",
user_input=None,
example=None,
template_filename=None,
template_path=None,
)
scoped_page_file = (
pathlib.Path(options.base_path)
/ options.page_path.replace(" ", "_")
/ options.filename.replace(" ", "_")
).with_suffix(f".{options.extension}")
# act
scoped_page = ScopedPageCreator(options).create_page()
scoped_page.save_to_disk()
# assert
assert scoped_page_file.exists()
assert caplog.records[0].message == f"Saved {scoped_page_file} to disk"
def test_create_page_dot_in_extension(tmpdir, caplog):
# arrange
options = PageCreatorOptions(
base_path=str(tmpdir),
page_path="some_path",
filename="some_filename",
extension=".md",
name="some_name",
user_input=None,
example=None,
template_filename=None,
template_path=None,
)
scoped_page_file = (
pathlib.Path(options.base_path) / options.page_path / options.filename
).with_suffix(f".{options.extension[1:]}")
# act
scoped_page = ScopedPageCreator(options).create_page()
scoped_page.save_to_disk()
# assert
assert scoped_page_file.exists()
assert caplog.records[0].message == f"Saved {scoped_page_file} to disk"
def test_create_page_str_representation(tmpdir):
# arrange
options = PageCreatorOptions(
base_path=str(tmpdir),
page_path="some_path",
filename="some_filename",
extension="md",
name="some_name",
user_input=None,
example=None,
template_filename=None,
template_path=None,
)
scoped_page_file = (
pathlib.Path(options.base_path) / options.page_path / options.filename
).with_suffix(f".{options.extension}")
# act
scoped_page = ScopedPageCreator(options).create_page()
# assert
assert str(scoped_page) == f"ScopedPage({scoped_page_file})"

View File

@@ -1 +0,0 @@
template contents

View File

@@ -0,0 +1 @@
some date token: {d:%d-%m-%Y}

View File

@@ -0,0 +1 @@
some input tokens {input1} {input0}

View File

@@ -0,0 +1 @@
some name token {name}

View File

@@ -0,0 +1,3 @@
scoped page file
no tokens

View File

@@ -0,0 +1 @@
this file already exists