Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Python 3.13, drop EOL 3.8 #605

Merged
merged 7 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/python.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
os:
- ubuntu-20.04
- ubuntu-latest
- macos-latest
- windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
Expand Down
2 changes: 1 addition & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## python-markdown2 2.5.2 (not yet released)

(nothing yet)
- [pull #605] Add support for Python 3.13, drop EOL 3.8


## python-markdown2 2.5.1
Expand Down
136 changes: 66 additions & 70 deletions lib/markdown2.py

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions perf/gen_perf_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ def _markdown_from_aspn_html(html):
title = None
escaped_href = href.replace('(', '\\(').replace(')', '\\)')
if title is None:
replacement = '[%s](%s)' % (content, escaped_href)
replacement = '[{}]({})'.format(content, escaped_href)
else:
replacement = '[%s](%s "%s")' % (content, escaped_href,
replacement = '[{}]({} "{}")'.format(content, escaped_href,
title.replace('"', "'"))
markdown = markdown[:start] + replacement + markdown[end:]

Expand Down
4 changes: 2 additions & 2 deletions perf/perf.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def time_markdown_py(cases_dir, repeat):
for i in range(repeat):
start = clock()
for path in glob(join(cases_dir, "*.text")):
f = open(path, 'r')
f = open(path)
content = f.read()
f.close()
try:
Expand All @@ -59,7 +59,7 @@ def time_markdown2_py(cases_dir, repeat):
for i in range(repeat):
start = clock()
for path in glob(join(cases_dir, "*.text")):
f = open(path, 'r')
f = open(path)
content = f.read()
f.close()
markdowner.convert(content)
Expand Down
1 change: 0 additions & 1 deletion perf/strip_cookbook_data.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

from os.path import *
from pprint import pformat

Expand Down
2 changes: 1 addition & 1 deletion perf/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def wrapper(*args, **kw):
return func(*args, **kw)
finally:
total_time = clock() - start_time
print("%s took %.3fs" % (func.__name__, total_time))
print("{} took {:.3f}s".format(func.__name__, total_time))
return wrapper

def hotshotit(func):
Expand Down
1 change: 0 additions & 1 deletion sandbox/wiki.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import sys
import re
from os.path import *
Expand Down
2 changes: 0 additions & 2 deletions setup.cfg

This file was deleted.

6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
License :: OSI Approved :: MIT License
Programming Language :: Python
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
Operating System :: OS Independent
Topic :: Software Development :: Libraries :: Python Modules
Topic :: Software Development :: Documentation
Expand All @@ -32,7 +32,7 @@

extras_require = {
"code_syntax_highlighting": ["pygments>=2.7.3"],
"wavedrom": ["wavedrom; python_version>='3.7'"],
"wavedrom": ["wavedrom"],
"latex": ['latex2mathml; python_version>="3.8.1"'],
}
# nested listcomp to combine all optional extras into convenient "all" option
Expand All @@ -56,7 +56,7 @@
]
},
description="A fast and complete Python implementation of Markdown",
python_requires=">=3.8, <4",
python_requires=">=3.9, <4",
extras_require=extras_require,
classifiers=classifiers.strip().split("\n"),
long_description="""markdown2: A fast and complete Python implementation of Markdown.
Expand Down
6 changes: 3 additions & 3 deletions test/markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def is_block_level (tag) :
(re.compile(">"), "&gt;"),
(re.compile("\""), "&quot;")]

ENTITY_NORMALIZATION_EXPRESSIONS_SOFT = [ (re.compile("&(?!\#)"), "&amp;"),
ENTITY_NORMALIZATION_EXPRESSIONS_SOFT = [ (re.compile(r"&(?!\#)"), "&amp;"),
(re.compile("<"), "&lt;"),
(re.compile(">"), "&gt;"),
(re.compile("\""), "&quot;")]
Expand Down Expand Up @@ -325,7 +325,7 @@ def toxml(self):
value = self.attribute_values[attr]
value = self.doc.normalizeEntities(value,
avoidDoubleNormalizing=True)
buffer += ' %s="%s"' % (attr, value)
buffer += ' {}="{}"'.format(attr, value)


# Now let's actually append the children
Expand Down Expand Up @@ -672,7 +672,7 @@ def run (self, lines) :
LINK_ANGLED_RE = BRK + r'\s*\(<([^\)]*)>\)' # [text](<url>)
IMAGE_LINK_RE = r'\!' + BRK + r'\s*\(([^\)]*)\)' # ![alttxt](http://x.com/)
REFERENCE_RE = BRK+ r'\s*\[([^\]]*)\]' # [Google][3]
IMAGE_REFERENCE_RE = r'\!' + BRK + '\s*\[([^\]]*)\]' # ![alt text][2]
IMAGE_REFERENCE_RE = r'\!' + BRK + r'\s*\[([^\]]*)\]' # ![alt text][2]
NOT_STRONG_RE = r'( \* )' # stand-alone * or _
AUTOLINK_RE = r'<(http://[^>]*)>' # <http://www.123.com>
AUTOMAIL_RE = r'<([^> \!]*@[^> ]*)>' # <me@example.com>
Expand Down
9 changes: 3 additions & 6 deletions test/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@ def setup():
import pygments # noqa
except ImportError:
pygments_dir = join(top_dir, "deps", "pygments")
if sys.version_info[0] <= 2:
sys.path.insert(0, pygments_dir)
else:
sys.path.insert(0, pygments_dir + "3")
sys.path.insert(0, pygments_dir + "3")

if __name__ == "__main__":
logging.basicConfig()
Expand All @@ -42,7 +39,7 @@ def setup():
try:
mod = importlib.import_module(extra_lib)
except ImportError:
warnings.append("skipping %s tests ('%s' module not found)" % (extra_lib, extra_lib))
warnings.append("skipping {} tests ('{}' module not found)".format(extra_lib, extra_lib))
default_tags.append("-%s" % extra_lib)
else:
if extra_lib == 'pygments':
Expand All @@ -51,7 +48,7 @@ def setup():
tag = "pygments<2.14"
else:
tag = "pygments>=2.14"
warnings.append("skipping %s tests (pygments %s found)" % (tag, mod.__version__))
warnings.append("skipping {} tests (pygments {} found)".format(tag, mod.__version__))
default_tags.append("-%s" % tag)

retval = testlib.harness(testdir_from_ns=testdir_from_ns,
Expand Down
4 changes: 2 additions & 2 deletions test/test_markdown2.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def generate_tests(cls):
if exists(opts_path):
try:
with warnings.catch_warnings(record=True) as caught_warnings:
opts = eval(open(opts_path, 'r').read())
opts = eval(open(opts_path).read())
for warning in caught_warnings:
print("WARNING: loading %s generated warning: %s - lineno %d" % (opts_path, warning.message, warning.lineno), file=sys.stderr)
except Exception:
Expand Down Expand Up @@ -335,7 +335,7 @@ def _markdown_email_link_sub(match):
href, text = match.groups()
href = _xml_escape_re.sub(_xml_escape_sub, href)
text = _xml_escape_re.sub(_xml_escape_sub, text)
return '<a href="%s">%s</a>' % (href, text)
return '<a href="{}">{}</a>'.format(href, text)

def norm_html_from_html(html):
"""Normalize (somewhat) Markdown'd HTML.
Expand Down
6 changes: 3 additions & 3 deletions test/testall.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ def testall():
# Don't support Python < 3.5
continue
ver_str = "%s.%s" % ver
print("-- test with Python %s (%s)" % (ver_str, python))
print("-- test with Python {} ({})".format(ver_str, python))
assert ' ' not in python

