From b10dfdc07136e56a55f902227c72270f9b5bea87 Mon Sep 17 00:00:00 2001 From: Ihor Kalnytskyi Date: Wed, 25 Dec 2024 00:48:00 +0200 Subject: [PATCH] Embrace most Ruff lint rules Because Ruff is fast and has many nice rules. Nasty ones we can ignore, but most of them do make sense. --- pyproject.toml | 48 +++++++++++++++++--- src/holocron/__main__.py | 17 +++---- src/holocron/_core/application.py | 20 ++++---- src/holocron/_core/factories.py | 4 +- src/holocron/_core/items.py | 15 +++--- src/holocron/_processors/chain.py | 3 +- src/holocron/_processors/commonmark.py | 3 +- src/holocron/_processors/feed.py | 30 ++++-------- src/holocron/_processors/frontmatter.py | 6 +-- src/holocron/_processors/jinja2/__init__.py | 5 +- src/holocron/_processors/restructuredtext.py | 4 +- src/holocron/_processors/sitemap.py | 3 +- src/holocron/_processors/source.py | 4 +- src/holocron/_processors/when.py | 3 +- tests/_core/test_application.py | 13 +++--- tests/_core/test_items.py | 16 +++---- tests/_processors/test_archive.py | 17 +++---- tests/_processors/test_chain.py | 8 ++-- tests/_processors/test_commonmark.py | 12 ++--- tests/_processors/test_feed.py | 45 ++++++------------ tests/_processors/test_frontmatter.py | 16 +++---- tests/_processors/test_import_processors.py | 18 +++----- tests/_processors/test_jinja2.py | 13 ++---- tests/_processors/test_markdown.py | 11 ++--- tests/_processors/test_metadata.py | 17 +++---- tests/_processors/test_pipe.py | 10 ++-- tests/_processors/test_prettyuri.py | 12 ++--- tests/_processors/test_restructuredtext.py | 6 +-- tests/_processors/test_save.py | 24 ++++------ tests/_processors/test_sitemap.py | 30 ++++-------- tests/_processors/test_source.py | 38 ++++++---------- tests/_processors/test_todatetime.py | 34 ++++++-------- tests/_processors/test_when.py | 17 +++---- tests/test_main.py | 8 ++-- 34 files changed, 227 insertions(+), 303 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 70f161e..a98ccff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,9 +8,7 @@ description = "An extendable static site generator powered by the Force. =/" readme = "README.rst" requires-python = ">= 3.10" license = "BSD-3-Clause" -authors = [ - { name = "Ihor Kalnytskyi", email = "ihor@kalnytskyi.com" } -] +authors = [{ name = "Ihor Kalnytskyi", email = "ihor@kalnytskyi.com" }] keywords = ["static", "site", "blog", "generator", "markdown"] classifiers = [ "Environment :: Console", @@ -76,12 +74,50 @@ dependencies = ["ruff == 0.8.*"] scripts.check = ["ruff check {args:.}", "ruff format --check --diff {args:.}"] scripts.fmt = ["ruff check --fix {args:.}", "ruff format {args:.}"] +[tool.ruff] +line-length = 100 + [tool.ruff.lint] -select = ["F", "E", "W", "I", "S", "FBT", "B", "C4", "DTZ", "T10", "ISC", "RET", "SLF", "RUF"] -ignore = ["S603", "S701", "B904", "ISC001"] +select = ["ALL"] +ignore = [ + "A001", + "A002", + "ANN", + "ARG001", + "ARG002", + "B904", + "C", + "COM812", + "D", + "INP001", + "ISC001", + "N801", + "N802", + "PERF203", + "PLR", + "PLW2901", + "PTH", + "S603", + "S701", + "SIM117", + "TID252", +] [tool.ruff.lint.isort] known-first-party = ["holocron"] [tool.ruff.lint.per-file-ignores] -"tests/*" = ["E501", "S101", "S607", "SLF001", "RUF001"] +"src/holocron/__main__.py" = ["T201"] +"tests/*" = [ + "BLE001", + "D", + "E501", + "PT011", + "PT012", + "RUF001", + "S101", + "S607", + "SIM108", + "SLF001", + "UP031", +] diff --git a/src/holocron/__main__.py b/src/holocron/__main__.py index 4411e2a..fb2d600 100644 --- a/src/holocron/__main__.py +++ b/src/holocron/__main__.py @@ -19,9 +19,8 @@ def create_app_from_yml(path): """Return an application instance created from YAML.""" - try: - with open(path, "rt", encoding="UTF-8") as f: + with open(path, encoding="UTF-8") as f: try: # Substitute ALL occurrences of '%(here)s' with a path to a # directory with '.holocron.yml'. Please note, we also want @@ -34,9 +33,7 @@ def create_app_from_yml(path): conf = yaml.safe_load(interpolated) except yaml.YAMLError as exc: - raise RuntimeError( - "Cannot parse a configuration file. Context: " + str(exc) - ) + raise RuntimeError("Cannot parse a configuration file. Context: " + str(exc)) except FileNotFoundError: conf = {"metadata": None, "pipes": {}} @@ -46,8 +43,7 @@ def create_app_from_yml(path): @contextlib.contextmanager def configure_logger(level): - """ - Configure a root logger to print records in pretty format. + """Configure a root logger to print records in pretty format. The format is more readable for end users, since it's not necessary at all to know a record's dateime and a source of the record. @@ -63,7 +59,7 @@ def configure_logger(level): class _PendingHandler(logging.handlers.MemoryHandler): def __init__(self, target): - return super(_PendingHandler, self).__init__(capacity=-1, target=target) + super().__init__(capacity=-1, target=target) def shouldFlush(self, record): return False @@ -71,7 +67,7 @@ def shouldFlush(self, record): class _Formatter(logging.Formatter): def format(self, record): record.levelname = record.levelname[:4] - return super(_Formatter, self).format(record) + return super().format(record) # create stream handler with custom formatter stream_handler = logging.StreamHandler() @@ -90,8 +86,7 @@ def format(self, record): def parse_command_line(args): - """ - Builds a command line interface, and parses its arguments. Returns + """Builds a command line interface, and parses its arguments. Returns an object with attributes, that are represent CLI arguments. :param args: a list of command line arguments diff --git a/src/holocron/_core/application.py b/src/holocron/_core/application.py index 7b0b8c3..9b5b590 100644 --- a/src/holocron/_core/application.py +++ b/src/holocron/_core/application.py @@ -3,7 +3,7 @@ import collections import logging -from .._processors import _misc +from holocron._processors import _misc _logger = logging.getLogger("holocron") @@ -55,7 +55,8 @@ def add_processor(self, name, processor): def add_processor_wrapper(self, name, processor): if name in self._processor_reserved_props: - raise ValueError(f"illegal wrapper name: {name}") + msg = f"illegal wrapper name: {name}" + raise ValueError(msg) self.add_processor(name, processor) self._processor_wrappers.add(name) @@ -73,7 +74,8 @@ def invoke(self, pipe, stream=None): # from some processor. if isinstance(pipe, str): if pipe not in self._pipes: - raise ValueError(f"no such pipe: '{pipe}'") + msg = f"no such pipe: '{pipe}'" + raise ValueError(msg) pipe = self._pipes[pipe] # Since processors expect an input stream to be an iterator, we cast a @@ -87,16 +89,15 @@ def invoke(self, pipe, stream=None): # parameters. Please note, we're doing this so late because we # want to take into account metadata and other changes produced # by previous processors in the pipe. - processor = _misc.resolve_json_references( - processor, {"metadata:": self.metadata} - ) + processor = _misc.resolve_json_references(processor, {"metadata:": self.metadata}) name, args, kwargs = _unpack_and_wrap_processor( processor, self._processor_reserved_props ) if name not in self._processors: - raise ValueError(f"no such processor: '{name}'") + msg = f"no such processor: '{name}'" + raise ValueError(msg) processfn = self._processors[name] stream = processfn(self, stream, *args, **kwargs) @@ -123,15 +124,12 @@ def _unpack_and_wrap_processor(processor, processor_reserved_props): processor. So this function naturally wraps `commonmark` and so we effectively resolve syntax sugar. """ - processor_name = processor["name"] processor_args = [] processor_kwrs = {} processor_opts = processor.get("args", {}) - wrapper_name = next( - (k for k in processor if k not in processor_reserved_props), None - ) + wrapper_name = next((k for k in processor if k not in processor_reserved_props), None) if wrapper_name: processor_name = wrapper_name diff --git a/src/holocron/_core/factories.py b/src/holocron/_core/factories.py index 73d8f43..848da2e 100644 --- a/src/holocron/_core/factories.py +++ b/src/holocron/_core/factories.py @@ -1,12 +1,12 @@ """Factory functions to create core instances.""" -from .._processors import import_processors, when +from holocron._processors import import_processors, when + from . import Application def create_app(metadata, processors=None, pipes=None): """Return an application instance with processors & pipes setup.""" - instance = Application(metadata) # In order to avoid code duplication, we use existing built-in import diff --git a/src/holocron/_core/items.py b/src/holocron/_core/items.py index bd92e80..e7f5b30 100644 --- a/src/holocron/_core/items.py +++ b/src/holocron/_core/items.py @@ -16,7 +16,8 @@ def __init__(self, *mappings, **properties): # behaviour. Anyway, passing more than one mapping to '__init__' is # senseless and confusing. if len(mappings) > 1: - raise TypeError("expected at most 1 argument, got 2") + msg = "expected at most 1 argument, got 2" + raise TypeError(msg) for mapping in itertools.chain(mappings, (properties,)): self._mapping.update(mapping) @@ -64,9 +65,7 @@ def as_mapping(self): key: value.__get__(self) for key, value in vars(self.__class__).items() if not key.startswith("_") - and ( - inspect.isdatadescriptor(value) or inspect.ismethoddescriptor(value) - ) + and (inspect.isdatadescriptor(value) or inspect.ismethoddescriptor(value)) }, **self._mapping, ) @@ -76,14 +75,14 @@ class WebSiteItem(Item): """Pipeline item wrapper for a static web site.""" def __init__(self, *mappings, **properties): - super(WebSiteItem, self).__init__(*mappings, **properties) + super().__init__(*mappings, **properties) missing = {"destination", "baseurl"} - self.keys() if missing: - raise TypeError( - "WebSiteItem is missing some required properties: %s" - % ", ".join(("'%s'" % prop for prop in sorted(missing))) + msg = "WebSiteItem is missing some required properties: {}".format( + ", ".join(f"'{prop}'" for prop in sorted(missing)) ) + raise TypeError(msg) @property def url(self): diff --git a/src/holocron/_processors/chain.py b/src/holocron/_processors/chain.py index 830ad3a..eb60733 100644 --- a/src/holocron/_processors/chain.py +++ b/src/holocron/_processors/chain.py @@ -18,7 +18,8 @@ ) def process(app, stream, *, order_by=None, direction=None): if direction and not order_by: - raise ValueError("'direction' cannot be set without 'order_by'") + msg = "'direction' cannot be set without 'order_by'" + raise ValueError(msg) if order_by: # WARNING: Sorting the stream requires evaluating all items from the diff --git a/src/holocron/_processors/commonmark.py b/src/holocron/_processors/commonmark.py index cb4b107..ff6ce3e 100644 --- a/src/holocron/_processors/commonmark.py +++ b/src/holocron/_processors/commonmark.py @@ -3,7 +3,6 @@ import json import logging import subprocess -import typing as t import markdown_it import markdown_it.renderer @@ -40,7 +39,7 @@ def fence(self, tokens, idx, options, env) -> str: return super().fence(tokens, idx, options, env) -def _exec_pipe(args: t.List[str], input_: t.ByteString, timeout: int = 1000) -> bytes: +def _exec_pipe(args: list[str], input_: bytes, timeout: int = 1000) -> bytes: try: completed_process = subprocess.run( args, diff --git a/src/holocron/_processors/feed.py b/src/holocron/_processors/feed.py index 97011b5..a0e3578 100644 --- a/src/holocron/_processors/feed.py +++ b/src/holocron/_processors/feed.py @@ -55,19 +55,15 @@ def _resolvefeed(name): return resolve_json_references(feed.get(name), {"feed:": feed}) def _resolveitem(name, streamitem): - return resolve_json_references( - item.get(name), {"item:": streamitem, "feed:": feed} - ) + return resolve_json_references(item.get(name), {"item:": streamitem, "feed:": feed}) feed_generator = feedgen.feed.FeedGenerator() - if any((key.startswith("itunes_") for key in feed)): + if any(key.startswith("itunes_") for key in feed): feed_generator.load_extension("podcast") feed_generator.podcast.itunes_author(_resolvefeed("itunes_author")) feed_generator.podcast.itunes_block(_resolvefeed("itunes_block")) - feed_generator.podcast.itunes_category( - _resolvefeed("itunes_category"), replace=True - ) + feed_generator.podcast.itunes_category(_resolvefeed("itunes_category"), replace=True) feed_generator.podcast.itunes_image(_resolvefeed("itunes_image")) feed_generator.podcast.itunes_explicit(_resolvefeed("itunes_explicit")) feed_generator.podcast.itunes_complete(_resolvefeed("itunes_complete")) @@ -125,25 +121,15 @@ def _resolveitem(name, streamitem): feed_entry.podcast.itunes_author(_resolveitem("itunes_author", streamitem)) feed_entry.podcast.itunes_block(_resolveitem("itunes_block", streamitem)) feed_entry.podcast.itunes_image(_resolveitem("itunes_image", streamitem)) - feed_entry.podcast.itunes_duration( - _resolveitem("itunes_duration", streamitem) - ) - feed_entry.podcast.itunes_duration( - _resolveitem("itunes_duration", streamitem) - ) - feed_entry.podcast.itunes_explicit( - _resolveitem("itunes_explicit", streamitem) - ) + feed_entry.podcast.itunes_duration(_resolveitem("itunes_duration", streamitem)) + feed_entry.podcast.itunes_duration(_resolveitem("itunes_duration", streamitem)) + feed_entry.podcast.itunes_explicit(_resolveitem("itunes_explicit", streamitem)) feed_entry.podcast.itunes_is_closed_captioned( _resolveitem("itunes_is_closed_captioned", streamitem) ) feed_entry.podcast.itunes_order(_resolveitem("itunes_order", streamitem)) - feed_entry.podcast.itunes_subtitle( - _resolveitem("itunes_subtitle", streamitem) - ) - feed_entry.podcast.itunes_summary( - _resolveitem("itunes_summary", streamitem) - ) + feed_entry.podcast.itunes_subtitle(_resolveitem("itunes_subtitle", streamitem)) + feed_entry.podcast.itunes_summary(_resolveitem("itunes_summary", streamitem)) to_bytes = {"atom": feed_generator.atom_str, "rss": feed_generator.rss_str} to_bytes = to_bytes[syndication_format] diff --git a/src/holocron/_processors/frontmatter.py b/src/holocron/_processors/frontmatter.py index 77c79d4..562648f 100644 --- a/src/holocron/_processors/frontmatter.py +++ b/src/holocron/_processors/frontmatter.py @@ -48,10 +48,8 @@ def process(app, stream, *, format="yaml", delimiter=None, overwrite=True): frontmatter = loader(match.group("frontmatter")) if not isinstance(frontmatter, collections.abc.Mapping): - raise ValueError( - "Frontmatter must be a mapping (i.e. key-value pairs), " - "not arrays." - ) + msg = "Frontmatter must be a mapping (i.e. key-value pairs), " "not arrays." + raise ValueError(msg) for key, value in frontmatter.items(): if overwrite or key not in item: diff --git a/src/holocron/_processors/jinja2/__init__.py b/src/holocron/_processors/jinja2/__init__.py index 0056447..b13fc4a 100644 --- a/src/holocron/_processors/jinja2/__init__.py +++ b/src/holocron/_processors/jinja2/__init__.py @@ -33,10 +33,7 @@ def process(app, stream, *, template="item.j2", context=None, themes=None): env = jinja2.Environment( loader=jinja2.ChoiceLoader( - [ - jinja2.FileSystemLoader(str(pathlib.Path(theme, "templates"))) - for theme in themes - ] + [jinja2.FileSystemLoader(str(pathlib.Path(theme, "templates"))) for theme in themes] ), trim_blocks=True, lstrip_blocks=True, diff --git a/src/holocron/_processors/restructuredtext.py b/src/holocron/_processors/restructuredtext.py index 4461456..cb0b6df 100644 --- a/src/holocron/_processors/restructuredtext.py +++ b/src/holocron/_processors/restructuredtext.py @@ -48,9 +48,7 @@ def process(app, stream, *, settings=None): # translator to fit our needs. writer.translator_class = _HTMLTranslator - parts = publish_parts( - item["content"], writer=writer, settings_overrides=settings - ) + parts = publish_parts(item["content"], writer=writer, settings_overrides=settings) item["content"] = parts["fragment"].strip() item["destination"] = item["destination"].with_suffix(".html") diff --git a/src/holocron/_processors/sitemap.py b/src/holocron/_processors/sitemap.py index 9b286a2..969bb1c 100644 --- a/src/holocron/_processors/sitemap.py +++ b/src/holocron/_processors/sitemap.py @@ -59,12 +59,13 @@ def _create_sitemap_xml(stream, sitemap, pretty): for item in stream: if not item["absurl"].startswith(owned_url): - raise ValueError( + msg = ( f"The location of a Sitemap file determines the set of URLs " f"that can be included in that Sitemap. A Sitemap file located " f"at {sitemap['absurl']} can include any URLs starting with " f"{owned_url} but can not include {item['absurl']}." ) + raise ValueError(msg) url = dom.createElement("url") loc = dom.createElement("loc") diff --git a/src/holocron/_processors/source.py b/src/holocron/_processors/source.py index 90501d8..7d28421 100644 --- a/src/holocron/_processors/source.py +++ b/src/holocron/_processors/source.py @@ -47,9 +47,7 @@ def _finditems(app, path, pattern, encoding, tzinfo): if pattern and not re_name.match(str(source)): continue - yield _createitem( - app, root / filename, source, encoding=encoding, tzinfo=tzinfo - ) + yield _createitem(app, root / filename, source, encoding=encoding, tzinfo=tzinfo) @parameters( diff --git a/src/holocron/_processors/when.py b/src/holocron/_processors/when.py index 120571a..c8e8b4b 100644 --- a/src/holocron/_processors/when.py +++ b/src/holocron/_processors/when.py @@ -62,7 +62,8 @@ def process(app, stream, processor, *_condition, condition=None): condition = _condition or condition if not condition: - raise TypeError("missing argument or value: 'condition'") + msg = "missing argument or value: 'condition'" + raise TypeError(msg) def smartstream(): for item in stream: diff --git a/tests/_core/test_application.py b/tests/_core/test_application.py index bd2d415..7b76154 100644 --- a/tests/_core/test_application.py +++ b/tests/_core/test_application.py @@ -135,7 +135,7 @@ def processor_wrapper_b(app, items, processor): assert caplog.records[0].message == "processor override: 'wrapper'" -@pytest.mark.parametrize(["wrapper_name"], [pytest.param("name"), pytest.param("args")]) +@pytest.mark.parametrize("wrapper_name", [pytest.param("name"), pytest.param("args")]) def test_add_processor_wrapper_illegal_name(caplog, wrapper_name): """.add_processor_wrapper() raises on illegal name.""" @@ -364,7 +364,7 @@ def processor(app, items): @pytest.mark.parametrize( - ["processor_args"], + "processor_args", [ pytest.param({"a": 1}, id="int"), pytest.param({"b": 1.13}, id="float"), @@ -388,7 +388,7 @@ def processor(app, items, **args): @pytest.mark.parametrize( - ["processor_args", "resolved"], + ("processor_args", "resolved"), [ pytest.param( {"a": {"$ref": "metadata://#/is_yoda_master"}}, @@ -418,9 +418,7 @@ def processor(app, items, **args): def test_invoke_resolves_jsonref(processor_args, resolved): """.invoke() resolves JSON references in processor's arguments.""" - testapp = holocron.Application( - {"extra": [{"luke": "skywalker"}], "is_yoda_master": True} - ) + testapp = holocron.Application({"extra": [{"luke": "skywalker"}], "is_yoda_master": True}) def processor(app, items, **args): assert args == resolved @@ -437,7 +435,8 @@ def test_invoke_processor_errors(): """.invoke() raises proper exception.""" def processor(app, documents): - raise ValueError("something bad happened") + msg = "something bad happened" + raise ValueError(msg) yield testapp = holocron.Application() diff --git a/tests/_core/test_items.py b/tests/_core/test_items.py index b575db5..b6d471f 100644 --- a/tests/_core/test_items.py +++ b/tests/_core/test_items.py @@ -8,7 +8,6 @@ @pytest.fixture( - scope="function", params=[ pytest.param(42, id="int-value"), pytest.param("key", id="str-value"), @@ -27,7 +26,7 @@ def supported_value(request): return request.param -@pytest.fixture(scope="function") +@pytest.fixture def item_descriptors_cls(): class methoddescriptor: def __init__(self, wrapped): @@ -327,12 +326,11 @@ def test_websiteitem_init_multiple_mappings(supported_value): @pytest.mark.parametrize( - ["properties", "error"], + ("properties", "error"), [ pytest.param( {}, - "WebSiteItem is missing some required properties: " - "'baseurl', 'destination'", + "WebSiteItem is missing some required properties: " "'baseurl', 'destination'", id="baseurl", ), pytest.param( @@ -529,7 +527,7 @@ def test_websiteitem_contains(): @pytest.mark.parametrize( - ["destination", "url"], + ("destination", "url"), [ pytest.param(pathlib.Path("path-to-item"), "/path-to-item", id="flat"), pytest.param(pathlib.Path("path", "to", "item"), "/path/to/item", id="nested"), @@ -541,15 +539,13 @@ def test_websiteitem_contains(): def test_websiteitem_url(destination, url): """'url' property is based on 'destination'.""" - instance = holocron.WebSiteItem( - {"destination": destination, "baseurl": "https://yoda.ua"} - ) + instance = holocron.WebSiteItem({"destination": destination, "baseurl": "https://yoda.ua"}) assert instance["url"] == url @pytest.mark.parametrize( - ["properties", "absurl"], + ("properties", "absurl"), [ pytest.param( { diff --git a/tests/_processors/test_archive.py b/tests/_processors/test_archive.py index edd1581..b76bc85 100644 --- a/tests/_processors/test_archive.py +++ b/tests/_processors/test_archive.py @@ -10,7 +10,7 @@ from holocron._processors import archive -@pytest.fixture(scope="function") +@pytest.fixture def testapp(): return holocron.Application({"url": "https://yoda.ua"}) @@ -18,9 +18,7 @@ def testapp(): def test_item(testapp): """Archive processor has to work!""" - stream = archive.process( - testapp, [holocron.Item({"title": "The Force", "content": "Obi-Wan"})] - ) + stream = archive.process(testapp, [holocron.Item({"title": "The Force", "content": "Obi-Wan"})]) assert isinstance(stream, collections.abc.Iterable) assert list(stream) == [ @@ -38,7 +36,7 @@ def test_item(testapp): @pytest.mark.parametrize( - ["amount"], + "amount", [ pytest.param(0), pytest.param(1), @@ -58,10 +56,7 @@ def test_item_many(testapp, amount): assert isinstance(stream, collections.abc.Iterable) assert list(stream) == list( itertools.chain( - [ - holocron.Item({"title": "The Force (part #%d)" % i}) - for i in range(amount) - ], + [holocron.Item({"title": "The Force (part #%d)" % i}) for i in range(amount)], [ holocron.WebSiteItem( { @@ -105,7 +100,7 @@ def test_args_template(testapp): @pytest.mark.parametrize( - ["save_as"], + "save_as", [ pytest.param(pathlib.Path("posts", "skywalker.luke"), id="deep"), pytest.param(pathlib.Path("yoda.jedi"), id="flat"), @@ -136,7 +131,7 @@ def test_args_save_as(testapp, save_as): @pytest.mark.parametrize( - ["args", "error"], + ("args", "error"), [ pytest.param( {"save_as": 42}, diff --git a/tests/_processors/test_chain.py b/tests/_processors/test_chain.py index 88aab79..9f5fb6c 100644 --- a/tests/_processors/test_chain.py +++ b/tests/_processors/test_chain.py @@ -8,7 +8,7 @@ from holocron._processors import chain -@pytest.fixture(scope="function") +@pytest.fixture def testapp(): return holocron.Application() @@ -16,9 +16,7 @@ def testapp(): def test_one_item(testapp): """Chain processor has to work with one item!""" - stream = chain.process( - testapp, [holocron.Item({"title": "The Force", "content": "Obi-Wan"})] - ) + stream = chain.process(testapp, [holocron.Item({"title": "The Force", "content": "Obi-Wan"})]) assert isinstance(stream, collections.abc.Iterable) assert list(stream) == [holocron.Item({"title": "The Force", "content": "Obi-Wan"})] @@ -165,7 +163,7 @@ def test_args_direction(testapp): @pytest.mark.parametrize( - ["args", "error"], + ("args", "error"), [ pytest.param( {"order_by": 42}, diff --git a/tests/_processors/test_commonmark.py b/tests/_processors/test_commonmark.py index 4296d4f..d491b3a 100644 --- a/tests/_processors/test_commonmark.py +++ b/tests/_processors/test_commonmark.py @@ -24,7 +24,7 @@ def __repr__(self): return self._regex.pattern -@pytest.fixture(scope="function") +@pytest.fixture def testapp(): return holocron.Application({"url": "https://yoda.ua"}) @@ -62,7 +62,7 @@ def test_item(testapp): @pytest.mark.parametrize( - ["content"], + "content", [ pytest.param( textwrap.dedent( @@ -267,7 +267,7 @@ def test_item_infer_title_with_sections(testapp): @pytest.mark.parametrize( - ["amount"], + "amount", [ pytest.param(0), pytest.param(1), @@ -305,7 +305,7 @@ def test_item_many(testapp, amount): @pytest.mark.parametrize( - ["rendered", "pygmentize"], + ("rendered", "pygmentize"), [ pytest.param( ( @@ -367,7 +367,7 @@ def test_args_pygmentize(testapp, rendered, pygmentize): ] -@pytest.mark.parametrize(["language"], [pytest.param("yoda"), pytest.param("vader")]) +@pytest.mark.parametrize("language", [pytest.param("yoda"), pytest.param("vader")]) def test_args_pygmentize_unknown_language(testapp, language): """Commonmark has to assume text/plain for unknown languages.""" @@ -620,7 +620,7 @@ def test_args_definition(testapp): @pytest.mark.parametrize( - ["args", "error"], + ("args", "error"), [ pytest.param( {"pygmentize": 42}, diff --git a/tests/_processors/test_feed.py b/tests/_processors/test_feed.py index 619e936..daafc22 100644 --- a/tests/_processors/test_feed.py +++ b/tests/_processors/test_feed.py @@ -16,7 +16,7 @@ _HOLOCRON_VERSION = importlib.metadata.version("holocron") -@pytest.fixture(scope="function") +@pytest.fixture def testapp(): return holocron.Application({"url": "https://yoda.ua"}) @@ -437,11 +437,9 @@ def test_item_rss_feed_metadata(testapp): assert parsed.rss.channel.item.itunes_summary == "berry" +@pytest.mark.parametrize("syndication_format", [pytest.param("atom"), pytest.param("rss")]) @pytest.mark.parametrize( - ["syndication_format"], [pytest.param("atom"), pytest.param("rss")] -) -@pytest.mark.parametrize( - ["amount"], + "amount", [ pytest.param(0), pytest.param(1), @@ -505,10 +503,8 @@ def test_item_many(testapp, syndication_format, amount): ) -@pytest.mark.parametrize( - ["syndication_format"], [pytest.param("atom"), pytest.param("rss")] -) -@pytest.mark.parametrize(["encoding"], [pytest.param("CP1251"), pytest.param("UTF-16")]) +@pytest.mark.parametrize("syndication_format", [pytest.param("atom"), pytest.param("rss")]) +@pytest.mark.parametrize("encoding", [pytest.param("CP1251"), pytest.param("UTF-16")]) def test_args_encoding(testapp, syndication_format, encoding): """Feed processor has to respect encoding argument.""" @@ -547,10 +543,8 @@ def test_args_encoding(testapp, syndication_format, encoding): assert untangle.parse(items[-1]["content"].decode(encoding)) -@pytest.mark.parametrize( - ["syndication_format"], [pytest.param("atom"), pytest.param("rss")] -) -@pytest.mark.parametrize(["encoding"], [pytest.param("CP1251"), pytest.param("UTF-16")]) +@pytest.mark.parametrize("syndication_format", [pytest.param("atom"), pytest.param("rss")]) +@pytest.mark.parametrize("encoding", [pytest.param("CP1251"), pytest.param("UTF-16")]) def test_args_encoding_fallback(testapp, syndication_format, encoding): """Feed processor has to respect encoding argument (fallback).""" @@ -590,11 +584,9 @@ def test_args_encoding_fallback(testapp, syndication_format, encoding): assert untangle.parse(items[-1]["content"].decode(encoding)) +@pytest.mark.parametrize("syndication_format", [pytest.param("atom"), pytest.param("rss")]) @pytest.mark.parametrize( - ["syndication_format"], [pytest.param("atom"), pytest.param("rss")] -) -@pytest.mark.parametrize( - ["save_as"], + "save_as", [ pytest.param(pathlib.Path("foo.xml")), pytest.param(pathlib.Path("foo", "bar.xml")), @@ -647,10 +639,8 @@ def test_args_save_as(testapp, syndication_format, save_as): ] -@pytest.mark.parametrize( - ["syndication_format"], [pytest.param("atom"), pytest.param("rss")] -) -@pytest.mark.parametrize(["limit"], [pytest.param(2), pytest.param(5)]) +@pytest.mark.parametrize("syndication_format", [pytest.param("atom"), pytest.param("rss")]) +@pytest.mark.parametrize("limit", [pytest.param(2), pytest.param(5)]) def test_args_limit(testapp, syndication_format, limit): """Feed processor has to respect limit argument.""" @@ -716,20 +706,15 @@ def test_args_limit(testapp, syndication_format, limit): assert len(items) == limit for i, item in enumerate(items): - if syndication_format == "atom": - content = item.content - else: - content = item.description + content = item.content if syndication_format == "atom" else item.description assert item.title == "Day 1" assert content == "the way of the Force, part %d" % (9 - i) +@pytest.mark.parametrize("syndication_format", [pytest.param("atom"), pytest.param("rss")]) @pytest.mark.parametrize( - ["syndication_format"], [pytest.param("atom"), pytest.param("rss")] -) -@pytest.mark.parametrize( - ["pretty", "check_fn"], + ("pretty", "check_fn"), [ pytest.param(False, lambda x: x == 2, id="no"), pytest.param(True, lambda x: x > 10, id="yes"), @@ -785,7 +770,7 @@ def test_args_pretty(testapp, syndication_format, pretty, check_fn): @pytest.mark.parametrize( - ["args", "error"], + ("args", "error"), [ pytest.param( {"encoding": "UTF-42"}, diff --git a/tests/_processors/test_frontmatter.py b/tests/_processors/test_frontmatter.py index 70faa9b..ccaa6e5 100644 --- a/tests/_processors/test_frontmatter.py +++ b/tests/_processors/test_frontmatter.py @@ -10,7 +10,7 @@ from holocron._processors import frontmatter -@pytest.fixture(scope="function") +@pytest.fixture def testapp(): return holocron.Application() @@ -327,7 +327,7 @@ def test_item_yaml_exploit(testapp): @pytest.mark.parametrize( - ["amount"], + "amount", [ pytest.param(0), pytest.param(1), @@ -373,7 +373,7 @@ def test_item_many(testapp, amount): ] -@pytest.mark.parametrize(["delimiter"], [pytest.param("+++"), pytest.param("***")]) +@pytest.mark.parametrize("delimiter", [pytest.param("+++"), pytest.param("***")]) def test_args_delimiter(testapp, delimiter): """Frontmatter processor has to respect 'delimiter' argument.""" @@ -411,7 +411,7 @@ def test_args_delimiter(testapp, delimiter): ] -@pytest.mark.parametrize(["overwrite"], [pytest.param(False), pytest.param(True)]) +@pytest.mark.parametrize("overwrite", [pytest.param(False), pytest.param(True)]) def test_args_overwrite(testapp, overwrite): """Frontmatter processor has to respect 'overwrite' argument.""" @@ -451,7 +451,7 @@ def test_args_overwrite(testapp, overwrite): @pytest.mark.parametrize( - ["frontsnippet", "format", "exception"], + ("frontsnippet", "format", "exception"), [ pytest.param( """\ @@ -486,9 +486,7 @@ def test_args_overwrite(testapp, overwrite): --- """.rstrip(), "yaml", - ValueError( - "Frontmatter must be a mapping (i.e. key-value pairs), not arrays." - ), + ValueError("Frontmatter must be a mapping (i.e. key-value pairs), not arrays."), id="toml-yaml", ), ], @@ -536,7 +534,7 @@ def test_args_format(testapp, frontsnippet, format, exception): @pytest.mark.parametrize( - ["args", "error"], + ("args", "error"), [ pytest.param( {"delimiter": 42}, diff --git a/tests/_processors/test_import_processors.py b/tests/_processors/test_import_processors.py index 1955349..625fb1d 100644 --- a/tests/_processors/test_import_processors.py +++ b/tests/_processors/test_import_processors.py @@ -9,12 +9,12 @@ from holocron._processors import import_processors -@pytest.fixture(scope="function") +@pytest.fixture def testapp(request): return holocron.Application() -@pytest.fixture(scope="function", params=["process", "invoke"]) +@pytest.fixture(params=["process", "invoke"]) def runprocessor(testapp, request): """Run the processor directly and as a part of anonymous pipe.""" @@ -66,7 +66,7 @@ def run(app, items): @pytest.mark.parametrize( - ["processors", "imports", "registered"], + ("processors", "imports", "registered"), [ pytest.param([], [], [], id="no-imports"), pytest.param( @@ -95,9 +95,7 @@ def run(app, items): ), ], ) -def test_imports_args_from( - testapp, runprocessor, tmpdir, processors, imports, registered -): +def test_imports_args_from(testapp, runprocessor, tmpdir, processors, imports, registered): """Imports must work from 3rd party directory.""" for processor in processors: @@ -120,7 +118,7 @@ def process(app, items): @pytest.mark.parametrize( - ["imports", "registered"], + ("imports", "registered"), [ pytest.param([], [], id="no-imports"), pytest.param(["yoda = os.path:join"], ["yoda"], id="yoda-imports-yoda"), @@ -175,16 +173,14 @@ def run(app, items): @pytest.mark.parametrize( - ["args", "error"], + ("args", "error"), [ pytest.param( {"imports": 42}, "imports: 42 is not of type 'array'", id="imports-int", ), - pytest.param( - {"from_": 42}, "from_: 42 is not of type 'string'", id="from_-int" - ), + pytest.param({"from_": 42}, "from_: 42 is not of type 'string'", id="from_-int"), ], ) def test_args_bad_value(testapp, args, error): diff --git a/tests/_processors/test_jinja2.py b/tests/_processors/test_jinja2.py index c351020..eede65c 100644 --- a/tests/_processors/test_jinja2.py +++ b/tests/_processors/test_jinja2.py @@ -12,7 +12,7 @@ from holocron._processors import jinja2 -@pytest.fixture(scope="function") +@pytest.fixture def testapp(): return holocron.Application({"url": "https://yoda.ua"}) @@ -92,7 +92,7 @@ def test_item_template(testapp, tmpdir): @pytest.mark.parametrize( - ["amount"], + "amount", [ pytest.param(0), pytest.param(1), @@ -121,12 +121,7 @@ def test_item_many(testapp, tmpdir, amount): assert ( items[:amount] - == [ - holocron.Item( - {"title": "History of the Force", "content": unittest.mock.ANY} - ) - ] - * amount + == [holocron.Item({"title": "History of the Force", "content": unittest.mock.ANY})] * amount ) for i, item in enumerate(items[:amount]): @@ -280,7 +275,7 @@ def test_args_themes_two_themes(testapp, tmpdir): @pytest.mark.parametrize( - ["args", "error"], + ("args", "error"), [ pytest.param( {"template": 42}, diff --git a/tests/_processors/test_markdown.py b/tests/_processors/test_markdown.py index 7ba5b90..7df4bbb 100644 --- a/tests/_processors/test_markdown.py +++ b/tests/_processors/test_markdown.py @@ -25,7 +25,7 @@ def __repr__(self): return self._regex.pattern -@pytest.fixture(scope="function") +@pytest.fixture def testapp(): return holocron.Application() @@ -435,7 +435,7 @@ def test_item_with_inline_code(testapp): @pytest.mark.parametrize( - ["amount"], + "amount", [ pytest.param(0), pytest.param(1), @@ -473,12 +473,11 @@ def test_item_many(testapp, amount): @pytest.mark.parametrize( - ["extensions", "rendered"], + ("extensions", "rendered"), [ pytest.param( {}, - r"

test codeblock

\s*" - r"
:::\s*lambda x: pass\s*
", + r"

test codeblock

\s*" r"
:::\s*lambda x: pass\s*
", id="no", ), pytest.param( @@ -523,7 +522,7 @@ def test_args_extensions(testapp, extensions, rendered): @pytest.mark.parametrize( - ["args", "error"], + ("args", "error"), [ pytest.param( {"extensions": 42}, diff --git a/tests/_processors/test_metadata.py b/tests/_processors/test_metadata.py index 167921a..39126fc 100644 --- a/tests/_processors/test_metadata.py +++ b/tests/_processors/test_metadata.py @@ -8,7 +8,7 @@ from holocron._processors import metadata -@pytest.fixture(scope="function") +@pytest.fixture def testapp(): return holocron.Application() @@ -37,13 +37,11 @@ def test_item_untouched(testapp): ) assert isinstance(stream, collections.abc.Iterable) - assert list(stream) == [ - holocron.Item({"content": "the Force", "author": "skywalker"}) - ] + assert list(stream) == [holocron.Item({"content": "the Force", "author": "skywalker"})] @pytest.mark.parametrize( - ["amount"], + "amount", [ pytest.param(0), pytest.param(1), @@ -57,10 +55,7 @@ def test_item_many(testapp, amount): stream = metadata.process( testapp, - [ - holocron.Item({"content": "the key is #%d" % i, "author": "luke"}) - for i in range(amount) - ], + [holocron.Item({"content": "the key is #%d" % i, "author": "luke"}) for i in range(amount)], metadata={"author": "yoda", "type": "memoire"}, ) @@ -78,7 +73,7 @@ def test_item_many(testapp, amount): @pytest.mark.parametrize( - ["overwrite", "author"], + ("overwrite", "author"), [ pytest.param(True, "yoda", id="overwrite"), pytest.param(False, "skywalker", id="not-overwrite"), @@ -101,7 +96,7 @@ def test_args_overwrite(testapp, overwrite, author): @pytest.mark.parametrize( - ["args", "error"], + ("args", "error"), [ pytest.param( {"metadata": 42}, diff --git a/tests/_processors/test_pipe.py b/tests/_processors/test_pipe.py index 6b1eded..bbee05b 100644 --- a/tests/_processors/test_pipe.py +++ b/tests/_processors/test_pipe.py @@ -8,7 +8,7 @@ from holocron._processors import pipe -@pytest.fixture(scope="function") +@pytest.fixture def testapp(): def spam(app, items, **args): for item in items: @@ -78,13 +78,11 @@ def test_args_pipeline_empty(testapp): ) assert isinstance(stream, collections.abc.Iterable) - assert list(stream) == [ - holocron.Item({"content": "the Force", "author": "skywalker"}) - ] + assert list(stream) == [holocron.Item({"content": "the Force", "author": "skywalker"})] @pytest.mark.parametrize( - ["amount"], + "amount", [ pytest.param(0), pytest.param(1), @@ -119,7 +117,7 @@ def test_item_many(testapp, amount): @pytest.mark.parametrize( - ["args", "error"], + ("args", "error"), [pytest.param({"pipe": 42}, "pipe: 42 is not of type 'array'", id="pipe-int")], ) def test_args_bad_value(testapp, args, error): diff --git a/tests/_processors/test_prettyuri.py b/tests/_processors/test_prettyuri.py index e7898ae..23d645a 100644 --- a/tests/_processors/test_prettyuri.py +++ b/tests/_processors/test_prettyuri.py @@ -9,7 +9,7 @@ from holocron._processors import prettyuri -@pytest.fixture(scope="function") +@pytest.fixture def testapp(): return holocron.Application() @@ -28,9 +28,7 @@ def test_item(testapp): ] -@pytest.mark.parametrize( - ["index"], [pytest.param("index.html"), pytest.param("index.htm")] -) +@pytest.mark.parametrize("index", [pytest.param("index.html"), pytest.param("index.htm")]) def test_item_index(testapp, index): """Prettyuri processor has to ignore index items.""" @@ -40,13 +38,11 @@ def test_item_index(testapp, index): ) assert isinstance(stream, collections.abc.Iterable) - assert list(stream) == [ - holocron.Item({"destination": pathlib.Path("about", "cv", index)}) - ] + assert list(stream) == [holocron.Item({"destination": pathlib.Path("about", "cv", index)})] @pytest.mark.parametrize( - ["amount"], + "amount", [ pytest.param(0), pytest.param(1), diff --git a/tests/_processors/test_restructuredtext.py b/tests/_processors/test_restructuredtext.py index ef73972..c78f005 100644 --- a/tests/_processors/test_restructuredtext.py +++ b/tests/_processors/test_restructuredtext.py @@ -24,7 +24,7 @@ def __repr__(self): return self._regex.pattern -@pytest.fixture(scope="function") +@pytest.fixture def testapp(): return holocron.Application() @@ -321,7 +321,7 @@ def test_args_settings(testapp): @pytest.mark.parametrize( - ["amount"], + "amount", [ pytest.param(0), pytest.param(1), @@ -359,7 +359,7 @@ def test_item_many(testapp, amount): @pytest.mark.parametrize( - ["args", "error"], + ("args", "error"), [ pytest.param( {"settings": 42}, diff --git a/tests/_processors/test_save.py b/tests/_processors/test_save.py index ab8d76b..e45a1ec 100644 --- a/tests/_processors/test_save.py +++ b/tests/_processors/test_save.py @@ -10,7 +10,7 @@ from holocron._processors import save -@pytest.fixture(scope="function") +@pytest.fixture def testapp(request): return holocron.Application() @@ -33,7 +33,7 @@ def test_item(testapp, monkeypatch, tmpdir): @pytest.mark.parametrize( - ["data", "loader"], + ("data", "loader"), [ pytest.param("text", py.path.local.read, id="text"), pytest.param(b"\xf1", py.path.local.read_binary, id="binary"), @@ -50,14 +50,12 @@ def test_item_content_types(testapp, monkeypatch, tmpdir, data, loader): ) assert isinstance(stream, collections.abc.Iterable) - assert list(stream) == [ - holocron.Item({"content": data, "destination": pathlib.Path("1.dat")}) - ] + assert list(stream) == [holocron.Item({"content": data, "destination": pathlib.Path("1.dat")})] assert loader(tmpdir.join("_site", "1.dat")) == data @pytest.mark.parametrize( - ["destination"], + "destination", [ pytest.param(pathlib.Path("1.txt"), id="deep-0"), pytest.param(pathlib.Path("a", "2.txt"), id="deep-1"), @@ -76,14 +74,12 @@ def test_item_destination(testapp, monkeypatch, tmpdir, destination): ) assert isinstance(stream, collections.abc.Iterable) - assert list(stream) == [ - holocron.Item({"content": "Obi-Wan", "destination": destination}) - ] + assert list(stream) == [holocron.Item({"content": "Obi-Wan", "destination": destination})] assert tmpdir.join("_site", destination).read_text("UTF-8") == "Obi-Wan" @pytest.mark.parametrize( - ["amount"], + "amount", [ pytest.param(0), pytest.param(1), @@ -115,7 +111,7 @@ def test_item_many(testapp, monkeypatch, tmpdir, amount): assert tmpdir.join("_site", str(i)).read_text("UTF-8") == "Obi-Wan" -@pytest.mark.parametrize(["encoding"], [pytest.param("CP1251"), pytest.param("UTF-16")]) +@pytest.mark.parametrize("encoding", [pytest.param("CP1251"), pytest.param("UTF-16")]) def test_args_encoding(testapp, monkeypatch, tmpdir, encoding): """Save processor has to respect 'encoding' argument.""" @@ -134,7 +130,7 @@ def test_args_encoding(testapp, monkeypatch, tmpdir, encoding): assert tmpdir.join("_site", "1.html").read_text(encoding) == "Обі-Ван" -@pytest.mark.parametrize(["encoding"], [pytest.param("CP1251"), pytest.param("UTF-16")]) +@pytest.mark.parametrize("encoding", [pytest.param("CP1251"), pytest.param("UTF-16")]) def test_args_encoding_fallback(testapp, monkeypatch, tmpdir, encoding): """Save processor has to respect 'encoding' argument (fallback).""" @@ -153,7 +149,7 @@ def test_args_encoding_fallback(testapp, monkeypatch, tmpdir, encoding): assert tmpdir.join("_site", "1.html").read_text(encoding) == "Обі-Ван" -@pytest.mark.parametrize(["to"], [pytest.param("_build"), pytest.param("_public")]) +@pytest.mark.parametrize("to", [pytest.param("_build"), pytest.param("_public")]) def test_args_to(testapp, monkeypatch, tmpdir, to): """Save processor has to respect 'to' argument.""" @@ -173,7 +169,7 @@ def test_args_to(testapp, monkeypatch, tmpdir, to): @pytest.mark.parametrize( - ["args", "error"], + ("args", "error"), [ pytest.param({"to": 42}, "to: 42 is not of type 'string'", id="to-int"), pytest.param({"to": [42]}, "to: [42] is not of type 'string'", id="to-list"), diff --git a/tests/_processors/test_sitemap.py b/tests/_processors/test_sitemap.py index 9062346..23ed671 100644 --- a/tests/_processors/test_sitemap.py +++ b/tests/_processors/test_sitemap.py @@ -32,13 +32,13 @@ def __repr__(self): return self._expected -@pytest.fixture(scope="function") +@pytest.fixture def testapp(): return holocron.Application({"url": "https://yoda.ua"}) @pytest.mark.parametrize( - ["filename", "escaped"], + ("filename", "escaped"), [ pytest.param("s.html", "s.html"), pytest.param("ы.html", "%D1%8B.html"), @@ -97,7 +97,7 @@ def test_item(testapp, filename, escaped): @pytest.mark.parametrize( - ["amount"], + "amount", [pytest.param(1), pytest.param(2), pytest.param(5), pytest.param(10)], ) def test_item_many(testapp, amount): @@ -139,9 +139,7 @@ def test_item_many(testapp, amount): "content": _pytest_xmlasdict( { "urlset": { - "@xmlns": ( - "http://www.sitemaps.org/schemas/sitemap/0.9" - ), + "@xmlns": ("http://www.sitemaps.org/schemas/sitemap/0.9"), "url": [ { "loc": "https://yoda.ua/%d" % i, @@ -173,11 +171,7 @@ def test_item_many_zero(testapp): "source": pathlib.Path("sitemap://sitemap.xml"), "destination": pathlib.Path("sitemap.xml"), "content": _pytest_xmlasdict( - { - "urlset": { - "@xmlns": "http://www.sitemaps.org/schemas/sitemap/0.9" - } - } + {"urlset": {"@xmlns": "http://www.sitemaps.org/schemas/sitemap/0.9"}} ), "baseurl": testapp.metadata["url"], } @@ -235,7 +229,7 @@ def test_args_gzip(testapp): @pytest.mark.parametrize( - ["save_as"], + "save_as", [ pytest.param(pathlib.Path("posts", "skywalker.luke"), id="deep"), pytest.param(pathlib.Path("yoda.jedi"), id="flat"), @@ -280,13 +274,11 @@ def test_args_save_as(testapp, save_as): @pytest.mark.parametrize( - ["document_path", "sitemap_path"], + ("document_path", "sitemap_path"), [ pytest.param(pathlib.Path("1.html"), pathlib.Path("b", "sitemap.xml")), pytest.param(pathlib.Path("a", "1.html"), pathlib.Path("b", "sitemap.xml")), - pytest.param( - pathlib.Path("a", "1.html"), pathlib.Path("a", "c", "sitemap.xml") - ), + pytest.param(pathlib.Path("a", "1.html"), pathlib.Path("a", "c", "sitemap.xml")), pytest.param(pathlib.Path("ab", "1.html"), pathlib.Path("a", "sitemap.xml")), ], ) @@ -321,9 +313,7 @@ def test_args_save_as_unsupported(testapp, document_path, sitemap_path): ) -@pytest.mark.parametrize( - ["pretty", "lines"], [pytest.param(False, 1), pytest.param(True, 7)] -) +@pytest.mark.parametrize(("pretty", "lines"), [pytest.param(False, 1), pytest.param(True, 7)]) def test_args_pretty(testapp, pretty, lines): """Sitemap processor has to respect pretty argument.""" @@ -366,7 +356,7 @@ def test_args_pretty(testapp, pretty, lines): @pytest.mark.parametrize( - ["args", "error"], + ("args", "error"), [ pytest.param( {"gzip": "true"}, diff --git a/tests/_processors/test_source.py b/tests/_processors/test_source.py index 38e0cd3..46b228e 100644 --- a/tests/_processors/test_source.py +++ b/tests/_processors/test_source.py @@ -24,13 +24,13 @@ def __repr__(self): return self._timestamp -@pytest.fixture(scope="function") +@pytest.fixture def testapp(): return holocron.Application({"url": "https://yoda.ua"}) @pytest.mark.parametrize( - ["path"], + "path", [ pytest.param(["about", "luke", "cv.pdf"], id="deep-subdir"), pytest.param(["about", "cv.pdf"], id="subdir"), @@ -61,7 +61,7 @@ def test_item(testapp, monkeypatch, tmpdir, path): ] -@pytest.mark.parametrize(["data"], [pytest.param("text"), pytest.param(b"\xf1")]) +@pytest.mark.parametrize("data", [pytest.param("text"), pytest.param(b"\xf1")]) def test_item_content_types(testapp, monkeypatch, tmpdir, data): """Source processor has to properly read items" content.""" @@ -114,7 +114,7 @@ def test_item_empty(testapp, monkeypatch, tmpdir): @pytest.mark.parametrize( - ["discovered"], + "discovered", [ pytest.param(0), pytest.param(1), @@ -124,7 +124,7 @@ def test_item_empty(testapp, monkeypatch, tmpdir): ], ) @pytest.mark.parametrize( - ["passed"], + "passed", [ pytest.param(0), pytest.param(1), @@ -149,9 +149,7 @@ def test_item_many(testapp, monkeypatch, tmpdir, discovered, passed): assert isinstance(stream, collections.abc.Iterable) items = list(stream) - assert items[:passed] == [ - holocron.Item({"marker": "the key is %d" % i}) for i in range(passed) - ] + assert items[:passed] == [holocron.Item({"marker": "the key is %d" % i}) for i in range(passed)] # Since we don"t know in which order items are discovered, we sort them so # we can avoid possible flakes of the test. @@ -171,7 +169,7 @@ def test_item_many(testapp, monkeypatch, tmpdir, discovered, passed): @pytest.mark.parametrize( - ["path"], + "path", [ pytest.param(["a"]), pytest.param(["a", "b"]), @@ -193,12 +191,8 @@ def test_args_path(testapp, monkeypatch, tmpdir, path): "source": pathlib.Path("test"), "destination": pathlib.Path("test"), "content": "Obi-Wan", - "created": _pytest_timestamp( - tmpdir.join(*path).join("test").stat().ctime - ), - "updated": _pytest_timestamp( - tmpdir.join(*path).join("test").stat().mtime - ), + "created": _pytest_timestamp(tmpdir.join(*path).join("test").stat().ctime), + "updated": _pytest_timestamp(tmpdir.join(*path).join("test").stat().mtime), "baseurl": testapp.metadata["url"], } ) @@ -244,7 +238,7 @@ def test_args_pattern(testapp, monkeypatch, tmpdir): ] -@pytest.mark.parametrize(["encoding"], [pytest.param("CP1251"), pytest.param("UTF-16")]) +@pytest.mark.parametrize("encoding", [pytest.param("CP1251"), pytest.param("UTF-16")]) def test_args_encoding(testapp, monkeypatch, tmpdir, encoding): """Source processor has to respect encoding argument.""" @@ -268,7 +262,7 @@ def test_args_encoding(testapp, monkeypatch, tmpdir, encoding): ] -@pytest.mark.parametrize(["encoding"], [pytest.param("CP1251"), pytest.param("UTF-16")]) +@pytest.mark.parametrize("encoding", [pytest.param("CP1251"), pytest.param("UTF-16")]) def test_args_encoding_fallback(testapp, monkeypatch, tmpdir, encoding): """Source processor has to respect encoding argument (fallback).""" @@ -294,7 +288,7 @@ def test_args_encoding_fallback(testapp, monkeypatch, tmpdir, encoding): @pytest.mark.parametrize( - ["timezone", "tznames"], + ("timezone", "tznames"), [ pytest.param("UTC", ["UTC"]), pytest.param("Europe/Kiev", ["EET", "EEST"]), @@ -320,7 +314,7 @@ def test_args_timezone(testapp, monkeypatch, tmpdir, timezone, tznames): @pytest.mark.parametrize( - ["tz", "tznames"], + ("tz", "tznames"), [ pytest.param("UTC", ["UTC"]), pytest.param("Europe/Kiev", ["EET", "EEST"]), @@ -367,15 +361,13 @@ def test_args_timezone_in_action(testapp, monkeypatch, tmpdir): created_utc = items_utc[0]["created"] created_kie = items_kie[0]["created"] - assert created_kie.tzinfo.utcoffset(created_kie) >= created_utc.tzinfo.utcoffset( - created_utc - ) + assert created_kie.tzinfo.utcoffset(created_kie) >= created_utc.tzinfo.utcoffset(created_utc) assert created_kie.isoformat() > created_utc.isoformat() assert created_kie.isoformat().split("+")[-1] in ("02:00", "03:00") @pytest.mark.parametrize( - ["args", "error"], + ("args", "error"), [ pytest.param({"path": 42}, "path: 42 is not of type 'string'", id="path-int"), pytest.param( diff --git a/tests/_processors/test_todatetime.py b/tests/_processors/test_todatetime.py index fdde85d..e6d769c 100644 --- a/tests/_processors/test_todatetime.py +++ b/tests/_processors/test_todatetime.py @@ -14,13 +14,13 @@ _TZ_EET = dateutil.tz.gettz("EET") -@pytest.fixture(scope="function") +@pytest.fixture def testapp(): return holocron.Application() @pytest.mark.parametrize( - ["timestamp", "parsed"], + ("timestamp", "parsed"), [ pytest.param( "2019-01-15T21:07:07+00:00", @@ -128,7 +128,7 @@ def test_item(testapp, timestamp, parsed): @pytest.mark.parametrize( - ["amount"], + "amount", [ pytest.param(0), pytest.param(1), @@ -176,9 +176,7 @@ def test_item_timestamp_missing(testapp): ) assert isinstance(stream, collections.abc.Iterable) - assert list(stream) == [ - holocron.Item({"content": "the Force is strong with this one"}) - ] + assert list(stream) == [holocron.Item({"content": "the Force is strong with this one"})] def test_item_timestamp_bad_value(testapp): @@ -205,7 +203,7 @@ def test_item_timestamp_bad_value(testapp): @pytest.mark.parametrize( - ["timestamp"], + "timestamp", [ pytest.param("2019-01-11", id="str"), pytest.param(pathlib.Path("2019-01-11"), id="path"), @@ -240,7 +238,7 @@ def test_args_todatetime(testapp, timestamp): @pytest.mark.parametrize( - ["timestamp", "parsearea"], + ("timestamp", "parsearea"), [ pytest.param("2019/01/11/luke-skywalker-part-1.txt", r"\d{4}/\d{2}/\d{2}"), pytest.param("2019-01-11-luke-skywalker-part-1.txt", r"\d{4}-\d{2}-\d{2}"), @@ -306,7 +304,7 @@ def test_args_parsearea_not_found(testapp): @pytest.mark.parametrize( - ["timestamp"], + "timestamp", [ pytest.param("2019/01/11/luke-skywalker.txt"), pytest.param("2019/01/11/luke-skywalker/index.txt"), @@ -348,7 +346,7 @@ def test_args_fuzzy(testapp, timestamp): ] -@pytest.mark.parametrize(["tz"], [pytest.param("EET"), pytest.param("UTC")]) +@pytest.mark.parametrize("tz", [pytest.param("EET"), pytest.param("UTC")]) def test_args_timezone(testapp, tz): """Todatetime processor has to respect "timezone" argument.""" @@ -386,15 +384,13 @@ def test_args_timezone(testapp, tz): holocron.Item( { "content": "may the Force be with you", - "timestamp": datetime.datetime( - 2019, 1, 15, 21, 7, tzinfo=dateutil.tz.gettz(tz) - ), + "timestamp": datetime.datetime(2019, 1, 15, 21, 7, tzinfo=dateutil.tz.gettz(tz)), } ), ] -@pytest.mark.parametrize(["tz"], [pytest.param("EET"), pytest.param("UTC")]) +@pytest.mark.parametrize("tz", [pytest.param("EET"), pytest.param("UTC")]) def test_args_timezone_fallback(testapp, tz): """Todatetime processor has to respect "timezone" argument (fallback).""" @@ -433,16 +429,14 @@ def test_args_timezone_fallback(testapp, tz): holocron.Item( { "content": "may the Force be with you", - "timestamp": datetime.datetime( - 2019, 1, 15, 21, 7, tzinfo=dateutil.tz.gettz(tz) - ), + "timestamp": datetime.datetime(2019, 1, 15, 21, 7, tzinfo=dateutil.tz.gettz(tz)), } ), ] @pytest.mark.parametrize( - ["args", "error"], + ("args", "error"), [ pytest.param( {"todatetime": 42}, @@ -459,9 +453,7 @@ def test_args_timezone_fallback(testapp, tz): "timezone: 'Europe/Kharkiv' is not a 'timezone'", id="timezone-wrong", ), - pytest.param( - {"fuzzy": 42}, "fuzzy: 42 is not of type 'boolean'", id="fuzzy-int" - ), + pytest.param({"fuzzy": 42}, "fuzzy: 42 is not of type 'boolean'", id="fuzzy-int"), ], ) def test_args_bad_value(testapp, args, error): diff --git a/tests/_processors/test_when.py b/tests/_processors/test_when.py index 1eb6baa..7a1fc32 100644 --- a/tests/_processors/test_when.py +++ b/tests/_processors/test_when.py @@ -10,7 +10,7 @@ from holocron._processors import when -@pytest.fixture(scope="function") +@pytest.fixture def testapp(request): def spam(app, items, *, text=42): for item in items: @@ -39,7 +39,7 @@ def eggs(app, items): @pytest.mark.parametrize( - ["cond", "item"], + ("cond", "item"), [ pytest.param( "item.author == 'yoda'", @@ -68,7 +68,7 @@ def test_item_spam(testapp, cond, item): @pytest.mark.parametrize( - ["amount"], + "amount", [ pytest.param(0), pytest.param(1), @@ -97,7 +97,7 @@ def test_item_many_spam(testapp, amount): @pytest.mark.parametrize( - ["amount"], + "amount", [ pytest.param(0), pytest.param(1), @@ -119,10 +119,7 @@ def test_item_many_rice(testapp, amount): assert isinstance(stream, collections.abc.Iterable) assert list(stream) == list( itertools.chain( - [ - holocron.Item({"content": "the great jedi", "key": i}) - for i in range(amount) - ], + [holocron.Item({"content": "the great jedi", "key": i}) for i in range(amount)], [holocron.Item({"content": "rice"})], ) ) @@ -148,7 +145,7 @@ def test_item_many_eggs(testapp): @pytest.mark.parametrize( - ["cond"], + "cond", [ pytest.param([r"item.author == 'yoda'"], id="=="), pytest.param([r"item.source.suffix == '.md'"], id="endswith"), @@ -194,7 +191,7 @@ def test_args_condition(testapp, cond): @pytest.mark.parametrize( - ["cond"], + "cond", [ pytest.param([r"item.author == 'yoda'"], id="=="), pytest.param([r"item.source.suffix == '.md'"], id="endswith"), diff --git a/tests/test_main.py b/tests/test_main.py index 248ecda..dc050f3 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -5,8 +5,8 @@ import subprocess import sys import textwrap +from unittest import mock -import mock import pytest import yaml @@ -18,7 +18,7 @@ def _fake_root_logger(monkeypatch): monkeypatch.setattr(logging, "root", logging.getLogger("fakeroot")) -@pytest.fixture(scope="function") +@pytest.fixture def create_site(tmpdir): def create(structure): for path, content in structure: @@ -27,7 +27,7 @@ def create(structure): return create -@pytest.fixture(scope="function") +@pytest.fixture def example_site(create_site): holocron_yml = yaml.safe_dump( { @@ -51,7 +51,7 @@ def example_site(create_site): ) -@pytest.fixture(scope="function") +@pytest.fixture def execute(capsys): def execute(args, *, as_subprocess=True): if as_subprocess: