Skip to content

Commit

Permalink
Drop support for Python 2.7 (#865)
Browse files Browse the repository at this point in the history
* Python syntax upgraded using `pyupgrade --py3-plus`
* Travis no longer uses `sudo`. See https://blog.travis-ci.com/2018-11-19-required-linux-infrastructure-migration

See #760 for Python Version Support Timeline and related dicussion.
  • Loading branch information
hugovk authored and waylan committed Oct 24, 2019
1 parent c6a9985 commit dab931f
Show file tree
Hide file tree
Showing 60 changed files with 132 additions and 255 deletions.
11 changes: 1 addition & 10 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
dist: xenial
sudo: false
language: python
cache: pip

matrix:
include:
- python: '2.7'
env: TOXENV=py27
- python: '3.5'
env: TOXENV=py35
- python: '3.6'
env: TOXENV=py36
- python: '3.7'
env: TOXENV=py37
- python: 'pypy'
env: TOXENV=pypy
dist: trusty
- python: 'pypy3'
env: TOXENV=pypy3
dist: trusty
- env: TOXENV=flake8
- env: TOXENV=checkspelling
addons:
Expand All @@ -34,8 +26,7 @@ addons:
- libtidy-0.99-0

install:
# NOTE: setuptools needs to be installed explicitly for py34 (trusty).
- pip install 'setuptools>=36' tox
- pip install tox

script:
- tox
Expand Down
7 changes: 6 additions & 1 deletion docs/change_log/release-3.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ title: Release Notes for v3.2

# Python-Markdown 3.2 Release Notes

Python-Markdown version 3.2 supports Python versions 2.7, 3.5, 3.6, 3.7,
Python-Markdown version 3.2 supports Python versions 3.5, 3.6, 3.7,
PyPy and PyPy3.

## Backwards-incompatible changes

### Drop support for Python 2.7

Python 2.7 reaches end-of-life on 2020-01-01 and Python-Markdown 3.2 has dropped
support for it. Please upgrade to Python 3, or use Python-Markdown 3.1.

### `em` and `strong` inline processor changes

In order to fix issue #792, `em`/`strong` inline processors were refactored. This
Expand Down
10 changes: 5 additions & 5 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ Goals

The Python-Markdown project is developed with the following goals in mind:

* Maintain a Python 2 *and* Python 3 library (with an optional CLI wrapper)
suited to use in web server environments (never raise an exception, never
write to stdout, etc.) as an implementation of the markdown parser that
follows the [syntax rules](https://daringfireball.net/projects/markdown/syntax)
and the behavior of the original (markdown.pl) implementation as reasonably as
* Maintain a Python library (with an optional CLI wrapper) suited to use in web
server environments (never raise an exception, never write to stdout, etc.) as
an implementation of the markdown parser that follows the
[syntax rules](https://daringfireball.net/projects/markdown/syntax) and the
behavior of the original (markdown.pl) implementation as reasonably as
possible (see [differences](#differences) for a few exceptions).

* Provide an [Extension API](extensions/api.md) which makes it possible
Expand Down
3 changes: 0 additions & 3 deletions markdown/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
Python Markdown
Expand All @@ -20,8 +19,6 @@
License: BSD (see LICENSE.md for details).
"""

from __future__ import absolute_import
from __future__ import unicode_literals
from .core import Markdown, markdown, markdownFromFile
from .util import PY37
from .pep562 import Pep562
Expand Down
3 changes: 1 addition & 2 deletions markdown/__main__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
Python Markdown
Expand Down Expand Up @@ -148,5 +147,5 @@ def run(): # pragma: no cover

if __name__ == '__main__': # pragma: no cover
# Support running module as a commandline command.
# Python 2.7 & 3.x do: `python -m markdown [options] [args]`.
# `python -m markdown [options] [args]`.
run()
1 change: 0 additions & 1 deletion markdown/__meta__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
Python Markdown
Expand Down
3 changes: 0 additions & 3 deletions markdown/blockparser.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
Python Markdown
Expand All @@ -20,8 +19,6 @@
License: BSD (see LICENSE.md for details).
"""

from __future__ import unicode_literals
from __future__ import absolute_import
from . import util


Expand Down
24 changes: 10 additions & 14 deletions markdown/blockprocessors.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
Python Markdown
Expand Down Expand Up @@ -31,9 +30,6 @@
as they need to alter how markdown blocks are parsed.
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import logging
import re
from . import util
Expand All @@ -58,7 +54,7 @@ def build_block_parser(md, **kwargs):
return parser


class BlockProcessor(object):
class BlockProcessor:
""" Base class for block processors.
Each subclass will provide the methods below to work with the source and
Expand Down Expand Up @@ -161,7 +157,7 @@ class ListIndentProcessor(BlockProcessor):
LIST_TYPES = ['ul', 'ol']

def __init__(self, *args):
super(ListIndentProcessor, self).__init__(*args)
super().__init__(*args)
self.INDENT_RE = re.compile(r'^(([ ]{%s})+)' % self.tab_length)

def test(self, parent, block):
Expand Down Expand Up @@ -259,7 +255,7 @@ def run(self, parent, blocks):
code = sibling[0]
block, theRest = self.detab(block)
code.text = util.AtomicString(
'%s\n%s\n' % (code.text, util.code_escape(block.rstrip()))
'{}\n{}\n'.format(code.text, util.code_escape(block.rstrip()))
)
else:
# This is a new codeblock. Create the elements and insert text.
Expand Down Expand Up @@ -331,7 +327,7 @@ class OListProcessor(BlockProcessor):
SIBLING_TAGS = ['ol', 'ul']

def __init__(self, parser):
super(OListProcessor, self).__init__(parser)
super().__init__(parser)
# Detect an item (``1. item``). ``group(1)`` contains contents of item.
self.RE = re.compile(r'^[ ]{0,%d}\d+\.[ ]+(.*)' % (self.tab_length - 1))
# Detect items on secondary lines. they can be of either list type.
Expand Down Expand Up @@ -421,12 +417,12 @@ def get_items(self, block):
# This is an indented (possibly nested) item.
if items[-1].startswith(' '*self.tab_length):
# Previous item was indented. Append to that item.
items[-1] = '%s\n%s' % (items[-1], line)
items[-1] = '{}\n{}'.format(items[-1], line)
else:
items.append(line)
else:
# This is another line of previous item. Append to that item.
items[-1] = '%s\n%s' % (items[-1], line)
items[-1] = '{}\n{}'.format(items[-1], line)
return items


Expand All @@ -436,7 +432,7 @@ class UListProcessor(OListProcessor):
TAG = 'ul'

def __init__(self, parser):
super(UListProcessor, self).__init__(parser)
super().__init__(parser)
# Detect an item (``1. item``). ``group(1)`` contains contents of item.
self.RE = re.compile(r'^[ ]{0,%d}[*+-][ ]+(.*)' % (self.tab_length - 1))

Expand Down Expand Up @@ -553,7 +549,7 @@ def run(self, parent, blocks):
len(sibling) and sibling[0].tag == 'code'):
# Last block is a codeblock. Append to preserve whitespace.
sibling[0].text = util.AtomicString(
'%s%s' % (sibling[0].text, filler)
'{}{}'.format(sibling[0].text, filler)
)


Expand All @@ -580,13 +576,13 @@ def run(self, parent, blocks):
if sibling is not None:
# Insetrt after sibling.
if sibling.tail:
sibling.tail = '%s\n%s' % (sibling.tail, block)
sibling.tail = '{}\n{}'.format(sibling.tail, block)
else:
sibling.tail = '\n%s' % block
else:
# Append to parent.text
if parent.text:
parent.text = '%s\n%s' % (parent.text, block)
parent.text = '{}\n{}'.format(parent.text, block)
else:
parent.text = block.lstrip()
else:
Expand Down
19 changes: 8 additions & 11 deletions markdown/core.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
Python Markdown
Expand All @@ -20,8 +19,6 @@
License: BSD (see LICENSE.md for details).
"""

from __future__ import absolute_import
from __future__ import unicode_literals
import codecs
import sys
import logging
Expand All @@ -42,7 +39,7 @@
logger = logging.getLogger('MARKDOWN')


class Markdown(object):
class Markdown:
"""Convert Markdown to HTML."""

doc_tag = "div" # Element used to wrap document - later removed
Expand Down Expand Up @@ -122,7 +119,7 @@ def registerExtensions(self, extensions, configs):
"""
for ext in extensions:
if isinstance(ext, util.string_type):
if isinstance(ext, str):
ext = self.build_extension(ext, configs.get(ext, {}))
if isinstance(ext, Extension):
ext._extendMarkdown(self)
Expand All @@ -132,7 +129,7 @@ def registerExtensions(self, extensions, configs):
)
elif ext is not None:
raise TypeError(
'Extension "%s.%s" must be of type: "%s.%s"' % (
'Extension "{}.{}" must be of type: "{}.{}"'.format(
ext.__class__.__module__, ext.__class__.__name__,
Extension.__module__, Extension.__name__
)
Expand Down Expand Up @@ -221,7 +218,7 @@ def set_output_format(self, format):

def is_block_level(self, tag):
"""Check if the tag is a block level HTML tag."""
if isinstance(tag, util.string_type):
if isinstance(tag, str):
return tag.lower().rstrip('/') in self.block_level_elements
# Some ElementTree tags are not strings, so return False.
return False
Expand Down Expand Up @@ -253,7 +250,7 @@ def convert(self, source):
return '' # a blank unicode string

try:
source = util.text_type(source)
source = str(source)
except UnicodeDecodeError as e: # pragma: no cover
# Customise error message while maintaining original trackback
e.reason += '. -- Note: Markdown only accepts unicode input!'
Expand Down Expand Up @@ -321,15 +318,15 @@ def convertFile(self, input=None, output=None, encoding=None):

# Read the source
if input:
if isinstance(input, util.string_type):
if isinstance(input, str):
input_file = codecs.open(input, mode="r", encoding=encoding)
else:
input_file = codecs.getreader(encoding)(input)
text = input_file.read()
input_file.close()
else:
text = sys.stdin.read()
if not isinstance(text, util.text_type): # pragma: no cover
if not isinstance(text, str): # pragma: no cover
text = text.decode(encoding)

text = text.lstrip('\ufeff') # remove the byte-order mark
Expand All @@ -339,7 +336,7 @@ def convertFile(self, input=None, output=None, encoding=None):

# Write to file or stdout
if output:
if isinstance(output, util.string_type):
if isinstance(output, str):
output_file = codecs.open(output, "w",
encoding=encoding,
errors="xmlcharrefreplace")
Expand Down
8 changes: 3 additions & 5 deletions markdown/extensions/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
Python Markdown
Expand All @@ -20,12 +19,11 @@
License: BSD (see LICENSE.md for details).
"""

from __future__ import unicode_literals
import warnings
from ..util import parseBoolValue


class Extension(object):
class Extension:
""" Base class for extensions to subclass. """

# Default config -- to be overriden by a subclass
Expand All @@ -50,7 +48,7 @@ def getConfig(self, key, default=''):

def getConfigs(self):
""" Return all configs settings as a dict. """
return dict([(key, self.getConfig(key)) for key in self.config.keys()])
return {key: self.getConfig(key) for key in self.config.keys()}

def getConfigInfo(self):
""" Return all config descriptions as a list of tuples. """
Expand Down Expand Up @@ -81,7 +79,7 @@ def _extendMarkdown(self, *args):
# Must be a 2.x extension. Pass in a dumby md_globals.
self.extendMarkdown(md, {})
warnings.warn(
"The 'md_globals' parameter of '{0}.{1}.extendMarkdown' is "
"The 'md_globals' parameter of '{}.{}.extendMarkdown' is "
"deprecated.".format(self.__class__.__module__, self.__class__.__name__),
category=DeprecationWarning,
stacklevel=2
Expand Down
4 changes: 1 addition & 3 deletions markdown/extensions/abbr.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
'''

from __future__ import absolute_import
from __future__ import unicode_literals
from . import Extension
from ..preprocessors import Preprocessor
from ..inlinepatterns import InlineProcessor
Expand Down Expand Up @@ -81,7 +79,7 @@ class AbbrInlineProcessor(InlineProcessor):
""" Abbreviation inline pattern. """

def __init__(self, pattern, title):
super(AbbrInlineProcessor, self).__init__(pattern)
super().__init__(pattern)
self.title = title

def handleMatch(self, m, data):
Expand Down
4 changes: 1 addition & 3 deletions markdown/extensions/admonition.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
"""

from __future__ import absolute_import
from __future__ import unicode_literals
from . import Extension
from ..blockprocessors import BlockProcessor
from ..util import etree
Expand Down Expand Up @@ -61,7 +59,7 @@ def run(self, parent, blocks):
if m:
klass, title = self.get_class_and_title(m)
div = etree.SubElement(parent, 'div')
div.set('class', '%s %s' % (self.CLASSNAME, klass))
div.set('class', '{} {}'.format(self.CLASSNAME, klass))
if title:
p = etree.SubElement(div, 'p')
p.text = title
Expand Down
4 changes: 1 addition & 3 deletions markdown/extensions/attr_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
"""

from __future__ import absolute_import
from __future__ import unicode_literals
from . import Extension
from ..treeprocessors import Treeprocessor
import re
Expand Down Expand Up @@ -145,7 +143,7 @@ def assign_attrs(self, elem, attrs):
# add to class
cls = elem.get('class')
if cls:
elem.set('class', '%s %s' % (cls, v))
elem.set('class', '{} {}'.format(cls, v))
else:
elem.set('class', v)
else:
Expand Down
Loading

0 comments on commit dab931f

Please sign in to comment.