env_args = 'MACOSX_DEPLOYMENT_TARGET= ' if sys.platform == 'darwin' else ''

proc = subprocess.Popen(
# pass "-u" option to force unbuffered output
"%s%s -u test.py -- -knownfailure" % (env_args, python),
"{}{} -u test.py -- -knownfailure".format(env_args, python),
shell=True, stderr=subprocess.PIPE
)

Expand All @@ -77,6 +77,6 @@ def testall():

for python, ver_str, warning in all_warnings:
# now re-print all warnings to make sure they are seen
print('-- warning raised by Python %s (%s) -- %s' % (ver_str, python, warning))
print('-- warning raised by Python {} ({}) -- {}'.format(ver_str, python, warning))

testall()
12 changes: 6 additions & 6 deletions test/testlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ def wrapper(*args, **kw):
finally:
total_time = time.time() - start_time
if total_time > max_time + tolerance:
raise DurationError(('Test was too long (%.2f s)'
% total_time))
raise DurationError('Test was too long (%.2f s)'
% total_time)
return wrapper

return _timedtest
Expand All @@ -140,7 +140,7 @@ def wrapper(*args, **kw):

#---- module api

class Test(object):
class Test:
def __init__(self, ns, testmod, testcase, testfn_name,
testsuite_class=None):
self.ns = ns
Expand Down Expand Up @@ -439,7 +439,7 @@ def list_tests(testdir_from_ns, tags):
if testfile.endswith(".pyc"):
testfile = testfile[:-1]
print("%s:" % t.shortname())
print(" from: %s#%s.%s" % (testfile,
print(" from: {}#{}.{}".format(testfile,
t.testcase.__class__.__name__, t.testfn_name))
wrapped = textwrap.fill(' '.join(t.tags()), WIDTH-10)
print(" tags: %s" % _indent(wrapped, 8, True))
Expand Down Expand Up @@ -470,7 +470,7 @@ def __init__(self, stream):

def getDescription(self, test):
if test._testlib_explicit_tags_:
return "%s [%s]" % (test._testlib_shortname_,
return "{} [{}]".format(test._testlib_shortname_,
', '.join(test._testlib_explicit_tags_))
else:
return test._testlib_shortname_
Expand Down Expand Up @@ -514,7 +514,7 @@ def printErrorList(self, flavour, errors):
self.stream.write("%s\n" % err)


class ConsoleTestRunner(object):
class ConsoleTestRunner:
"""A test runner class that displays results on the console.

It prints out the names of tests as they are run, errors as they
Expand Down
15 changes: 7 additions & 8 deletions tools/cutarelease.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2009-2012 Trent Mick

"""cutarelease -- Cut a release of your project.
Expand Down Expand Up @@ -154,10 +153,10 @@ def cutarelease(project_name, version_files, dry_run=False):
% (changes_path, version))

# Tag version and push.
curr_tags = set(t for t in _capture_stdout(["git", "tag", "-l"]).split(b'\n') if t)
curr_tags = {t for t in _capture_stdout(["git", "tag", "-l"]).split(b'\n') if t}
if not dry_run and version not in curr_tags:
log.info("tag the release")
run('git tag -a "%s" -m "version %s"' % (version, version))
run('git tag -a "{}" -m "version {}"'.format(version, version))
run('git push --tags')

# Optionally release.
Expand Down Expand Up @@ -193,9 +192,9 @@ def cutarelease(project_name, version_files, dry_run=False):
if marker not in changes_txt:
raise Error("couldn't find `%s' marker in `%s' "
"content: can't prep for subsequent dev" % (marker, changes_path))
next_verline = "%s %s%s" % (marker.rsplit(None, 1)[0], next_version, nyr)
next_verline = "{} {}{}".format(marker.rsplit(None, 1)[0], next_version, nyr)
changes_txt = changes_txt.replace(marker + '\n',
"%s\n\n(nothing yet)\n\n\n%s\n" % (next_verline, marker))
"{}\n\n(nothing yet)\n\n\n{}\n".format(next_verline, marker))
if not dry_run:
f = codecs.open(changes_path, 'w', 'utf-8')
f.write(changes_txt)
Expand All @@ -221,12 +220,12 @@ def cutarelease(project_name, version_files, dry_run=False):
ver_content = ver_content.replace(marker,
'var VERSION = "%s";' % next_version)
elif ver_file_type == "python":
marker = "__version_info__ = %r" % (version_info,)
marker = "__version_info__ = {!r}".format(version_info)
if marker not in ver_content:
raise Error("couldn't find `%s' version marker in `%s' "
"content: can't prep for subsequent dev" % (marker, ver_file))
ver_content = ver_content.replace(marker,
"__version_info__ = %r" % (next_version_tuple,))
"__version_info__ = {!r}".format(next_version_tuple))
elif ver_file_type == "version":
ver_content = next_version
else:
Expand All @@ -238,7 +237,7 @@ def cutarelease(project_name, version_files, dry_run=False):
f.close()

if not dry_run:
run('git commit %s %s -m "prep for future dev"' % (
run('git commit {} {} -m "prep for future dev"'.format(
changes_path, ' '.join(version_files)))
run('git push')

Expand Down
3 changes: 2 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
# and then run "tox" from this directory.

[tox]
envlist = py36, py37, py38, py39, py310, py311, py312, pypy
envlist = py{39, 310, 311, 312, 313, py}

[testenv]
allowlist_externals = make
commands = make testone