Skip to main content

Merge pull request #17 from alexwlchan/less-ruff-config

ID
ca6964e
date
2026-04-16 07:50:45+00:00
author
Alex Chan <alex@alexwlchan.net>
parents
f5418eb, e8ef8bc
message
Merge pull request #17 from alexwlchan/less-ruff-config

Fix all Ruff docstring lints; fix tests for bad SSL certificate coverage
changed files
9 files, 74 additions, 21 deletions

Changed files

pyproject.toml (1327) → pyproject.toml (1510)

diff --git a/pyproject.toml b/pyproject.toml
index 6a9a9b6..45135cc 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -58,4 +58,10 @@ strict = true
 
 [tool.ruff.lint]
 select = ["D", "E", "F"]
-ignore = ["D200", "D203", "D204", "D205", "D212", "D401"]
+ignore = [
+    "D200",  # unnecessary-multiline-docstring
+    "D203",  # incorrect-blank-line-before-class
+    "D205",  # missing-blank-line-after-summary
+    "D211",  # blank-line-before-class
+    "D212",  # multi-line-summary-first-line
+]

src/chives/dates.py (2429) → src/chives/dates.py (2426)

diff --git a/src/chives/dates.py b/src/chives/dates.py
index e93bc42..4c4cf4a 100644
--- a/src/chives/dates.py
+++ b/src/chives/dates.py
@@ -13,7 +13,7 @@ from typing import Any
 
 def now() -> str:
     """
-    Returns the current time in the standard format used by my static sites.
+    Return the current time in the standard format used by my static sites.
     """
     return (
         datetime.now(tz=timezone.utc)
@@ -53,7 +53,7 @@ def find_all_dates(json_value: Any) -> Iterator[tuple[dict[str, Any], str, str]]
 
 def date_matches_format(date_string: str, format: str) -> bool:
     """
-    Returns True if `date_string` can be parsed as a datetime
+    Return True if `date_string` can be parsed as a datetime
     using `format`, False otherwise.
     """
     try:
@@ -65,7 +65,7 @@ def date_matches_format(date_string: str, format: str) -> bool:
 
 def date_matches_any_format(date_string: str, formats: Iterable[str]) -> bool:
     """
-    Returns True if `date_string` can be parsed as a datetime
+    Return True if `date_string` can be parsed as a datetime
     with any of the `formats`, False otherwise.
     """
     return any(date_matches_format(date_string, fmt) for fmt in formats)

src/chives/media.py (10520) → src/chives/media.py (10515)

diff --git a/src/chives/media.py b/src/chives/media.py
index c7990ef..196488a 100644
--- a/src/chives/media.py
+++ b/src/chives/media.py
@@ -38,7 +38,7 @@ __all__ = [
 
 def is_av1_video(path: str | Path) -> bool:
     """
-    Returns True if a video is encoded with AV1, False otherwise.
+    Return True if a video is encoded with AV1, False otherwise.
     """
     # fmt: off
     cmd = [
@@ -146,7 +146,7 @@ MediaEntity = ImageEntity | VideoEntity
 
 def get_media_paths(e: MediaEntity) -> set[Path]:
     """
-    Returns a list of all media paths represented by this media entity.
+    Return a list of all media paths represented by this media entity.
     """
     result: set[str | Path] = set()
 
@@ -276,14 +276,14 @@ def create_video_entity(
 
 def _is_animated(im: "PIL.Image.Image") -> bool:
     """
-    Returns True if an image is animated, False otherwise.
+    Return True if an image is animated, False otherwise.
     """
     return getattr(im, "is_animated", False)
 
 
 def _has_transparency(im: "PIL.Image.Image") -> bool:
     """
-    Returns True if an image has transparent pixels, False otherwise.
+    Return True if an image has transparent pixels, False otherwise.
 
     By Vinyl Da.i'gyu-Kazotetsu on Stack Overflow:
     https://stackoverflow.com/a/58567453
@@ -345,7 +345,7 @@ def _create_thumbnail(path: str | Path, thumbnail_config: ThumbnailConfig) -> st
 
 def _get_video_data(video_path: str | Path) -> tuple[int, int, str]:
     """
-    Returns the dimensions and duration of a video, as a width/height fraction.
+    Return the dimensions and duration of a video, as a width/height fraction.
     """
     cmd = [
         "ffprobe",

src/chives/static_site_tests.py (9797) → src/chives/static_site_tests.py (9790)

diff --git a/src/chives/static_site_tests.py b/src/chives/static_site_tests.py
index 5092266..e8430ad 100644
--- a/src/chives/static_site_tests.py
+++ b/src/chives/static_site_tests.py
@@ -37,7 +37,7 @@ def pytest_generate_tests(metafunc: pytest.Metafunc) -> None:
 
 class StaticSiteTestSuite[M](ABC):
     """
-    Defines a base set of tests to run against any of my static sites.
+    Define a base set of tests to run against any of my static sites.
 
     This should be subclassed as a Test* class, which allows you to use
     the fixtures and write site-specific tests.
@@ -47,7 +47,7 @@ class StaticSiteTestSuite[M](ABC):
     @abstractmethod
     def get_site_root(cls) -> Path:
         """
-        Returns the path to the folder at the root of the site.
+        Return the path to the folder at the root of the site.
         """
         ...
 
@@ -55,27 +55,27 @@ class StaticSiteTestSuite[M](ABC):
     @pytest.fixture
     def metadata(self, site_root: Path) -> M:
         """
-        Returns all the metadata for this project.
+        Return all the metadata for this project.
         """
         ...
 
     @abstractmethod
     def list_paths_in_metadata(self, metadata: M) -> set[Path]:
         """
-        Returns a set of paths described in the metadata.
+        Return a set of paths described in the metadata.
         """
         ...
 
     @pytest.fixture
     def site_root(self) -> Path:
         """
-        Returns the path to the folder at the root of the site.
+        Return the path to the folder at the root of the site.
         """
         return self.get_site_root()
 
     def list_tags_in_metadata(self, metadata: M) -> Iterator[str]:  # pragma: no cover
         """
-        Returns all the tags used in the metadata, once for every usage.
+        Return all the tags used in the metadata, once for every usage.
 
         For example, if three documents use the same tag, the tag will
         be returned three times.
@@ -99,7 +99,7 @@ class StaticSiteTestSuite[M](ABC):
 
     def list_paths_saved_locally(self, site_root: Path) -> set[Path]:
         """
-        Returns a set of paths saved locally.
+        Return a set of paths saved locally.
         """
         paths_saved_locally = set()
 

src/chives/urls.py (4636) → src/chives/urls.py (4635)

diff --git a/src/chives/urls.py b/src/chives/urls.py
index 917a2a1..17596aa 100644
--- a/src/chives/urls.py
+++ b/src/chives/urls.py
@@ -171,7 +171,7 @@ def parse_tumblr_post_url(url: str) -> tuple[str, str]:
 
 def is_url_safe(path: str | Path) -> bool:
     """
-    Returns True if a path is safe to use in a URL, False otherwise.
+    Return True if a path is safe to use in a URL, False otherwise.
     """
     p = str(path)
     return not ("?" in p or "#" in p or "%" in p)

tests/cassettes.py (2213) → tests/cassettes.py (2210)

diff --git a/tests/cassettes.py b/tests/cassettes.py
index b568dd8..6fc5fbd 100644
--- a/tests/cassettes.py
+++ b/tests/cassettes.py
@@ -24,7 +24,7 @@ __all__ = ["cassette_name", "vcr_cassette"]
 
 def get_cassette_name(request: pytest.FixtureRequest) -> str:
     """
-    Returns the name of a cassette for vcr.py.
+    Return the name of a cassette for vcr.py.
 
     The name can be made up of (up to) three parts:
 
@@ -53,7 +53,7 @@ def get_cassette_name(request: pytest.FixtureRequest) -> str:
 @pytest.fixture
 def cassette_name(request: pytest.FixtureRequest) -> str:
     """
-    Returns the filename of a VCR cassette to use in tests.
+    Return the filename of a VCR cassette to use in tests.
 
     This is useful when you need some custom vcr.py options, and
     can't use the prebuilt `vcr_cassette` fixture.
@@ -64,7 +64,7 @@ def cassette_name(request: pytest.FixtureRequest) -> str:
 @pytest.fixture
 def vcr_cassette(cassette_name: str) -> Iterator[Cassette]:
     """
-    Creates a VCR cassette for use in tests.
+    Create a VCR cassette for use in tests.
 
     Tests will record their HTTP interactions as "cassettes" using vcr.py,
     which can be replayed offline (e.g. in CI tests).

tests/fixtures/cassettes/TestIsMastodonHost.test_non_mastodon_servers[example.com].yml (0) → tests/fixtures/cassettes/TestIsMastodonHost.test_non_mastodon_servers[example.com].yml (1220)

diff --git a/tests/fixtures/cassettes/TestIsMastodonHost.test_non_mastodon_servers[example.com].yml b/tests/fixtures/cassettes/TestIsMastodonHost.test_non_mastodon_servers[example.com].yml
new file mode 100644
index 0000000..ad3cd1b
--- /dev/null
+++ b/tests/fixtures/cassettes/TestIsMastodonHost.test_non_mastodon_servers[example.com].yml
@@ -0,0 +1,43 @@
+interactions:
+- request:
+    body: null
+    headers:
+      Connection:
+      - close
+      Host:
+      - example.com
+      User-Agent:
+      - Python-urllib/3.13
+    method: GET
+    uri: https://example.com/.well-known/nodeinfo
+  response:
+    body:
+      string: '<!doctype html><html lang="en"><head><title>Example Domain</title><meta
+        name="viewport" content="width=device-width, initial-scale=1"><style>body{background:#eee;width:60vw;margin:15vh
+        auto;font-family:system-ui,sans-serif}h1{font-size:1.5em}div{opacity:0.8}a:link,a:visited{color:#348}</style></head><body><div><h1>Example
+        Domain</h1><p>This domain is for use in documentation examples without needing
+        permission. Avoid use in operations.</p><p><a href="https://iana.org/domains/example">Learn
+        more</a></p></div></body></html>
+
+        '
+    headers:
+      Age:
+      - '12220'
+      CF-RAY:
+      - 9ed186ff4e92773e-LHR
+      Connection:
+      - close
+      Content-Type:
+      - text/html
+      Date:
+      - Thu, 16 Apr 2026 07:37:53 GMT
+      Server:
+      - cloudflare
+      Transfer-Encoding:
+      - chunked
+      cf-cache-status:
+      - HIT
+    status:
+      code: 404
+      message: Not Found
+version: 1

tests/test_media.py (14722) → tests/test_media.py (14721)

diff --git a/tests/test_media.py b/tests/test_media.py
index d96e68c..081c1b8 100644
--- a/tests/test_media.py
+++ b/tests/test_media.py
@@ -17,7 +17,7 @@ from chives.media import (
 @pytest.fixture
 def fixtures_dir() -> Path:
     """
-    Returns the directory where media fixtures are stored.
+    Return the directory where media fixtures are stored.
     """
     return Path("tests/fixtures/media")
 

tests/test_urls.py (5594) → tests/test_urls.py (5789)

diff --git a/tests/test_urls.py b/tests/test_urls.py
index 12151b7..d67b690 100644
--- a/tests/test_urls.py
+++ b/tests/test_urls.py
@@ -173,6 +173,10 @@ class TestIsMastodonHost:
             # PeerTube exposes /.well-known/nodeinfo, but it's running
             # different software.
             "peertube.tv",
+            #
+            # A website with a known bad SSL certificate, which is assumed
+            # not to be a Mastodon host because we can't connect to it.
+            "expired.badssl.com",
         ],
     )
     def test_non_mastodon_servers(self, host: str, vcr_cassette: Cassette) -> None: