summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Lord <davidism@gmail.com>2018-11-03 15:26:05 -0700
committerDavid Lord <davidism@gmail.com>2018-11-03 15:31:24 -0700
commitb41c96e00afd09eca075a98589886c78666d4d33 (patch)
treebf372cf97c44210717b8954919436023f275627b
parent6247e015ebe0006ee16e69da7aaaba20de18ec94 (diff)
downloadmarkupsafe-b41c96e00afd09eca075a98589886c78666d4d33.tar.gz
add style checks
-rw-r--r--.editorconfig13
-rw-r--r--.pre-commit-config.yaml18
-rw-r--r--.travis.yml2
-rw-r--r--bench/bench_basic.py2
-rw-r--r--bench/bench_largestring.py2
-rw-r--r--bench/bench_long_empty_string.py2
-rw-r--r--bench/bench_long_suffix.py2
-rw-r--r--bench/bench_short_empty_string.py2
-rw-r--r--bench/runbench.py25
-rw-r--r--setup.cfg16
-rw-r--r--setup.py112
-rw-r--r--src/markupsafe/__init__.py144
-rw-r--r--src/markupsafe/_compat.py11
-rw-r--r--src/markupsafe/_constants.py506
-rw-r--r--src/markupsafe/_native.py19
-rw-r--r--tests/conftest.py23
-rw-r--r--tests/test_escape.py39
-rw-r--r--tests/test_leak.py10
-rw-r--r--tests/test_markupsafe.py127
-rw-r--r--tox.ini6
20 files changed, 590 insertions, 491 deletions
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..e32c802
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,13 @@
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+insert_final_newline = true
+trim_trailing_whitespace = true
+end_of_line = lf
+charset = utf-8
+max_line_length = 88
+
+[*.{yml,yaml,json,js,css,html}]
+indent_size = 2
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..7be015d
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,18 @@
+repos:
+ - repo: https://github.com/asottile/reorder_python_imports
+ rev: v1.3.1
+ hooks:
+ - id: reorder-python-imports
+ args: ["--application-directories", "src"]
+ - repo: https://github.com/ambv/black
+ rev: 18.9b0
+ hooks:
+ - id: black
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v2.0.0
+ hooks:
+ - id: check-byte-order-marker
+ - id: trailing-whitespace
+ - id: end-of-file-fixer
+ - id: flake8
+ additional_dependencies: [flake8-bugbear]
diff --git a/.travis.yml b/.travis.yml
index 367c8de..7abf38b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,7 +15,7 @@ matrix:
- dist: xenial
sudo: required
python: "3.7"
- - env: TOXENV=docs-html
+ - env: TOXENV=stylecheck,docs-html
- stage: wheel
sudo: required
services:
diff --git a/bench/bench_basic.py b/bench/bench_basic.py
index 1172d15..b67eda4 100644
--- a/bench/bench_basic.py
+++ b/bench/bench_basic.py
@@ -2,4 +2,4 @@ from markupsafe import escape
def run():
- escape('<strong>Hello World!</strong>')
+ escape("<strong>Hello World!</strong>")
diff --git a/bench/bench_largestring.py b/bench/bench_largestring.py
index 7bde595..9ced67f 100644
--- a/bench/bench_largestring.py
+++ b/bench/bench_largestring.py
@@ -2,5 +2,5 @@ from markupsafe import escape
def run():
- string = '<strong>Hello World!</strong>' * 1000
+ string = "<strong>Hello World!</strong>" * 1000
escape(string)
diff --git a/bench/bench_long_empty_string.py b/bench/bench_long_empty_string.py
index 320fb0a..ad2480c 100644
--- a/bench/bench_long_empty_string.py
+++ b/bench/bench_long_empty_string.py
@@ -2,5 +2,5 @@ from markupsafe import escape
def run():
- string = 'Hello World!' * 1000
+ string = "Hello World!" * 1000
escape(string)
diff --git a/bench/bench_long_suffix.py b/bench/bench_long_suffix.py
index 43fe563..35f38da 100644
--- a/bench/bench_long_suffix.py
+++ b/bench/bench_long_suffix.py
@@ -2,5 +2,5 @@ from markupsafe import escape
def run():
- string = '<strong>Hello World!</strong>' + 'x' * 100000
+ string = "<strong>Hello World!</strong>" + "x" * 100000
escape(string)
diff --git a/bench/bench_short_empty_string.py b/bench/bench_short_empty_string.py
index 91cccc4..0664a6f 100644
--- a/bench/bench_short_empty_string.py
+++ b/bench/bench_short_empty_string.py
@@ -2,4 +2,4 @@ from markupsafe import escape
def run():
- escape('Hello World!')
+ escape("Hello World!")
diff --git a/bench/runbench.py b/bench/runbench.py
index ac2cbb1..38cf128 100644
--- a/bench/runbench.py
+++ b/bench/runbench.py
@@ -3,12 +3,13 @@
Runs the benchmarks
"""
from __future__ import print_function
-import sys
+
import os
import re
+import sys
from subprocess import Popen
-_filename_re = re.compile(r'^bench_(.*?)\.py$')
+_filename_re = re.compile(r"^bench_(.*?)\.py$")
bench_directory = os.path.abspath(os.path.dirname(__file__))
@@ -18,27 +19,27 @@ def list_benchmarks():
match = _filename_re.match(name)
if match is not None:
result.append(match.group(1))
- result.sort(key=lambda x: (x.startswith('logging_'), x.lower()))
+ result.sort(key=lambda x: (x.startswith("logging_"), x.lower()))
return result
def run_bench(name):
- sys.stdout.write('%-32s' % name)
+ sys.stdout.write("%-32s" % name)
sys.stdout.flush()
- Popen([sys.executable, '-mtimeit', '-s',
- 'from bench_%s import run' % name,
- 'run()']).wait()
+ Popen(
+ [sys.executable, "-mtimeit", "-s", "from bench_%s import run" % name, "run()"]
+ ).wait()
def main():
- print('=' * 80)
- print('Running benchmark for MarkupSafe')
- print('-' * 80)
+ print("=" * 80)
+ print("Running benchmark for MarkupSafe")
+ print("-" * 80)
os.chdir(bench_directory)
for bench in list_benchmarks():
run_bench(bench)
- print('-' * 80)
+ print("-" * 80)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/setup.cfg b/setup.cfg
index f8e3b5e..08cecbb 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -14,3 +14,19 @@ source =
src/markupsafe
.tox/*/lib/python*/site-packages/markupsafe
.tox/*/site-packages/markupsafe
+
+[flake8]
+# B = bugbear
+# E = pycodestyle errors
+# F = flake8 pyflakes
+# W = pycodestyle warnings
+# B9 = bugbear opinions
+select = B, E, F, W, B9
+# E203 = slice notation whitespace, invalid
+# E501 = line length, handled by bugbear B950
+# W503 = bin op line break, invalid
+ignore = E203, E501, W503
+# up to 88 allowed by bugbear B950
+max-line-length = 80
+# _compat names and imports will always look bad, ignore warnings
+exclude = src/markupsafe/_compat.py
diff --git a/setup.py b/setup.py
index f93e52d..4ad5182 100644
--- a/setup.py
+++ b/setup.py
@@ -1,33 +1,27 @@
from __future__ import print_function
-import sys
-
import io
import re
-from distutils.errors import (
- CCompilerError,
- DistutilsExecError,
- DistutilsPlatformError,
-)
-from setuptools import (
- Extension,
- find_packages,
- setup,
-)
+import sys
+from distutils.errors import CCompilerError
+from distutils.errors import DistutilsExecError
+from distutils.errors import DistutilsPlatformError
+
+from setuptools import Extension
+from setuptools import find_packages
+from setuptools import setup
from setuptools.command.build_ext import build_ext
-with io.open('README.rst', 'rt', encoding='utf8') as f:
+with io.open("README.rst", "rt", encoding="utf8") as f:
readme = f.read()
-with io.open('src/markupsafe/__init__.py', 'rt', encoding='utf8') as f:
- version = re.search(r'__version__ = \'(.*?)\'', f.read()).group(1)
+with io.open("src/markupsafe/__init__.py", "rt", encoding="utf8") as f:
+ version = re.search(r'__version__ = "(.*?)"', f.read()).group(1)
-is_jython = 'java' in sys.platform
-is_pypy = hasattr(sys, 'pypy_version_info')
+is_jython = "java" in sys.platform
+is_pypy = hasattr(sys, "pypy_version_info")
-ext_modules = [
- Extension('markupsafe._speedups', ['src/markupsafe/_speedups.c']),
-]
+ext_modules = [Extension("markupsafe._speedups", ["src/markupsafe/_speedups.c"])]
class BuildFailed(Exception):
@@ -50,60 +44,60 @@ class ve_build_ext(build_ext):
raise BuildFailed()
except ValueError:
# this can happen on Windows 64 bit, see Python issue 7511
- if "'path'" in str(sys.exc_info()[1]): # works with Python 2 and 3
+ if "'path'" in str(sys.exc_info()[1]): # works with Python 2 and 3
raise BuildFailed()
raise
def run_setup(with_binary):
setup(
- name='MarkupSafe',
+ name="MarkupSafe",
version=version,
- url='https://www.palletsprojects.com/p/markupsafe/',
+ url="https://www.palletsprojects.com/p/markupsafe/",
project_urls={
"Documentation": "https://markupsafe.palletsprojects.com/",
"Code": "https://github.com/pallets/markupsafe",
"Issue tracker": "https://github.com/pallets/markupsafe/issues",
},
- license='BSD',
- author='Armin Ronacher',
- author_email='armin.ronacher@active-4.com',
- maintainer='Pallets Team',
- maintainer_email='contact@palletsprojects.com',
- description='Safely add untrusted strings to HTML/XML markup.',
+ license="BSD",
+ author="Armin Ronacher",
+ author_email="armin.ronacher@active-4.com",
+ maintainer="Pallets Team",
+ maintainer_email="contact@palletsprojects.com",
+ description="Safely add untrusted strings to HTML/XML markup.",
long_description=readme,
classifiers=[
- 'Development Status :: 5 - Production/Stable',
- 'Environment :: Web Environment',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: BSD License',
- 'Operating System :: OS Independent',
- 'Programming Language :: Python',
- 'Programming Language :: Python :: 2',
- 'Programming Language :: Python :: 2.7',
- 'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3.4',
- 'Programming Language :: Python :: 3.5',
- 'Programming Language :: Python :: 3.6',
- 'Programming Language :: Python :: 3.7',
- 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
- 'Topic :: Software Development :: Libraries :: Python Modules',
- 'Topic :: Text Processing :: Markup :: HTML',
+ "Development Status :: 5 - Production/Stable",
+ "Environment :: Web Environment",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: BSD License",
+ "Operating System :: OS Independent",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 2",
+ "Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.4",
+ "Programming Language :: Python :: 3.5",
+ "Programming Language :: Python :: 3.6",
+ "Programming Language :: Python :: 3.7",
+ "Topic :: Internet :: WWW/HTTP :: Dynamic Content",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+ "Topic :: Text Processing :: Markup :: HTML",
],
packages=find_packages("src"),
package_dir={"": "src"},
include_package_data=True,
- python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*',
- cmdclass={'build_ext': ve_build_ext},
+ python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*",
+ cmdclass={"build_ext": ve_build_ext},
ext_modules=ext_modules if with_binary else [],
)
def show_message(*lines):
- print('=' * 74)
+ print("=" * 74)
for line in lines:
print(line)
- print('=' * 74)
+ print("=" * 74)
if not (is_pypy or is_jython):
@@ -111,21 +105,21 @@ if not (is_pypy or is_jython):
run_setup(True)
except BuildFailed:
show_message(
- 'WARNING: The C extension could not be compiled, speedups'
- ' are not enabled.',
- 'Failure information, if any, is above.',
- 'Retrying the build without the C extension now.'
+ "WARNING: The C extension could not be compiled, speedups"
+ " are not enabled.",
+ "Failure information, if any, is above.",
+ "Retrying the build without the C extension now.",
)
run_setup(False)
show_message(
- 'WARNING: The C extension could not be compiled, speedups'
- ' are not enabled.',
- 'Plain-Python build succeeded.'
+ "WARNING: The C extension could not be compiled, speedups"
+ " are not enabled.",
+ "Plain-Python build succeeded.",
)
else:
run_setup(False)
show_message(
- 'WARNING: C extensions are not supported on this Python'
- ' platform, speedups are not enabled.',
- 'Plain-Python build succeeded.'
+ "WARNING: C extensions are not supported on this Python"
+ " platform, speedups are not enabled.",
+ "Plain-Python build succeeded.",
)
diff --git a/src/markupsafe/__init__.py b/src/markupsafe/__init__.py
index 29fe1bd..e02c15d 100644
--- a/src/markupsafe/__init__.py
+++ b/src/markupsafe/__init__.py
@@ -12,16 +12,20 @@ special characters with safe representations.
import re
import string
-from markupsafe._compat import (
- PY2, int_types, iteritems, string_types, text_type, unichr, Mapping
-)
+from ._compat import int_types
+from ._compat import iteritems
+from ._compat import Mapping
+from ._compat import PY2
+from ._compat import string_types
+from ._compat import text_type
+from ._compat import unichr
-__version__ = '1.1.dev'
+__version__ = "1.1.dev"
-__all__ = ['Markup', 'soft_unicode', 'escape', 'escape_silent']
+__all__ = ["Markup", "soft_unicode", "escape", "escape_silent"]
-_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
-_entity_re = re.compile(r'&([^& ;]+);')
+_striptags_re = re.compile(r"(<!--.*?-->|<[^>]*>)")
+_entity_re = re.compile(r"&([^& ;]+);")
class Markup(text_type):
@@ -60,10 +64,11 @@ class Markup(text_type):
>>> Markup('<em>Hello</em> ') + '<foo>'
Markup('<em>Hello</em> &lt;foo&gt;')
"""
+
__slots__ = ()
- def __new__(cls, base=u'', encoding=None, errors='strict'):
- if hasattr(base, '__html__'):
+ def __new__(cls, base=u"", encoding=None, errors="strict"):
+ if hasattr(base, "__html__"):
base = base.__html__()
if encoding is None:
return text_type.__new__(cls, base)
@@ -73,12 +78,12 @@ class Markup(text_type):
return self
def __add__(self, other):
- if isinstance(other, string_types) or hasattr(other, '__html__'):
+ if isinstance(other, string_types) or hasattr(other, "__html__"):
return self.__class__(super(Markup, self).__add__(self.escape(other)))
return NotImplemented
def __radd__(self, other):
- if hasattr(other, '__html__') or isinstance(other, string_types):
+ if hasattr(other, "__html__") or isinstance(other, string_types):
return self.escape(other).__add__(self)
return NotImplemented
@@ -86,6 +91,7 @@ class Markup(text_type):
if isinstance(num, int_types):
return self.__class__(text_type.__mul__(self, num))
return NotImplemented
+
__rmul__ = __mul__
def __mod__(self, arg):
@@ -96,26 +102,26 @@ class Markup(text_type):
return self.__class__(text_type.__mod__(self, arg))
def __repr__(self):
- return '%s(%s)' % (
- self.__class__.__name__,
- text_type.__repr__(self)
- )
+ return "%s(%s)" % (self.__class__.__name__, text_type.__repr__(self))
def join(self, seq):
return self.__class__(text_type.join(self, map(self.escape, seq)))
+
join.__doc__ = text_type.join.__doc__
def split(self, *args, **kwargs):
return list(map(self.__class__, text_type.split(self, *args, **kwargs)))
+
split.__doc__ = text_type.split.__doc__
def rsplit(self, *args, **kwargs):
return list(map(self.__class__, text_type.rsplit(self, *args, **kwargs)))
+
rsplit.__doc__ = text_type.rsplit.__doc__
def splitlines(self, *args, **kwargs):
- return list(map(self.__class__, text_type.splitlines(
- self, *args, **kwargs)))
+ return list(map(self.__class__, text_type.splitlines(self, *args, **kwargs)))
+
splitlines.__doc__ = text_type.splitlines.__doc__
def unescape(self):
@@ -125,20 +131,22 @@ class Markup(text_type):
>>> Markup('Main &raquo; <em>About</em>').unescape()
'Main » <em>About</em>'
"""
- from markupsafe._constants import HTML_ENTITIES
+ from ._constants import HTML_ENTITIES
+
def handle_match(m):
name = m.group(1)
if name in HTML_ENTITIES:
return unichr(HTML_ENTITIES[name])
try:
- if name[:2] in ('#x', '#X'):
+ if name[:2] in ("#x", "#X"):
return unichr(int(name[2:], 16))
- elif name.startswith('#'):
+ elif name.startswith("#"):
return unichr(int(name[1:]))
except ValueError:
pass
# Don't modify unexpected input.
return m.group()
+
return _entity_re.sub(handle_match, text_type(self))
def striptags(self):
@@ -148,7 +156,7 @@ class Markup(text_type):
>>> Markup('Main &raquo;\t<em>About</em>').striptags()
'Main » About'
"""
- stripped = u' '.join(_striptags_re.sub('', self).split())
+ stripped = u" ".join(_striptags_re.sub("", self).split())
return Markup(stripped).unescape()
@classmethod
@@ -161,45 +169,57 @@ class Markup(text_type):
return cls(rv)
return rv
- def make_simple_escaping_wrapper(name):
+ def make_simple_escaping_wrapper(name): # noqa: B902
orig = getattr(text_type, name)
+
def func(self, *args, **kwargs):
args = _escape_argspec(list(args), enumerate(args), self.escape)
_escape_argspec(kwargs, iteritems(kwargs), self.escape)
return self.__class__(orig(self, *args, **kwargs))
+
func.__name__ = orig.__name__
func.__doc__ = orig.__doc__
return func
- for method in '__getitem__', 'capitalize', \
- 'title', 'lower', 'upper', 'replace', 'ljust', \
- 'rjust', 'lstrip', 'rstrip', 'center', 'strip', \
- 'translate', 'expandtabs', 'swapcase', 'zfill':
+ for method in (
+ "__getitem__",
+ "capitalize",
+ "title",
+ "lower",
+ "upper",
+ "replace",
+ "ljust",
+ "rjust",
+ "lstrip",
+ "rstrip",
+ "center",
+ "strip",
+ "translate",
+ "expandtabs",
+ "swapcase",
+ "zfill",
+ ):
locals()[method] = make_simple_escaping_wrapper(method)
def partition(self, sep):
- return tuple(map(self.__class__,
- text_type.partition(self, self.escape(sep))))
+ return tuple(map(self.__class__, text_type.partition(self, self.escape(sep))))
def rpartition(self, sep):
- return tuple(map(self.__class__,
- text_type.rpartition(self, self.escape(sep))))
+ return tuple(map(self.__class__, text_type.rpartition(self, self.escape(sep))))
- def format(*args, **kwargs):
- self, args = args[0], args[1:]
+ def format(self, *args, **kwargs):
formatter = EscapeFormatter(self.escape)
kwargs = _MagicFormatMapping(args, kwargs)
return self.__class__(formatter.vformat(self, args, kwargs))
def __html_format__(self, format_spec):
if format_spec:
- raise ValueError('Unsupported format specification '
- 'for Markup.')
+ raise ValueError("Unsupported format specification " "for Markup.")
return self
# not in python 3
- if hasattr(text_type, '__getslice__'):
- __getslice__ = make_simple_escaping_wrapper('__getslice__')
+ if hasattr(text_type, "__getslice__"):
+ __getslice__ = make_simple_escaping_wrapper("__getslice__")
del method, make_simple_escaping_wrapper
@@ -218,7 +238,7 @@ class _MagicFormatMapping(Mapping):
self._last_index = 0
def __getitem__(self, key):
- if key == '':
+ if key == "":
idx = self._last_index
self._last_index += 1
try:
@@ -235,38 +255,37 @@ class _MagicFormatMapping(Mapping):
return len(self._kwargs)
-if hasattr(text_type, 'format'):
- class EscapeFormatter(string.Formatter):
+if hasattr(text_type, "format"):
+ class EscapeFormatter(string.Formatter):
def __init__(self, escape):
self.escape = escape
def format_field(self, value, format_spec):
- if hasattr(value, '__html_format__'):
+ if hasattr(value, "__html_format__"):
rv = value.__html_format__(format_spec)
- elif hasattr(value, '__html__'):
+ elif hasattr(value, "__html__"):
if format_spec:
raise ValueError(
- 'Format specifier {0} given, but {1} does not'
- ' define __html_format__. A class that defines'
- ' __html__ must define __html_format__ to work'
- ' with format specifiers.'.format(
- format_spec, type(value)))
+ "Format specifier {0} given, but {1} does not"
+ " define __html_format__. A class that defines"
+ " __html__ must define __html_format__ to work"
+ " with format specifiers.".format(format_spec, type(value))
+ )
rv = value.__html__()
else:
# We need to make sure the format spec is unicode here as
# otherwise the wrong callback methods are invoked. For
# instance a byte string there would invoke __str__ and
# not __unicode__.
- rv = string.Formatter.format_field(
- self, value, text_type(format_spec))
+ rv = string.Formatter.format_field(self, value, text_type(format_spec))
return text_type(self.escape(rv))
def _escape_argspec(obj, iterable, escape):
"""Helper for various string-wrapped functions."""
for key, value in iterable:
- if hasattr(value, '__html__') or isinstance(value, string_types):
+ if hasattr(value, "__html__") or isinstance(value, string_types):
obj[key] = escape(value)
return obj
@@ -278,20 +297,31 @@ class _MarkupEscapeHelper(object):
self.obj = obj
self.escape = escape
- __getitem__ = lambda s, x: _MarkupEscapeHelper(s.obj[x], s.escape)
- __unicode__ = __str__ = lambda s: text_type(s.escape(s.obj))
- __repr__ = lambda s: str(s.escape(repr(s.obj)))
- __int__ = lambda s: int(s.obj)
- __float__ = lambda s: float(s.obj)
+ def __getitem__(self, item):
+ return _MarkupEscapeHelper(self.obj[item], self.escape)
+
+ def __str__(self):
+ return text_type(self.escape(self.obj))
+
+ __unicode__ = __str__
+
+ def __repr__(self):
+ return str(self.escape(repr(self.obj)))
+
+ def __int__(self):
+ return int(self.obj)
+
+ def __float__(self):
+ return float(self.obj)
# we have to import it down here as the speedups and native
# modules imports the markup type which is define above.
try:
- from markupsafe._speedups import escape, escape_silent, soft_unicode
+ from ._speedups import escape, escape_silent, soft_unicode
except ImportError:
- from markupsafe._native import escape, escape_silent, soft_unicode
+ from ._native import escape, escape_silent, soft_unicode
if not PY2:
soft_str = soft_unicode
- __all__.append('soft_str')
+ __all__.append("soft_str")
diff --git a/src/markupsafe/_compat.py b/src/markupsafe/_compat.py
index 4d2e2cd..e51d57d 100644
--- a/src/markupsafe/_compat.py
+++ b/src/markupsafe/_compat.py
@@ -15,12 +15,19 @@ if not PY2:
string_types = (str,)
unichr = chr
int_types = (int,)
- iteritems = lambda x: iter(x.items())
+
+ def iteritems(x):
+ return iter(x.items())
+
from collections.abc import Mapping
+
else:
text_type = unicode
string_types = (str, unicode)
unichr = unichr
int_types = (int, long)
- iteritems = lambda x: x.iteritems()
+
+ def iteritems(x):
+ return x.iteritems()
+
from collections import Mapping
diff --git a/src/markupsafe/_constants.py b/src/markupsafe/_constants.py
index ea6ac2f..83670cb 100644
--- a/src/markupsafe/_constants.py
+++ b/src/markupsafe/_constants.py
@@ -8,257 +8,257 @@ markupsafe._constants
"""
HTML_ENTITIES = {
- 'AElig': 198,
- 'Aacute': 193,
- 'Acirc': 194,
- 'Agrave': 192,
- 'Alpha': 913,
- 'Aring': 197,
- 'Atilde': 195,
- 'Auml': 196,
- 'Beta': 914,
- 'Ccedil': 199,
- 'Chi': 935,
- 'Dagger': 8225,
- 'Delta': 916,
- 'ETH': 208,
- 'Eacute': 201,
- 'Ecirc': 202,
- 'Egrave': 200,
- 'Epsilon': 917,
- 'Eta': 919,
- 'Euml': 203,
- 'Gamma': 915,
- 'Iacute': 205,
- 'Icirc': 206,
- 'Igrave': 204,
- 'Iota': 921,
- 'Iuml': 207,
- 'Kappa': 922,
- 'Lambda': 923,
- 'Mu': 924,
- 'Ntilde': 209,
- 'Nu': 925,
- 'OElig': 338,
- 'Oacute': 211,
- 'Ocirc': 212,
- 'Ograve': 210,
- 'Omega': 937,
- 'Omicron': 927,
- 'Oslash': 216,
- 'Otilde': 213,
- 'Ouml': 214,
- 'Phi': 934,
- 'Pi': 928,
- 'Prime': 8243,
- 'Psi': 936,
- 'Rho': 929,
- 'Scaron': 352,
- 'Sigma': 931,
- 'THORN': 222,
- 'Tau': 932,
- 'Theta': 920,
- 'Uacute': 218,
- 'Ucirc': 219,
- 'Ugrave': 217,
- 'Upsilon': 933,
- 'Uuml': 220,
- 'Xi': 926,
- 'Yacute': 221,
- 'Yuml': 376,
- 'Zeta': 918,
- 'aacute': 225,
- 'acirc': 226,
- 'acute': 180,
- 'aelig': 230,
- 'agrave': 224,
- 'alefsym': 8501,
- 'alpha': 945,
- 'amp': 38,
- 'and': 8743,
- 'ang': 8736,
- 'apos': 39,
- 'aring': 229,
- 'asymp': 8776,
- 'atilde': 227,
- 'auml': 228,
- 'bdquo': 8222,
- 'beta': 946,
- 'brvbar': 166,
- 'bull': 8226,
- 'cap': 8745,
- 'ccedil': 231,
- 'cedil': 184,
- 'cent': 162,
- 'chi': 967,
- 'circ': 710,
- 'clubs': 9827,
- 'cong': 8773,
- 'copy': 169,
- 'crarr': 8629,
- 'cup': 8746,
- 'curren': 164,
- 'dArr': 8659,
- 'dagger': 8224,
- 'darr': 8595,
- 'deg': 176,
- 'delta': 948,
- 'diams': 9830,
- 'divide': 247,
- 'eacute': 233,
- 'ecirc': 234,
- 'egrave': 232,
- 'empty': 8709,
- 'emsp': 8195,
- 'ensp': 8194,
- 'epsilon': 949,
- 'equiv': 8801,
- 'eta': 951,
- 'eth': 240,
- 'euml': 235,
- 'euro': 8364,
- 'exist': 8707,
- 'fnof': 402,
- 'forall': 8704,
- 'frac12': 189,
- 'frac14': 188,
- 'frac34': 190,
- 'frasl': 8260,
- 'gamma': 947,
- 'ge': 8805,
- 'gt': 62,
- 'hArr': 8660,
- 'harr': 8596,
- 'hearts': 9829,
- 'hellip': 8230,
- 'iacute': 237,
- 'icirc': 238,
- 'iexcl': 161,
- 'igrave': 236,
- 'image': 8465,
- 'infin': 8734,
- 'int': 8747,
- 'iota': 953,
- 'iquest': 191,
- 'isin': 8712,
- 'iuml': 239,
- 'kappa': 954,
- 'lArr': 8656,
- 'lambda': 955,
- 'lang': 9001,
- 'laquo': 171,
- 'larr': 8592,
- 'lceil': 8968,
- 'ldquo': 8220,
- 'le': 8804,
- 'lfloor': 8970,
- 'lowast': 8727,
- 'loz': 9674,
- 'lrm': 8206,
- 'lsaquo': 8249,
- 'lsquo': 8216,
- 'lt': 60,
- 'macr': 175,
- 'mdash': 8212,
- 'micro': 181,
- 'middot': 183,
- 'minus': 8722,
- 'mu': 956,
- 'nabla': 8711,
- 'nbsp': 160,
- 'ndash': 8211,
- 'ne': 8800,
- 'ni': 8715,
- 'not': 172,
- 'notin': 8713,
- 'nsub': 8836,
- 'ntilde': 241,
- 'nu': 957,
- 'oacute': 243,
- 'ocirc': 244,
- 'oelig': 339,
- 'ograve': 242,
- 'oline': 8254,
- 'omega': 969,
- 'omicron': 959,
- 'oplus': 8853,
- 'or': 8744,
- 'ordf': 170,
- 'ordm': 186,
- 'oslash': 248,
- 'otilde': 245,
- 'otimes': 8855,
- 'ouml': 246,
- 'para': 182,
- 'part': 8706,
- 'permil': 8240,
- 'perp': 8869,
- 'phi': 966,
- 'pi': 960,
- 'piv': 982,
- 'plusmn': 177,
- 'pound': 163,
- 'prime': 8242,
- 'prod': 8719,
- 'prop': 8733,
- 'psi': 968,
- 'quot': 34,
- 'rArr': 8658,
- 'radic': 8730,
- 'rang': 9002,
- 'raquo': 187,
- 'rarr': 8594,
- 'rceil': 8969,
- 'rdquo': 8221,
- 'real': 8476,
- 'reg': 174,
- 'rfloor': 8971,
- 'rho': 961,
- 'rlm': 8207,
- 'rsaquo': 8250,
- 'rsquo': 8217,
- 'sbquo': 8218,
- 'scaron': 353,
- 'sdot': 8901,
- 'sect': 167,
- 'shy': 173,
- 'sigma': 963,
- 'sigmaf': 962,
- 'sim': 8764,
- 'spades': 9824,
- 'sub': 8834,
- 'sube': 8838,
- 'sum': 8721,
- 'sup': 8835,
- 'sup1': 185,
- 'sup2': 178,
- 'sup3': 179,
- 'supe': 8839,
- 'szlig': 223,
- 'tau': 964,
- 'there4': 8756,
- 'theta': 952,
- 'thetasym': 977,
- 'thinsp': 8201,
- 'thorn': 254,
- 'tilde': 732,
- 'times': 215,
- 'trade': 8482,
- 'uArr': 8657,
- 'uacute': 250,
- 'uarr': 8593,
- 'ucirc': 251,
- 'ugrave': 249,
- 'uml': 168,
- 'upsih': 978,
- 'upsilon': 965,
- 'uuml': 252,
- 'weierp': 8472,
- 'xi': 958,
- 'yacute': 253,
- 'yen': 165,
- 'yuml': 255,
- 'zeta': 950,
- 'zwj': 8205,
- 'zwnj': 8204
+ "AElig": 198,
+ "Aacute": 193,
+ "Acirc": 194,
+ "Agrave": 192,
+ "Alpha": 913,
+ "Aring": 197,
+ "Atilde": 195,
+ "Auml": 196,
+ "Beta": 914,
+ "Ccedil": 199,
+ "Chi": 935,
+ "Dagger": 8225,
+ "Delta": 916,
+ "ETH": 208,
+ "Eacute": 201,
+ "Ecirc": 202,
+ "Egrave": 200,
+ "Epsilon": 917,
+ "Eta": 919,
+ "Euml": 203,
+ "Gamma": 915,
+ "Iacute": 205,
+ "Icirc": 206,
+ "Igrave": 204,
+ "Iota": 921,
+ "Iuml": 207,
+ "Kappa": 922,
+ "Lambda": 923,
+ "Mu": 924,
+ "Ntilde": 209,
+ "Nu": 925,
+ "OElig": 338,
+ "Oacute": 211,
+ "Ocirc": 212,
+ "Ograve": 210,
+ "Omega": 937,
+ "Omicron": 927,
+ "Oslash": 216,
+ "Otilde": 213,
+ "Ouml": 214,
+ "Phi": 934,
+ "Pi": 928,
+ "Prime": 8243,
+ "Psi": 936,
+ "Rho": 929,
+ "Scaron": 352,
+ "Sigma": 931,
+ "THORN": 222,
+ "Tau": 932,
+ "Theta": 920,
+ "Uacute": 218,
+ "Ucirc": 219,
+ "Ugrave": 217,
+ "Upsilon": 933,
+ "Uuml": 220,
+ "Xi": 926,
+ "Yacute": 221,
+ "Yuml": 376,
+ "Zeta": 918,
+ "aacute": 225,
+ "acirc": 226,
+ "acute": 180,
+ "aelig": 230,
+ "agrave": 224,
+ "alefsym": 8501,
+ "alpha": 945,
+ "amp": 38,
+ "and": 8743,
+ "ang": 8736,
+ "apos": 39,
+ "aring": 229,
+ "asymp": 8776,
+ "atilde": 227,
+ "auml": 228,
+ "bdquo": 8222,
+ "beta": 946,
+ "brvbar": 166,
+ "bull": 8226,
+ "cap": 8745,
+ "ccedil": 231,
+ "cedil": 184,
+ "cent": 162,
+ "chi": 967,
+ "circ": 710,
+ "clubs": 9827,
+ "cong": 8773,
+ "copy": 169,
+ "crarr": 8629,
+ "cup": 8746,
+ "curren": 164,
+ "dArr": 8659,
+ "dagger": 8224,
+ "darr": 8595,
+ "deg": 176,
+ "delta": 948,
+ "diams": 9830,
+ "divide": 247,
+ "eacute": 233,
+ "ecirc": 234,
+ "egrave": 232,
+ "empty": 8709,
+ "emsp": 8195,
+ "ensp": 8194,
+ "epsilon": 949,
+ "equiv": 8801,
+ "eta": 951,
+ "eth": 240,
+ "euml": 235,
+ "euro": 8364,
+ "exist": 8707,
+ "fnof": 402,
+ "forall": 8704,
+ "frac12": 189,
+ "frac14": 188,
+ "frac34": 190,
+ "frasl": 8260,
+ "gamma": 947,
+ "ge": 8805,
+ "gt": 62,
+ "hArr": 8660,
+ "harr": 8596,
+ "hearts": 9829,
+ "hellip": 8230,
+ "iacute": 237,
+ "icirc": 238,
+ "iexcl": 161,
+ "igrave": 236,
+ "image": 8465,
+ "infin": 8734,
+ "int": 8747,
+ "iota": 953,
+ "iquest": 191,
+ "isin": 8712,
+ "iuml": 239,
+ "kappa": 954,
+ "lArr": 8656,
+ "lambda": 955,
+ "lang": 9001,
+ "laquo": 171,
+ "larr": 8592,
+ "lceil": 8968,
+ "ldquo": 8220,
+ "le": 8804,
+ "lfloor": 8970,
+ "lowast": 8727,
+ "loz": 9674,
+ "lrm": 8206,
+ "lsaquo": 8249,
+ "lsquo": 8216,
+ "lt": 60,
+ "macr": 175,
+ "mdash": 8212,
+ "micro": 181,
+ "middot": 183,
+ "minus": 8722,
+ "mu": 956,
+ "nabla": 8711,
+ "nbsp": 160,
+ "ndash": 8211,
+ "ne": 8800,
+ "ni": 8715,
+ "not": 172,
+ "notin": 8713,
+ "nsub": 8836,
+ "ntilde": 241,
+ "nu": 957,
+ "oacute": 243,
+ "ocirc": 244,
+ "oelig": 339,
+ "ograve": 242,
+ "oline": 8254,
+ "omega": 969,
+ "omicron": 959,
+ "oplus": 8853,
+ "or": 8744,
+ "ordf": 170,
+ "ordm": 186,
+ "oslash": 248,
+ "otilde": 245,
+ "otimes": 8855,
+ "ouml": 246,
+ "para": 182,
+ "part": 8706,
+ "permil": 8240,
+ "perp": 8869,
+ "phi": 966,
+ "pi": 960,
+ "piv": 982,
+ "plusmn": 177,
+ "pound": 163,
+ "prime": 8242,
+ "prod": 8719,
+ "prop": 8733,
+ "psi": 968,
+ "quot": 34,
+ "rArr": 8658,
+ "radic": 8730,
+ "rang": 9002,
+ "raquo": 187,
+ "rarr": 8594,
+ "rceil": 8969,
+ "rdquo": 8221,
+ "real": 8476,
+ "reg": 174,
+ "rfloor": 8971,
+ "rho": 961,
+ "rlm": 8207,
+ "rsaquo": 8250,
+ "rsquo": 8217,
+ "sbquo": 8218,
+ "scaron": 353,
+ "sdot": 8901,
+ "sect": 167,
+ "shy": 173,
+ "sigma": 963,
+ "sigmaf": 962,
+ "sim": 8764,
+ "spades": 9824,
+ "sub": 8834,
+ "sube": 8838,
+ "sum": 8721,
+ "sup": 8835,
+ "sup1": 185,
+ "sup2": 178,
+ "sup3": 179,
+ "supe": 8839,
+ "szlig": 223,
+ "tau": 964,
+ "there4": 8756,
+ "theta": 952,
+ "thetasym": 977,
+ "thinsp": 8201,
+ "thorn": 254,
+ "tilde": 732,
+ "times": 215,
+ "trade": 8482,
+ "uArr": 8657,
+ "uacute": 250,
+ "uarr": 8593,
+ "ucirc": 251,
+ "ugrave": 249,
+ "uml": 168,
+ "upsih": 978,
+ "upsilon": 965,
+ "uuml": 252,
+ "weierp": 8472,
+ "xi": 958,
+ "yacute": 253,
+ "yen": 165,
+ "yuml": 255,
+ "zeta": 950,
+ "zwj": 8205,
+ "zwnj": 8204,
}
diff --git a/src/markupsafe/_native.py b/src/markupsafe/_native.py
index 801f285..245f03a 100644
--- a/src/markupsafe/_native.py
+++ b/src/markupsafe/_native.py
@@ -8,8 +8,8 @@ Native Python implementation used when the C module is not compiled.
:copyright: © 2010 by the Pallets team.
:license: BSD, see LICENSE for more details.
"""
-from markupsafe import Markup
-from markupsafe._compat import text_type
+from . import Markup
+from ._compat import text_type
def escape(s):
@@ -23,14 +23,15 @@ def escape(s):
:param s: An object to be converted to a string and escaped.
:return: A :class:`Markup` string with the escaped text.
"""
- if hasattr(s, '__html__'):
+ if hasattr(s, "__html__"):
return Markup(s.__html__())
- return Markup(text_type(s)
- .replace('&', '&amp;')
- .replace('>', '&gt;')
- .replace('<', '&lt;')
- .replace("'", '&#39;')
- .replace('"', '&#34;')
+ return Markup(
+ text_type(s)
+ .replace("&", "&amp;")
+ .replace(">", "&gt;")
+ .replace("<", "&lt;")
+ .replace("'", "&#39;")
+ .replace('"', "&#34;")
)
diff --git a/tests/conftest.py b/tests/conftest.py
index 06614cc..296cd58 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -8,27 +8,30 @@ except ImportError:
_speedups = None
-@pytest.fixture(scope='session', params=(
- _native,
- pytest.param(_speedups, marks=pytest.mark.skipif(
- _speedups is None,
- reason='speedups unavailable',
- ))
-))
+@pytest.fixture(
+ scope="session",
+ params=(
+ _native,
+ pytest.param(
+ _speedups,
+ marks=pytest.mark.skipif(_speedups is None, reason="speedups unavailable"),
+ ),
+ ),
+)
def _mod(request):
return request.param
-@pytest.fixture(scope='session')
+@pytest.fixture(scope="session")
def escape(_mod):
return _mod.escape
-@pytest.fixture(scope='session')
+@pytest.fixture(scope="session")
def escape_silent(_mod):
return _mod.escape_silent
-@pytest.fixture(scope='session')
+@pytest.fixture(scope="session")
def soft_str(_mod):
return _mod.soft_unicode
diff --git a/tests/test_escape.py b/tests/test_escape.py
index 337cd19..788134a 100644
--- a/tests/test_escape.py
+++ b/tests/test_escape.py
@@ -4,22 +4,27 @@ import pytest
from markupsafe import Markup
-@pytest.mark.parametrize(('value', 'expect'), (
- # empty
- (u'', u''),
- # ascii
- (u'abcd&><\'"efgh', u'abcd&amp;&gt;&lt;&#39;&#34;efgh'),
- (u'&><\'"efgh', u'&amp;&gt;&lt;&#39;&#34;efgh'),
- (u'abcd&><\'"', u'abcd&amp;&gt;&lt;&#39;&#34;'),
- # 2 byte
- (u'こんにちは&><\'"こんばんは',
- u'こんにちは&amp;&gt;&lt;&#39;&#34;こんばんは'),
- (u'&><\'"こんばんは', u'&amp;&gt;&lt;&#39;&#34;こんばんは'),
- (u'こんにちは&><\'"', u'こんにちは&amp;&gt;&lt;&#39;&#34;'),
- # 4 byte
- (u'\U0001F363\U0001F362&><\'"\U0001F37A xyz', u'\U0001F363\U0001F362&amp;&gt;&lt;&#39;&#34;\U0001F37A xyz'),
- (u'&><\'"\U0001F37A xyz', u'&amp;&gt;&lt;&#39;&#34;\U0001F37A xyz'),
- (u'\U0001F363\U0001F362&><\'"', u'\U0001F363\U0001F362&amp;&gt;&lt;&#39;&#34;'),
-))
+@pytest.mark.parametrize(
+ ("value", "expect"),
+ (
+ # empty
+ (u"", u""),
+ # ascii
+ (u"abcd&><'\"efgh", u"abcd&amp;&gt;&lt;&#39;&#34;efgh"),
+ (u"&><'\"efgh", u"&amp;&gt;&lt;&#39;&#34;efgh"),
+ (u"abcd&><'\"", u"abcd&amp;&gt;&lt;&#39;&#34;"),
+ # 2 byte
+ (u"こんにちは&><'\"こんばんは", u"こんにちは&amp;&gt;&lt;&#39;&#34;こんばんは"),
+ (u"&><'\"こんばんは", u"&amp;&gt;&lt;&#39;&#34;こんばんは"),
+ (u"こんにちは&><'\"", u"こんにちは&amp;&gt;&lt;&#39;&#34;"),
+ # 4 byte
+ (
+ u"\U0001F363\U0001F362&><'\"\U0001F37A xyz",
+ u"\U0001F363\U0001F362&amp;&gt;&lt;&#39;&#34;\U0001F37A xyz",
+ ),
+ (u"&><'\"\U0001F37A xyz", u"&amp;&gt;&lt;&#39;&#34;\U0001F37A xyz"),
+ (u"\U0001F363\U0001F362&><'\"", u"\U0001F363\U0001F362&amp;&gt;&lt;&#39;&#34;"),
+ ),
+)
def test_escape(escape, value, expect):
assert escape(value) == Markup(expect)
diff --git a/tests/test_leak.py b/tests/test_leak.py
index 29e1ec1..b36a4ce 100644
--- a/tests/test_leak.py
+++ b/tests/test_leak.py
@@ -8,20 +8,20 @@ from markupsafe import escape
@pytest.mark.skipif(
- escape.__module__ == 'markupsafe._native',
- reason='only test memory leak with speedups'
+ escape.__module__ == "markupsafe._native",
+ reason="only test memory leak with speedups",
)
def test_markup_leaks():
counts = set()
- for count in range(20):
- for item in range(1000):
+ for _i in range(20):
+ for _j in range(1000):
escape("foo")
escape("<foo>")
escape(u"foo")
escape(u"<foo>")
- if hasattr(sys, 'pypy_version_info'):
+ if hasattr(sys, "pypy_version_info"):
gc.collect()
counts.add(len(gc.get_objects()))
diff --git a/tests/test_markupsafe.py b/tests/test_markupsafe.py
index ffbf8a3..5b08006 100644
--- a/tests/test_markupsafe.py
+++ b/tests/test_markupsafe.py
@@ -1,32 +1,38 @@
# -*- coding: utf-8 -*-
import pytest
-from markupsafe import Markup, escape, escape_silent
-from markupsafe._compat import PY2, text_type
+from markupsafe import escape
+from markupsafe import escape_silent
+from markupsafe import Markup
+from markupsafe._compat import PY2
+from markupsafe._compat import text_type
def test_adding():
unsafe = '<script type="application/x-some-script">alert("foo");</script>'
- safe = Markup('<em>username</em>')
+ safe = Markup("<em>username</em>")
assert unsafe + safe == text_type(escape(unsafe)) + text_type(safe)
-@pytest.mark.parametrize(('template', 'data', 'expect'), (
- ('<em>%s</em>', '<bad user>', '<em>&lt;bad user&gt;</em>'),
+@pytest.mark.parametrize(
+ ("template", "data", "expect"),
(
- '<em>%(username)s</em>',
- {'username': '<bad user>'},
- '<em>&lt;bad user&gt;</em>'
+ ("<em>%s</em>", "<bad user>", "<em>&lt;bad user&gt;</em>"),
+ (
+ "<em>%(username)s</em>",
+ {"username": "<bad user>"},
+ "<em>&lt;bad user&gt;</em>",
+ ),
+ ("%i", 3.14, "3"),
+ ("%.2f", 3.14, "3.14"),
),
- ('%i', 3.14, '3'),
- ('%.2f', 3.14, '3.14'),
-))
+)
def test_string_interpolation(template, data, expect):
assert Markup(template) % data == expect
def test_type_behavior():
- assert type(Markup('foo') + 'bar') is Markup
+ assert type(Markup("foo") + "bar") is Markup
x = Markup("foo")
assert x.__html__() is x
@@ -34,39 +40,36 @@ def test_type_behavior():
def test_html_interop():
class Foo(object):
def __html__(self):
- return '<em>awesome</em>'
+ return "<em>awesome</em>"
def __unicode__(self):
- return 'awesome'
+ return "awesome"
__str__ = __unicode__
- assert Markup(Foo()) == '<em>awesome</em>'
- result = Markup('<strong>%s</strong>') % Foo()
- assert result == '<strong><em>awesome</em></strong>'
+ assert Markup(Foo()) == "<em>awesome</em>"
+ result = Markup("<strong>%s</strong>") % Foo()
+ assert result == "<strong><em>awesome</em></strong>"
def test_tuple_interpol():
- result = Markup('<em>%s:%s</em>') % ('<foo>', '<bar>')
- expect = Markup(u'<em>&lt;foo&gt;:&lt;bar&gt;</em>')
+ result = Markup("<em>%s:%s</em>") % ("<foo>", "<bar>")
+ expect = Markup(u"<em>&lt;foo&gt;:&lt;bar&gt;</em>")
assert result == expect
def test_dict_interpol():
- result = Markup('<em>%(foo)s</em>') % {'foo': '<foo>'}
- expect = Markup(u'<em>&lt;foo&gt;</em>')
+ result = Markup("<em>%(foo)s</em>") % {"foo": "<foo>"}
+ expect = Markup(u"<em>&lt;foo&gt;</em>")
assert result == expect
- result = Markup('<em>%(foo)s:%(bar)s</em>') % {
- 'foo': '<foo>',
- 'bar': '<bar>',
- }
- expect = Markup(u'<em>&lt;foo&gt;:&lt;bar&gt;</em>')
+ result = Markup("<em>%(foo)s:%(bar)s</em>") % {"foo": "<foo>", "bar": "<bar>"}
+ expect = Markup(u"<em>&lt;foo&gt;:&lt;bar&gt;</em>")
assert result == expect
def test_escaping():
- assert escape('"<>&\'') == '&#34;&lt;&gt;&amp;&#39;'
+ assert escape("\"<>&'") == "&#34;&lt;&gt;&amp;&#39;"
assert Markup("<em>Foo &amp; Bar</em>").striptags() == "Foo & Bar"
@@ -77,7 +80,7 @@ def test_unescape():
expect = "jack & tavi are cooler than mike & russ"
assert result == expect
- original = '&foo&#x3b;'
+ original = "&foo&#x3b;"
once = Markup(original).unescape()
twice = Markup(once).unescape()
expect = "&foo;"
@@ -86,35 +89,35 @@ def test_unescape():
def test_format():
- result = Markup('<em>{awesome}</em>').format(awesome='<awesome>')
- assert result == '<em>&lt;awesome&gt;</em>'
+ result = Markup("<em>{awesome}</em>").format(awesome="<awesome>")
+ assert result == "<em>&lt;awesome&gt;</em>"
- result = Markup('{0[1][bar]}').format([0, {'bar': '<bar/>'}])
- assert result == '&lt;bar/&gt;'
+ result = Markup("{0[1][bar]}").format([0, {"bar": "<bar/>"}])
+ assert result == "&lt;bar/&gt;"
- result = Markup('{0[1][bar]}').format([0, {'bar': Markup('<bar/>')}])
- assert result == '<bar/>'
+ result = Markup("{0[1][bar]}").format([0, {"bar": Markup("<bar/>")}])
+ assert result == "<bar/>"
def test_formatting_empty():
- formatted = Markup('{}').format(0)
- assert formatted == Markup('0')
+ formatted = Markup("{}").format(0)
+ assert formatted == Markup("0")
def test_custom_formatting():
class HasHTMLOnly(object):
def __html__(self):
- return Markup('<foo>')
+ return Markup("<foo>")
class HasHTMLAndFormat(object):
def __html__(self):
- return Markup('<foo>')
+ return Markup("<foo>")
def __html_format__(self, spec):
- return Markup('<FORMAT>')
+ return Markup("<FORMAT>")
- assert Markup('{0}').format(HasHTMLOnly()) == Markup('<foo>')
- assert Markup('{0}').format(HasHTMLAndFormat()) == Markup('<FORMAT>')
+ assert Markup("{0}").format(HasHTMLOnly()) == Markup("<foo>")
+ assert Markup("{0}").format(HasHTMLAndFormat()) == Markup("<FORMAT>")
def test_complex_custom_formatting():
@@ -124,36 +127,38 @@ def test_complex_custom_formatting():
self.username = username
def __html_format__(self, format_spec):
- if format_spec == 'link':
+ if format_spec == "link":
return Markup('<a href="/user/{0}">{1}</a>').format(
- self.id, self.__html__())
+ self.id, self.__html__()
+ )
elif format_spec:
- raise ValueError('Invalid format spec')
+ raise ValueError("Invalid format spec")
return self.__html__()
def __html__(self):
- return Markup('<span class=user>{0}</span>').format(self.username)
+ return Markup("<span class=user>{0}</span>").format(self.username)
- user = User(1, 'foo')
- result = Markup('<p>User: {0:link}').format(user)
- expect = Markup(
- '<p>User: <a href="/user/1"><span class=user>foo</span></a>')
+ user = User(1, "foo")
+ result = Markup("<p>User: {0:link}").format(user)
+ expect = Markup('<p>User: <a href="/user/1"><span class=user>foo</span></a>')
assert result == expect
def test_formatting_with_objects():
class Stringable(object):
def __unicode__(self):
- return u'строка'
+ return u"строка"
if PY2:
+
def __str__(self):
- return 'some other value'
+ return "some other value"
+
else:
__str__ = __unicode__
- assert Markup('{s}').format(s=Stringable()) == Markup(u'строка')
+ assert Markup("{s}").format(s=Stringable()) == Markup(u"строка")
def test_all_set():
@@ -166,26 +171,26 @@ def test_all_set():
def test_escape_silent():
assert escape_silent(None) == Markup()
assert escape(None) == Markup(None)
- assert escape_silent('<foo>') == Markup(u'&lt;foo&gt;')
+ assert escape_silent("<foo>") == Markup(u"&lt;foo&gt;")
def test_splitting():
- expect = [Markup('a'), Markup('b')]
- assert Markup('a b').split() == expect
- assert Markup('a b').rsplit() == expect
- assert Markup('a\nb').splitlines() == expect
+ expect = [Markup("a"), Markup("b")]
+ assert Markup("a b").split() == expect
+ assert Markup("a b").rsplit() == expect
+ assert Markup("a\nb").splitlines() == expect
def test_mul():
- assert Markup('a') * 3 == Markup('aaa')
+ assert Markup("a") * 3 == Markup("aaa")
def test_escape_return_type():
- assert isinstance(escape('a'), Markup)
- assert isinstance(escape(Markup('a')), Markup)
+ assert isinstance(escape("a"), Markup)
+ assert isinstance(escape(Markup("a")), Markup)
class Foo:
def __html__(self):
- return '<strong>Foo</strong>'
+ return "<strong>Foo</strong>"
assert isinstance(escape(Foo()), Markup)
diff --git a/tox.ini b/tox.ini
index b5021d7..aaa666e 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,6 +1,7 @@
[tox]
envlist =
py{37,36,35,34,27,py3,py}
+ stylecheck
docs-html
coverage-report
skip_missing_interpreters = true
@@ -12,6 +13,11 @@ deps =
pytest-cov
commands = pytest --tb=short --cov --cov-report= {posargs}
+[testenv:stylecheck]
+deps = pre-commit
+skip_install = true
+commands = pre-commit run --all-files --show-diff-on-failure
+
[testenv:docs-html]
deps = -r docs/requirements.txt
commands = sphinx-build -W -b html -d {envtmpdir}/doctrees docs {envtmpdir}/html