diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 9fc011f..27b589d 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,6 +1,6 @@ # These are supported funding model platforms -github: [frostming]# Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +github: [frostming] patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b4c989..b08af0e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,11 +11,21 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.7, 3.8, 3.9, "3.10", 3.11, 3.12] - os: [ubuntu-latest, macOS-latest, windows-latest] + python-version: [3.8, 3.9, "3.10", 3.11, 3.12, 3.13] + os: [ubuntu-latest, macos-latest, windows-latest] + exclude: + - python-version: 3.8 + os: macos-latest + - python-version: 3.9 + os: macos-latest + include: + - python-version: 3.8 + os: macos-13 + - python-version: 3.9 + os: macos-13 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: Set up PDM @@ -23,6 +33,7 @@ jobs: with: python-version: ${{ matrix.python-version }} cache: true + allow-python-prereleases: true - name: Install dependencies run: pdm install -G toc -G codehilite diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bd98209..1c539e9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,24 +7,24 @@ repos: - id: fix-future-annotations - repo: https://github.com/psf/black - rev: 23.3.0 + rev: 24.4.2 hooks: - id: black - repo: https://github.com/PyCQA/flake8 - rev: 6.0.0 + rev: 7.0.0 hooks: - id: flake8 additional_dependencies: - flake8-bugbear - repo: https://github.com/pycqa/isort - rev: 5.12.0 + rev: 5.13.2 hooks: - id: isort - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.3.0 + rev: v1.10.0 hooks: - id: mypy exclude: ^docs/ diff --git a/README.md b/README.md index 4edb02d..6abc375 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Marko is a pure Python markdown parser that adheres to the specifications of [CommonMark's spec v0.30][spec]. It has been designed with high extensibility in mind, as detailed in the [Extensions](#extensions) section. -Marko requires Python 3.7 or higher. +Marko requires Python 3.8 or higher. ## Why Marko diff --git a/marko/__init__.py b/marko/__init__.py index 9b94e7a..786588e 100644 --- a/marko/__init__.py +++ b/marko/__init__.py @@ -9,6 +9,7 @@ Licensed under MIT. Created by Frost Ming """ + from __future__ import annotations from typing import TYPE_CHECKING, Iterable, cast diff --git a/marko/__main__.py b/marko/__main__.py index d9f8e26..c9c6534 100644 --- a/marko/__main__.py +++ b/marko/__main__.py @@ -9,6 +9,7 @@ Licensed under MIT. Created by Frost Ming """ + from . import cli if __name__ == "__main__": diff --git a/marko/ast_renderer.py b/marko/ast_renderer.py index 3dbf502..44acb67 100644 --- a/marko/ast_renderer.py +++ b/marko/ast_renderer.py @@ -1,6 +1,7 @@ """ AST renderers for inspecting the markdown parsing result. """ + from __future__ import annotations import html @@ -35,23 +36,20 @@ class ASTRenderer(Renderer): def render_raw_text(self, element: inline.RawText) -> dict[str, Any]: return { "element": "raw_text", - "children": html.unescape(element.children) - if element.escape - else element.children, + "children": ( + html.unescape(element.children) if element.escape else element.children + ), "escape": element.escape, } @overload - def render_children(self, element: list[Element]) -> list[dict[str, Any]]: - ... + def render_children(self, element: list[Element]) -> list[dict[str, Any]]: ... @overload - def render_children(self, element: Element) -> dict[str, Any]: - ... + def render_children(self, element: Element) -> dict[str, Any]: ... @overload - def render_children(self, element: str) -> str: - ... + def render_children(self, element: str) -> str: ... def render_children(self, element): if isinstance(element, list): diff --git a/marko/block.py b/marko/block.py index 4ea0367..2e893d5 100644 --- a/marko/block.py +++ b/marko/block.py @@ -1,6 +1,7 @@ """ Block level elements """ + from __future__ import annotations import re diff --git a/marko/cli.py b/marko/cli.py index cf3a50e..73882fe 100644 --- a/marko/cli.py +++ b/marko/cli.py @@ -1,6 +1,7 @@ """ Command line interfaces """ + import codecs import importlib import sys diff --git a/marko/element.py b/marko/element.py index 23db057..c8a8bde 100644 --- a/marko/element.py +++ b/marko/element.py @@ -18,7 +18,11 @@ def get_type(cls, snake_case: bool = False) -> str: """ # Prevent override of BlockElement and InlineElement - if cls.override and cls.__base__ not in Element.__subclasses__(): + if ( + cls.override + and cls.__base__ + and cls.__base__ not in Element.__subclasses__() + ): name = cls.__base__.__name__ else: name = cls.__name__ diff --git a/marko/ext/codehilite.py b/marko/ext/codehilite.py index 71de137..dc32d70 100644 --- a/marko/ext/codehilite.py +++ b/marko/ext/codehilite.py @@ -16,6 +16,7 @@ markdown = Markdown(extensions=['codehilite']) markdown.convert('```python filename="my_script.py"\nprint('hello world')\n```') """ + import json from pygments import highlight diff --git a/marko/ext/gfm/elements.py b/marko/ext/gfm/elements.py index 9680e0b..084a9fa 100644 --- a/marko/ext/gfm/elements.py +++ b/marko/ext/gfm/elements.py @@ -1,6 +1,7 @@ """ Extra elements """ + from __future__ import annotations import itertools diff --git a/marko/ext/gfm/renderer.py b/marko/ext/gfm/renderer.py index 0733a00..13ced0e 100644 --- a/marko/ext/gfm/renderer.py +++ b/marko/ext/gfm/renderer.py @@ -40,7 +40,7 @@ def render_paragraph(self, element): @render_dispatch(HTMLRenderer) def render_strikethrough(self, element): - return "{}".format(self.render_children(element)) + return f"{self.render_children(element)}" @render_strikethrough.dispatch(MarkdownRenderer) def render_strikethrough(self, element): @@ -57,7 +57,7 @@ def render_html_block(self, element): @render_dispatch(HTMLRenderer) def render_table(self, element): head, *body = element.children - theader = "\n{}".format(self.render(head)) + theader = f"\n{self.render(head)}" tbody = "" if body: tbody = "\n\n{}".format( @@ -77,7 +77,7 @@ def render_table(self, element): @render_dispatch(HTMLRenderer) def render_table_row(self, element): - return "\n{}\n".format(self.render_children(element)) + return f"\n{self.render_children(element)}\n" @render_table_row.dispatch(MarkdownRenderer) def render_table_row(self, element): diff --git a/marko/ext/latex_renderer.py b/marko/ext/latex_renderer.py index 77918ee..2f08f62 100644 --- a/marko/ext/latex_renderer.py +++ b/marko/ext/latex_renderer.py @@ -1,6 +1,7 @@ """ LaTeX renderer """ + from __future__ import annotations import logging diff --git a/marko/ext/pangu.py b/marko/ext/pangu.py index f86d344..4b173b8 100644 --- a/marko/ext/pangu.py +++ b/marko/ext/pangu.py @@ -16,6 +16,7 @@ markdown = Markdown(extensions=['pangu']) print(markdown(text)) """ + import re from marko import HTMLRenderer diff --git a/marko/ext/toc.py b/marko/ext/toc.py index d05ed57..c4a40a6 100644 --- a/marko/ext/toc.py +++ b/marko/ext/toc.py @@ -22,6 +22,7 @@ print(markdown.renderer.render_toc()) """ + import re from slugify import slugify diff --git a/marko/helpers.py b/marko/helpers.py index 10f16f2..666f67f 100644 --- a/marko/helpers.py +++ b/marko/helpers.py @@ -1,6 +1,7 @@ """ Helper functions and data structures """ + from __future__ import annotations import dataclasses @@ -169,12 +170,10 @@ def super_render(self, r: Any, element: Element) -> Any: raise NotImplementedError(f"Unsupported renderer {type(r)}") from None @overload - def __get__(self: D, obj: None, owner: type) -> D: - ... + def __get__(self: D, obj: None, owner: type) -> D: ... @overload - def __get__(self: D, obj: Renderer, owner: type) -> RendererFunc: - ... + def __get__(self: D, obj: Renderer, owner: type) -> RendererFunc: ... def __get__(self: D, obj: Renderer | None, owner: type) -> RendererFunc | D: if obj is None: diff --git a/marko/html_renderer.py b/marko/html_renderer.py index 4ec0e80..1849255 100644 --- a/marko/html_renderer.py +++ b/marko/html_renderer.py @@ -1,6 +1,7 @@ """ HTML renderer """ + from __future__ import annotations import html diff --git a/marko/inline.py b/marko/inline.py index bb0d1c4..e642920 100644 --- a/marko/inline.py +++ b/marko/inline.py @@ -1,6 +1,7 @@ """ Inline(span) level elements """ + from __future__ import annotations import re diff --git a/marko/inline_parser.py b/marko/inline_parser.py index b08cf58..3150fdd 100644 --- a/marko/inline_parser.py +++ b/marko/inline_parser.py @@ -1,6 +1,7 @@ """ Parse inline elements """ + from __future__ import annotations import re diff --git a/marko/md_renderer.py b/marko/md_renderer.py index b13186f..69919d7 100644 --- a/marko/md_renderer.py +++ b/marko/md_renderer.py @@ -1,6 +1,7 @@ """ Markdown renderer """ + from __future__ import annotations import re diff --git a/marko/parser.py b/marko/parser.py index 8b7551d..33ee5da 100644 --- a/marko/parser.py +++ b/marko/parser.py @@ -1,6 +1,7 @@ """ Base parser """ + from __future__ import annotations import itertools diff --git a/marko/patterns.py b/marko/patterns.py index 644efd7..56bfe87 100644 --- a/marko/patterns.py +++ b/marko/patterns.py @@ -1,6 +1,7 @@ """ Some regex patterns """ + import re tags = [ diff --git a/marko/renderer.py b/marko/renderer.py index d4ff234..ec1ba49 100644 --- a/marko/renderer.py +++ b/marko/renderer.py @@ -1,6 +1,7 @@ """ Base renderer class """ + from __future__ import annotations import html diff --git a/marko/source.py b/marko/source.py index 1df10ad..7c9c355 100644 --- a/marko/source.py +++ b/marko/source.py @@ -77,7 +77,7 @@ def _expect_re(self, regexp: Pattern[str] | str, pos: int) -> Match[str] | None: return regexp.match(self._buffer, pos) @staticmethod - @functools.lru_cache() + @functools.lru_cache def match_prefix(prefix: str, line: str) -> int: """Check if the line starts with given prefix and return the position of the end of prefix. @@ -112,12 +112,10 @@ def expect_re(self, regexp: Pattern[str] | str) -> Match[str] | None: return None @overload - def next_line(self, require_prefix: Literal[False] = ...) -> str: - ... + def next_line(self, require_prefix: Literal[False] = ...) -> str: ... @overload - def next_line(self, require_prefix: Literal[True] = ...) -> str | None: - ... + def next_line(self, require_prefix: Literal[True] = ...) -> str | None: ... def next_line(self, require_prefix: bool = True) -> str | None: """Return the next line in the source. diff --git a/pyproject.toml b/pyproject.toml index 72ba2d1..a6f835a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ authors = [ {name = "Frost Ming", email = "mianghong@gmail.com"}, ] dynamic = ["version"] -requires-python = ">=3.7" +requires-python = ">=3.8" license = {text = "MIT"} dependencies = [] description = "A markdown parser with high extensibility." @@ -20,7 +20,6 @@ classifiers = [ "Intended Audience :: Developers", 'Operating System :: OS Independent', "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", diff --git a/setup.cfg b/setup.cfg index d1985c4..7af0abd 100644 --- a/setup.cfg +++ b/setup.cfg @@ -24,7 +24,7 @@ exclude_lines = if TYPE_CHECKING: [flake8] -ignore = E203,E501,W503,W504,W605,E741 +ignore = E203,E501,W503,W504,W605,E741,E704 [mypy-tests.*] ignore_errors = True