summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Lord <davidism@gmail.com>2018-05-04 07:37:47 -0700
committerDavid Lord <davidism@gmail.com>2018-05-04 07:46:55 -0700
commitb7a31f5f151a3641975df1b113573947efe923a8 (patch)
treeed36b41fcdae730b66fd3fd11d16eed8dae806b9
parentf6a491d9348597e67e3bed5f4d0ff3cbf38857e3 (diff)
downloadmarkupsafe-b7a31f5f151a3641975df1b113573947efe923a8.tar.gz
add sphinx docs, update docstrings
-rw-r--r--.travis.yml2
-rw-r--r--README.rst26
-rw-r--r--docs/Makefile20
-rw-r--r--docs/conf.py72
-rw-r--r--docs/escaping.rst21
-rw-r--r--docs/formatting.rst77
-rw-r--r--docs/html.rst51
-rw-r--r--docs/index.rst35
-rw-r--r--docs/make.bat36
-rw-r--r--markupsafe/__init__.py119
-rw-r--r--markupsafe/_compat.py10
-rw-r--r--markupsafe/_constants.py11
-rw-r--r--markupsafe/_native.py46
-rw-r--r--markupsafe/_speedups.c9
-rw-r--r--setup.py8
-rw-r--r--tox.ini11
16 files changed, 448 insertions, 106 deletions
diff --git a/.travis.yml b/.travis.yml
index 23cd92b..bf894e3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,6 +6,8 @@ matrix:
include:
- python: 3.6
env: TOXENV=py,codecov
+ - python: 3.6
+ env: TOXENV=docs-html
- python: 3.5
env: TOXENV=py,codecov
- python: 3.4
diff --git a/README.rst b/README.rst
index c30be04..fb1e930 100644
--- a/README.rst
+++ b/README.rst
@@ -13,10 +13,12 @@ Installing
Install and update using `pip`_:
-.. code-block:: none
+.. code-block:: text
pip install -U MarkupSafe
+.. _pip: https://pip.pypa.io/en/stable/quickstart/
+
Examples
--------
@@ -53,17 +55,15 @@ projects, `please donate today`_.
Links
-----
-* Website: https://www.palletsprojects.com/p/markupsafe/
-* Documentation: https://markupsafe.readthedocs.io/
-* License: `BSD <https://github.com/pallets/markupsafe/blob/master/LICENSE.rst>`_
-* Releases: https://pypi.org/project/MarkupSafe/
-* Code: https://github.com/pallets/markupsafe
-* Issue tracker: https://github.com/pallets/markupsafe/issues
-* Test status:
+* Website: https://www.palletsprojects.com/p/markupsafe/
+* Documentation: https://markupsafe.readthedocs.io/
+* License: `BSD <https://github.com/pallets/markupsafe/blob/master/LICENSE.rst>`_
+* Releases: https://pypi.org/project/MarkupSafe/
+* Code: https://github.com/pallets/markupsafe
+* Issue tracker: https://github.com/pallets/markupsafe/issues
+* Test status:
- * Linux, Mac: https://travis-ci.org/pallets/markupsafe
- * Windows: https://ci.appveyor.com/project/pallets/markupsafe
+ * Linux, Mac: https://travis-ci.org/pallets/markupsafe
+ * Windows: https://ci.appveyor.com/project/pallets/markupsafe
-* Test coverage: https://codecov.io/gh/pallets/markupsafe
-
-.. _pip: https://pip.pypa.io/en/stable/quickstart/
+* Test coverage: https://codecov.io/gh/pallets/markupsafe
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..d10ee88
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+SPHINXPROJ = MarkupSafe
+SOURCEDIR = .
+BUILDDIR = _build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..0fe75a4
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+from __future__ import print_function
+
+from pallets_sphinx_themes import ProjectLink, get_version
+
+# Project --------------------------------------------------------------
+
+project = 'MarkupSafe'
+copyright = '2010 Pallets team'
+author = 'Pallets team'
+release, version = get_version('MarkupSafe')
+
+# General --------------------------------------------------------------
+
+master_doc = 'index'
+
+extensions = [
+ 'sphinx.ext.autodoc',
+ 'sphinx.ext.intersphinx',
+]
+
+intersphinx_mapping = {
+ 'python': ('https://docs.python.org/3/', None),
+}
+
+# HTML -----------------------------------------------------------------
+
+html_theme = 'flask'
+html_context = {
+ 'project_links': [
+ ProjectLink(
+ 'Donate to Pallets',
+ 'https://psfmember.org/civicrm/contribute/transact?reset=1&id=20'),
+ ProjectLink(
+ 'MarkupSafe Website', 'https://palletsprojects.com/p/markupsafe/'),
+ ProjectLink('PyPI Releases', 'https://pypi.org/project/MarkupSafe/'),
+ ProjectLink('Source Code', 'https://github.com/pallets/markupsafe/'),
+ ProjectLink(
+ 'Issue Tracker', 'https://github.com/pallets/MarkupSafe/issues/'),
+ ],
+}
+html_sidebars = {
+ 'index': [
+ 'project.html',
+ 'searchbox.html',
+ ],
+ '**': [
+ 'localtoc.html',
+ 'relations.html',
+ 'searchbox.html',
+ ]
+}
+html_show_sourcelink = False
+
+# LaTeX ----------------------------------------------------------------
+
+latex_documents = [
+ (
+ master_doc, 'MarkupSafe.tex', 'MarkupSafe Documentation',
+ 'Pallets team', 'manual'
+ ),
+]
+latex_use_modindex = False
+latex_elements = {
+ 'papersize': 'a4paper',
+ 'pointsize': '12pt',
+}
+latex_use_parts = True
+
+# linkcheck ------------------------------------------------------------
+
+linkcheck_anchors = False
diff --git a/docs/escaping.rst b/docs/escaping.rst
new file mode 100644
index 0000000..d99674d
--- /dev/null
+++ b/docs/escaping.rst
@@ -0,0 +1,21 @@
+.. module:: markupsafe
+
+Working With Safe Text
+======================
+
+.. autofunction:: escape
+
+.. autoclass:: Markup
+ :members: escape, unescape, striptags
+
+
+Optional Values
+---------------
+
+.. autofunction:: escape_silent
+
+
+Convert an Object to a String
+-----------------------------
+
+.. autofunction:: soft_unicode
diff --git a/docs/formatting.rst b/docs/formatting.rst
new file mode 100644
index 0000000..c425134
--- /dev/null
+++ b/docs/formatting.rst
@@ -0,0 +1,77 @@
+.. currentmodule:: markupsafe
+
+String Formatting
+=================
+
+The :class:`Markup` class can be used as a format string. Objects
+formatted into a markup string will be escaped first.
+
+
+Format Method
+-------------
+
+The ``format`` method extends the standard :meth:`str.format` behavior
+to use an ``__html_format__`` method.
+
+#. If an object has an ``__html_format__`` method, it is called as a
+ replacement for the ``__format__`` method. It is passed a format
+ specifier if it's given. The method must return a string or
+ :class:`Markup` instance.
+
+#. If an object has an ``__html__`` method, it is called. If a format
+ specifier was passed and the class defined ``__html__`` but not
+ ``__html_format__``, a ``ValueError`` is raised.
+
+#. Otherwise Python's default format behavior is used and the result
+ is escaped.
+
+For example, to implement a ``User`` that wraps its ``name`` in a
+``span`` tag, and adds a link when using the ``'link'`` format
+specifier:
+
+.. code-block:: python
+
+ class User(object):
+ def __init__(self, id, name):
+ self.id = id
+ self.name = name
+
+ def __html_format__(self, format_spec):
+ if format_spec == 'link':
+ return Markup(
+ '<a href="/user/{}">{}</a>'
+ ).format(self.id, self.__html__())
+ elif format_spec:
+ raise ValueError('Invalid format spec')
+ return self.__html__()
+
+ def __html__(self):
+ return Markup(
+ '<span class="user">{0}</span>'
+ ).format(self.name)
+
+
+.. code-block:: pycon
+
+ >>> user = User(3, '<script>')
+ >>> escape(user)
+ Markup('<span class="user">&lt;script&gt;</span>')
+ >>> Markup('<p>User: {user:link}').format(user=user)
+ Markup('<p>User: <a href="/user/3"><span class="user">&lt;script&gt;</span></a>
+
+See Python's docs on :ref:`format string syntax <python:formatstrings>`.
+
+
+printf-style Formatting
+-----------------------
+
+Besides escaping, there's no special behavior involved with percent
+formatting.
+
+.. code-block:: pycon
+
+ >>> user = User(3, '<script>')
+ >>> Markup('<a href="/user/%d">"%s</a>') % (user.id, user.name)
+ Markup('<a href="/user/3">&lt;script&gt;</a>')
+
+See Python's docs on :ref:`printf-style formatting <python:old-string-formatting>`.
diff --git a/docs/html.rst b/docs/html.rst
new file mode 100644
index 0000000..3a0c11b
--- /dev/null
+++ b/docs/html.rst
@@ -0,0 +1,51 @@
+.. currentmodule:: markupsafe
+
+HTML Representations
+====================
+
+In many frameworks, if a class implements an ``__html__`` method it
+will be used to get the object's representation in HTML. MarkupSafe's
+:func:`escape` function and :class:`Markup` class understand and
+implement this method. If an object has an ``__html__`` method it will
+be called rather than converting the object to a string, and the result
+will be assumed safe and not escaped.
+
+For example, an ``Image`` class might automatically generate an
+``<img>`` tag:
+
+.. code-block:: python
+
+ class Image:
+ def __init__(self, url):
+ self.url = url
+
+ def __html__(self):
+ return '<img src="%s">' % self.url
+
+.. code-block:: pycon
+
+ >>> img = Image('/static/logo.png')
+ >>> Markup(img)
+ Markup('<img src="/static/logo.png">')
+
+Since this bypasses escaping, you need to be careful about using
+user-provided data in the output. For example, a user's display name
+should still be escaped:
+
+.. code-block:: python
+
+ class User:
+ def __init__(self, id, name):
+ self.id = id
+ self.name = name
+
+ def __html__(self):
+ return '<a href="/user/{}">{}</a>'.format(
+ self.id, escape(self.name)
+ )
+
+.. code-block:: pycon
+
+ >>> user = User(3, '<script>')
+ >>> escape(user)
+ Markup('<a href="/users/3">&lt;script&gt;</a>')
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..016fd1c
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,35 @@
+.. currentmodule:: markupsafe
+
+MarkupSafe
+==========
+
+MarkupSafe escapes characters so text is safe to use in HTML and XML.
+Characters that have special meanings are replaced so that they display
+as the actual characters. This mitigates injection attacks, meaning
+untrusted user input can safely be displayed on a page.
+
+The :func:`escape` function escapes text and returns a :class:`Markup`
+object. The object won't be escaped anymore, but any text that is used
+with it will be, ensuring that the result remains safe to use in HTML.
+
+>>> from markupsafe import escape
+>>> hello = escape('<em>Hello</em>')
+>>> hello
+Markup('&lt;em&gt;Hello&lt;/em&gt;')
+>>> escape(hello)
+Markup('&lt;em&gt;Hello&lt;/em&gt;')
+>>> hello + ' <strong>World</strong>'
+Markup('&lt;em&gt;Hello&lt;/em&gt; &lt;strong&gt;World&lt;/strong&gt;')
+
+.. note::
+
+ The docs assume you're using Python 3. The terms "text" and "string"
+ refer to the :class:`str` class. In Python 2, this would be the
+ ``unicode`` class instead.
+
+.. toctree::
+ :maxdepth: 2
+
+ escaping
+ html
+ formatting
diff --git a/docs/make.bat b/docs/make.bat
new file mode 100644
index 0000000..7639bf3
--- /dev/null
+++ b/docs/make.bat
@@ -0,0 +1,36 @@
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=.
+set BUILDDIR=_build
+set SPHINXPROJ=MarkupSafe
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
+
+:end
+popd
diff --git a/markupsafe/__init__.py b/markupsafe/__init__.py
index b932225..0acf735 100644
--- a/markupsafe/__init__.py
+++ b/markupsafe/__init__.py
@@ -1,70 +1,66 @@
# -*- coding: utf-8 -*-
"""
- markupsafe
- ~~~~~~~~~~
+markupsafe
+~~~~~~~~~~
- Implements a Markup string.
+Implements an escape function and a Markup string to replace HTML
+special characters with safe representations.
- :copyright: (c) 2010 by Armin Ronacher.
- :license: BSD, see LICENSE for more details.
+:copyright: © 2010 by the Pallets team.
+:license: BSD, see LICENSE for more details.
"""
+from collections import Mapping
+
import re
import string
-from collections import Mapping
-from markupsafe._compat import text_type, string_types, int_types, \
- unichr, iteritems, PY2
+
+from markupsafe._compat import (
+ PY2, int_types, iteritems, string_types, text_type, unichr
+)
__version__ = '1.1'
__all__ = ['Markup', 'soft_unicode', 'escape', 'escape_silent']
-
_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
_entity_re = re.compile(r'&([^& ;]+);')
class Markup(text_type):
- r"""Marks a string as being safe for inclusion in HTML/XML output without
- needing to be escaped. This implements the `__html__` interface a couple
- of frameworks and web applications use. :class:`Markup` is a direct
- subclass of `unicode` and provides all the methods of `unicode` just that
- it escapes arguments passed and always returns `Markup`.
-
- The `escape` function returns markup objects so that double escaping can't
- happen.
-
- The constructor of the :class:`Markup` class can be used for three
- different things: When passed an unicode object it's assumed to be safe,
- when passed an object with an HTML representation (has an `__html__`
- method) that representation is used, otherwise the object passed is
- converted into a unicode string and then assumed to be safe:
-
- >>> Markup("Hello <em>World</em>!")
- Markup(u'Hello <em>World</em>!')
- >>> class Foo(object):
- ... def __html__(self):
- ... return '<a href="#">foo</a>'
+ """A string that is ready to be safely inserted into an HTML or XML
+ document, either because it was escaped or because it was marked
+ safe.
+
+ Passing an object to the constructor converts it to text and wraps
+ it to mark it safe without escaping. To escape the text, use the
+ :meth:`escape` class method instead.
+
+ >>> Markup('Hello, <em>World</em>!')
+ Markup('Hello, <em>World</em>!')
+ >>> Markup(42)
+ Markup('42')
+ >>> Markup.escape('Hello, <em>World</em>!')
+ Markup('Hello &lt;em&gt;World&lt;/em&gt;!')
+
+ This implements the ``__html__()`` interface that some frameworks
+ use. Passing an object that implements ``__html__()`` will wrap the
+ output of that method, marking it safe.
+
+ >>> class Foo:
+ ... def __html__(self):
+ ... return '<a href="/foo">foo</a>'
...
>>> Markup(Foo())
- Markup(u'<a href="#">foo</a>')
-
- If you want object passed being always treated as unsafe you can use the
- :meth:`escape` classmethod to create a :class:`Markup` object:
-
- >>> Markup.escape("Hello <em>World</em>!")
- Markup(u'Hello &lt;em&gt;World&lt;/em&gt;!')
+ Markup('<a href="/foo">foo</a>')
- Operations on a markup string are markup aware which means that all
- arguments are passed through the :func:`escape` function:
+ This is a subclass of the text type (``str`` in Python 3,
+ ``unicode`` in Python 2). It has the same methods as that type, but
+ all methods escape their arguments and return a ``Markup`` instance.
- >>> em = Markup("<em>%s</em>")
- >>> em % "foo & bar"
- Markup(u'<em>foo &amp; bar</em>')
- >>> strong = Markup("<strong>%(text)s</strong>")
- >>> strong % {'text': '<blink>hacker here</blink>'}
- Markup(u'<strong>&lt;blink&gt;hacker here&lt;/blink&gt;</strong>')
- >>> Markup("<em>Hello</em> ") + "<foo>"
- Markup(u'<em>Hello</em> &lt;foo&gt;')
+ >>> Markup('<em>%s</em>') % 'foo & bar'
+ Markup('<em>foo &amp; bar</em>')
+ >>> Markup('<em>Hello</em> ') + '<foo>'
+ Markup('<em>Hello</em> &lt;foo&gt;')
"""
__slots__ = ()
@@ -125,11 +121,11 @@ class Markup(text_type):
splitlines.__doc__ = text_type.splitlines.__doc__
def unescape(self):
- r"""Unescape markup again into an text_type string. This also resolves
- known HTML4 and XHTML entities:
+ """Convert escaped markup back into a text string. This replaces
+ HTML entities with the characters they represent.
- >>> Markup("Main &raquo; <em>About</em>").unescape()
- u'Main \xbb <em>About</em>'
+ >>> Markup('Main &raquo; <em>About</em>').unescape()
+ 'Main » <em>About</em>'
"""
from markupsafe._constants import HTML_ENTITIES
def handle_match(m):
@@ -148,21 +144,19 @@ class Markup(text_type):
return _entity_re.sub(handle_match, text_type(self))
def striptags(self):
- r"""Unescape markup into an text_type string and strip all tags. This
- also resolves known HTML4 and XHTML entities. Whitespace is
- normalized to one:
+ """:meth:`unescape` the markup, remove tags, and normalize
+ whitespace to single spaces.
- >>> Markup("Main &raquo; <em>About</em>").striptags()
- u'Main \xbb About'
+ >>> Markup('Main &raquo;\t<em>About</em>').striptags()
+ 'Main » About'
"""
stripped = u' '.join(_striptags_re.sub('', self).split())
return Markup(stripped).unescape()
@classmethod
def escape(cls, s):
- """Escape the string. Works like :func:`escape` with the difference
- that for subclasses of :class:`Markup` this function would return the
- correct subclass.
+ """Escape a string. Calls :func:`escape` and ensures that for
+ subclasses the correct type is returned.
"""
rv = escape(s)
if rv.__class__ is not cls:
@@ -254,9 +248,12 @@ if hasattr(text_type, 'format'):
rv = value.__html_format__(format_spec)
elif hasattr(value, '__html__'):
if format_spec:
- raise ValueError('No format specification allowed '
- 'when formatting an object with '
- 'its __html__ method.')
+ 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)))
rv = value.__html__()
else:
# We need to make sure the format spec is unicode here as
diff --git a/markupsafe/_compat.py b/markupsafe/_compat.py
index 62e5632..7435faf 100644
--- a/markupsafe/_compat.py
+++ b/markupsafe/_compat.py
@@ -1,12 +1,10 @@
# -*- coding: utf-8 -*-
"""
- markupsafe._compat
- ~~~~~~~~~~~~~~~~~~
+markupsafe._compat
+~~~~~~~~~~~~~~~~~~
- Compatibility module for different Python versions.
-
- :copyright: (c) 2013 by Armin Ronacher.
- :license: BSD, see LICENSE for more details.
+:copyright: © 2010 by the Pallets team.
+:license: BSD, see LICENSE for more details.
"""
import sys
diff --git a/markupsafe/_constants.py b/markupsafe/_constants.py
index 919bf03..ea6ac2f 100644
--- a/markupsafe/_constants.py
+++ b/markupsafe/_constants.py
@@ -1,15 +1,12 @@
# -*- coding: utf-8 -*-
"""
- markupsafe._constants
- ~~~~~~~~~~~~~~~~~~~~~
+markupsafe._constants
+~~~~~~~~~~~~~~~~~~~~~
- Highlevel implementation of the Markup string.
-
- :copyright: (c) 2010 by Armin Ronacher.
- :license: BSD, see LICENSE for more details.
+:copyright: © 2010 by the Pallets team.
+:license: BSD, see LICENSE for more details.
"""
-
HTML_ENTITIES = {
'AElig': 198,
'Aacute': 193,
diff --git a/markupsafe/_native.py b/markupsafe/_native.py
index 2c54a2d..801f285 100644
--- a/markupsafe/_native.py
+++ b/markupsafe/_native.py
@@ -1,21 +1,27 @@
# -*- coding: utf-8 -*-
"""
- markupsafe._native
- ~~~~~~~~~~~~~~~~~~
+markupsafe._native
+~~~~~~~~~~~~~~~~~~
- Native Python implementation the C module is not compiled.
+Native Python implementation used when the C module is not compiled.
- :copyright: (c) 2010 by Armin Ronacher.
- :license: BSD, see LICENSE for more details.
+:copyright: © 2010 by the Pallets team.
+:license: BSD, see LICENSE for more details.
"""
from markupsafe import Markup
from markupsafe._compat import text_type
def escape(s):
- """Convert the characters &, <, >, ' and " in string s to HTML-safe
- sequences. Use this if you need to display text that might contain
- such characters in HTML. Marks return value as markup string.
+ """Replace the characters ``&``, ``<``, ``>``, ``'``, and ``"`` in
+ the string with HTML-safe sequences. Use this if you need to display
+ text that might contain such characters in HTML.
+
+ If the object has an ``__html__`` method, it is called and the
+ return value is assumed to already be safe for HTML.
+
+ :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__'):
return Markup(s.__html__())
@@ -29,8 +35,14 @@ def escape(s):
def escape_silent(s):
- """Like :func:`escape` but converts `None` into an empty
- markup string.
+ """Like :func:`escape` but treats ``None`` as the empty string.
+ Useful with optional values, as otherwise you get the string
+ ``'None'`` when the value is ``None``.
+
+ >>> escape(None)
+ Markup('None')
+ >>> escape_silent(None)
+ Markup('')
"""
if s is None:
return Markup()
@@ -38,8 +50,18 @@ def escape_silent(s):
def soft_unicode(s):
- """Make a string unicode if it isn't already. That way a markup
- string is not converted back to unicode.
+ """Convert an object to a string if it isn't already. This preserves
+ a :class:`Markup` string rather than converting it back to a basic
+ string, so it will still be marked as safe and won't be escaped
+ again.
+
+ >>> value = escape('<User 1>')
+ >>> value
+ Markup('&lt;User 1&gt;')
+ >>> escape(str(value))
+ Markup('&amp;lt;User 1&amp;gt;')
+ >>> escape(soft_unicode(value))
+ Markup('&lt;User 1&gt;')
"""
if not isinstance(s, text_type):
s = text_type(s)
diff --git a/markupsafe/_speedups.c b/markupsafe/_speedups.c
index aa9f499..fb4a03e 100644
--- a/markupsafe/_speedups.c
+++ b/markupsafe/_speedups.c
@@ -2,11 +2,11 @@
* markupsafe._speedups
* ~~~~~~~~~~~~~~~~~~~~
*
- * This module implements functions for automatic escaping in C for better
- * performance.
+ * C implementation of escaping for better performance. Used instead of
+ * the native Python implementation when compiled.
*
- * :copyright: (c) 2010 by Armin Ronacher.
- * :license: BSD.
+ * :copyright: © 2010 by the Pallets team.
+ * :license: BSD, see LICENSE for more details.
*/
#include <Python.h>
@@ -14,7 +14,6 @@
#define ESCAPED_CHARS_TABLE_SIZE 63
#define UNICHR(x) (PyUnicode_AS_UNICODE((PyUnicodeObject*)PyUnicode_DecodeASCII(x, strlen(x), NULL)));
-
static PyObject* markup;
static Py_ssize_t escaped_chars_delta_len[ESCAPED_CHARS_TABLE_SIZE];
static Py_UNICODE *escaped_chars_repl[ESCAPED_CHARS_TABLE_SIZE];
diff --git a/setup.py b/setup.py
index 3b6f4d3..6cf59ef 100644
--- a/setup.py
+++ b/setup.py
@@ -67,7 +67,7 @@ def run_setup(with_binary):
author_email='armin.ronacher@active-4.com',
maintainer='Pallets team',
maintainer_email='contact@palletsprojects.com',
- description='Safely add untrusted strings to XML/HTML markup.',
+ description='Safely add untrusted strings to HTML/XML markup.',
long_description=readme,
classifiers=[
'Development Status :: 5 - Production/Stable',
@@ -92,6 +92,12 @@ def run_setup(with_binary):
'pytest',
'coverage',
'tox',
+ 'sphinx',
+ 'pallets-sphinx-themes',
+ ],
+ 'docs': [
+ 'sphinx',
+ 'pallets-sphinx-themes',
],
},
packages=['markupsafe'],
diff --git a/tox.ini b/tox.ini
index 8f372c5..9247e76 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,6 +1,7 @@
[tox]
envlist =
py{36,35,34,27,py}
+ docs-html
coverage_report
[testenv]
@@ -10,7 +11,15 @@ deps =
coverage
commands = coverage run -p -m pytest {posargs}
-[testenv:coverage_report]
+[testenv:docs-html]
+deps =
+ sphinx
+ pallets-sphinx-themes
+ sphinxcontrib-log-cabinet
+commands =
+ sphinx-build -M html docs {envtmpdir}
+
+[testenv:coverage-report]
deps = coverage
skip_install = true
commands =