Skip to content

Commit 7d3d4f9

Browse files
authored
Add early support for Python 3.14 (#2697)
1 parent beb841e commit 7d3d4f9

File tree

8 files changed

+15
-11
lines changed

8 files changed

+15
-11
lines changed

.github/workflows/build.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
max-parallel: 4
1818
matrix:
1919
platform: [ubuntu-latest, windows-latest]
20-
python-version: [3.9, '3.10', '3.11', '3.12', '3.13']
20+
python-version: [3.9, '3.10', '3.11', '3.12', '3.13', '3.14']
2121
include:
2222
- python-version: 3.9
2323
tox-env: py39
@@ -29,6 +29,8 @@ jobs:
2929
tox-env: py312
3030
- python-version: '3.13'
3131
tox-env: py313
32+
- python-version: '3.14'
33+
tox-env: py314
3234
# exclude:
3335
# - platform: windows-latest
3436
# python-version: 3.14

docs/src/markdown/about/changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## 10.16
44

5+
- **NEW**: Add early support for Python 3.14.
56
- **NEW**: Drop support for Python 3.8.
67
- **NEW**: Snippets: Added `max_retries` and `backoff_retries` options to configure new retry logic for HTTP 429
78
errors (Too Many Requests client error).

hatch_build.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ def update(self, metadata):
3333
"Programming Language :: Python :: 3.11",
3434
"Programming Language :: Python :: 3.12",
3535
"Programming Language :: Python :: 3.13",
36+
"Programming Language :: Python :: 3.14",
3637
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
3738
"Topic :: Software Development :: Libraries :: Python Modules",
3839
"Topic :: Text Processing :: Filters",

pymdownx/snippets.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import functools
2828
import urllib
2929
import re
30-
import codecs
3130
import os
3231
from . import util
3332
import textwrap
@@ -362,7 +361,7 @@ def parse_snippets(self, lines, file_name=None, is_url=False, is_section=False):
362361

363362
if not url:
364363
# Read file content
365-
with codecs.open(snippet, 'r', encoding=self.encoding) as f:
364+
with open(snippet, 'r', encoding=self.encoding) as f:
366365
last = False
367366
s_lines = []
368367
for l in f:

pymdownx/util.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
_PLATFORM = "linux"
3434

3535
PY39 = (3, 9) <= sys.version_info
36+
PY314 = (3, 14) <= sys.version_info
3637

3738

3839
def clamp(value: float, mn: float, mx: float) -> float:
@@ -79,6 +80,8 @@ def path2url(url: str) -> str:
7980
# If on windows, replace the notation to use a default protocol `///` with nothing.
8081
if is_win() and RE_WIN_DEFAULT_PROTOCOL.match(path):
8182
path = path.replace('///', '', 1)
83+
if PY314:
84+
path = path.replace('///', '/')
8285
return path
8386

8487

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ legacy_tox_ini = """
139139
[tox]
140140
isolated_build = true
141141
envlist =
142-
{py39,py310,py311,py312,py313}, lint, documents
142+
{py39,py310,py311,py312,py313,py314}, lint, documents
143143
144144
[testenv]
145145
passenv = LANG

tests/test_syntax.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import os
33
import markdown
44
import difflib
5-
import codecs
65
import pytest
76
import copy
87
from . import util
@@ -55,15 +54,15 @@ def check_markdown(testfile, extension, extension_config, wrapper, update=False)
5554
"""Check the markdown."""
5655

5756
expected_html = os.path.splitext(testfile)[0] + '.html'
58-
with codecs.open(testfile, 'r', encoding='utf-8') as f:
57+
with open(testfile, 'r', encoding='utf-8') as f:
5958
source = f.read()
6059

6160
results = wrapper % markdown.Markdown(
6261
extensions=extension, extension_configs=extension_config
6362
).convert(source)
6463

6564
try:
66-
with codecs.open(expected_html, 'r', encoding='utf-8') as f:
65+
with open(expected_html, 'r', encoding='utf-8') as f:
6766
expected = f.read().replace("\r\n", "\n")
6867
except Exception:
6968
expected = ''
@@ -80,7 +79,7 @@ def check_markdown(testfile, extension, extension_config, wrapper, update=False)
8079
if diff:
8180
if update:
8281
print('Updated: %s' % expected_html)
83-
with codecs.open(expected_html, 'w', encoding='utf-8') as f:
82+
with open(expected_html, 'w', encoding='utf-8') as f:
8483
f.write(results)
8584
else:
8685
raise Exception(
@@ -100,7 +99,7 @@ def gather_test_params():
10099
if os.path.exists(cfg_path):
101100
files.remove('tests.yml')
102101
[files.remove(file) for file in files[:] if not file.endswith('.txt')]
103-
with codecs.open(cfg_path, 'r', encoding='utf-8') as f:
102+
with open(cfg_path, 'r', encoding='utf-8') as f:
104103
cfg = util.yaml_load(f.read())
105104
for testfile in files:
106105
key = os.path.splitext(testfile)[0]

tools/gen_gemoji.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import sys
33
import os
44
import json
5-
import codecs
65
current_dir = os.path.dirname(os.path.abspath(__file__))
76

87
U_JOIN = 0x200d
@@ -84,7 +83,7 @@ def get_gemoji_specific(value):
8483
def parse(repo, tag):
8584
"""Save test files."""
8685
# Load emoji database
87-
with codecs.open(os.path.join(current_dir, 'tags', repo, repo, 'db', 'emoji.json'), 'r', encoding='utf-8') as f:
86+
with open(os.path.join(current_dir, 'tags', repo, repo, 'db', 'emoji.json'), 'r', encoding='utf-8') as f:
8887
emojis = json.loads(f.read())
8988

9089
emoji_db = {}

0 commit comments

Comments
 (0)