From d6eae35b59ec248968ec7a33f0519b3e7074ce3d Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 10 Jun 2024 17:14:44 +0200 Subject: [PATCH 1/3] tooling: bump minimal Python version to 3.10 --- .pre-commit-config.yaml | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0de88fc..2bd5bd6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,27 +1,29 @@ -# See https://pre-commit.com for more information -# See https://pre-commit.com/hooks.html for more hooks -exclude: "node_modules|migrations|.venv|.direnv|tests/dev/|tests/fixtures/" +exclude: ".venv|.direnv|tests/dev/|tests/fixtures/" fail_fast: false repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.6.0 hooks: - id: check-added-large-files - args: ["--maxkb=500"] + args: + - --maxkb=500 - id: check-ast - id: check-builtin-literals - id: check-case-conflict - id: check-json - id: check-toml - id: check-yaml - args: [--unsafe] + args: + - --unsafe - id: detect-private-key - id: end-of-file-fixer - id: fix-byte-order-marker - id: fix-encoding-pragma - args: [--remove] + args: + - --remove - id: trailing-whitespace - args: [--markdown-linebreak-ext=md] + args: + - --markdown-linebreak-ext=md - repo: https://github.com/pre-commit/pygrep-hooks rev: v1.10.0 @@ -33,32 +35,40 @@ repos: hooks: - id: pyupgrade args: - - "--py38-plus" + - "--py310-plus" - repo: https://github.com/astral-sh/ruff-pre-commit rev: "v0.4.7" hooks: - id: ruff - args: ["--fix-only", "--target-version=py38"] + args: + - --fix-only + - --target-version=py310 - repo: https://github.com/pycqa/isort rev: 5.13.2 hooks: - id: isort - args: ["--profile", "black", "--filter-files"] + args: + - --profile + - black + - --filter-files - repo: https://github.com/psf/black rev: 24.4.2 hooks: - id: black - args: ["--target-version=py38"] + args: + - --target-version=py310 - repo: https://github.com/pycqa/flake8 rev: 7.0.0 hooks: - id: flake8 language: python - args: ["--config=setup.cfg", "--select=E9,F63,F7,F82"] + args: + - --config=setup.cfg + - --select=E9,F63,F7,F82 ci: autofix_prs: true From a8138f9fd7d353f92b8d7cc30c89f4c17d9e9078 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 10 Jun 2024 17:15:18 +0200 Subject: [PATCH 2/3] chore(packaging): remove support of Python 3.8 and 3.9 --- .github/workflows/lint-and-tests.yml | 2 -- setup.py | 7 ++----- sonar-project.properties | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/lint-and-tests.yml b/.github/workflows/lint-and-tests.yml index 44f22db..6a2820d 100644 --- a/.github/workflows/lint-and-tests.yml +++ b/.github/workflows/lint-and-tests.yml @@ -22,8 +22,6 @@ jobs: fail-fast: false matrix: python-version: - - "3.8" - - "3.9" - "3.10" - "3.11" - "3.12" diff --git a/setup.py b/setup.py index 76b4b2a..a245d3b 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,6 @@ # standard library from pathlib import Path -from typing import List, Union # 3rd party from setuptools import find_packages, setup @@ -26,7 +25,7 @@ # ################################## -def load_requirements(requirements_files: Union[Path, List[Path]]) -> list: +def load_requirements(requirements_files: Path | list[Path]) -> list: """Helper to load requirements list from a path or a list of paths. Args: @@ -79,7 +78,7 @@ def load_requirements(requirements_files: Union[Path, List[Path]]) -> list: # run entry_points={"mkdocs.plugins": ["rss = mkdocs_rss_plugin.plugin:GitRssPlugin"]}, # dependencies - python_requires=">=3.8, <4", + python_requires=">=3.10, <4", extras_require={ # tooling "dev": load_requirements(HERE / "requirements/development.txt"), @@ -93,8 +92,6 @@ def load_requirements(requirements_files: Union[Path, List[Path]]) -> list: "Intended Audience :: Developers", "Intended Audience :: Information Technology", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", diff --git a/sonar-project.properties b/sonar-project.properties index dd18175..d33fa5c 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -6,7 +6,7 @@ sonar.projectKey=Guts_mkdocs-rss-plugin # only=main # Python versions -sonar.python.version=3.8, 3.9, 3.10, 3.11, 3.12 +sonar.python.version=3.10, 3.11, 3.12 # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. sonar.sources=mkdocs_rss_plugin From 8ec616461c91038cdf173f9aaa45cd78fe303ded Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 10 Jun 2024 17:16:22 +0200 Subject: [PATCH 3/3] refacto(python): apply git hooks with Python >= 3.10 --- .../theme_material_social_plugin.py | 5 ++-- mkdocs_rss_plugin/models.py | 24 +++++++-------- mkdocs_rss_plugin/plugin.py | 9 +++--- mkdocs_rss_plugin/util.py | 29 +++++++++---------- tests/test_build.py | 16 ++++++---- 5 files changed, 41 insertions(+), 42 deletions(-) diff --git a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py index a8f6e42..f932112 100644 --- a/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py +++ b/mkdocs_rss_plugin/integrations/theme_material_social_plugin.py @@ -6,7 +6,6 @@ # standard library from pathlib import Path -from typing import Optional # 3rd party from mkdocs.config.config_options import Config @@ -174,7 +173,7 @@ def get_social_cards_dir(self, mkdocs_config: Config) -> str: return social_plugin_cfg.config.cards_dir def get_social_card_build_path_for_page( - self, mkdocs_page: Page, mkdocs_site_dir: Optional[str] = None + self, mkdocs_page: Page, mkdocs_site_dir: str | None = None ) -> Path: """Get social card URL for a specific page in documentation. @@ -197,7 +196,7 @@ def get_social_card_build_path_for_page( def get_social_card_url_for_page( self, mkdocs_page: Page, - mkdocs_site_url: Optional[str] = None, + mkdocs_site_url: str | None = None, ) -> str: """Get social card URL for a specific page in documentation. diff --git a/mkdocs_rss_plugin/models.py b/mkdocs_rss_plugin/models.py index 7e863bd..bdc6866 100644 --- a/mkdocs_rss_plugin/models.py +++ b/mkdocs_rss_plugin/models.py @@ -7,7 +7,7 @@ # standard from datetime import datetime from pathlib import Path -from typing import NamedTuple, Optional +from typing import NamedTuple # ############################################################################ @@ -16,14 +16,14 @@ class PageInformation(NamedTuple): """Data type to set and get page information in order to produce the RSS feed.""" - abs_path: Optional[Path] = None - categories: Optional[list] = None - authors: Optional[tuple] = None - created: Optional[datetime] = None - description: Optional[str] = None - guid: Optional[str] = None - image: Optional[str] = None - title: Optional[str] = None - updated: Optional[datetime] = None - url_comments: Optional[str] = None - url_full: Optional[str] = None + abs_path: Path | None = None + categories: list | None = None + authors: tuple | None = None + created: datetime | None = None + description: str | None = None + guid: str | None = None + image: str | None = None + title: str | None = None + updated: datetime | None = None + url_comments: str | None = None + url_full: str | None = None diff --git a/mkdocs_rss_plugin/plugin.py b/mkdocs_rss_plugin/plugin.py index a0f4356..4e8f18b 100644 --- a/mkdocs_rss_plugin/plugin.py +++ b/mkdocs_rss_plugin/plugin.py @@ -11,7 +11,6 @@ from email.utils import formatdate from pathlib import Path from re import compile -from typing import Optional # 3rd party from jinja2 import Environment, FileSystemLoader, select_autoescape @@ -58,9 +57,9 @@ def __init__(self): """Instanciation.""" # dates source self.src_date_created = self.src_date_updated = "git" - self.meta_datetime_format: Optional[str] = None + self.meta_datetime_format: str | None = None self.meta_default_timezone: str = "UTC" - self.meta_default_time: Optional[datetime.time] = None + self.meta_default_time: datetime.time | None = None # pages storage self.pages_to_filter: list = [] # prepare output feeds @@ -208,7 +207,7 @@ def on_config(self, config: config_options.Config) -> dict: @event_priority(priority=-75) def on_page_content( self, html: str, page: Page, config: config_options.Config, files - ) -> Optional[str]: + ) -> str | None: """The page_content event is called after the Markdown text is rendered to HTML (but before being passed to a template) and can be used to alter the HTML body of the page. @@ -297,7 +296,7 @@ def on_page_content( ) ) - def on_post_build(self, config: config_options.Config) -> Optional[dict]: + def on_post_build(self, config: config_options.Config) -> dict | None: """The post_build event does not alter any variables. \ Use this event to call post-build scripts. \ See: diff --git a/mkdocs_rss_plugin/util.py b/mkdocs_rss_plugin/util.py index 426c7ce..07d4586 100644 --- a/mkdocs_rss_plugin/util.py +++ b/mkdocs_rss_plugin/util.py @@ -7,12 +7,12 @@ # standard library import logging import ssl -import sys +from collections.abc import Iterable from datetime import date, datetime from email.utils import format_datetime from mimetypes import guess_type from pathlib import Path -from typing import Any, Iterable, Optional, Tuple, Union +from typing import Any from urllib import request from urllib.error import HTTPError, URLError from urllib.parse import urlencode, urlparse, urlunparse @@ -33,10 +33,7 @@ ) # conditional imports -if sys.version_info < (3, 9): - from mkdocs_rss_plugin.timezoner_pre39 import set_datetime_zoneinfo -else: - from mkdocs_rss_plugin.timezoner_py39 import set_datetime_zoneinfo +from mkdocs_rss_plugin.timezoner_py39 import set_datetime_zoneinfo # ############################################################################ # ########## Globals ############# @@ -58,9 +55,9 @@ def __init__( self, path: str = ".", use_git: bool = True, - integration_material_social_cards: Optional[ + integration_material_social_cards: None | ( IntegrationMaterialSocialCards - ] = None, + ) = None, ): """Class hosting the plugin logic. @@ -139,7 +136,7 @@ def build_url(self, base_url: str, path: str, args_dict: dict = None) -> str: url_parts[4] = urlencode(args_dict) return urlunparse(url_parts) - def get_value_from_dot_key(self, data: dict, dot_key: Union[str, bool]) -> Any: + def get_value_from_dot_key(self, data: dict, dot_key: str | bool) -> Any: """ Retrieves a value from a dictionary using a dot notation key. @@ -168,8 +165,8 @@ def get_file_dates( source_date_update: str = "git", meta_datetime_format: str = "%Y-%m-%d %H:%M", meta_default_timezone: str = "UTC", - meta_default_time: Optional[datetime] = None, - ) -> Tuple[datetime, datetime]: + meta_default_time: datetime | None = None, + ) -> tuple[datetime, datetime]: """Extract creation and update dates from page metadata (yaml frontmatter) or git log for given file. @@ -325,7 +322,7 @@ def get_file_dates( get_build_datetime(), ) - def get_authors_from_meta(self, in_page: Page) -> Optional[Tuple[str]]: + def get_authors_from_meta(self, in_page: Page) -> tuple[str] | None: """Returns authors from page meta. It handles 'author' and 'authors' for keys, \ str and iterable as values types. @@ -508,7 +505,7 @@ def get_description_or_abstract( ) return "" - def get_image(self, in_page: Page, base_url: str) -> Optional[Tuple[str, str, int]]: + def get_image(self, in_page: Page, base_url: str) -> tuple[str, str, int] | None: """Get page's image from page meta or social cards and returns properties. Args: @@ -610,7 +607,7 @@ def get_remote_image_length( http_method: str = "HEAD", attempt: int = 0, ssl_context: ssl.SSLContext = None, - ) -> Optional[int]: + ) -> int | None: """Retrieve length for remote images (starting with 'http' \ in meta.image or meta.illustration). \ It tries to perform a HEAD request and get the length from the headers. \ @@ -662,7 +659,7 @@ def get_remote_image_length( return int(img_length) @staticmethod - def get_site_url(mkdocs_config: Config) -> Optional[str]: + def get_site_url(mkdocs_config: Config) -> str | None: """Extract site URL from MkDocs configuration and enforce the behavior to ensure \ returning a str with length > 0 or None. If exists, it adds an ending slash. @@ -688,7 +685,7 @@ def get_site_url(mkdocs_config: Config) -> Optional[str]: return site_url - def guess_locale(self, mkdocs_config: Config) -> Optional[str]: + def guess_locale(self, mkdocs_config: Config) -> str | None: """Extract language code from MkDocs or Theme configuration. :param mkdocs_config: configuration object diff --git a/tests/test_build.py b/tests/test_build.py index a888d01..3dcef84 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -699,16 +699,20 @@ def test_json_feed_validation(self): self.assertIsNone(cli_result.exception) # created items - with Path(tmpdirname).joinpath(OUTPUT_JSON_FEED_CREATED).open( - "r", encoding="UTF-8" - ) as in_json: + with ( + Path(tmpdirname) + .joinpath(OUTPUT_JSON_FEED_CREATED) + .open("r", encoding="UTF-8") as in_json + ): json_feed_created_data = json.load(in_json) jsonfeed.Feed.parse(json_feed_created_data) # updated items - with Path(tmpdirname).joinpath(OUTPUT_JSON_FEED_UPDATED).open( - "r", encoding="UTF-8" - ) as in_json: + with ( + Path(tmpdirname) + .joinpath(OUTPUT_JSON_FEED_UPDATED) + .open("r", encoding="UTF-8") as in_json + ): json_feed_updated_data = json.load(in_json) jsonfeed.Feed.parse(json_feed_updated_data)