diff options
-rw-r--r-- | .coveragerc | 1 | ||||
-rw-r--r-- | .github/workflows/tox.yml | 14 | ||||
-rw-r--r-- | docs/change_log/release-3.4.md | 2 | ||||
-rw-r--r-- | markdown/__init__.py | 8 | ||||
-rw-r--r-- | markdown/__meta__.py | 2 | ||||
-rw-r--r-- | markdown/pep562.py | 245 | ||||
-rw-r--r-- | markdown/util.py | 10 | ||||
-rwxr-xr-x | setup.py | 3 | ||||
-rw-r--r-- | tox.ini | 3 |
9 files changed, 14 insertions, 274 deletions
diff --git a/.coveragerc b/.coveragerc index c28a02a..c785d90 100644 --- a/.coveragerc +++ b/.coveragerc @@ -3,4 +3,3 @@ omit= *site-packages* tests/* markdown/test_tools.py - markdown/pep562.py diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index 08cbb49..e2004ad 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -20,10 +20,8 @@ jobs: fail-fast: false max-parallel: 4 matrix: - tox-env: [py36, py37, py38, py39, py310, pypy3, pygments] + tox-env: [py37, py38, py39, py310, pypy37, pypy38, pypy39, pygments] include: - - tox-env: py36 - python-version: '3.6' - tox-env: py37 python-version: '3.7' - tox-env: py38 @@ -32,8 +30,12 @@ jobs: python-version: '3.9' - tox-env: py310 python-version: '3.10' - - tox-env: pypy3 - python-version: pypy3 + - tox-env: pypy37 + python-version: pypy-3.7 + - tox-env: pypy38 + python-version: pypy-3.8 + - tox-env: pypy39 + python-version: pypy-3.9 - tox-env: pygments python-version: '3.7' @@ -43,7 +45,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Setup Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/docs/change_log/release-3.4.md b/docs/change_log/release-3.4.md index 7abdf5d..eb36b40 100644 --- a/docs/change_log/release-3.4.md +++ b/docs/change_log/release-3.4.md @@ -2,7 +2,7 @@ title: Release Notes for v3.4 # Python-Markdown 3.4 Release Notes -Python-Markdown version 3.4 supports Python versions 3.6, 3.7, 3.8, 3.9, 3.10 and +Python-Markdown version 3.4 supports Python versions 3.7, 3.8, 3.9, 3.10 and PyPy3. ## Backwards-incompatible changes diff --git a/markdown/__init__.py b/markdown/__init__.py index e05af10..7760a0c 100644 --- a/markdown/__init__.py +++ b/markdown/__init__.py @@ -27,8 +27,6 @@ if sys.version_info[0] < 3: # pragma: no cover raise ImportError('A recent version of Python 3 is required.') from .core import Markdown, markdown, markdownFromFile # noqa: E402 -from .util import PY37 # noqa: E402 -from .pep562 import Pep562 # noqa: E402 from .__meta__ import __version__, __version_info__ # noqa: E402 import warnings # noqa: E402 @@ -51,11 +49,7 @@ def __getattr__(name): warnings.warn( "'{}' is deprecated. Use '{}' instead.".format(name, deprecated[0]), category=DeprecationWarning, - stacklevel=(3 if PY37 else 4) + stacklevel=(3 if (3, 7) <= sys.version_info else 4) ) return deprecated[1] raise AttributeError("module '{}' has no attribute '{}'".format(__name__, name)) - - -if not PY37: - Pep562(__name__) diff --git a/markdown/__meta__.py b/markdown/__meta__.py index 84884b6..92dd5cf 100644 --- a/markdown/__meta__.py +++ b/markdown/__meta__.py @@ -26,7 +26,7 @@ License: BSD (see LICENSE.md for details). # (1, 2, 0, 'beta', 2) => "1.2b2" # (1, 2, 0, 'rc', 4) => "1.2rc4" # (1, 2, 0, 'final', 0) => "1.2" -__version_info__ = (3, 3, 7, 'final', 0) +__version_info__ = (3, 4, 0, 'dev', 0) def _get_version(version_info): diff --git a/markdown/pep562.py b/markdown/pep562.py deleted file mode 100644 index b130d3b..0000000 --- a/markdown/pep562.py +++ /dev/null @@ -1,245 +0,0 @@ -""" -Backport of PEP 562. - -https://pypi.org/search/?q=pep562 - -Licensed under MIT -Copyright (c) 2018 Isaac Muse <isaacmuse@gmail.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, -and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. -""" -import sys -from collections import namedtuple -import re - -__all__ = ('Pep562',) - -RE_VER = re.compile( - r'''(?x) - (?P<major>\d+)(?:\.(?P<minor>\d+))?(?:\.(?P<micro>\d+))? - (?:(?P<type>a|b|rc)(?P<pre>\d+))? - (?:\.post(?P<post>\d+))? - (?:\.dev(?P<dev>\d+))? - ''' -) - -REL_MAP = { - ".dev": "", - ".dev-alpha": "a", - ".dev-beta": "b", - ".dev-candidate": "rc", - "alpha": "a", - "beta": "b", - "candidate": "rc", - "final": "" -} - -DEV_STATUS = { - ".dev": "2 - Pre-Alpha", - ".dev-alpha": "2 - Pre-Alpha", - ".dev-beta": "2 - Pre-Alpha", - ".dev-candidate": "2 - Pre-Alpha", - "alpha": "3 - Alpha", - "beta": "4 - Beta", - "candidate": "4 - Beta", - "final": "5 - Production/Stable" -} - -PRE_REL_MAP = {"a": 'alpha', "b": 'beta', "rc": 'candidate'} - - -class Version(namedtuple("Version", ["major", "minor", "micro", "release", "pre", "post", "dev"])): - """ - Get the version (PEP 440). - - A biased approach to the PEP 440 semantic version. - - Provides a tuple structure which is sorted for comparisons `v1 > v2` etc. - (major, minor, micro, release type, pre-release build, post-release build, development release build) - Release types are named in is such a way they are comparable with ease. - Accessors to check if a development, pre-release, or post-release build. Also provides accessor to get - development status for setup files. - - How it works (currently): - - - You must specify a release type as either `final`, `alpha`, `beta`, or `candidate`. - - To define a development release, you can use either `.dev`, `.dev-alpha`, `.dev-beta`, or `.dev-candidate`. - The dot is used to ensure all development specifiers are sorted before `alpha`. - You can specify a `dev` number for development builds, but do not have to as implicit development releases - are allowed. - - You must specify a `pre` value greater than zero if using a prerelease as this project (not PEP 440) does not - allow implicit prereleases. - - You can optionally set `post` to a value greater than zero to make the build a post release. While post releases - are technically allowed in prereleases, it is strongly discouraged, so we are rejecting them. It should be - noted that we do not allow `post0` even though PEP 440 does not restrict this. This project specifically - does not allow implicit post releases. - - It should be noted that we do not support epochs `1!` or local versions `+some-custom.version-1`. - - Acceptable version releases: - - ``` - Version(1, 0, 0, "final") 1.0 - Version(1, 2, 0, "final") 1.2 - Version(1, 2, 3, "final") 1.2.3 - Version(1, 2, 0, ".dev-alpha", pre=4) 1.2a4 - Version(1, 2, 0, ".dev-beta", pre=4) 1.2b4 - Version(1, 2, 0, ".dev-candidate", pre=4) 1.2rc4 - Version(1, 2, 0, "final", post=1) 1.2.post1 - Version(1, 2, 3, ".dev") 1.2.3.dev0 - Version(1, 2, 3, ".dev", dev=1) 1.2.3.dev1 - ``` - - """ - - def __new__(cls, major, minor, micro, release="final", pre=0, post=0, dev=0): - """Validate version info.""" - - # Ensure all parts are positive integers. - for value in (major, minor, micro, pre, post): - if not (isinstance(value, int) and value >= 0): - raise ValueError("All version parts except 'release' should be integers.") - - if release not in REL_MAP: - raise ValueError("'{}' is not a valid release type.".format(release)) - - # Ensure valid pre-release (we do not allow implicit pre-releases). - if ".dev-candidate" < release < "final": - if pre == 0: - raise ValueError("Implicit pre-releases not allowed.") - elif dev: - raise ValueError("Version is not a development release.") - elif post: - raise ValueError("Post-releases are not allowed with pre-releases.") - - # Ensure valid development or development/pre release - elif release < "alpha": - if release > ".dev" and pre == 0: - raise ValueError("Implicit pre-release not allowed.") - elif post: - raise ValueError("Post-releases are not allowed with pre-releases.") - - # Ensure a valid normal release - else: - if pre: - raise ValueError("Version is not a pre-release.") - elif dev: - raise ValueError("Version is not a development release.") - - return super().__new__(cls, major, minor, micro, release, pre, post, dev) - - def _is_pre(self): - """Is prerelease.""" - - return self.pre > 0 - - def _is_dev(self): - """Is development.""" - - return bool(self.release < "alpha") - - def _is_post(self): - """Is post.""" - - return self.post > 0 - - def _get_dev_status(self): # pragma: no cover - """Get development status string.""" - - return DEV_STATUS[self.release] - - def _get_canonical(self): - """Get the canonical output string.""" - - # Assemble major, minor, micro version and append `pre`, `post`, or `dev` if needed.. - if self.micro == 0: - ver = "{}.{}".format(self.major, self.minor) - else: - ver = "{}.{}.{}".format(self.major, self.minor, self.micro) - if self._is_pre(): - ver += '{}{}'.format(REL_MAP[self.release], self.pre) - if self._is_post(): - ver += ".post{}".format(self.post) - if self._is_dev(): - ver += ".dev{}".format(self.dev) - - return ver - - -def parse_version(ver, pre=False): - """Parse version into a comparable Version tuple.""" - - m = RE_VER.match(ver) - - # Handle major, minor, micro - major = int(m.group('major')) - minor = int(m.group('minor')) if m.group('minor') else 0 - micro = int(m.group('micro')) if m.group('micro') else 0 - - # Handle pre releases - if m.group('type'): - release = PRE_REL_MAP[m.group('type')] - pre = int(m.group('pre')) - else: - release = "final" - pre = 0 - - # Handle development releases - dev = m.group('dev') if m.group('dev') else 0 - if m.group('dev'): - dev = int(m.group('dev')) - release = '.dev-' + release if pre else '.dev' - else: - dev = 0 - - # Handle post - post = int(m.group('post')) if m.group('post') else 0 - - return Version(major, minor, micro, release, pre, post, dev) - - -class Pep562: - """ - Backport of PEP 562 <https://pypi.org/search/?q=pep562>. - - Wraps the module in a class that exposes the mechanics to override `__dir__` and `__getattr__`. - The given module will be searched for overrides of `__dir__` and `__getattr__` and use them when needed. - """ - - def __init__(self, name): - """Acquire `__getattr__` and `__dir__`, but only replace module for versions less than Python 3.7.""" - - self._module = sys.modules[name] - self._get_attr = getattr(self._module, '__getattr__', None) - self._get_dir = getattr(self._module, '__dir__', None) - sys.modules[name] = self - - def __dir__(self): - """Return the overridden `dir` if one was provided, else apply `dir` to the module.""" - - return self._get_dir() if self._get_dir else dir(self._module) - - def __getattr__(self, name): - """Attempt to retrieve the attribute from the module, and if missing, use the overridden function if present.""" - - try: - return getattr(self._module, name) - except AttributeError: - if self._get_attr: - return self._get_attr(name) - raise - - -__version_info__ = Version(1, 0, 0, "final") -__version__ = __version_info__._get_canonical() diff --git a/markdown/util.py b/markdown/util.py index a6a32bf..6d3a195 100644 --- a/markdown/util.py +++ b/markdown/util.py @@ -27,10 +27,6 @@ from collections import namedtuple from functools import wraps, lru_cache from itertools import count -from .pep562 import Pep562 - -PY37 = (3, 7) <= sys.version_info - # TODO: Remove deprecated variables in a future release. __deprecated__ = { @@ -462,11 +458,7 @@ def __getattr__(name): warnings.warn( "'{}' is deprecated. Use '{}' instead.".format(name, deprecated[0]), category=DeprecationWarning, - stacklevel=(3 if PY37 else 4) + stacklevel=(3 if (3, 7) <= sys.version_info else 4) ) return deprecated[1] raise AttributeError("module '{}' has no attribute '{}'".format(__name__, name)) - - -if not PY37: - Pep562(__name__) @@ -73,7 +73,7 @@ setup( maintainer_email='python.markdown@gmail.com', license='BSD License', packages=['markdown', 'markdown.extensions'], - python_requires='>=3.6', + python_requires='>=3.7', install_requires=["importlib-metadata>=4.4;python_version<'3.10'"], extras_require={ 'testing': [ @@ -113,7 +113,6 @@ setup( 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', @@ -1,5 +1,5 @@ [tox] -envlist = py36, py37, py38, py39, py310, pypy3, pygments, flake8, checkspelling, pep517check, checklinks +envlist = py{37, 38, 39, 310}, pypy{37, 38, 39}, pygments, flake8, checkspelling, pep517check, checklinks isolated_build = True [testenv] @@ -41,4 +41,3 @@ skip_install = true [flake8] max-line-length = 119 -exclude=markdown/pep562.py |