diff options
-rw-r--r-- | README.md | 18 | ||||
-rw-r--r-- | requirements.txt | 1 | ||||
-rw-r--r-- | setup.cfg | 1 | ||||
-rw-r--r-- | src/pyssg/configuration.py | 2 | ||||
-rw-r--r-- | src/pyssg/md_parser.py | 12 | ||||
-rw-r--r-- | src/pyssg/page.py | 101 | ||||
-rw-r--r-- | src/pyssg/plt/default.yaml | 5 | ||||
-rw-r--r-- | tests/conftest.py | 31 | ||||
-rw-r--r-- | tests/sample_files/__init__.py (renamed from tests/io_files/__init__.py) | 0 | ||||
-rw-r--r-- | tests/sample_files/checksum.txt | 1 | ||||
-rw-r--r-- | tests/sample_files/config/__init__.py (renamed from tests/io_files/md/__init__.py) | 0 | ||||
-rw-r--r-- | tests/sample_files/config/default.yaml (renamed from tests/io_files/simple.yaml) | 5 | ||||
-rw-r--r-- | tests/sample_files/config/default_missing_dirs.yaml (renamed from tests/io_files/simple_missing_dirs.yaml) | 6 | ||||
-rw-r--r-- | tests/sample_files/config/default_missing_mandatory_key.yaml (renamed from tests/io_files/simple_missing_key.yaml) | 5 | ||||
-rw-r--r-- | tests/sample_files/config/default_missing_root_dir.yaml (renamed from tests/io_files/simple_missing_root_dir.yaml) | 6 | ||||
-rw-r--r-- | tests/sample_files/config/multiple_default.yaml (renamed from tests/io_files/multiple.yaml) | 10 | ||||
-rw-r--r-- | tests/sample_files/config/multiple_default_one_doc_error.yaml (renamed from tests/io_files/multiple_one_doc_error.yaml) | 9 | ||||
-rw-r--r-- | tests/sample_files/md/__init__.py (renamed from tests/io_files/md/a/__init__.py) | 0 | ||||
-rw-r--r-- | tests/sample_files/md/a/__init__.py | 0 | ||||
-rw-r--r-- | tests/sample_files/md/a/second.md (renamed from tests/io_files/md/a/second.md) | 0 | ||||
-rw-r--r-- | tests/sample_files/md/first.md (renamed from tests/io_files/md/first.md) | 0 | ||||
-rw-r--r-- | tests/sample_files/md/new.md (renamed from tests/io_files/md/new.md) | 0 | ||||
-rw-r--r-- | tests/test_configuration.py | 54 | ||||
-rw-r--r-- | tests/test_database.py | 9 | ||||
-rw-r--r-- | tests/test_utils.py | 23 | ||||
-rw-r--r-- | tests/test_yaml_parser.py | 12 |
26 files changed, 133 insertions, 178 deletions
@@ -12,19 +12,15 @@ Initially inspired by Roman Zolotarev's [`ssg5`](https://rgz.ee/bin/ssg5) and [` - [x] Uses [`jinja`](https://jinja.palletsprojects.com/en/3.0.x/) for templating. - [x] Preserves hand-made `*.html` files. - [x] Tag functionality, useful for blog-style sites. - - [ ] Open Graph (and similar) support. - - Technically, this works if you add the correct metadata to the `*.md` files and use the variables available for Jinja. - [x] Build `sitemap.xml` file. - [ ] Include manually added `*.html` files. - [x] Build `rss.xml` file. - - [ ] Join the `static_url` to all relative URLs found to comply with the [RSS 2.0 spec](https://validator.w3.org/feed/docs/rss2.html). - - This would be added to the parsed HTML text extracted from the MD files, so it would be available to the created `*.html` and `*.xml` files. Note that depending on the reader, it will append the URL specified in the RSS file or use the [`xml:base`](https://www.rssboard.org/news/151/relative-links) specified (for example, [newsboat](https://newsboat.org/) parses `xml:base`). - [ ] Include manually added `*.html` files. - [x] YAML for configuration file, uses [`PyYAML`](https://pyyaml.org/). - - [ ] Handle multiple "documents". - - [ ] More complex directory structure to support multiple subdomains and different types of pages. + - [x] Handle multiple "documents". `PyYAML` supports this. + - [x] More complex directory structure to support multiple subdomains and different types of pages. This is supported by using mupltiple "documents" in the `yaml` config file. +- [x] File checksum checking for modification of files. - [ ] Option/change to using an SQL database instead of the custom solution. -- [x] Checksum checking because the timestamp of the file is not enough. - [ ] Use external markdown extensions. ### Markdown features @@ -37,6 +33,7 @@ This program uses the base [`markdown` syntax](https://daringfireball.net/projec - SmartyPants. - Table of Contents. (With defaults as specified [here](https://python-markdown.github.io/extensions/toc/)) - WikiLinks. +- [pymdvar](https://github.com/luevano/pymdvar) (made by me). - [yafg - Yet Another Figure Generator](https://git.sr.ht/~ferruck/yafg) - [Markdown Checklist](https://github.com/FND/markdown-checklist) - [PyMdown Extensions](https://facelessuser.github.io/pymdown-extensions/) @@ -196,19 +193,18 @@ These variables are exposed to use within the templates. The below list is displ - `toc` (`str`): table of contents as taken from `md.toc`. - `toc_tokens` (`list(dict)`): table of contents tokens as taken from `md.toc_tokens`. - `cdatetime` (`datetime.datetime`): creation datetime object of the page. - - `cdate` (`method`): method thtat takes the name of the `fmt.FMT` and applies it to the `cdatetime` object. + - `cdate` (`method`): method that takes the name of the `fmt.FMT` and applies it to the `cdatetime` object. - `cdate_rss` (`str`): formatted `cdatetime` as required by rss. - `cdate_sitemap` (`str`): formatted `cdatetime` as required by sitemap. - `mdatetime` (`datetime.datetime`): modification datetime object of the page. Defaults to `None`. - - `mdate` (`method`): method thtat takes the name of the `fmt.FMT` and applies it to the `mdatetime` object. + - `mdate` (`method`): method that takes the name of the `fmt.FMT` and applies it to the `mdatetime` object. - `mdate_rss` (`str`): formatted `mdatetime` as required by rss. - `mdate_sitemap` (`str`): formatted `mdatetime` as required by sitemap. - `tags` (`list(tuple(str))`): list of tuple of tags of the page, containing the name and the url of the tag, in that order. Defaults to empty list. - `url` (`str`): url of the page, this already includes the `url/main` from config file. - `image_url` (`str`): image url of the page, this already includes the `url/static`. Defaults to the `url/default_image` config option. - `next/previous` (`Page`): reference to the next or previous page object (containing all these attributes). Defaults to `None`. - - `og` (`dict(str, str)`): dict for object graph metadata. - - `meta` (`dict(str, list(str))`): meta dict as obtained from python-markdown, in case you use a meta tag not yet supported, it will be available there. + - `meta` (`dict(str, list(str))`): meta dict as obtained from python-markdown, in case you use a meta tag not directly supported, it will be available there. - `tag` (`tuple(str)`) (`tag.html`): tuple of name and url of the current tag. - `tag_pages` (`list(Page)`) (`tag.html`): similar to `all_pages` but contains all the pages for the current tag. - `all_tags` (`list(tuple(str))`) (all): similar to `page.tags` but contains all the tags. diff --git a/requirements.txt b/requirements.txt index 6078047..807946b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,3 +6,4 @@ yafg>=0.3 pymdown-extensions>=9.9.2 pymdvar>=1.0.3 PyYAML>=6.0 +validators>=0.20.0 @@ -63,6 +63,7 @@ per-file-ignores = arg_parser.py: E501 custom_logger.py: E501 test_database_entry.py: E501 + test_configuration.py: E501 [pbr] skip_authors = True diff --git a/src/pyssg/configuration.py b/src/pyssg/configuration.py index e2dc26b..c7b4248 100644 --- a/src/pyssg/configuration.py +++ b/src/pyssg/configuration.py @@ -12,6 +12,7 @@ DEFAULT_CONFIG_PATH: str = '$XDG_CONFIG_HOME/pyssg/config.yaml' VERSION: str = version('pyssg') +# TODO: add checking for extensions config (such as pymdvar) def __check_well_formed_config(config: dict[str, Any], config_base: list[dict[str, Any]], prefix_key: str = '') -> None: @@ -80,6 +81,7 @@ def get_static_config(sc_package: str = 'static_config.yaml', log.debug('reading and setting static config') config: dict[str, Any] = get_parsed_yaml(sc_package, plt_resource)[0] + # TODO: move this to utils and update the tests def __time(fmt: str) -> str: return datetime.now(tz=timezone.utc).strftime(config['fmt'][fmt]) diff --git a/src/pyssg/md_parser.py b/src/pyssg/md_parser.py index 3ef297d..3b62985 100644 --- a/src/pyssg/md_parser.py +++ b/src/pyssg/md_parser.py @@ -4,6 +4,7 @@ from logging import Logger, getLogger from markdown import Markdown from yafg import YafgExtension +from pymdvar import VariableExtension from markdown_checklist.extension import ChecklistExtension from .database import Database @@ -12,13 +13,17 @@ from .page import Page log: Logger = getLogger(__name__) -def _get_md_obj() -> Markdown: +# TODO: add configuration testing for extensions config (pymdvar for ex) +def get_md_obj(variables: dict[str, str] = dict(), + enable_env: bool = False) -> Markdown: exts: list = ['extra', 'meta', 'sane_lists', 'smarty', 'toc', 'wikilinks', + VariableExtension(variables=variables, + enable_env=enable_env), # stripTitle generates an error when True, # if there is no title attr YafgExtension(stripTitle=False, @@ -50,7 +55,7 @@ class MDParser: self.config: dict = config self.dir_config: dict = dir_config self.db: Database = db - self.md: Markdown = _get_md_obj() + self.md: Markdown = get_md_obj() self.all_files: list[Page] = [] self.all_tags: list[tuple[str, str]] = [] @@ -65,7 +70,8 @@ class MDParser: log.debug('parsing md into html') content: str = self.md.reset().convert(open(src_file).read()) - # ignoring md.Meta type as it is not yet defined (because it is from an extension) + # ignoring md.Meta type as it is not yet defined + # (because it is from an extension) page: Page = Page(f, self.db.e[f].ctimestamp, self.db.e[f].mtimestamp, diff --git a/src/pyssg/page.py b/src/pyssg/page.py index 6b8916d..4902bea 100644 --- a/src/pyssg/page.py +++ b/src/pyssg/page.py @@ -1,22 +1,21 @@ -import sys from datetime import datetime, timezone from logging import Logger, getLogger +from typing import Any log: Logger = getLogger(__name__) class Page: - def __init__(self, - name: str, - ctime: float, - mtime: float, - html: str, - toc: str, - toc_tokens: list[str], - meta: dict, - config: dict, - dir_config: dict) -> None: - log.debug('initializing the page object with name "%s"', name) + def __init__(self, name: str, + ctime: float, + mtime: float, + html: str, + toc: str, + toc_tokens: list[str], + meta: dict[str, Any], + config: dict[str, Any], + dir_config: dict[str, Any]) -> None: + log.debug('initializing a page object with name "%s"', name) # initial data self.name: str = name self.ctimestamp: float = ctime @@ -24,9 +23,9 @@ class Page: self.content: str = html self.toc: str = toc self.toc_tokens: list[str] = toc_tokens - self.meta: dict = meta - self.config: dict = config - self.dir_config: dict = dir_config + self.meta: dict[str, Any] = meta + self.config: dict[str, Any] = config + self.dir_config: dict[str, Any] = dir_config # data from self.meta self.title: str @@ -48,25 +47,25 @@ class Page: self.next: Page | None = None self.previous: Page | None = None - # also from self.meta, but for og metadata - self.og: dict[str, str] = dict() - def __lt__(self, other): return self.ctimestamp < other.ctimestamp - def __get_meta(self, var: str, or_else: str | list[str]) -> str | list[str]: + def __get_meta(self, var: str, + or_else: str | list[str] = '') -> str | list[str] | Any: if var in self.meta: log.debug('getting metadata "%s"', var) return self.meta[var] else: - log.debug('getting metadata "%s" failed, using optional value "%s"', var, or_else) + log.debug('getting metadata "%s" failed, using optional value "%s"', + var, or_else) return or_else def cdate(self, format: str) -> str: if format in self.config['fmt']: return self.cdatetime.strftime(self.config['fmt'][format]) else: - log.warning('format "%s" not found in config["fmt"], returning empty string', format) + log.warning('format "%s" not found in config, returning ' + 'empty string', format) return '' def mdate(self, format: str) -> str: @@ -74,28 +73,32 @@ class Page: log.warning('no mdatetime found, can\'t return a formatted string') return '' if format in self.config['fmt']: - return self.mdatetime.strftime(self.config['fmt'][format]) # type: ignore + return self.mdatetime.strftime(self.config['fmt'][format]) else: - log.warning('format "%s" not found in config["fmt"], returning empty string', format) + log.warning('format "%s" not found in config, returning ' + 'empty string', format) return '' + def from_timestamp(self, timestamp: float) -> datetime: + return datetime.fromtimestamp(timestamp, tz=timezone.utc) + # parses meta from self.meta, for og, it prioritizes, # the actual og meta def parse_metadata(self): log.debug('parsing metadata for file "%s"', self.name) - self.title = self.__get_meta('title', [''])[0] + self.title = str(self.__get_meta('title')) self.author = list(self.__get_meta('author', [''])) - self.summary = self.__get_meta('summary', [''])[0] - self.lang = self.__get_meta('lang', ['en'])[0] + self.summary = str(self.__get_meta('summary')) + self.lang = str(self.__get_meta('lang', 'en')) log.debug('parsing timestamp') - self.cdatetime = datetime.fromtimestamp(self.ctimestamp, tz=timezone.utc) + self.cdatetime = self.from_timestamp(self.ctimestamp) self.cdate_rss = self.cdate('rss_date') self.cdate_sitemap = self.cdate('sitemap_date') if self.mtimestamp != 0.0: log.debug('parsing modified timestamp') - self.mdatetime = datetime.fromtimestamp(self.mtimestamp, tz=timezone.utc) + self.mdatetime = self.from_timestamp(self.mtimestamp) self.mdate_rss = self.mdate('rss_date') self.mdate_sitemap = self.mdate('sitemap_date') else: @@ -108,30 +111,35 @@ class Page: tags_only.sort() for t in tags_only: - # need to specify dir_config['url'] as it is a hardcoded tag url - self.tags.append((t, f'{self.dir_config["url"]}/tag/@{t}.html')) + # need to specify dir_config['url'] as it is + # a hardcoded tag url + tag_url: str = f'{self.dir_config["url"]}/tag/@{t}.html' + self.tags.append((t, tag_url)) else: log.debug('no tags to parse') - log.debug('parsing url') - # no need to specify dir_config['url'] as self.name already contains the relative url - self.url = f'{self.config["url"]["main"]}/{self.name.replace(".md", ".html")}' + log.debug('parsing page url') + # no need to specify dir_config['url'] as self.name already + # contains the relative url + name_html: str = self.name.replace(".md", ".html") + self.url = f'{self.config["url"]["main"]}/{name_html}' log.debug('final url "%s"', self.url) log.debug('parsing image url') default_image_url: str = '' if 'default_image' in self.config['url']: - log.debug('"default_image" url found, will use if no "image_url" is found') + log.debug('"default_image" url found, will use if no "image_url" ' + 'is found') default_image_url = self.config['url']['default_image'] image_url: str - image_url = self.__get_meta('image_url', [default_image_url])[0] + image_url = str(self.__get_meta('image_url', default_image_url)) if image_url != '': if 'static' in self.config['url']: self.image_url = f'{self.config["url"]["static"]}/{image_url}' else: - log.debug('no static url set, using main url, this could cause problems') + log.debug('no static url set, using main url') self.image_url = f'{self.config["url"]["main"]}/{image_url}' log.debug('final image url "%s"', self.image_url) else: @@ -139,24 +147,3 @@ class Page: log.debug('no image url set for the page, could be because no' ' "image_url" was found in the metadata and/or no ' ' "default_image" set in the config file') - - # if contains open graph elements - # TODO: better handle this part - # og_e = object graph entry - og_elements: list[str] = list(self.__get_meta('og', [])) - if og_elements: - log.debug('parsing og metadata') - for og_e in og_elements: - kv: list[str] = og_e.split(',', 1) - if len(kv) != 2: - log.error('invalid og syntax for "%s", needs to be "k, v"', og_e) - sys.exit(1) - - k: str = kv[0].strip() - v: str = kv[1].strip() - - log.debug('og element: ("%s", "%s")', k, v) - self.og[k] = v - - else: - log.debug('no tags to parse') diff --git a/src/pyssg/plt/default.yaml b/src/pyssg/plt/default.yaml index 0b722a6..ca2f7ad 100644 --- a/src/pyssg/plt/default.yaml +++ b/src/pyssg/plt/default.yaml @@ -10,12 +10,8 @@ path: db: !join [*root, ".files"] url: main: "https://example.com" - static: "https://static.example.com" - default_image: "images/default.png" fmt: date: "%a, %b %d, %Y @ %H:%M %Z" - list_date: "%b %d" - list_sep_date: "%B %Y" dirs: /: cfg: @@ -24,5 +20,4 @@ dirs: index: False rss: False sitemap: False - exclude_dirs: [] ...
\ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index d3f28d7..aaf0b3a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -31,18 +31,18 @@ def sitemap_date_fmt(): @pytest.fixture(scope='session') -def test_dir() -> str: - return str(os.path.dirname(os.path.abspath(__file__))) +def sample_files_path() -> str: + return f'{str(os.path.dirname(os.path.abspath(__file__)))}/sample_files' @pytest.fixture(scope='session') -def test_resource() -> str: - return 'tests.io_files' +def config_resource() -> str: + return 'tests.sample_files.config' @pytest.fixture(scope='session') -def simple_yaml() -> str: - return 'simple.yaml' +def default_yaml() -> str: + return 'default.yaml' @pytest.fixture(scope='session') @@ -76,7 +76,7 @@ def get_fmt_time() -> Callable[..., str]: @pytest.fixture -def simple_dict() -> dict[str, Any]: +def default_config_dict() -> dict[str, Any]: return {'define': '$PYSSG_HOME/pyssg/site_example/', 'title': 'Example site', 'path': { @@ -85,13 +85,9 @@ def simple_dict() -> dict[str, Any]: 'plt': '/tmp/pyssg/pyssg/site_example/plt', 'db': '/tmp/pyssg/pyssg/site_example/.files'}, 'url': { - 'main': 'https://example.com', - 'static': 'https://static.example.com', - 'default_image': 'images/default.png'}, + 'main': 'https://example.com'}, 'fmt': { - 'date': '%a, %b %d, %Y @ %H:%M %Z', - 'list_date': '%b %d', - 'list_sep_date': '%B %Y'}, + 'date': '%a, %b %d, %Y @ %H:%M %Z'}, 'dirs': { '/': { 'cfg': { @@ -99,13 +95,12 @@ def simple_dict() -> dict[str, Any]: 'tags': False, 'index': False, 'rss': False, - 'sitemap': False, - 'exclude_dirs': []}}}} + 'sitemap': False}}}} @pytest.fixture(scope='function') def tmp_dir_structure(tmp_path: Path) -> Path: - root: Path = tmp_path/'dir_str' + root: Path = tmp_path/'dir_structure' # order matters dirs: list[Path] = [root, root/'first', @@ -165,12 +160,12 @@ def tmp_db_wrong_col_num(tmp_path: Path) -> Path: @pytest.fixture(scope='function') def tmp_src_dir(tmp_path: Path, - test_dir: str) -> Path: + sample_files_path: str) -> Path: src: Path = tmp_path/'src' src_a: Path = src/'a' src.mkdir() src_a.mkdir() - src_test: str = f'{test_dir}/io_files/md' + src_test: str = f'{sample_files_path}/md' files: list[str] = ['first.md', 'new.md', 'a/second.md'] for f in files: diff --git a/tests/io_files/__init__.py b/tests/sample_files/__init__.py index e69de29..e69de29 100644 --- a/tests/io_files/__init__.py +++ b/tests/sample_files/__init__.py diff --git a/tests/sample_files/checksum.txt b/tests/sample_files/checksum.txt new file mode 100644 index 0000000..025b879 --- /dev/null +++ b/tests/sample_files/checksum.txt @@ -0,0 +1 @@ +The content of this file is irrelevant as it is only to test the checksum function.
\ No newline at end of file diff --git a/tests/io_files/md/__init__.py b/tests/sample_files/config/__init__.py index e69de29..e69de29 100644 --- a/tests/io_files/md/__init__.py +++ b/tests/sample_files/config/__init__.py diff --git a/tests/io_files/simple.yaml b/tests/sample_files/config/default.yaml index df3888b..08121a6 100644 --- a/tests/io_files/simple.yaml +++ b/tests/sample_files/config/default.yaml @@ -10,12 +10,8 @@ path: db: !join [*root, ".files"] url: main: "https://example.com" - static: "https://static.example.com" - default_image: "images/default.png" fmt: date: "%a, %b %d, %Y @ %H:%M %Z" - list_date: "%b %d" - list_sep_date: "%B %Y" dirs: /: cfg: @@ -24,5 +20,4 @@ dirs: index: False rss: False sitemap: False - exclude_dirs: [] ...
\ No newline at end of file diff --git a/tests/io_files/simple_missing_dirs.yaml b/tests/sample_files/config/default_missing_dirs.yaml index aa15fb5..03ee35a 100644 --- a/tests/io_files/simple_missing_dirs.yaml +++ b/tests/sample_files/config/default_missing_dirs.yaml @@ -10,12 +10,8 @@ path: db: !join [*root, ".files"] url: main: "https://example.com" - static: "https://static.example.com" - default_image: "images/default.png" fmt: date: "%a, %b %d, %Y @ %H:%M %Z" - list_date: "%b %d" - list_sep_date: "%B %Y" dirs: -# test missing dirs +# test missing dirs (doesn't have any) ...
\ No newline at end of file diff --git a/tests/io_files/simple_missing_key.yaml b/tests/sample_files/config/default_missing_mandatory_key.yaml index ac81563..b5554f7 100644 --- a/tests/io_files/simple_missing_key.yaml +++ b/tests/sample_files/config/default_missing_mandatory_key.yaml @@ -11,12 +11,8 @@ path: db: !join [*root, ".files"] url: main: "https://example.com" - static: "https://static.example.com" - default_image: "images/default.png" fmt: date: "%a, %b %d, %Y @ %H:%M %Z" - list_date: "%b %d" - list_sep_date: "%B %Y" dirs: /: cfg: @@ -25,5 +21,4 @@ dirs: index: False rss: False sitemap: False - exclude_dirs: [] ...
\ No newline at end of file diff --git a/tests/io_files/simple_missing_root_dir.yaml b/tests/sample_files/config/default_missing_root_dir.yaml index 07fa824..896e141 100644 --- a/tests/io_files/simple_missing_root_dir.yaml +++ b/tests/sample_files/config/default_missing_root_dir.yaml @@ -10,13 +10,9 @@ path: db: !join [*root, ".files"] url: main: "https://example.com" - static: "https://static.example.com" - default_image: "images/default.png" fmt: date: "%a, %b %d, %Y @ %H:%M %Z" - list_date: "%b %d" - list_sep_date: "%B %Y" dirs: -# test missing /: +# test missing "/" dir in specific something: ...
\ No newline at end of file diff --git a/tests/io_files/multiple.yaml b/tests/sample_files/config/multiple_default.yaml index 8d99c40..54954b1 100644 --- a/tests/io_files/multiple.yaml +++ b/tests/sample_files/config/multiple_default.yaml @@ -10,12 +10,8 @@ path: db: !join [*root, ".files"] url: main: "https://example.com" - static: "https://static.example.com" - default_image: "images/default.png" fmt: date: "%a, %b %d, %Y @ %H:%M %Z" - list_date: "%b %d" - list_sep_date: "%B %Y" dirs: /: cfg: @@ -24,7 +20,6 @@ dirs: index: False rss: False sitemap: False - exclude_dirs: [] ... --- define: &root "$PYSSG_HOME/pyssg/site_example/" @@ -37,12 +32,8 @@ path: db: !join [*root, ".files"] url: main: "https://example.com" - static: "https://static.example.com" - default_image: "images/default.png" fmt: date: "%a, %b %d, %Y @ %H:%M %Z" - list_date: "%b %d" - list_sep_date: "%B %Y" dirs: /: cfg: @@ -51,5 +42,4 @@ dirs: index: False rss: False sitemap: False - exclude_dirs: [] ...
\ No newline at end of file diff --git a/tests/io_files/multiple_one_doc_error.yaml b/tests/sample_files/config/multiple_default_one_doc_error.yaml index 86f6546..44d9beb 100644 --- a/tests/io_files/multiple_one_doc_error.yaml +++ b/tests/sample_files/config/multiple_default_one_doc_error.yaml @@ -10,12 +10,8 @@ path: db: !join [*root, ".files"] url: main: "https://example.com" - static: "https://static.example.com" - default_image: "images/default.png" fmt: date: "%a, %b %d, %Y @ %H:%M %Z" - list_date: "%b %d" - list_sep_date: "%B %Y" dirs: /: cfg: @@ -24,7 +20,6 @@ dirs: index: False rss: False sitemap: False - exclude_dirs: [] ... --- define: &root "$PYSSG_HOME/pyssg/site_example/" @@ -37,12 +32,8 @@ path: db: !join [*root, ".files"] url: main: "https://example.com" - static: "https://static.example.com" - default_image: "images/default.png" fmt: date: "%a, %b %d, %Y @ %H:%M %Z" - list_date: "%b %d" - list_sep_date: "%B %Y" dirs: # just removing all paths as it will cause an error ...
\ No newline at end of file diff --git a/tests/io_files/md/a/__init__.py b/tests/sample_files/md/__init__.py index e69de29..e69de29 100644 --- a/tests/io_files/md/a/__init__.py +++ b/tests/sample_files/md/__init__.py diff --git a/tests/sample_files/md/a/__init__.py b/tests/sample_files/md/a/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/sample_files/md/a/__init__.py diff --git a/tests/io_files/md/a/second.md b/tests/sample_files/md/a/second.md index cb4e333..cb4e333 100644 --- a/tests/io_files/md/a/second.md +++ b/tests/sample_files/md/a/second.md diff --git a/tests/io_files/md/first.md b/tests/sample_files/md/first.md index 567ea3e..567ea3e 100644 --- a/tests/io_files/md/first.md +++ b/tests/sample_files/md/first.md diff --git a/tests/io_files/md/new.md b/tests/sample_files/md/new.md index ce684a7..ce684a7 100644 --- a/tests/io_files/md/new.md +++ b/tests/sample_files/md/new.md diff --git a/tests/test_configuration.py b/tests/test_configuration.py index 68f7808..36761eb 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -7,10 +7,10 @@ from pyssg.configuration import get_static_config, get_parsed_config # this test is a bit sketchy, as the way the datetimes are calculated could vary # by milliseconds or even have a difference in seconds -def test_static_default(rss_date_fmt: str, - sitemap_date_fmt: str, - get_fmt_time: Callable[..., str], - version: str) -> None: +def test_static_config(rss_date_fmt: str, + sitemap_date_fmt: str, + get_fmt_time: Callable[..., str], + version: str) -> None: rss_run_date: str = get_fmt_time(rss_date_fmt) sitemap_run_date: str = get_fmt_time(sitemap_date_fmt) sc_dict: dict[str, Any] = {'fmt': {'rss_date': rss_date_fmt, @@ -22,21 +22,21 @@ def test_static_default(rss_date_fmt: str, assert static_config == sc_dict -def test_simple(test_dir: str, - simple_yaml: str, - simple_dict: dict[str, Any]) -> None: - yaml_path: str = f'{test_dir}/io_files/{simple_yaml}' +def test_default_config(sample_files_path: str, + default_yaml: str, + default_config_dict: dict[str, Any]) -> None: + yaml_path: str = f'{sample_files_path}/config/{default_yaml}' yaml: list[dict[str, Any]] = get_parsed_config(yaml_path) assert len(yaml) == 1 - assert yaml[0] == simple_dict + assert yaml[0] == default_config_dict -def test_simple_mising_key(test_dir: str, - caplog: LogCaptureFixture) -> None: +def test_default_config_mising_mandatory_key(sample_files_path: str, + caplog: LogCaptureFixture) -> None: err: tuple[str, int, str] = ('pyssg.configuration', ERROR, 'config doesn\'t have "title"') - yaml_path: str = f'{test_dir}/io_files/simple_missing_key.yaml' + yaml_path: str = f'{sample_files_path}/config/default_missing_mandatory_key.yaml' with pytest.raises(SystemExit) as system_exit: get_parsed_config(yaml_path) assert system_exit.type == SystemExit @@ -44,12 +44,12 @@ def test_simple_mising_key(test_dir: str, assert caplog.record_tuples[-1] == err -def test_simple_mising_dirs(test_dir: str, - caplog: LogCaptureFixture) -> None: +def test_default_config_mising_dirs(sample_files_path: str, + caplog: LogCaptureFixture) -> None: err: tuple[str, int, str] = ('pyssg.configuration', ERROR, 'config doesn\'t have any dirs (dirs.*)') - yaml_path: str = f'{test_dir}/io_files/simple_missing_dirs.yaml' + yaml_path: str = f'{sample_files_path}/config/default_missing_dirs.yaml' with pytest.raises(SystemExit) as system_exit: get_parsed_config(yaml_path) assert system_exit.type == SystemExit @@ -57,12 +57,12 @@ def test_simple_mising_dirs(test_dir: str, assert caplog.record_tuples[-1] == err -def test_simple_root_dir(test_dir: str, - caplog: LogCaptureFixture) -> None: +def test_default_config_root_dir(sample_files_path: str, + caplog: LogCaptureFixture) -> None: err: tuple[str, int, str] = ('pyssg.configuration', ERROR, 'config doesn\'t have "dirs./"') - yaml_path: str = f'{test_dir}/io_files/simple_missing_root_dir.yaml' + yaml_path: str = f'{sample_files_path}/config/default_missing_root_dir.yaml' with pytest.raises(SystemExit) as system_exit: get_parsed_config(yaml_path) assert system_exit.type == SystemExit @@ -71,24 +71,24 @@ def test_simple_root_dir(test_dir: str, # this really just tests that both documents in the yaml file are read, -# multiple.yaml is just simple.yaml with the same document twice, -# shouldn't be an issue as the yaml package handles this -def test_multiple(test_dir: str, simple_dict: dict[str, Any]) -> None: - yaml_path: str = f'{test_dir}/io_files/multiple.yaml' +# both documents are the same (the default.yaml) +def test_multiple_default_config(sample_files_path: str, + default_config_dict: dict[str, Any]) -> None: + yaml_path: str = f'{sample_files_path}/config/multiple_default.yaml' yaml: list[dict[str, Any]] = get_parsed_config(yaml_path) assert len(yaml) == 2 - assert yaml[0] == simple_dict - assert yaml[1] == simple_dict + assert yaml[0] == default_config_dict + assert yaml[1] == default_config_dict # also, this just tests that the checks for a well formed config file are # processed for all documents -def test_multiple_one_doc_error(test_dir: str, - caplog: LogCaptureFixture) -> None: +def test_multiple_default_config_one_doc_error(sample_files_path: str, + caplog: LogCaptureFixture) -> None: err: tuple[str, int, str] = ('pyssg.configuration', ERROR, 'config doesn\'t have any dirs (dirs.*)') - yaml_path: str = f'{test_dir}/io_files/multiple_one_doc_error.yaml' + yaml_path: str = f'{sample_files_path}/config/multiple_default_one_doc_error.yaml' with pytest.raises(SystemExit) as system_exit: get_parsed_config(yaml_path) assert system_exit.type == SystemExit diff --git a/tests/test_database.py b/tests/test_database.py index 7ca597f..c5957e4 100644 --- a/tests/test_database.py +++ b/tests/test_database.py @@ -6,8 +6,9 @@ from pyssg.database import Database from pyssg.database_entry import DatabaseEntry -def test_read_database_no_db(test_dir: str, caplog: LogCaptureFixture) -> None: - path: str = f'{test_dir}/non_existent_db.psv' +def test_read_database_no_db(sample_files_path: str, + caplog: LogCaptureFixture) -> None: + path: str = f'{sample_files_path}/non_existent_db.psv' war: tuple[str, int, str] = ('pyssg.database', WARNING, f'"{path}" doesn\'t exist, will be created ' @@ -18,9 +19,9 @@ def test_read_database_no_db(test_dir: str, caplog: LogCaptureFixture) -> None: assert caplog.record_tuples[-1] == war -def test_read_database_not_a_file(test_dir: str, +def test_read_database_not_a_file(sample_files_path: str, caplog: LogCaptureFixture) -> None: - path: str = test_dir + path: str = sample_files_path err: tuple[str, int, str] = ('pyssg.database', ERROR, f'"{path}" is not a file') diff --git a/tests/test_utils.py b/tests/test_utils.py index 86242c2..75b79c2 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -33,13 +33,14 @@ def test_path_expansion_failure(path: str) -> None: assert system_exit.value.code == 1 -def test_checksum(test_dir: str, simple_yaml: str) -> None: - path: str = f'{test_dir}/io_files/{simple_yaml}' - simple_yaml_checksum: str = 'd4f0a3ed56fd530d3ea485dced25534c' +def test_checksum(sample_files_path: str) -> None: + path: str = f'{sample_files_path}/checksum.txt' + simple_yaml_checksum: str = '437b5a0e20d32fc14944c1c00d066303' checksum: str = get_checksum(path) assert checksum == simple_yaml_checksum +# TODO: actually check the existence of the files and not just the log def test_copy_file(tmp_path: Path, caplog: LogCaptureFixture) -> None: src: Path = tmp_path/'src' dst: Path = tmp_path/'dst' @@ -55,7 +56,9 @@ def test_copy_file(tmp_path: Path, caplog: LogCaptureFixture) -> None: assert caplog.record_tuples[-1] == inf -def test_copy_file_failure(tmp_path: Path, caplog: LogCaptureFixture) -> None: +# TODO: actually check the existence of the files and not just the log +def test_copy_file_already_exists(tmp_path: Path, + caplog: LogCaptureFixture) -> None: src: Path = tmp_path/'src' dst: Path = tmp_path/'dst' src.mkdir() @@ -82,7 +85,9 @@ def test_create_dir(tmp_path: Path, caplog: LogCaptureFixture) -> None: assert caplog.record_tuples[-1] == inf -def test_create_dir_failure(tmp_path: Path, caplog: LogCaptureFixture) -> None: +# TODO: actually check the existence of the files and not just the log +def test_create_dir_already_exists(tmp_path: Path, + caplog: LogCaptureFixture) -> None: path: Path = tmp_path/'new_dir' inf: tuple[str, int, str] = ('pyssg.utils', INFO, @@ -106,7 +111,9 @@ def test_create_dirs(tmp_path: Path, caplog: LogCaptureFixture) -> None: assert caplog.record_tuples[-1] == inf -def test_create_dirs_failure(tmp_path: Path, caplog: LogCaptureFixture) -> None: +# TODO: actually check the existence of the files and not just the log +def test_create_dirs_already_exists(tmp_path: Path, + caplog: LogCaptureFixture) -> None: path: Path = tmp_path/'new_dir' sub_path: Path = path/'sub_dir' inf: tuple[str, int, str] = ('pyssg.utils', @@ -131,7 +138,7 @@ def test_dir_structure(tmp_dir_structure: Path, exclude: list[str], exp_dir_str: list[str]) -> None: dir_str: list[str] = get_dir_structure(str(tmp_dir_structure), exclude) - # order doesn't matter + # order doesn't matter, only for checking that both lists contain the same assert sorted(dir_str) == sorted(exp_dir_str) @@ -158,5 +165,5 @@ def test_file_list(tmp_dir_structure: Path, exclude_dirs: list[str], exp_flist: list[str]) -> None: flist: list[str] = get_file_list(str(tmp_dir_structure), exts, exclude_dirs) - # order doesn't matter + # order doesn't matter, only for checking that both lists contain the same assert sorted(flist) == sorted(exp_flist) diff --git a/tests/test_yaml_parser.py b/tests/test_yaml_parser.py index 906c7e6..0d8df96 100644 --- a/tests/test_yaml_parser.py +++ b/tests/test_yaml_parser.py @@ -5,19 +5,19 @@ from pyssg.yaml_parser import get_parsed_yaml # and test the join functionality -def test_yaml_resource_read(simple_yaml: str, test_resource: str) -> None: - yaml: list[dict[str, Any]] = get_parsed_yaml(simple_yaml, test_resource) +def test_yaml_resource_read(default_yaml: str, config_resource: str) -> None: + yaml: list[dict[str, Any]] = get_parsed_yaml(default_yaml, config_resource) assert len(yaml) == 1 -def test_yaml_path_read(test_dir: str) -> None: - yaml_path: str = f'{test_dir}/io_files/simple.yaml' +def test_yaml_path_read(sample_files_path: str, default_yaml: str) -> None: + yaml_path: str = f'{sample_files_path}/config/{default_yaml}' yaml: list[dict[str, Any]] = get_parsed_yaml(yaml_path) assert len(yaml) == 1 -def test_yaml_join(simple_yaml: str, test_resource: str) -> None: - yaml: dict[str, Any] = get_parsed_yaml(simple_yaml, test_resource)[0] +def test_yaml_join(default_yaml: str, config_resource: str) -> None: + yaml: dict[str, Any] = get_parsed_yaml(default_yaml, config_resource)[0] define_str: str = '$PYSSG_HOME/pyssg/site_example/' assert yaml['define'] == define_str assert yaml['path']['src'] == f'{define_str}src' |