Add Py2.6 compatibility

This commit is contained in:
Steffen Prince 2015-10-29 13:39:22 -07:00
parent abf6cfdb4c
commit 686d87d30f
10 changed files with 74 additions and 66 deletions

View File

@ -1,6 +1,7 @@
# http://travis-ci.org/#!/FSX/misaka
language: python
python:
- 2.6
- 2.7
- 3.2
- 3.3

View File

@ -20,7 +20,7 @@ Documentation can be found at: http://misaka.61924.nl/
Installation
------------
Misaka has been tested on CPython 2.7, 3.2, 3.3, 3.4, 3.5 and PyPy 2.6. It needs
Misaka has been tested on CPython 2.6, 2.7, 3.2, 3.3, 3.4, 3.5 and PyPy 2.6. It needs
CFFI 1.0 or newer, because of this it will not work on PyPy 2.5 and older.
With pip::

View File

@ -82,33 +82,33 @@ ffi.cdef("""\
typedef enum hoedown_extensions {{
/* block-level extensions */
HOEDOWN_EXT_TABLES = {},
HOEDOWN_EXT_FENCED_CODE = {},
HOEDOWN_EXT_FOOTNOTES = {},
HOEDOWN_EXT_AUTOLINK = {},
HOEDOWN_EXT_STRIKETHROUGH = {},
HOEDOWN_EXT_UNDERLINE = {},
HOEDOWN_EXT_HIGHLIGHT = {},
HOEDOWN_EXT_QUOTE = {},
HOEDOWN_EXT_SUPERSCRIPT = {},
HOEDOWN_EXT_MATH = {},
HOEDOWN_EXT_NO_INTRA_EMPHASIS = {},
HOEDOWN_EXT_SPACE_HEADERS = {},
HOEDOWN_EXT_MATH_EXPLICIT = {},
HOEDOWN_EXT_DISABLE_INDENTED_CODE = {}
HOEDOWN_EXT_TABLES = {0},
HOEDOWN_EXT_FENCED_CODE = {1},
HOEDOWN_EXT_FOOTNOTES = {2},
HOEDOWN_EXT_AUTOLINK = {3},
HOEDOWN_EXT_STRIKETHROUGH = {4},
HOEDOWN_EXT_UNDERLINE = {5},
HOEDOWN_EXT_HIGHLIGHT = {6},
HOEDOWN_EXT_QUOTE = {7},
HOEDOWN_EXT_SUPERSCRIPT = {8},
HOEDOWN_EXT_MATH = {9},
HOEDOWN_EXT_NO_INTRA_EMPHASIS = {10},
HOEDOWN_EXT_SPACE_HEADERS = {11},
HOEDOWN_EXT_MATH_EXPLICIT = {12},
HOEDOWN_EXT_DISABLE_INDENTED_CODE = {13}
}} hoedown_extensions;
typedef enum hoedown_list_flags {{
HOEDOWN_LIST_ORDERED = {},
HOEDOWN_LI_BLOCK = {}
HOEDOWN_LIST_ORDERED = {14},
HOEDOWN_LI_BLOCK = {15}
}} hoedown_list_flags;
typedef enum hoedown_table_flags {{
HOEDOWN_TABLE_ALIGN_LEFT = {},
HOEDOWN_TABLE_ALIGN_RIGHT = {},
HOEDOWN_TABLE_ALIGN_CENTER = {},
HOEDOWN_TABLE_ALIGNMASK = {},
HOEDOWN_TABLE_HEADER = {}
HOEDOWN_TABLE_ALIGN_LEFT = {16},
HOEDOWN_TABLE_ALIGN_RIGHT = {17},
HOEDOWN_TABLE_ALIGN_CENTER = {18},
HOEDOWN_TABLE_ALIGNMASK = {19},
HOEDOWN_TABLE_HEADER = {20}
}} hoedown_table_flags;
// ----------------------
@ -116,10 +116,10 @@ typedef enum hoedown_table_flags {{
// ----------------------
typedef enum hoedown_html_flags {{
HOEDOWN_HTML_SKIP_HTML = {},
HOEDOWN_HTML_ESCAPE = {},
HOEDOWN_HTML_HARD_WRAP = {},
HOEDOWN_HTML_USE_XHTML = {}
HOEDOWN_HTML_SKIP_HTML = {21},
HOEDOWN_HTML_ESCAPE = {22},
HOEDOWN_HTML_HARD_WRAP = {23},
HOEDOWN_HTML_USE_XHTML = {24}
}} hoedown_html_flags;
""".format(
EXT_TABLES,

View File

@ -15,7 +15,7 @@ See the :doc:`/changelog` for all changes.
Installation
------------
Misaka has been tested on CPython 2.7, 3.2, 3.3, 3.4, 3.5 and PyPy 2.6.
Misaka has been tested on CPython 2.6, 2.7, 3.2, 3.3, 3.4, 3.5 and PyPy 2.6.
CFFI 1.0 or newer is required. This means Misaka will not work on PyPy 2.5
and older versions.

View File

@ -41,13 +41,13 @@ if __name__ == '__main__':
elif arg.startswith('--ext-'):
arg = arg[6:]
if not arg in extension_map:
print('--ext-{} is not a valid Markdown extension'.format(arg))
print('--ext-{0} is not a valid Markdown extension'.format(arg))
sys.exit(1)
extensions.append(arg)
elif arg.startswith('--html-'):
arg = arg[7:]
if not arg in html_flag_map:
print('--html-{} is not a valid HTML render flag'.format(arg))
print('--html-{0} is not a valid HTML render flag'.format(arg))
sys.exit(1)
flags.append(arg)
else:

View File

@ -6,6 +6,12 @@ import sys
from setuptools import setup, Command
install_requires=['cffi>=1.0.0']
try:
import importlib
except ImportError:
install_requires.append('importlib')
dirname = os.path.dirname(os.path.abspath(__file__))
@ -52,6 +58,7 @@ setup(
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Programming Language :: C',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
@ -64,6 +71,6 @@ setup(
'Topic :: Utilities'
],
setup_requires=['cffi>=1.0.0'],
install_requires=['cffi>=1.0.0'],
install_requires=install_requires,
cffi_modules=['build_ffi.py:ffi'],
)

View File

@ -36,20 +36,20 @@ def _exc_name(exception_class):
if not inspect.isclass(exception_class):
exception_class = exception_class.__class__
return '<{}.{}>'.format(
return '<{0}.{1}>'.format(
exception_class.__module__,
exception_class.__name__)
def readable_duration(s, suffix=''):
if s >= 1:
f = '{:.2f} s'.format(s)
f = '{0:.2f} s'.format(s)
elif s < 1:
ms = 1000 * s
if ms >= 1:
f = '{:.2f} ms'.format(ms)
f = '{0:.2f} ms'.format(ms)
elif ms < 1:
f = '{:.2f} us'.format(ms * 1000)
f = '{0:.2f} us'.format(ms * 1000)
return f + suffix
@ -60,38 +60,38 @@ class AssertionObject(object):
def __lt__(self, other):
if not self._target < other:
raise AssertionError('{!r} < {!r}'.format(self._target, other))
raise AssertionError('{0!r} < {1!r}'.format(self._target, other))
def __le__(self, other):
if not self._target <= other:
raise AssertionError('{!r} <= {!r}'.format(self._target, other))
raise AssertionError('{0!r} <= {1!r}'.format(self._target, other))
def __eq__(self, other):
if not self._target == other:
raise AssertionError('{!r} == {!r}'.format(self._target, other))
raise AssertionError('{0!r} == {1!r}'.format(self._target, other))
def __ne__(self, other):
if not self._target != other:
raise AssertionError('{!r} != {!r}'.format(self._target, other))
raise AssertionError('{0!r} != {1!r}'.format(self._target, other))
def __gt__(self, other):
if not self._target > other:
raise AssertionError('{!r} > {!r}'.format(self._target, other))
raise AssertionError('{0!r} > {1!r}'.format(self._target, other))
def __ge__(self, other):
if not self._target >= other:
raise AssertionError('{!r} >= {!r}'.format(self._target, other))
raise AssertionError('{0!r} >= {1!r}'.format(self._target, other))
def length(self, other):
target_length = len(self._target)
if target_length > other:
raise AssertionError(
'Higher than desired length: {!r} > {!r}'
'Higher than desired length: {0!r} > {1!r}'
.format(target_length, other))
elif target_length < other:
raise AssertionError(
'Lower than desired length: {!r} < {!r}'
'Lower than desired length: {0!r} < {1!r}'
.format(target_length, other))
def diff(self, other):
@ -103,11 +103,11 @@ class AssertionObject(object):
def contains(self, other):
if other not in self._target:
raise AssertionError('{!r} in {!r}'.format(other, self._target))
raise AssertionError('{0!r} in {1!r}'.format(other, self._target))
def not_contains(self, other):
if other in self._target:
raise AssertionError('{!r} not in {!r}'.format(other, self._target))
raise AssertionError('{0!r} not in {1!r}'.format(other, self._target))
def raises(self, exception_class=Exception):
name = _exc_name(exception_class)
@ -120,10 +120,10 @@ class AssertionObject(object):
except exception_class:
pass
except Exception as e:
raise AssertionError('Expected {}, but got {}:\n{}'
raise AssertionError('Expected {0}, but got {1}:\n{2}'
.format(name, _exc_name(e), e))
else:
raise AssertionError('{} not raised'.format(name))
raise AssertionError('{0} not raised'.format(name))
def not_raises(self, exception_class=Exception):
name = _exc_name(exception_class)
@ -134,9 +134,9 @@ class AssertionObject(object):
try:
self._target()
except exception_class as e:
raise AssertionError('{} raised:\n{}'.format(name, e))
raise AssertionError('{0} raised:\n{1}'.format(name, e))
except Exception as e:
raise AssertionError('Expected {} when failing, but got {}:\n{}'
raise AssertionError('Expected {0} when failing, but got {1}:\n{2}'
.format(name, _exc_name(e), e))
@ -159,9 +159,9 @@ class TestResult(object):
return 'PASSED' if self.passed else 'FAILED'
def __str__(self):
s = '{} ... {}'.format(self.name(), self.status())
s = '{0} ... {1}'.format(self.name(), self.status())
if self.message:
s += '\n{}\n{}\n{}'.format(LINE, self.message, LINE)
s += '\n{0}\n{1}\n{2}'.format(LINE, self.message, LINE)
return s
@ -175,16 +175,16 @@ class BenchmarkResult(TestResult):
def __str__(self):
if self.passed:
s = '{:<25} {:>8} {:>16} {:>16}'.format(
s = '{0:<25} {1:>8} {2:>16} {3:>16}'.format(
self.name(),
self.repetitions,
readable_duration(self.timing, suffix='/t'),
readable_duration(self.timing / self.repetitions, suffix='/op'))
else:
s = '{} ... FAILED'.format(self.name())
s = '{0} ... FAILED'.format(self.name())
if self.message:
s += '\n{}\n{}\n{}'.format(LINE, self.message, LINE)
s += '\n{0}\n{1}\n{2}'.format(LINE, self.message, LINE)
return s
@ -202,7 +202,7 @@ class TestCase(object):
def name(cls):
name = _get_doc_line(cls)
if name:
return '{} ({})'.format(name, cls.__name__)
return '{0} ({1})'.format(name, cls.__name__)
else:
return cls.__name__
@ -299,7 +299,7 @@ def runner(testcases, setup_func=None, teardown_func=None, config={}):
for testcase in testcases:
tests = testcase(config)
print('>> {}'.format(testcase.name()))
print('>> {0}'.format(testcase.name()))
for result in tests.run():
if result.passed:
@ -313,6 +313,6 @@ def runner(testcases, setup_func=None, teardown_func=None, config={}):
if teardown_func:
teardown_func()
print('{} passed; {} failed.'.format(passed, failed))
print('{0} passed; {1} failed.'.format(passed, failed))
if failed > 0:
sys.exit(1)

View File

@ -43,7 +43,7 @@ class MarkdownConformanceTest_10(TestCase):
name = name.replace(' - ', '_')
name = name.replace(' ', '_')
name = re.sub('[(),]', '', name)
return 'test_{}'.format(name.lower())
return 'test_{0}'.format(name.lower())
class MarkdownConformanceTest_103(MarkdownConformanceTest_10):

View File

@ -221,19 +221,19 @@ class TestRenderer(m.BaseRenderer):
return '[PARAGRAPH] {0}\n'.format(text)
def table(self, content):
return '[TABLE]\n{}'.format(content)
return '[TABLE]\n{0}'.format(content)
def table_header(self, content):
return '[TABLE_HEADER]\n{}'.format(content)
return '[TABLE_HEADER]\n{0}'.format(content)
def table_body(self, content):
return '[TABLE_BODY]\n{}'.format(content)
return '[TABLE_BODY]\n{0}'.format(content)
def table_row(self, content):
return '[TABLE_ROW]\n{0}\n'.format(content)
def table_cell(self, text, align, is_header):
align = 'align={} '.format(align) if align else ''
align = 'align={0} '.format(align) if align else ''
header = 'header=true ' if is_header else ''
return '[TABLE_CELL {2}{1}text={0}]'.format(text, align, header)
@ -278,7 +278,7 @@ class TestRenderer(m.BaseRenderer):
return '[LINEBREAK]'
def link(self, content, link, title):
return '[LINK link={} title={}] {}'.format(link, title, content)
return '[LINK link={0} title={1}] {2}'.format(link, title, content)
def strikethrough(self, text):
return '[STRIKETHROUGH] {0}'.format(text)
@ -293,7 +293,7 @@ class TestRenderer(m.BaseRenderer):
return '[TRIPLE_EMPHASIS] {0}'.format(text)
def math(self, text, displaymode):
return '[MATH] {}'.format(text)
return '[MATH] {0}'.format(text)
def normal_text(self, text):
return text
@ -312,10 +312,10 @@ class TestRendererLowlevel(m.BaseRenderer):
return text
def entity(self, text):
return '[ENTITY] {}'.format(text)
return '[ENTITY] {0}'.format(text)
def normal_text(self, text):
return '[NORMAL_TEXT] {}'.format(text)
return '[NORMAL_TEXT] {0}'.format(text)
class CustomRendererTest(TestCase):

View File

@ -4,7 +4,7 @@
# and then run "tox" from this directory.
[tox]
envlist = py27, py32, py33, py34, py35, pypy
envlist = py26, py27, py32, py33, py34, py35, pypy
[testenv]
commands = {envpython} setup.py test