mirror of
https://github.com/getpelican/pelican.git
synced 2025-10-15 20:28:56 +02:00
Drop support for EOL Python 3.8
This commit is contained in:
parent
7d4adfce3f
commit
714a3d53a1
9 changed files with 22 additions and 40 deletions
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
|
|
@ -17,8 +17,6 @@ jobs:
|
||||||
os: [ubuntu, macos, windows]
|
os: [ubuntu, macos, windows]
|
||||||
python: ["3.10", "3.11", "3.12", "3.13"]
|
python: ["3.10", "3.11", "3.12", "3.13"]
|
||||||
include:
|
include:
|
||||||
- os: ubuntu
|
|
||||||
python: "3.8"
|
|
||||||
- os: ubuntu
|
- os: ubuntu
|
||||||
python: "3.9"
|
python: "3.9"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import os
|
||||||
import re
|
import re
|
||||||
from datetime import timezone
|
from datetime import timezone
|
||||||
from html import unescape
|
from html import unescape
|
||||||
from typing import Any, Dict, Optional, Set, Tuple
|
from typing import Any, Optional
|
||||||
from urllib.parse import ParseResult, unquote, urljoin, urlparse, urlunparse
|
from urllib.parse import ParseResult, unquote, urljoin, urlparse, urlunparse
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -47,7 +47,7 @@ class Content:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
default_template: Optional[str] = None
|
default_template: Optional[str] = None
|
||||||
mandatory_properties: Tuple[str, ...] = ()
|
mandatory_properties: tuple[str, ...] = ()
|
||||||
|
|
||||||
@deprecated_attribute(old="filename", new="source_path", since=(3, 2, 0))
|
@deprecated_attribute(old="filename", new="source_path", since=(3, 2, 0))
|
||||||
def filename():
|
def filename():
|
||||||
|
|
@ -56,10 +56,10 @@ class Content:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
content: str,
|
content: str,
|
||||||
metadata: Optional[Dict[str, Any]] = None,
|
metadata: Optional[dict[str, Any]] = None,
|
||||||
settings: Optional[Settings] = None,
|
settings: Optional[Settings] = None,
|
||||||
source_path: Optional[str] = None,
|
source_path: Optional[str] = None,
|
||||||
context: Optional[Dict[Any, Any]] = None,
|
context: Optional[dict[Any, Any]] = None,
|
||||||
):
|
):
|
||||||
if metadata is None:
|
if metadata is None:
|
||||||
metadata = {}
|
metadata = {}
|
||||||
|
|
@ -226,7 +226,7 @@ class Content:
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def url_format(self) -> Dict[str, Any]:
|
def url_format(self) -> dict[str, Any]:
|
||||||
"""Returns the URL, formatted with the proper values"""
|
"""Returns the URL, formatted with the proper values"""
|
||||||
metadata = copy.copy(self.metadata)
|
metadata = copy.copy(self.metadata)
|
||||||
path = self.metadata.get("path", self.get_relative_source_path())
|
path = self.metadata.get("path", self.get_relative_source_path())
|
||||||
|
|
@ -397,7 +397,7 @@ class Content:
|
||||||
hrefs = self._get_intrasite_link_regex()
|
hrefs = self._get_intrasite_link_regex()
|
||||||
return hrefs.sub(lambda m: self._link_replacer(siteurl, m), content)
|
return hrefs.sub(lambda m: self._link_replacer(siteurl, m), content)
|
||||||
|
|
||||||
def get_static_links(self) -> Set[str]:
|
def get_static_links(self) -> set[str]:
|
||||||
static_links = set()
|
static_links = set()
|
||||||
hrefs = self._get_intrasite_link_regex()
|
hrefs = self._get_intrasite_link_regex()
|
||||||
for m in hrefs.finditer(self._content):
|
for m in hrefs.finditer(self._content):
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ from collections import defaultdict
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from itertools import chain, groupby
|
from itertools import chain, groupby
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
from typing import List, Optional, Set
|
from typing import Optional
|
||||||
|
|
||||||
from jinja2 import (
|
from jinja2 import (
|
||||||
BaseLoader,
|
BaseLoader,
|
||||||
|
|
@ -158,8 +158,8 @@ class Generator:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_files(
|
def get_files(
|
||||||
self, paths, exclude: Optional[List[str]] = None, extensions=None
|
self, paths, exclude: Optional[list[str]] = None, extensions=None
|
||||||
) -> Set[str]:
|
) -> set[str]:
|
||||||
"""Return a list of files to use, based on rules
|
"""Return a list of files to use, based on rules
|
||||||
|
|
||||||
:param paths: the list pf paths to search (relative to self.path)
|
:param paths: the list pf paths to search (relative to self.path)
|
||||||
|
|
@ -253,7 +253,7 @@ class Generator:
|
||||||
# return the name of the class for logging purposes
|
# return the name of the class for logging purposes
|
||||||
return self.__class__.__name__
|
return self.__class__.__name__
|
||||||
|
|
||||||
def _check_disabled_readers(self, paths, exclude: Optional[List[str]]) -> None:
|
def _check_disabled_readers(self, paths, exclude: Optional[list[str]]) -> None:
|
||||||
"""Log warnings for files that would have been processed by disabled readers."""
|
"""Log warnings for files that would have been processed by disabled readers."""
|
||||||
for fil in self.get_files(
|
for fil in self.get_files(
|
||||||
paths, exclude=exclude, extensions=self.readers.disabled_extensions
|
paths, exclude=exclude, extensions=self.readers.disabled_extensions
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import sys
|
||||||
from os.path import isabs
|
from os.path import isabs
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from types import ModuleType
|
from types import ModuleType
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
from pelican.log import LimitFilter
|
from pelican.log import LimitFilter
|
||||||
|
|
||||||
|
|
@ -24,7 +24,7 @@ def load_source(name: str, path: str) -> ModuleType:
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
Settings = Dict[str, Any]
|
Settings = dict[str, Any]
|
||||||
|
|
||||||
DEFAULT_THEME = os.path.join(
|
DEFAULT_THEME = os.path.join(
|
||||||
os.path.dirname(os.path.abspath(__file__)), "themes", "notmyidea"
|
os.path.dirname(os.path.abspath(__file__)), "themes", "notmyidea"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
from shutil import copy, rmtree
|
from shutil import copy, rmtree
|
||||||
from tempfile import mkdtemp
|
from tempfile import mkdtemp
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
@ -1528,18 +1527,9 @@ class TestStaticGenerator(unittest.TestCase):
|
||||||
self.generator.generate_context()
|
self.generator.generate_context()
|
||||||
self.generator.generate_output(None)
|
self.generator.generate_output(None)
|
||||||
self.assertTrue(os.path.islink(self.endfile))
|
self.assertTrue(os.path.islink(self.endfile))
|
||||||
|
self.assertEqual(
|
||||||
# os.path.realpath is broken on Windows before python3.8 for symlinks.
|
os.path.realpath(self.endfile), os.path.realpath(self.startfile)
|
||||||
# This is a (ugly) workaround.
|
)
|
||||||
# see: https://bugs.python.org/issue9949
|
|
||||||
if os.name == "nt" and sys.version_info < (3, 8):
|
|
||||||
|
|
||||||
def get_real_path(path):
|
|
||||||
return os.readlink(path) if os.path.islink(path) else path
|
|
||||||
else:
|
|
||||||
get_real_path = os.path.realpath
|
|
||||||
|
|
||||||
self.assertEqual(get_real_path(self.endfile), get_real_path(self.startfile))
|
|
||||||
|
|
||||||
def test_delete_existing_file_before_mkdir(self):
|
def test_delete_existing_file_before_mkdir(self):
|
||||||
with open(self.startfile, "w") as f:
|
with open(self.startfile, "w") as f:
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
import argparse
|
import argparse
|
||||||
import locale
|
import locale
|
||||||
import os
|
import os
|
||||||
from typing import Mapping
|
from collections.abc import Mapping
|
||||||
|
|
||||||
from jinja2 import Environment, FileSystemLoader
|
from jinja2 import Environment, FileSystemLoader
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import shutil
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
import urllib
|
import urllib
|
||||||
from collections.abc import Hashable
|
from collections.abc import Collection, Generator, Hashable, Iterable, Sequence
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from html import entities
|
from html import entities
|
||||||
|
|
@ -22,10 +22,6 @@ from typing import (
|
||||||
TYPE_CHECKING,
|
TYPE_CHECKING,
|
||||||
Any,
|
Any,
|
||||||
Callable,
|
Callable,
|
||||||
Collection,
|
|
||||||
Generator,
|
|
||||||
Iterable,
|
|
||||||
Sequence,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
import dateutil.parser
|
import dateutil.parser
|
||||||
|
|
@ -133,8 +129,9 @@ class DateFormatter:
|
||||||
def __call__(self, date: datetime.datetime, date_format: str) -> str:
|
def __call__(self, date: datetime.datetime, date_format: str) -> str:
|
||||||
# on OSX, encoding from LC_CTYPE determines the unicode output in PY3
|
# on OSX, encoding from LC_CTYPE determines the unicode output in PY3
|
||||||
# make sure it's same as LC_TIME
|
# make sure it's same as LC_TIME
|
||||||
with temporary_locale(self.locale, locale.LC_TIME), temporary_locale(
|
with (
|
||||||
self.locale, locale.LC_CTYPE
|
temporary_locale(self.locale, locale.LC_TIME),
|
||||||
|
temporary_locale(self.locale, locale.LC_CTYPE),
|
||||||
):
|
):
|
||||||
formatted = strftime(date, date_format)
|
formatted = strftime(date, date_format)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ classifiers = [
|
||||||
"License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",
|
"License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",
|
||||||
"Operating System :: OS Independent",
|
"Operating System :: OS Independent",
|
||||||
"Programming Language :: Python :: 3",
|
"Programming Language :: Python :: 3",
|
||||||
"Programming Language :: Python :: 3.8",
|
|
||||||
"Programming Language :: Python :: 3.9",
|
"Programming Language :: Python :: 3.9",
|
||||||
"Programming Language :: Python :: 3.10",
|
"Programming Language :: Python :: 3.10",
|
||||||
"Programming Language :: Python :: 3.11",
|
"Programming Language :: Python :: 3.11",
|
||||||
|
|
@ -28,7 +27,7 @@ classifiers = [
|
||||||
"Topic :: Text Processing :: Markup :: HTML",
|
"Topic :: Text Processing :: Markup :: HTML",
|
||||||
"Topic :: Text Processing :: Markup :: reStructuredText",
|
"Topic :: Text Processing :: Markup :: reStructuredText",
|
||||||
]
|
]
|
||||||
requires-python = ">=3.8.1,<4.0"
|
requires-python = ">=3.9,<4.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"blinker>=1.7.0",
|
"blinker>=1.7.0",
|
||||||
"docutils>=0.20.1",
|
"docutils>=0.20.1",
|
||||||
|
|
@ -39,7 +38,6 @@ dependencies = [
|
||||||
"python-dateutil>=2.8.2",
|
"python-dateutil>=2.8.2",
|
||||||
"rich>=13.6.0",
|
"rich>=13.6.0",
|
||||||
"unidecode>=1.3.7",
|
"unidecode>=1.3.7",
|
||||||
"backports-zoneinfo>=0.2.1; python_version < \"3.9\"",
|
|
||||||
"watchfiles>=0.21.0",
|
"watchfiles>=0.21.0",
|
||||||
"tzdata; sys_platform == 'win32'",
|
"tzdata; sys_platform == 'win32'",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
3
tox.ini
3
tox.ini
|
|
@ -1,9 +1,8 @@
|
||||||
[tox]
|
[tox]
|
||||||
envlist = py{3.8,3.9,3.10,3.11,3.12,3.13},docs
|
envlist = py{3.9,3.10,3.11,3.12,3.13},docs
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
basepython =
|
basepython =
|
||||||
py3.8: python3.8
|
|
||||||
py3.9: python3.9
|
py3.9: python3.9
|
||||||
py3.10: python3.10
|
py3.10: python3.10
|
||||||
py3.11: python3.11
|
py3.11: python3.11
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue