diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index aab9f7d..74fc4e6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -33,7 +33,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ['pypy-3.10', '3.10', '3.11', '3.12', '3.13'] + python-version: ['pypy-3.10', '3.10', '3.11', '3.12', '3.13', '3.14'] steps: - uses: actions/checkout@v4 @@ -59,6 +59,28 @@ jobs: # coverage is informational: an upload failure must not fail CI fail_ci_if_error: false + tests-floor: + + # the oldest markdown-it-py the package declares (`markdown-it-py>=3.0.0`): + # the plugins that need 4.1 skip their tests and check their version guard + name: tests (3.10, markdown-it-py 3.0.0) + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up Python 3.10 + uses: actions/setup-python@v5 + with: + python-version: "3.10" + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -e .[testing] markdown-it-py==3.0.0 + - name: Check the installed markdown-it-py + run: python -c "import markdown_it; assert markdown_it.__version__ == '3.0.0', markdown_it.__version__" + - name: Run pytest + run: pytest + build: name: Build distributions @@ -103,6 +125,7 @@ jobs: needs: - pre-commit - tests + - tests-floor - build steps: - run: echo "Great success!" @@ -110,7 +133,7 @@ jobs: publish: name: Publish to PyPI - needs: [pre-commit, tests, build] + needs: [pre-commit, tests, tests-floor, build] if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest permissions: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1b32767..65ddc6d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -30,5 +30,5 @@ repos: rev: v2.4.1 hooks: - id: mypy - additional_dependencies: [markdown-it-py~=3.0] + additional_dependencies: [markdown-it-py~=4.2] exclude: ^tests/ diff --git a/pyproject.toml b/pyproject.toml index f6746e4..639ec91 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,11 +14,11 @@ classifiers = [ "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "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", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development :: Libraries :: Python Modules", @@ -26,7 +26,7 @@ classifiers = [ ] keywords = ["markdown", "markdown-it", "lexer", "parser", "development"] requires-python = ">=3.10" -dependencies = ["markdown-it-py>=2.0.0,<5.0.0"] +dependencies = ["markdown-it-py>=3.0.0,<5.0.0"] [project.urls] Homepage = "https://github.com/executablebooks/mdit-py-plugins" diff --git a/tests/test_gfm.py b/tests/test_gfm.py index 3bc3678..1b94dea 100644 --- a/tests/test_gfm.py +++ b/tests/test_gfm.py @@ -8,6 +8,10 @@ from mdit_py_plugins.gfm import gfm_plugin +# The plugin needs markdown-it-py >= 4.1.0 (it raises RuntimeError below that); +# the guard itself is tested in test_mdit_version_guard.py, on every version. +pytest.importorskip("markdown_it", minversion="4.1.0") + FIXTURE_PATH = Path(__file__).parent.joinpath("fixtures", "gfm.md") diff --git a/tests/test_gfm_autolink.py b/tests/test_gfm_autolink.py index 16d0074..a7f236f 100644 --- a/tests/test_gfm_autolink.py +++ b/tests/test_gfm_autolink.py @@ -8,6 +8,10 @@ from mdit_py_plugins.gfm_autolink import gfm_autolink_plugin +# The plugin needs markdown-it-py >= 4.1.0 (it raises RuntimeError below that); +# the guard itself is tested in test_mdit_version_guard.py, on every version. +pytest.importorskip("markdown_it", minversion="4.1.0") + FIXTURE_PATH = Path(__file__).parent.joinpath("fixtures", "gfm_autolink.md") diff --git a/tests/test_mdit_version_guard.py b/tests/test_mdit_version_guard.py new file mode 100644 index 0000000..363692c --- /dev/null +++ b/tests/test_mdit_version_guard.py @@ -0,0 +1,38 @@ +"""The plugins that need markdown-it-py >= 4.1.0 refuse older versions. + +``test_gfm``, ``test_gfm_autolink`` and ``test_section_ref`` skip below 4.1.0, +so their version guards are tested here, where they run on every supported version +(CI runs the suite on the declared floor, markdown-it-py 3.0.0, as well as the latest). +""" + +from types import SimpleNamespace + +from markdown_it import MarkdownIt +from markdown_it import __version__ as mdit_version +from packaging.version import Version +import pytest + +from mdit_py_plugins.gfm import gfm_plugin +from mdit_py_plugins.gfm_autolink import gfm_autolink_plugin +from mdit_py_plugins.section_ref import section_ref_plugin + + +@pytest.mark.skipif( + Version(mdit_version) >= Version("4.1.0"), + reason="needs markdown-it-py < 4.1.0 installed", +) +@pytest.mark.parametrize( + "plugin", [gfm_plugin, gfm_autolink_plugin, section_ref_plugin] +) +def test_raises_below_4_1(plugin): + """On markdown-it-py < 4.1.0 the plugin raises a clear error, not a late failure.""" + with pytest.raises(RuntimeError, match=r"requires markdown-it-py >= 4\.1\.0"): + MarkdownIt().use(plugin) + + +def test_section_ref_runtime_error(): + """The plugin requires the ``add_terminator_char`` API (markdown-it-py >= 4.1.0).""" + md = MarkdownIt() + md.inline = SimpleNamespace() # type: ignore[assignment] # lacks add_terminator_char + with pytest.raises(RuntimeError, match="requires markdown-it-py"): + section_ref_plugin(md) diff --git a/tests/test_section_ref.py b/tests/test_section_ref.py index df777dc..fb1ee5f 100644 --- a/tests/test_section_ref.py +++ b/tests/test_section_ref.py @@ -1,6 +1,5 @@ from pathlib import Path import time -from types import SimpleNamespace from markdown_it import MarkdownIt from markdown_it.token import Token @@ -9,6 +8,10 @@ from mdit_py_plugins.section_ref import section_ref_plugin +# The plugin needs markdown-it-py >= 4.1.0 (it raises RuntimeError below that); +# the guard itself is tested in test_mdit_version_guard.py, on every version. +pytest.importorskip("markdown_it", minversion="4.1.0") + FIXTURE_PATH = Path(__file__).parent.joinpath("fixtures", "section_ref.md") @@ -133,14 +136,6 @@ def test_token_shape_is_public_api(): assert token.meta == {"numbers": [1, 2]} -def test_runtime_error(): - """The plugin requires the ``add_terminator_char`` API (markdown-it-py >= 4.1.0).""" - md = MarkdownIt() - md.inline = SimpleNamespace() # type: ignore[assignment] # lacks add_terminator_char - with pytest.raises(RuntimeError, match="requires markdown-it-py"): - section_ref_plugin(md) - - @pytest.mark.parametrize("line,title,input,expected", read_fixture_file(FIXTURE_PATH)) def test_all(line, title, input, expected): md = MarkdownIt("commonmark").use(section_ref_plugin) diff --git a/tox.ini b/tox.ini index c14ddf5..89db037 100644 --- a/tox.ini +++ b/tox.ini @@ -9,7 +9,7 @@ envlist = py310 [testenv] usedevelop = true -[testenv:py{310,311,312,313}] +[testenv:py{310,311,312,313,314}] extras = testing deps = markdown-it-py>=4.1.0 commands = pytest {posargs}