Bug 1712151: Vendor pystache automatically r=ahal

Add pystache to vendor `requirements.in` so that it's vendored according
to `./mach vendor python` "ignore" rules.
This ensures that sufficient files are vendored such that installing the
package from it's `setup.py` file is possible.

Differential Revision: https://phabricator.services.mozilla.com/D122898
This commit is contained in:
Mitchell Hentges 2021-09-09 18:18:45 +00:00
Родитель a16f941f30
Коммит 648d810e4b
76 изменённых файлов: 5112 добавлений и 35 удалений

17
third_party/python/pystache/.gitignore поставляемый
Просмотреть файл

@ -1,17 +0,0 @@
*.pyc
.DS_Store
# Tox support. See: http://pypi.python.org/pypi/tox
.tox
# Our tox runs convert the doctests in *.rst files to Python 3 prior to
# running tests. Ignore these temporary files.
*.temp2to3.rst
# The setup.py "prep" command converts *.md to *.temp.rst (via *.temp.md).
*.temp.md
*.temp.rst
# TextMate project file
*.tmproj
# Distribution-related folders and files.
build
dist
MANIFEST
pystache.egg-info

3
third_party/python/pystache/.gitmodules поставляемый
Просмотреть файл

@ -1,3 +0,0 @@
[submodule "ext/spec"]
path = ext/spec
url = http://github.com/mustache/spec.git

14
third_party/python/pystache/.travis.yml поставляемый
Просмотреть файл

@ -1,14 +0,0 @@
language: python
# Travis CI has no plans to support Jython and no longer supports Python 2.5.
python:
- 2.6
- 2.7
- 3.2
- pypy
script:
- python setup.py install
# Include the spec tests directory for Mustache spec tests and the
# project directory for doctests.
- pystache-test . ext/spec/specs

536
third_party/python/pystache/PKG-INFO поставляемый Normal file
Просмотреть файл

@ -0,0 +1,536 @@
Metadata-Version: 1.1
Name: pystache
Version: 0.5.4
Summary: Mustache for Python
Home-page: http://github.com/defunkt/pystache
Author: Chris Jerdonek
Author-email: chris.jerdonek@gmail.com
License: MIT
Description: .. Do not edit this file. This file is auto-generated for PyPI by setup.py
.. using pandoc, so edits should go in the source files rather than here.
Pystache
========
.. figure:: http://defunkt.github.com/pystache/images/logo_phillips.png
:alt: mustachioed, monocled snake by David Phillips
.. figure:: https://secure.travis-ci.org/defunkt/pystache.png
:alt: Travis CI current build status
`Pystache <http://defunkt.github.com/pystache>`__ is a Python
implementation of `Mustache <http://mustache.github.com/>`__. Mustache
is a framework-agnostic, logic-free templating system inspired by
`ctemplate <http://code.google.com/p/google-ctemplate/>`__ and
`et <http://www.ivan.fomichev.name/2008/05/erlang-template-engine-prototype.html>`__.
Like ctemplate, Mustache "emphasizes separating logic from presentation:
it is impossible to embed application logic in this template language."
The `mustache(5) <http://mustache.github.com/mustache.5.html>`__ man
page provides a good introduction to Mustache's syntax. For a more
complete (and more current) description of Mustache's behavior, see the
official `Mustache spec <https://github.com/mustache/spec>`__.
Pystache is `semantically versioned <http://semver.org>`__ and can be
found on `PyPI <http://pypi.python.org/pypi/pystache>`__. This version
of Pystache passes all tests in `version
1.1.2 <https://github.com/mustache/spec/tree/v1.1.2>`__ of the spec.
Requirements
------------
Pystache is tested with--
- Python 2.4 (requires simplejson `version
2.0.9 <http://pypi.python.org/pypi/simplejson/2.0.9>`__ or earlier)
- Python 2.5 (requires
`simplejson <http://pypi.python.org/pypi/simplejson/>`__)
- Python 2.6
- Python 2.7
- Python 3.1
- Python 3.2
- Python 3.3
- `PyPy <http://pypy.org/>`__
`Distribute <http://packages.python.org/distribute/>`__ (the setuptools
fork) is recommended over
`setuptools <http://pypi.python.org/pypi/setuptools>`__, and is required
in some cases (e.g. for Python 3 support). If you use
`pip <http://www.pip-installer.org/>`__, you probably already satisfy
this requirement.
JSON support is needed only for the command-line interface and to run
the spec tests. We require simplejson for earlier versions of Python
since Python's `json <http://docs.python.org/library/json.html>`__
module was added in Python 2.6.
For Python 2.4 we require an earlier version of simplejson since
simplejson stopped officially supporting Python 2.4 in simplejson
version 2.1.0. Earlier versions of simplejson can be installed manually,
as follows:
::
pip install 'simplejson<2.1.0'
Official support for Python 2.4 will end with Pystache version 0.6.0.
Install It
----------
::
pip install pystache
And test it--
::
pystache-test
To install and test from source (e.g. from GitHub), see the Develop
section.
Use It
------
::
>>> import pystache
>>> print pystache.render('Hi {{person}}!', {'person': 'Mom'})
Hi Mom!
You can also create dedicated view classes to hold your view logic.
Here's your view class (in .../examples/readme.py):
::
class SayHello(object):
def to(self):
return "Pizza"
Instantiating like so:
::
>>> from pystache.tests.examples.readme import SayHello
>>> hello = SayHello()
Then your template, say\_hello.mustache (by default in the same
directory as your class definition):
::
Hello, {{to}}!
Pull it together:
::
>>> renderer = pystache.Renderer()
>>> print renderer.render(hello)
Hello, Pizza!
For greater control over rendering (e.g. to specify a custom template
directory), use the ``Renderer`` class like above. One can pass
attributes to the Renderer class constructor or set them on a Renderer
instance. To customize template loading on a per-view basis, subclass
``TemplateSpec``. See the docstrings of the
`Renderer <https://github.com/defunkt/pystache/blob/master/pystache/renderer.py>`__
class and
`TemplateSpec <https://github.com/defunkt/pystache/blob/master/pystache/template_spec.py>`__
class for more information.
You can also pre-parse a template:
::
>>> parsed = pystache.parse(u"Hey {{#who}}{{.}}!{{/who}}")
>>> print parsed
[u'Hey ', _SectionNode(key=u'who', index_begin=12, index_end=18, parsed=[_EscapeNode(key=u'.'), u'!'])]
And then:
::
>>> print renderer.render(parsed, {'who': 'Pops'})
Hey Pops!
>>> print renderer.render(parsed, {'who': 'you'})
Hey you!
Python 3
--------
Pystache has supported Python 3 since version 0.5.1. Pystache behaves
slightly differently between Python 2 and 3, as follows:
- In Python 2, the default html-escape function ``cgi.escape()`` does
not escape single quotes. In Python 3, the default escape function
``html.escape()`` does escape single quotes.
- In both Python 2 and 3, the string and file encodings default to
``sys.getdefaultencoding()``. However, this function can return
different values under Python 2 and 3, even when run from the same
system. Check your own system for the behavior on your system, or do
not rely on the defaults by passing in the encodings explicitly (e.g.
to the ``Renderer`` class).
Unicode
-------
This section describes how Pystache handles unicode, strings, and
encodings.
Internally, Pystache uses `only unicode
strings <http://docs.python.org/howto/unicode.html#tips-for-writing-unicode-aware-programs>`__
(``str`` in Python 3 and ``unicode`` in Python 2). For input, Pystache
accepts both unicode strings and byte strings (``bytes`` in Python 3 and
``str`` in Python 2). For output, Pystache's template rendering methods
return only unicode.
Pystache's ``Renderer`` class supports a number of attributes to control
how Pystache converts byte strings to unicode on input. These include
the ``file_encoding``, ``string_encoding``, and ``decode_errors``
attributes.
The ``file_encoding`` attribute is the encoding the renderer uses to
convert to unicode any files read from the file system. Similarly,
``string_encoding`` is the encoding the renderer uses to convert any
other byte strings encountered during the rendering process into unicode
(e.g. context values that are encoded byte strings).
The ``decode_errors`` attribute is what the renderer passes as the
``errors`` argument to Python's built-in unicode-decoding function
(``str()`` in Python 3 and ``unicode()`` in Python 2). The valid values
for this argument are ``strict``, ``ignore``, and ``replace``.
Each of these attributes can be set via the ``Renderer`` class's
constructor using a keyword argument of the same name. See the Renderer
class's docstrings for further details. In addition, the
``file_encoding`` attribute can be controlled on a per-view basis by
subclassing the ``TemplateSpec`` class. When not specified explicitly,
these attributes default to values set in Pystache's ``defaults``
module.
Develop
-------
To test from a source distribution (without installing)--
::
python test_pystache.py
To test Pystache with multiple versions of Python (with a single
command!), you can use `tox <http://pypi.python.org/pypi/tox>`__:
::
pip install 'virtualenv<1.8' # Version 1.8 dropped support for Python 2.4.
pip install 'tox<1.4' # Version 1.4 dropped support for Python 2.4.
tox
If you do not have all Python versions listed in ``tox.ini``--
::
tox -e py26,py32 # for example
The source distribution tests also include doctests and tests from the
Mustache spec. To include tests from the Mustache spec in your test
runs:
::
git submodule init
git submodule update
The test harness parses the spec's (more human-readable) yaml files if
`PyYAML <http://pypi.python.org/pypi/PyYAML>`__ is present. Otherwise,
it parses the json files. To install PyYAML--
::
pip install pyyaml
To run a subset of the tests, you can use
`nose <http://somethingaboutorange.com/mrl/projects/nose/0.11.1/testing.html>`__:
::
pip install nose
nosetests --tests pystache/tests/test_context.py:GetValueTests.test_dictionary__key_present
Using Python 3 with Pystache from source
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Pystache is written in Python 2 and must be converted to Python 3 prior
to using it with Python 3. The installation process (and tox) do this
automatically.
To convert the code to Python 3 manually (while using Python 3)--
::
python setup.py build
This writes the converted code to a subdirectory called ``build``. By
design, Python 3 builds
`cannot <https://bitbucket.org/tarek/distribute/issue/292/allow-use_2to3-with-python-2>`__
be created from Python 2.
To convert the code without using setup.py, you can use
`2to3 <http://docs.python.org/library/2to3.html>`__ as follows (two
steps)--
::
2to3 --write --nobackups --no-diffs --doctests_only pystache
2to3 --write --nobackups --no-diffs pystache
This converts the code (and doctests) in place.
To ``import pystache`` from a source distribution while using Python 3,
be sure that you are importing from a directory containing a converted
version of the code (e.g. from the ``build`` directory after
converting), and not from the original (unconverted) source directory.
Otherwise, you will get a syntax error. You can help prevent this by not
running the Python IDE from the project directory when importing
Pystache while using Python 3.
Mailing List
------------
There is a `mailing list <http://librelist.com/browser/pystache/>`__.
Note that there is a bit of a delay between posting a message and seeing
it appear in the mailing list archive.
Credits
-------
::
>>> context = { 'author': 'Chris Wanstrath', 'maintainer': 'Chris Jerdonek' }
>>> print pystache.render("Author: {{author}}\nMaintainer: {{maintainer}}", context)
Author: Chris Wanstrath
Maintainer: Chris Jerdonek
Pystache logo by `David Phillips <http://davidphillips.us/>`__ is
licensed under a `Creative Commons Attribution-ShareAlike 3.0 Unported
License <http://creativecommons.org/licenses/by-sa/3.0/deed.en_US>`__.
|image0|
History
=======
**Note:** Official support for Python 2.4 will end with Pystache version
0.6.0.
0.5.4 (2014-07-11)
------------------
- Bugfix: made test with filenames OS agnostic (issue #162).
0.5.3 (2012-11-03)
------------------
- Added ability to customize string coercion (e.g. to have None render
as ``''``) (issue #130).
- Added Renderer.render\_name() to render a template by name (issue
#122).
- Added TemplateSpec.template\_path to specify an absolute path to a
template (issue #41).
- Added option of raising errors on missing tags/partials:
``Renderer(missing_tags='strict')`` (issue #110).
- Added support for finding and loading templates by file name in
addition to by template name (issue #127). [xgecko]
- Added a ``parse()`` function that yields a printable, pre-compiled
parse tree.
- Added support for rendering pre-compiled templates.
- Added Python 3.3 to the list of supported versions.
- Added support for `PyPy <http://pypy.org/>`__ (issue #125).
- Added support for `Travis CI <http://travis-ci.org>`__ (issue #124).
[msabramo]
- Bugfix: ``defaults.DELIMITERS`` can now be changed at runtime (issue
#135). [bennoleslie]
- Bugfix: exceptions raised from a property are no longer swallowed
when getting a key from a context stack (issue #110).
- Bugfix: lambda section values can now return non-ascii, non-unicode
strings (issue #118).
- Bugfix: allow ``test_pystache.py`` and ``tox`` to pass when run from
a downloaded sdist (i.e. without the spec test directory).
- Convert HISTORY and README files from reST to Markdown.
- More robust handling of byte strings in Python 3.
- Added Creative Commons license for David Phillips's logo.
0.5.2 (2012-05-03)
------------------
- Added support for dot notation and version 1.1.2 of the spec (issue
#99). [rbp]
- Missing partials now render as empty string per latest version of
spec (issue #115).
- Bugfix: falsey values now coerced to strings using str().
- Bugfix: lambda return values for sections no longer pushed onto
context stack (issue #113).
- Bugfix: lists of lambdas for sections were not rendered (issue #114).
0.5.1 (2012-04-24)
------------------
- Added support for Python 3.1 and 3.2.
- Added tox support to test multiple Python versions.
- Added test script entry point: pystache-test.
- Added \_\_version\_\_ package attribute.
- Test harness now supports both YAML and JSON forms of Mustache spec.
- Test harness no longer requires nose.
0.5.0 (2012-04-03)
------------------
This version represents a major rewrite and refactoring of the code base
that also adds features and fixes many bugs. All functionality and
nearly all unit tests have been preserved. However, some backwards
incompatible changes to the API have been made.
Below is a selection of some of the changes (not exhaustive).
Highlights:
- Pystache now passes all tests in version 1.0.3 of the `Mustache
spec <https://github.com/mustache/spec>`__. [pvande]
- Removed View class: it is no longer necessary to subclass from View
or from any other class to create a view.
- Replaced Template with Renderer class: template rendering behavior
can be modified via the Renderer constructor or by setting attributes
on a Renderer instance.
- Added TemplateSpec class: template rendering can be specified on a
per-view basis by subclassing from TemplateSpec.
- Introduced separation of concerns and removed circular dependencies
(e.g. between Template and View classes, cf. `issue
#13 <https://github.com/defunkt/pystache/issues/13>`__).
- Unicode now used consistently throughout the rendering process.
- Expanded test coverage: nosetests now runs doctests and ~105 test
cases from the Mustache spec (increasing the number of tests from 56
to ~315).
- Added a rudimentary benchmarking script to gauge performance while
refactoring.
- Extensive documentation added (e.g. docstrings).
Other changes:
- Added a command-line interface. [vrde]
- The main rendering class now accepts a custom partial loader (e.g. a
dictionary) and a custom escape function.
- Non-ascii characters in str strings are now supported while
rendering.
- Added string encoding, file encoding, and errors options for decoding
to unicode.
- Removed the output encoding option.
- Removed the use of markupsafe.
Bug fixes:
- Context values no longer processed as template strings.
[jakearchibald]
- Whitespace surrounding sections is no longer altered, per the spec.
[heliodor]
- Zeroes now render correctly when using PyPy. [alex]
- Multline comments now permitted. [fczuardi]
- Extensionless template files are now supported.
- Passing ``**kwargs`` to ``Template()`` no longer modifies the
context.
- Passing ``**kwargs`` to ``Template()`` with no context no longer
raises an exception.
0.4.1 (2012-03-25)
------------------
- Added support for Python 2.4. [wangtz, jvantuyl]
0.4.0 (2011-01-12)
------------------
- Add support for nested contexts (within template and view)
- Add support for inverted lists
- Decoupled template loading
0.3.1 (2010-05-07)
------------------
- Fix package
0.3.0 (2010-05-03)
------------------
- View.template\_path can now hold a list of path
- Add {{& blah}} as an alias for {{{ blah }}}
- Higher Order Sections
- Inverted sections
0.2.0 (2010-02-15)
------------------
- Bugfix: Methods returning False or None are not rendered
- Bugfix: Don't render an empty string when a tag's value is 0.
[enaeseth]
- Add support for using non-callables as View attributes.
[joshthecoder]
- Allow using View instances as attributes. [joshthecoder]
- Support for Unicode and non-ASCII-encoded bytestring output.
[enaeseth]
- Template file encoding awareness. [enaeseth]
0.1.1 (2009-11-13)
------------------
- Ensure we're dealing with strings, always
- Tests can be run by executing the test file directly
0.1.0 (2009-11-12)
------------------
- First release
License
=======
Copyright (C) 2012 Chris Jerdonek. All rights reserved.
Copyright (c) 2009 Chris Wanstrath
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.
.. |image0| image:: http://i.creativecommons.org/l/by-sa/3.0/88x31.png
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.4
Classifier: Programming Language :: Python :: 2.5
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.1
Classifier: Programming Language :: Python :: 3.2
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: Implementation :: PyPy

Двоичные данные
third_party/python/pystache/gh/images/logo_phillips.png поставляемый

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 170 KiB

Просмотреть файл

@ -43,7 +43,7 @@ def parse(template, delimiters=None):
def _compile_template_re(delimiters):
"""
Return a regular expression object (re.RegexObject) instance.
Return a regular expresssion object (re.RegexObject) instance.
"""
# The possible tag type characters following the opening tag,

4
third_party/python/pystache/pystache/tests/__init__.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,4 @@
"""
TODO: add a docstring.
"""

94
third_party/python/pystache/pystache/tests/benchmark.py поставляемый Executable file
Просмотреть файл

@ -0,0 +1,94 @@
#!/usr/bin/env python
# coding: utf-8
"""
A rudimentary backward- and forward-compatible script to benchmark pystache.
Usage:
tests/benchmark.py 10000
"""
import sys
from timeit import Timer
import pystache
# TODO: make the example realistic.
examples = [
# Test case: 1
("""{{#person}}Hi {{name}}{{/person}}""",
{"person": {"name": "Jon"}},
"Hi Jon"),
# Test case: 2
("""\
<div class="comments">
<h3>{{header}}</h3>
<ul>
{{#comments}}<li class="comment">
<h5>{{name}}</h5><p>{{body}}</p>
</li>{{/comments}}
</ul>
</div>""",
{'header': "My Post Comments",
'comments': [
{'name': "Joe", 'body': "Thanks for this post!"},
{'name': "Sam", 'body': "Thanks for this post!"},
{'name': "Heather", 'body': "Thanks for this post!"},
{'name': "Kathy", 'body': "Thanks for this post!"},
{'name': "George", 'body': "Thanks for this post!"}]},
"""\
<div class="comments">
<h3>My Post Comments</h3>
<ul>
<li class="comment">
<h5>Joe</h5><p>Thanks for this post!</p>
</li><li class="comment">
<h5>Sam</h5><p>Thanks for this post!</p>
</li><li class="comment">
<h5>Heather</h5><p>Thanks for this post!</p>
</li><li class="comment">
<h5>Kathy</h5><p>Thanks for this post!</p>
</li><li class="comment">
<h5>George</h5><p>Thanks for this post!</p>
</li>
</ul>
</div>"""),
]
def make_test_function(example):
template, context, expected = example
def test():
actual = pystache.render(template, context)
if actual != expected:
raise Exception("Benchmark mismatch: \n%s\n*** != ***\n%s" % (expected, actual))
return test
def main(sys_argv):
args = sys_argv[1:]
count = int(args[0])
print "Benchmarking: %sx" % count
print
for example in examples:
test = make_test_function(example)
t = Timer(test,)
print min(t.repeat(repeat=3, number=count))
print "Done"
if __name__ == '__main__':
main(sys.argv)

237
third_party/python/pystache/pystache/tests/common.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,237 @@
# coding: utf-8
"""
Provides test-related code that can be used by all tests.
"""
import os
import pystache
from pystache import defaults
from pystache.tests import examples
# Save a reference to the original function to avoid recursion.
_DEFAULT_TAG_ESCAPE = defaults.TAG_ESCAPE
_TESTS_DIR = os.path.dirname(pystache.tests.__file__)
DATA_DIR = os.path.join(_TESTS_DIR, 'data') # i.e. 'pystache/tests/data'.
EXAMPLES_DIR = os.path.dirname(examples.__file__)
PACKAGE_DIR = os.path.dirname(pystache.__file__)
PROJECT_DIR = os.path.join(PACKAGE_DIR, '..')
# TEXT_DOCTEST_PATHS: the paths to text files (i.e. non-module files)
# containing doctests. The paths should be relative to the project directory.
TEXT_DOCTEST_PATHS = ['README.md']
UNITTEST_FILE_PREFIX = "test_"
def get_spec_test_dir(project_dir):
return os.path.join(project_dir, 'ext', 'spec', 'specs')
def html_escape(u):
"""
An html escape function that behaves the same in both Python 2 and 3.
This function is needed because single quotes are escaped in Python 3
(to '&#x27;'), but not in Python 2.
The global defaults.TAG_ESCAPE can be set to this function in the
setUp() and tearDown() of unittest test cases, for example, for
consistent test results.
"""
u = _DEFAULT_TAG_ESCAPE(u)
return u.replace("'", '&#x27;')
def get_data_path(file_name=None):
"""Return the path to a file in the test data directory."""
if file_name is None:
file_name = ""
return os.path.join(DATA_DIR, file_name)
# Functions related to get_module_names().
def _find_files(root_dir, should_include):
"""
Return a list of paths to all modules below the given directory.
Arguments:
should_include: a function that accepts a file path and returns True or False.
"""
paths = [] # Return value.
is_module = lambda path: path.endswith(".py")
# os.walk() is new in Python 2.3
# http://docs.python.org/library/os.html#os.walk
for dir_path, dir_names, file_names in os.walk(root_dir):
new_paths = [os.path.join(dir_path, file_name) for file_name in file_names]
new_paths = filter(is_module, new_paths)
new_paths = filter(should_include, new_paths)
paths.extend(new_paths)
return paths
def _make_module_names(package_dir, paths):
"""
Return a list of fully-qualified module names given a list of module paths.
"""
package_dir = os.path.abspath(package_dir)
package_name = os.path.split(package_dir)[1]
prefix_length = len(package_dir)
module_names = []
for path in paths:
path = os.path.abspath(path) # for example <path_to_package>/subpackage/module.py
rel_path = path[prefix_length:] # for example /subpackage/module.py
rel_path = os.path.splitext(rel_path)[0] # for example /subpackage/module
parts = []
while True:
(rel_path, tail) = os.path.split(rel_path)
if not tail:
break
parts.insert(0, tail)
# We now have, for example, ['subpackage', 'module'].
parts.insert(0, package_name)
module = ".".join(parts)
module_names.append(module)
return module_names
def get_module_names(package_dir=None, should_include=None):
"""
Return a list of fully-qualified module names in the given package.
"""
if package_dir is None:
package_dir = PACKAGE_DIR
if should_include is None:
should_include = lambda path: True
paths = _find_files(package_dir, should_include)
names = _make_module_names(package_dir, paths)
names.sort()
return names
class AssertStringMixin:
"""A unittest.TestCase mixin to check string equality."""
def assertString(self, actual, expected, format=None):
"""
Assert that the given strings are equal and have the same type.
Arguments:
format: a format string containing a single conversion specifier %s.
Defaults to "%s".
"""
if format is None:
format = "%s"
# Show both friendly and literal versions.
details = """String mismatch: %%s
Expected: \"""%s\"""
Actual: \"""%s\"""
Expected: %s
Actual: %s""" % (expected, actual, repr(expected), repr(actual))
def make_message(reason):
description = details % reason
return format % description
self.assertEqual(actual, expected, make_message("different characters"))
reason = "types different: %s != %s (actual)" % (repr(type(expected)), repr(type(actual)))
self.assertEqual(type(expected), type(actual), make_message(reason))
class AssertIsMixin:
"""A unittest.TestCase mixin adding assertIs()."""
# unittest.assertIs() is not available until Python 2.7:
# http://docs.python.org/library/unittest.html#unittest.TestCase.assertIsNone
def assertIs(self, first, second):
self.assertTrue(first is second, msg="%s is not %s" % (repr(first), repr(second)))
class AssertExceptionMixin:
"""A unittest.TestCase mixin adding assertException()."""
# unittest.assertRaisesRegexp() is not available until Python 2.7:
# http://docs.python.org/library/unittest.html#unittest.TestCase.assertRaisesRegexp
def assertException(self, exception_type, msg, callable, *args, **kwds):
try:
callable(*args, **kwds)
raise Exception("Expected exception: %s: %s" % (exception_type, repr(msg)))
except exception_type, err:
self.assertEqual(str(err), msg)
class SetupDefaults(object):
"""
Mix this class in to a unittest.TestCase for standard defaults.
This class allows for consistent test results across Python 2/3.
"""
def setup_defaults(self):
self.original_decode_errors = defaults.DECODE_ERRORS
self.original_file_encoding = defaults.FILE_ENCODING
self.original_string_encoding = defaults.STRING_ENCODING
defaults.DECODE_ERRORS = 'strict'
defaults.FILE_ENCODING = 'ascii'
defaults.STRING_ENCODING = 'ascii'
def teardown_defaults(self):
defaults.DECODE_ERRORS = self.original_decode_errors
defaults.FILE_ENCODING = self.original_file_encoding
defaults.STRING_ENCODING = self.original_string_encoding
class Attachable(object):
"""
A class that attaches all constructor named parameters as attributes.
For example--
>>> obj = Attachable(foo=42, size="of the universe")
>>> repr(obj)
"Attachable(foo=42, size='of the universe')"
>>> obj.foo
42
>>> obj.size
'of the universe'
"""
def __init__(self, **kwargs):
self.__args__ = kwargs
for arg, value in kwargs.iteritems():
setattr(self, arg, value)
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__,
", ".join("%s=%s" % (k, repr(v))
for k, v in self.__args__.iteritems()))

4
third_party/python/pystache/pystache/tests/data/__init__.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,4 @@
"""
TODO: add a docstring.
"""

Просмотреть файл

@ -0,0 +1 @@
ascii: abc

Просмотреть файл

@ -0,0 +1 @@
This file is used to test locate_path()'s search order.

Просмотреть файл

@ -0,0 +1,4 @@
"""
TODO: add a docstring.
"""

Просмотреть файл

@ -0,0 +1 @@
This file is used to test locate_path()'s search order.

Просмотреть файл

@ -0,0 +1 @@
Test template file

Просмотреть файл

@ -0,0 +1 @@
non-ascii: é

Просмотреть файл

@ -0,0 +1 @@
ascii: abc

Просмотреть файл

@ -0,0 +1 @@
Hello, {{to}}

21
third_party/python/pystache/pystache/tests/data/views.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,21 @@
# coding: utf-8
"""
TODO: add a docstring.
"""
from pystache import TemplateSpec
class SayHello(object):
def to(self):
return "World"
class SampleView(TemplateSpec):
pass
class NonAscii(TemplateSpec):
pass

94
third_party/python/pystache/pystache/tests/doctesting.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,94 @@
# coding: utf-8
"""
Exposes a get_doctests() function for the project's test harness.
"""
import doctest
import os
import pkgutil
import sys
import traceback
if sys.version_info >= (3,):
# Then pull in modules needed for 2to3 conversion. The modules
# below are not necessarily available in older versions of Python.
from lib2to3.main import main as lib2to3main # new in Python 2.6?
from shutil import copyfile
from pystache.tests.common import TEXT_DOCTEST_PATHS
from pystache.tests.common import get_module_names
# This module follows the guidance documented here:
#
# http://docs.python.org/library/doctest.html#unittest-api
#
def get_doctests(text_file_dir):
"""
Return a list of TestSuite instances for all doctests in the project.
Arguments:
text_file_dir: the directory in which to search for all text files
(i.e. non-module files) containing doctests.
"""
# Since module_relative is False in our calls to DocFileSuite below,
# paths should be OS-specific. See the following for more info--
#
# http://docs.python.org/library/doctest.html#doctest.DocFileSuite
#
paths = [os.path.normpath(os.path.join(text_file_dir, path)) for path in TEXT_DOCTEST_PATHS]
if sys.version_info >= (3,):
# Skip the README doctests in Python 3 for now because examples
# rendering to unicode do not give consistent results
# (e.g. 'foo' vs u'foo').
# paths = _convert_paths(paths)
paths = []
suites = []
for path in paths:
suite = doctest.DocFileSuite(path, module_relative=False)
suites.append(suite)
modules = get_module_names()
for module in modules:
suite = doctest.DocTestSuite(module)
suites.append(suite)
return suites
def _convert_2to3(path):
"""
Convert the given file, and return the path to the converted files.
"""
base, ext = os.path.splitext(path)
# For example, "README.temp2to3.rst".
new_path = "%s.temp2to3%s" % (base, ext)
copyfile(path, new_path)
args = ['--doctests_only', '--no-diffs', '--write', '--nobackups', new_path]
lib2to3main("lib2to3.fixes", args=args)
return new_path
def _convert_paths(paths):
"""
Convert the given files, and return the paths to the converted files.
"""
new_paths = []
for path in paths:
new_path = _convert_2to3(path)
new_paths.append(new_path)
return new_paths

Просмотреть файл

@ -0,0 +1,4 @@
"""
TODO: add a docstring.
"""

Просмотреть файл

@ -0,0 +1 @@
<h1>{{title}}{{! just something interesting... #or not... }}</h1>

10
third_party/python/pystache/pystache/tests/examples/comments.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,10 @@
"""
TODO: add a docstring.
"""
class Comments(object):
def title(self):
return "A Comedy of Errors"

Просмотреть файл

@ -0,0 +1,6 @@
<h1>{{ header }}</h1>
{{#list}}
<ul>
{{#item}}{{# current }}<li><strong>{{name}}</strong></li>
{{/ current }}{{#link}}<li><a href="{{url}}">{{name}}</a></li>
{{/link}}{{/item}}</ul>{{/list}}{{#empty}}<p>The list is empty.</p>{{/empty}}

26
third_party/python/pystache/pystache/tests/examples/complex.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,26 @@
"""
TODO: add a docstring.
"""
class Complex(object):
def header(self):
return "Colors"
def item(self):
items = []
items.append({ 'name': 'red', 'current': True, 'url': '#Red' })
items.append({ 'name': 'green', 'link': True, 'url': '#Green' })
items.append({ 'name': 'blue', 'link': True, 'url': '#Blue' })
return items
def list(self):
return not self.empty()
def empty(self):
return len(self.item()) == 0
def empty_list(self):
return [];

Просмотреть файл

@ -0,0 +1,6 @@
{{=<% %>=}}
* <% first %>
<%=| |=%>
* | second |
|={{ }}=|
* {{ third }}

Просмотреть файл

@ -0,0 +1,16 @@
"""
TODO: add a docstring.
"""
class Delimiters(object):
def first(self):
return "It worked the first time."
def second(self):
return "And it worked the second time."
def third(self):
return "Then, surprisingly, it worked the third time."

Просмотреть файл

@ -0,0 +1,3 @@
{{#t}}* first{{/t}}
* {{two}}
{{#t}}* third{{/t}}

Просмотреть файл

@ -0,0 +1,13 @@
"""
TODO: add a docstring.
"""
class DoubleSection(object):
def t(self):
return True
def two(self):
return "second"

Просмотреть файл

@ -0,0 +1 @@
<h1>{{title}}</h1>

10
third_party/python/pystache/pystache/tests/examples/escaped.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,10 @@
"""
TODO: add a docstring.
"""
class Escaped(object):
def title(self):
return "Bear > Shark"

Просмотреть файл

@ -0,0 +1 @@
Again, {{title}}!

Просмотреть файл

@ -0,0 +1 @@
## Again, {{title}}! ##

Просмотреть файл

@ -0,0 +1 @@
{{^f}}one{{/f}}, {{ two }}, {{^f}}three{{/f}}{{^t}}, four!{{/t}}{{^empty_list}}, empty list{{/empty_list}}{{^populated_list}}, shouldn't see me{{/populated_list}}

33
third_party/python/pystache/pystache/tests/examples/inverted.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,33 @@
"""
TODO: add a docstring.
"""
from pystache import TemplateSpec
class Inverted(object):
def t(self):
return True
def f(self):
return False
def two(self):
return 'two'
def empty_list(self):
return []
def populated_list(self):
return ['some_value']
class InvertedLists(Inverted, TemplateSpec):
template_name = 'inverted'
def t(self):
return [0, 1, 2]
def f(self):
return []

Просмотреть файл

@ -0,0 +1 @@
{{#replace_foo_with_bar}}foo != bar. oh, it does!{{/replace_foo_with_bar}}

38
third_party/python/pystache/pystache/tests/examples/lambdas.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,38 @@
"""
TODO: add a docstring.
"""
from pystache import TemplateSpec
def rot(s, n=13):
r = ""
for c in s:
cc = c
if cc.isalpha():
cc = cc.lower()
o = ord(cc)
ro = (o+n) % 122
if ro == 0: ro = 122
if ro < 97: ro += 96
cc = chr(ro)
r = ''.join((r,cc))
return r
def replace(subject, this='foo', with_this='bar'):
return subject.replace(this, with_this)
# This class subclasses TemplateSpec because at least one unit test
# sets the template attribute.
class Lambdas(TemplateSpec):
def replace_foo_with_bar(self, text=None):
return replace
def rot13(self, text=None):
return rot
def sort(self, text=None):
return lambda text: ''.join(sorted(text))

Просмотреть файл

@ -0,0 +1 @@
Looping partial {{item}}!

Просмотреть файл

@ -0,0 +1 @@
{{#foo}}{{thing1}} and {{thing2}} and {{outer_thing}}{{/foo}}{{^foo}}Not foo!{{/foo}}

Просмотреть файл

@ -0,0 +1,32 @@
"""
TODO: add a docstring.
"""
from pystache import TemplateSpec
class NestedContext(TemplateSpec):
def __init__(self, renderer):
self.renderer = renderer
def _context_get(self, key):
return self.renderer.context.get(key)
def outer_thing(self):
return "two"
def foo(self):
return {'thing1': 'one', 'thing2': 'foo'}
def derp(self):
return [{'inner': 'car'}]
def herp(self):
return [{'outer': 'car'}]
def nested_context_in_view(self):
if self._context_get('outer') == self._context_get('inner'):
return 'it works!'
return ''

Просмотреть файл

@ -0,0 +1 @@
{{>simple}}

Просмотреть файл

@ -0,0 +1 @@
{{#rot13}}abcdefghijklm{{/rot13}}

Просмотреть файл

@ -0,0 +1 @@
{{>partial_with_lambda}}{{#rot13}}abcdefghijklm{{/rot13}}

Просмотреть файл

@ -0,0 +1,12 @@
"""
TODO: add a docstring.
"""
from pystache.tests.examples.lambdas import rot
class PartialsWithLambdas(object):
def rot(self):
return rot

9
third_party/python/pystache/pystache/tests/examples/readme.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,9 @@
"""
TODO: add a docstring.
"""
class SayHello(object):
def to(self):
return "Pizza"

Просмотреть файл

@ -0,0 +1 @@
Hello, {{to}}!

Просмотреть файл

@ -0,0 +1 @@
Hi {{thing}}!{{blank}}

15
third_party/python/pystache/pystache/tests/examples/simple.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,15 @@
"""
TODO: add a docstring.
"""
from pystache import TemplateSpec
class Simple(TemplateSpec):
def thing(self):
return "pizza"
def blank(self):
return ''

Просмотреть файл

@ -0,0 +1 @@
No tags...

Просмотреть файл

@ -0,0 +1,2 @@
<h1>{{title}}</h1>
{{>inner_partial}}

Просмотреть файл

@ -0,0 +1,27 @@
"""
TODO: add a docstring.
"""
from pystache import TemplateSpec
class TemplatePartial(TemplateSpec):
def __init__(self, renderer):
self.renderer = renderer
def _context_get(self, key):
return self.renderer.context.get(key)
def title(self):
return "Welcome"
def title_bars(self):
return '-' * len(self.title())
def looping(self):
return [{'item': 'one'}, {'item': 'two'}, {'item': 'three'}]
def thing(self):
return self._context_get('prop')

Просмотреть файл

@ -0,0 +1,4 @@
{{title}}
{{title_bars}}
{{>inner_partial}}

Просмотреть файл

@ -0,0 +1 @@
<h1>{{{title}}}</h1>

Просмотреть файл

@ -0,0 +1,10 @@
"""
TODO: add a docstring.
"""
class Unescaped(object):
def title(self):
return "Bear > Shark"

Просмотреть файл

@ -0,0 +1 @@
abcdé

Просмотреть файл

@ -0,0 +1,14 @@
"""
TODO: add a docstring.
"""
from pystache import TemplateSpec
class UnicodeInput(TemplateSpec):
template_encoding = 'utf8'
def age(self):
return 156

Просмотреть файл

@ -0,0 +1 @@
<p>Name: {{name}}</p>

Просмотреть файл

@ -0,0 +1,11 @@
# encoding: utf-8
"""
TODO: add a docstring.
"""
class UnicodeOutput(object):
def name(self):
return u'Henri Poincaré'

190
third_party/python/pystache/pystache/tests/main.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,190 @@
# coding: utf-8
"""
Exposes a main() function that runs all tests in the project.
This module is for our test console script.
"""
import os
import sys
import unittest
from unittest import TestCase, TestProgram
import pystache
from pystache.tests.common import PACKAGE_DIR, PROJECT_DIR, UNITTEST_FILE_PREFIX
from pystache.tests.common import get_module_names, get_spec_test_dir
from pystache.tests.doctesting import get_doctests
from pystache.tests.spectesting import get_spec_tests
# If this command option is present, then the spec test and doctest directories
# will be inserted if not provided.
FROM_SOURCE_OPTION = "--from-source"
def make_extra_tests(text_doctest_dir, spec_test_dir):
tests = []
if text_doctest_dir is not None:
doctest_suites = get_doctests(text_doctest_dir)
tests.extend(doctest_suites)
if spec_test_dir is not None:
spec_testcases = get_spec_tests(spec_test_dir)
tests.extend(spec_testcases)
return unittest.TestSuite(tests)
def make_test_program_class(extra_tests):
"""
Return a subclass of unittest.TestProgram.
"""
# The function unittest.main() is an alias for unittest.TestProgram's
# constructor. TestProgram's constructor does the following:
#
# 1. calls self.parseArgs(argv),
# 2. which in turn calls self.createTests().
# 3. then the constructor calls self.runTests().
#
# The createTests() method sets the self.test attribute by calling one
# of self.testLoader's "loadTests" methods. Each loadTest method returns
# a unittest.TestSuite instance. Thus, self.test is set to a TestSuite
# instance prior to calling runTests().
class PystacheTestProgram(TestProgram):
"""
Instantiating an instance of this class runs all tests.
"""
def createTests(self):
"""
Load tests and set self.test to a unittest.TestSuite instance
Compare--
http://docs.python.org/library/unittest.html#unittest.TestSuite
"""
super(PystacheTestProgram, self).createTests()
self.test.addTests(extra_tests)
return PystacheTestProgram
# Do not include "test" in this function's name to avoid it getting
# picked up by nosetests.
def main(sys_argv):
"""
Run all tests in the project.
Arguments:
sys_argv: a reference to sys.argv.
"""
# TODO: use logging module
print "pystache: running tests: argv: %s" % repr(sys_argv)
should_source_exist = False
spec_test_dir = None
project_dir = None
if len(sys_argv) > 1 and sys_argv[1] == FROM_SOURCE_OPTION:
# This usually means the test_pystache.py convenience script
# in the source directory was run.
should_source_exist = True
sys_argv.pop(1)
try:
# TODO: use optparse command options instead.
project_dir = sys_argv[1]
sys_argv.pop(1)
except IndexError:
if should_source_exist:
project_dir = PROJECT_DIR
try:
# TODO: use optparse command options instead.
spec_test_dir = sys_argv[1]
sys_argv.pop(1)
except IndexError:
if project_dir is not None:
# Then auto-detect the spec test directory.
_spec_test_dir = get_spec_test_dir(project_dir)
if not os.path.exists(_spec_test_dir):
# Then the user is probably using a downloaded sdist rather
# than a repository clone (since the sdist does not include
# the spec test directory).
print("pystache: skipping spec tests: spec test directory "
"not found")
else:
spec_test_dir = _spec_test_dir
if len(sys_argv) <= 1 or sys_argv[-1].startswith("-"):
# Then no explicit module or test names were provided, so
# auto-detect all unit tests.
module_names = _discover_test_modules(PACKAGE_DIR)
sys_argv.extend(module_names)
if project_dir is not None:
# Add the current module for unit tests contained here (e.g.
# to include SetupTests).
sys_argv.append(__name__)
SetupTests.project_dir = project_dir
extra_tests = make_extra_tests(project_dir, spec_test_dir)
test_program_class = make_test_program_class(extra_tests)
# We pass None for the module because we do not want the unittest
# module to resolve module names relative to a given module.
# (This would require importing all of the unittest modules from
# this module.) See the loadTestsFromName() method of the
# unittest.TestLoader class for more details on this parameter.
test_program_class(argv=sys_argv, module=None)
# No need to return since unitttest.main() exits.
def _discover_test_modules(package_dir):
"""
Discover and return a sorted list of the names of unit-test modules.
"""
def is_unittest_module(path):
file_name = os.path.basename(path)
return file_name.startswith(UNITTEST_FILE_PREFIX)
names = get_module_names(package_dir=package_dir, should_include=is_unittest_module)
# This is a sanity check to ensure that the unit-test discovery
# methods are working.
if len(names) < 1:
raise Exception("No unit-test modules found--\n in %s" % package_dir)
return names
class SetupTests(TestCase):
"""Tests about setup.py."""
project_dir = None
def test_version(self):
"""
Test that setup.py's version matches the package's version.
"""
original_path = list(sys.path)
sys.path.insert(0, self.project_dir)
try:
from setup import VERSION
self.assertEqual(VERSION, pystache.__version__)
finally:
sys.path = original_path

285
third_party/python/pystache/pystache/tests/spectesting.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,285 @@
# coding: utf-8
"""
Exposes a get_spec_tests() function for the project's test harness.
Creates a unittest.TestCase for the tests defined in the mustache spec.
"""
# TODO: this module can be cleaned up somewhat.
# TODO: move all of this code to pystache/tests/spectesting.py and
# have it expose a get_spec_tests(spec_test_dir) function.
FILE_ENCODING = 'utf-8' # the encoding of the spec test files.
yaml = None
try:
# We try yaml first since it is more convenient when adding and modifying
# test cases by hand (since the YAML is human-readable and is the master
# from which the JSON format is generated).
import yaml
except ImportError:
try:
import json
except:
# The module json is not available prior to Python 2.6, whereas
# simplejson is. The simplejson package dropped support for Python 2.4
# in simplejson v2.1.0, so Python 2.4 requires a simplejson install
# older than the most recent version.
try:
import simplejson as json
except ImportError:
# Raise an error with a type different from ImportError as a hack around
# this issue:
# http://bugs.python.org/issue7559
from sys import exc_info
ex_type, ex_value, tb = exc_info()
new_ex = Exception("%s: %s" % (ex_type.__name__, ex_value))
raise new_ex.__class__, new_ex, tb
file_extension = 'json'
parser = json
else:
file_extension = 'yml'
parser = yaml
import codecs
import glob
import os.path
import unittest
import pystache
from pystache import common
from pystache.renderer import Renderer
from pystache.tests.common import AssertStringMixin
def get_spec_tests(spec_test_dir):
"""
Return a list of unittest.TestCase instances.
"""
# TODO: use logging module instead.
print "pystache: spec tests: using %s" % _get_parser_info()
cases = []
# Make this absolute for easier diagnosis in case of error.
spec_test_dir = os.path.abspath(spec_test_dir)
spec_paths = glob.glob(os.path.join(spec_test_dir, '*.%s' % file_extension))
for path in spec_paths:
new_cases = _read_spec_tests(path)
cases.extend(new_cases)
# Store this as a value so that CheckSpecTestsFound is not checking
# a reference to cases that contains itself.
spec_test_count = len(cases)
# This test case lets us alert the user that spec tests are missing.
class CheckSpecTestsFound(unittest.TestCase):
def runTest(self):
if spec_test_count > 0:
return
raise Exception("Spec tests not found--\n in %s\n"
" Consult the README file on how to add the Mustache spec tests." % repr(spec_test_dir))
case = CheckSpecTestsFound()
cases.append(case)
return cases
def _get_parser_info():
return "%s (version %s)" % (parser.__name__, parser.__version__)
def _read_spec_tests(path):
"""
Return a list of unittest.TestCase instances.
"""
b = common.read(path)
u = unicode(b, encoding=FILE_ENCODING)
spec_data = parse(u)
tests = spec_data['tests']
cases = []
for data in tests:
case = _deserialize_spec_test(data, path)
cases.append(case)
return cases
# TODO: simplify the implementation of this function.
def _convert_children(node):
"""
Recursively convert to functions all "code strings" below the node.
This function is needed only for the json format.
"""
if not isinstance(node, (list, dict)):
# Then there is nothing to iterate over and recurse.
return
if isinstance(node, list):
for child in node:
_convert_children(child)
return
# Otherwise, node is a dict, so attempt the conversion.
for key in node.keys():
val = node[key]
if not isinstance(val, dict) or val.get('__tag__') != 'code':
_convert_children(val)
continue
# Otherwise, we are at a "leaf" node.
val = eval(val['python'])
node[key] = val
continue
def _deserialize_spec_test(data, file_path):
"""
Return a unittest.TestCase instance representing a spec test.
Arguments:
data: the dictionary of attributes for a single test.
"""
context = data['data']
description = data['desc']
# PyYAML seems to leave ASCII strings as byte strings.
expected = unicode(data['expected'])
# TODO: switch to using dict.get().
partials = data.has_key('partials') and data['partials'] or {}
template = data['template']
test_name = data['name']
_convert_children(context)
test_case = _make_spec_test(expected, template, context, partials, description, test_name, file_path)
return test_case
def _make_spec_test(expected, template, context, partials, description, test_name, file_path):
"""
Return a unittest.TestCase instance representing a spec test.
"""
file_name = os.path.basename(file_path)
test_method_name = "Mustache spec (%s): %s" % (file_name, repr(test_name))
# We subclass SpecTestBase in order to control the test method name (for
# the purposes of improved reporting).
class SpecTest(SpecTestBase):
pass
def run_test(self):
self._runTest()
# TODO: should we restore this logic somewhere?
# If we don't convert unicode to str, we get the following error:
# "TypeError: __name__ must be set to a string object"
# test.__name__ = str(name)
setattr(SpecTest, test_method_name, run_test)
case = SpecTest(test_method_name)
case._context = context
case._description = description
case._expected = expected
case._file_path = file_path
case._partials = partials
case._template = template
case._test_name = test_name
return case
def parse(u):
"""
Parse the contents of a spec test file, and return a dict.
Arguments:
u: a unicode string.
"""
# TODO: find a cleaner mechanism for choosing between the two.
if yaml is None:
# Then use json.
# The only way to get the simplejson module to return unicode strings
# is to pass it unicode. See, for example--
#
# http://code.google.com/p/simplejson/issues/detail?id=40
#
# and the documentation of simplejson.loads():
#
# "If s is a str then decoded JSON strings that contain only ASCII
# characters may be parsed as str for performance and memory reasons.
# If your code expects only unicode the appropriate solution is
# decode s to unicode prior to calling loads."
#
return json.loads(u)
# Otherwise, yaml.
def code_constructor(loader, node):
value = loader.construct_mapping(node)
return eval(value['python'], {})
yaml.add_constructor(u'!code', code_constructor)
return yaml.load(u)
class SpecTestBase(unittest.TestCase, AssertStringMixin):
def _runTest(self):
context = self._context
description = self._description
expected = self._expected
file_path = self._file_path
partials = self._partials
template = self._template
test_name = self._test_name
renderer = Renderer(partials=partials)
actual = renderer.render(template, context)
# We need to escape the strings that occur in our format string because
# they can contain % symbols, for example (in delimiters.yml)--
#
# "template: '{{=<% %>=}}(<%text%>)'"
#
def escape(s):
return s.replace("%", "%%")
parser_info = _get_parser_info()
subs = [repr(test_name), description, os.path.abspath(file_path),
template, repr(context), parser_info]
subs = tuple([escape(sub) for sub in subs])
# We include the parsing module version info to help with troubleshooting
# yaml/json/simplejson issues.
message = """%s: %s
File: %s
Template: \"""%s\"""
Context: %s
%%s
[using %s]
""" % subs
self.assertString(actual, expected, format=message)

36
third_party/python/pystache/pystache/tests/test___init__.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,36 @@
# coding: utf-8
"""
Tests of __init__.py.
"""
# Calling "import *" is allowed only at the module level.
GLOBALS_INITIAL = globals().keys()
from pystache import *
GLOBALS_PYSTACHE_IMPORTED = globals().keys()
import unittest
import pystache
class InitTests(unittest.TestCase):
def test___all__(self):
"""
Test that "from pystache import *" works as expected.
"""
actual = set(GLOBALS_PYSTACHE_IMPORTED) - set(GLOBALS_INITIAL)
expected = set(['parse', 'render', 'Renderer', 'TemplateSpec', 'GLOBALS_INITIAL'])
self.assertEqual(actual, expected)
def test_version_defined(self):
"""
Test that pystache.__version__ is set.
"""
actual_version = pystache.__version__
self.assertTrue(actual_version)

45
third_party/python/pystache/pystache/tests/test_commands.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,45 @@
# coding: utf-8
"""
Unit tests of commands.py.
"""
import sys
import unittest
from pystache.commands.render import main
ORIGINAL_STDOUT = sys.stdout
class MockStdout(object):
def __init__(self):
self.output = ""
def write(self, str):
self.output += str
class CommandsTestCase(unittest.TestCase):
def setUp(self):
sys.stdout = MockStdout()
def callScript(self, template, context):
argv = ['pystache', template, context]
main(argv)
return sys.stdout.output
def testMainSimple(self):
"""
Test a simple command-line case.
"""
actual = self.callScript("Hi {{thing}}", '{"thing": "world"}')
self.assertEqual(actual, u"Hi world\n")
def tearDown(self):
sys.stdout = ORIGINAL_STDOUT

499
third_party/python/pystache/pystache/tests/test_context.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,499 @@
# coding: utf-8
"""
Unit tests of context.py.
"""
from datetime import datetime
import unittest
from pystache.context import _NOT_FOUND, _get_value, KeyNotFoundError, ContextStack
from pystache.tests.common import AssertIsMixin, AssertStringMixin, AssertExceptionMixin, Attachable
class SimpleObject(object):
"""A sample class that does not define __getitem__()."""
def __init__(self):
self.foo = "bar"
def foo_callable(self):
return "called..."
class DictLike(object):
"""A sample class that implements __getitem__() and __contains__()."""
def __init__(self):
self._dict = {'foo': 'bar'}
self.fuzz = 'buzz'
def __contains__(self, key):
return key in self._dict
def __getitem__(self, key):
return self._dict[key]
class GetValueTestCase(unittest.TestCase, AssertIsMixin):
"""Test context._get_value()."""
def assertNotFound(self, item, key):
"""
Assert that a call to _get_value() returns _NOT_FOUND.
"""
self.assertIs(_get_value(item, key), _NOT_FOUND)
### Case: the item is a dictionary.
def test_dictionary__key_present(self):
"""
Test getting a key from a dictionary.
"""
item = {"foo": "bar"}
self.assertEqual(_get_value(item, "foo"), "bar")
def test_dictionary__callable_not_called(self):
"""
Test that callable values are returned as-is (and in particular not called).
"""
def foo_callable(self):
return "bar"
item = {"foo": foo_callable}
self.assertNotEqual(_get_value(item, "foo"), "bar")
self.assertTrue(_get_value(item, "foo") is foo_callable)
def test_dictionary__key_missing(self):
"""
Test getting a missing key from a dictionary.
"""
item = {}
self.assertNotFound(item, "missing")
def test_dictionary__attributes_not_checked(self):
"""
Test that dictionary attributes are not checked.
"""
item = {1: 2, 3: 4}
# I was not able to find a "public" attribute of dict that is
# the same across Python 2/3.
attr_name = "__len__"
self.assertEqual(getattr(item, attr_name)(), 2)
self.assertNotFound(item, attr_name)
def test_dictionary__dict_subclass(self):
"""
Test that subclasses of dict are treated as dictionaries.
"""
class DictSubclass(dict): pass
item = DictSubclass()
item["foo"] = "bar"
self.assertEqual(_get_value(item, "foo"), "bar")
### Case: the item is an object.
def test_object__attribute_present(self):
"""
Test getting an attribute from an object.
"""
item = SimpleObject()
self.assertEqual(_get_value(item, "foo"), "bar")
def test_object__attribute_missing(self):
"""
Test getting a missing attribute from an object.
"""
item = SimpleObject()
self.assertNotFound(item, "missing")
def test_object__attribute_is_callable(self):
"""
Test getting a callable attribute from an object.
"""
item = SimpleObject()
self.assertEqual(_get_value(item, "foo_callable"), "called...")
def test_object__non_built_in_type(self):
"""
Test getting an attribute from an instance of a type that isn't built-in.
"""
item = datetime(2012, 1, 2)
self.assertEqual(_get_value(item, "day"), 2)
def test_object__dict_like(self):
"""
Test getting a key from a dict-like object (an object that implements '__getitem__').
"""
item = DictLike()
self.assertEqual(item["foo"], "bar")
self.assertNotFound(item, "foo")
def test_object__property__raising_exception(self):
"""
Test getting a property that raises an exception.
"""
class Foo(object):
@property
def bar(self):
return 1
@property
def baz(self):
raise ValueError("test")
foo = Foo()
self.assertEqual(_get_value(foo, 'bar'), 1)
self.assertNotFound(foo, 'missing')
self.assertRaises(ValueError, _get_value, foo, 'baz')
### Case: the item is an instance of a built-in type.
def test_built_in_type__integer(self):
"""
Test getting from an integer.
"""
class MyInt(int): pass
cust_int = MyInt(10)
pure_int = 10
# We have to use a built-in method like __neg__ because "public"
# attributes like "real" were not added to Python until Python 2.6,
# when the numeric type hierarchy was added:
#
# http://docs.python.org/library/numbers.html
#
self.assertEqual(cust_int.__neg__(), -10)
self.assertEqual(pure_int.__neg__(), -10)
self.assertEqual(_get_value(cust_int, '__neg__'), -10)
self.assertNotFound(pure_int, '__neg__')
def test_built_in_type__string(self):
"""
Test getting from a string.
"""
class MyStr(str): pass
item1 = MyStr('abc')
item2 = 'abc'
self.assertEqual(item1.upper(), 'ABC')
self.assertEqual(item2.upper(), 'ABC')
self.assertEqual(_get_value(item1, 'upper'), 'ABC')
self.assertNotFound(item2, 'upper')
def test_built_in_type__list(self):
"""
Test getting from a list.
"""
class MyList(list): pass
item1 = MyList([1, 2, 3])
item2 = [1, 2, 3]
self.assertEqual(item1.pop(), 3)
self.assertEqual(item2.pop(), 3)
self.assertEqual(_get_value(item1, 'pop'), 2)
self.assertNotFound(item2, 'pop')
class ContextStackTestCase(unittest.TestCase, AssertIsMixin, AssertStringMixin,
AssertExceptionMixin):
"""
Test the ContextStack class.
"""
def test_init__no_elements(self):
"""
Check that passing nothing to __init__() raises no exception.
"""
context = ContextStack()
def test_init__many_elements(self):
"""
Check that passing more than two items to __init__() raises no exception.
"""
context = ContextStack({}, {}, {})
def test__repr(self):
context = ContextStack()
self.assertEqual(repr(context), 'ContextStack()')
context = ContextStack({'foo': 'bar'})
self.assertEqual(repr(context), "ContextStack({'foo': 'bar'},)")
context = ContextStack({'foo': 'bar'}, {'abc': 123})
self.assertEqual(repr(context), "ContextStack({'foo': 'bar'}, {'abc': 123})")
def test__str(self):
context = ContextStack()
self.assertEqual(str(context), 'ContextStack()')
context = ContextStack({'foo': 'bar'})
self.assertEqual(str(context), "ContextStack({'foo': 'bar'},)")
context = ContextStack({'foo': 'bar'}, {'abc': 123})
self.assertEqual(str(context), "ContextStack({'foo': 'bar'}, {'abc': 123})")
## Test the static create() method.
def test_create__dictionary(self):
"""
Test passing a dictionary.
"""
context = ContextStack.create({'foo': 'bar'})
self.assertEqual(context.get('foo'), 'bar')
def test_create__none(self):
"""
Test passing None.
"""
context = ContextStack.create({'foo': 'bar'}, None)
self.assertEqual(context.get('foo'), 'bar')
def test_create__object(self):
"""
Test passing an object.
"""
class Foo(object):
foo = 'bar'
context = ContextStack.create(Foo())
self.assertEqual(context.get('foo'), 'bar')
def test_create__context(self):
"""
Test passing a ContextStack instance.
"""
obj = ContextStack({'foo': 'bar'})
context = ContextStack.create(obj)
self.assertEqual(context.get('foo'), 'bar')
def test_create__kwarg(self):
"""
Test passing a keyword argument.
"""
context = ContextStack.create(foo='bar')
self.assertEqual(context.get('foo'), 'bar')
def test_create__precedence_positional(self):
"""
Test precedence of positional arguments.
"""
context = ContextStack.create({'foo': 'bar'}, {'foo': 'buzz'})
self.assertEqual(context.get('foo'), 'buzz')
def test_create__precedence_keyword(self):
"""
Test precedence of keyword arguments.
"""
context = ContextStack.create({'foo': 'bar'}, foo='buzz')
self.assertEqual(context.get('foo'), 'buzz')
## Test the get() method.
def test_get__single_dot(self):
"""
Test getting a single dot (".").
"""
context = ContextStack("a", "b")
self.assertEqual(context.get("."), "b")
def test_get__single_dot__missing(self):
"""
Test getting a single dot (".") with an empty context stack.
"""
context = ContextStack()
self.assertException(KeyNotFoundError, "Key '.' not found: empty context stack", context.get, ".")
def test_get__key_present(self):
"""
Test getting a key.
"""
context = ContextStack({"foo": "bar"})
self.assertEqual(context.get("foo"), "bar")
def test_get__key_missing(self):
"""
Test getting a missing key.
"""
context = ContextStack()
self.assertException(KeyNotFoundError, "Key 'foo' not found: first part", context.get, "foo")
def test_get__precedence(self):
"""
Test that get() respects the order of precedence (later items first).
"""
context = ContextStack({"foo": "bar"}, {"foo": "buzz"})
self.assertEqual(context.get("foo"), "buzz")
def test_get__fallback(self):
"""
Check that first-added stack items are queried on context misses.
"""
context = ContextStack({"fuzz": "buzz"}, {"foo": "bar"})
self.assertEqual(context.get("fuzz"), "buzz")
def test_push(self):
"""
Test push().
"""
key = "foo"
context = ContextStack({key: "bar"})
self.assertEqual(context.get(key), "bar")
context.push({key: "buzz"})
self.assertEqual(context.get(key), "buzz")
def test_pop(self):
"""
Test pop().
"""
key = "foo"
context = ContextStack({key: "bar"}, {key: "buzz"})
self.assertEqual(context.get(key), "buzz")
item = context.pop()
self.assertEqual(item, {"foo": "buzz"})
self.assertEqual(context.get(key), "bar")
def test_top(self):
key = "foo"
context = ContextStack({key: "bar"}, {key: "buzz"})
self.assertEqual(context.get(key), "buzz")
top = context.top()
self.assertEqual(top, {"foo": "buzz"})
# Make sure calling top() didn't remove the item from the stack.
self.assertEqual(context.get(key), "buzz")
def test_copy(self):
key = "foo"
original = ContextStack({key: "bar"}, {key: "buzz"})
self.assertEqual(original.get(key), "buzz")
new = original.copy()
# Confirm that the copy behaves the same.
self.assertEqual(new.get(key), "buzz")
# Change the copy, and confirm it is changed.
new.pop()
self.assertEqual(new.get(key), "bar")
# Confirm the original is unchanged.
self.assertEqual(original.get(key), "buzz")
def test_dot_notation__dict(self):
name = "foo.bar"
stack = ContextStack({"foo": {"bar": "baz"}})
self.assertEqual(stack.get(name), "baz")
# Works all the way down
name = "a.b.c.d.e.f.g"
stack = ContextStack({"a": {"b": {"c": {"d": {"e": {"f": {"g": "w00t!"}}}}}}})
self.assertEqual(stack.get(name), "w00t!")
def test_dot_notation__user_object(self):
name = "foo.bar"
stack = ContextStack({"foo": Attachable(bar="baz")})
self.assertEqual(stack.get(name), "baz")
# Works on multiple levels, too
name = "a.b.c.d.e.f.g"
A = Attachable
stack = ContextStack({"a": A(b=A(c=A(d=A(e=A(f=A(g="w00t!"))))))})
self.assertEqual(stack.get(name), "w00t!")
def test_dot_notation__mixed_dict_and_obj(self):
name = "foo.bar.baz.bak"
stack = ContextStack({"foo": Attachable(bar={"baz": Attachable(bak=42)})})
self.assertEqual(stack.get(name), 42)
def test_dot_notation__missing_attr_or_key(self):
name = "foo.bar.baz.bak"
stack = ContextStack({"foo": {"bar": {}}})
self.assertException(KeyNotFoundError, "Key 'foo.bar.baz.bak' not found: missing 'baz'", stack.get, name)
stack = ContextStack({"foo": Attachable(bar=Attachable())})
self.assertException(KeyNotFoundError, "Key 'foo.bar.baz.bak' not found: missing 'baz'", stack.get, name)
def test_dot_notation__missing_part_terminates_search(self):
"""
Test that dotted name resolution terminates on a later part not found.
Check that if a later dotted name part is not found in the result from
the former resolution, then name resolution terminates rather than
starting the search over with the next element of the context stack.
From the spec (interpolation section)--
5) If any name parts were retained in step 1, each should be resolved
against a context stack containing only the result from the former
resolution. If any part fails resolution, the result should be considered
falsey, and should interpolate as the empty string.
This test case is equivalent to the test case in the following pull
request:
https://github.com/mustache/spec/pull/48
"""
stack = ContextStack({'a': {'b': 'A.B'}}, {'a': 'A'})
self.assertEqual(stack.get('a'), 'A')
self.assertException(KeyNotFoundError, "Key 'a.b' not found: missing 'b'", stack.get, "a.b")
stack.pop()
self.assertEqual(stack.get('a.b'), 'A.B')
def test_dot_notation__autocall(self):
name = "foo.bar.baz"
# When any element in the path is callable, it should be automatically invoked
stack = ContextStack({"foo": Attachable(bar=Attachable(baz=lambda: "Called!"))})
self.assertEqual(stack.get(name), "Called!")
class Foo(object):
def bar(self):
return Attachable(baz='Baz')
stack = ContextStack({"foo": Foo()})
self.assertEqual(stack.get(name), "Baz")

68
third_party/python/pystache/pystache/tests/test_defaults.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,68 @@
# coding: utf-8
"""
Unit tests for defaults.py.
"""
import unittest
import pystache
from pystache.tests.common import AssertStringMixin
# TODO: make sure each default has at least one test.
class DefaultsConfigurableTestCase(unittest.TestCase, AssertStringMixin):
"""Tests that the user can change the defaults at runtime."""
# TODO: switch to using a context manager after 2.4 is deprecated.
def setUp(self):
"""Save the defaults."""
defaults = [
'DECODE_ERRORS', 'DELIMITERS',
'FILE_ENCODING', 'MISSING_TAGS',
'SEARCH_DIRS', 'STRING_ENCODING',
'TAG_ESCAPE', 'TEMPLATE_EXTENSION'
]
self.saved = {}
for e in defaults:
self.saved[e] = getattr(pystache.defaults, e)
def tearDown(self):
for key, value in self.saved.items():
setattr(pystache.defaults, key, value)
def test_tag_escape(self):
"""Test that changes to defaults.TAG_ESCAPE take effect."""
template = u"{{foo}}"
context = {'foo': '<'}
actual = pystache.render(template, context)
self.assertString(actual, u"&lt;")
pystache.defaults.TAG_ESCAPE = lambda u: u
actual = pystache.render(template, context)
self.assertString(actual, u"<")
def test_delimiters(self):
"""Test that changes to defaults.DELIMITERS take effect."""
template = u"[[foo]]{{foo}}"
context = {'foo': 'FOO'}
actual = pystache.render(template, context)
self.assertString(actual, u"[[foo]]FOO")
pystache.defaults.DELIMITERS = ('[[', ']]')
actual = pystache.render(template, context)
self.assertString(actual, u"FOO{{foo}}")
def test_missing_tags(self):
"""Test that changes to defaults.MISSING_TAGS take effect."""
template = u"{{foo}}"
context = {}
actual = pystache.render(template, context)
self.assertString(actual, u"")
pystache.defaults.MISSING_TAGS = 'strict'
self.assertRaises(pystache.context.KeyNotFoundError,
pystache.render, template, context)

106
third_party/python/pystache/pystache/tests/test_examples.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,106 @@
# encoding: utf-8
"""
TODO: add a docstring.
"""
import unittest
from examples.comments import Comments
from examples.double_section import DoubleSection
from examples.escaped import Escaped
from examples.unescaped import Unescaped
from examples.template_partial import TemplatePartial
from examples.delimiters import Delimiters
from examples.unicode_output import UnicodeOutput
from examples.unicode_input import UnicodeInput
from examples.nested_context import NestedContext
from pystache import Renderer
from pystache.tests.common import EXAMPLES_DIR
from pystache.tests.common import AssertStringMixin
class TestView(unittest.TestCase, AssertStringMixin):
def _assert(self, obj, expected):
renderer = Renderer()
actual = renderer.render(obj)
self.assertString(actual, expected)
def test_comments(self):
self._assert(Comments(), u"<h1>A Comedy of Errors</h1>")
def test_double_section(self):
self._assert(DoubleSection(), u"* first\n* second\n* third")
def test_unicode_output(self):
renderer = Renderer()
actual = renderer.render(UnicodeOutput())
self.assertString(actual, u'<p>Name: Henri Poincaré</p>')
def test_unicode_input(self):
renderer = Renderer()
actual = renderer.render(UnicodeInput())
self.assertString(actual, u'abcdé')
def test_escaping(self):
self._assert(Escaped(), u"<h1>Bear &gt; Shark</h1>")
def test_literal(self):
renderer = Renderer()
actual = renderer.render(Unescaped())
self.assertString(actual, u"<h1>Bear > Shark</h1>")
def test_template_partial(self):
renderer = Renderer(search_dirs=EXAMPLES_DIR)
actual = renderer.render(TemplatePartial(renderer=renderer))
self.assertString(actual, u"""<h1>Welcome</h1>
Again, Welcome!""")
def test_template_partial_extension(self):
renderer = Renderer(search_dirs=EXAMPLES_DIR, file_extension='txt')
view = TemplatePartial(renderer=renderer)
actual = renderer.render(view)
self.assertString(actual, u"""Welcome
-------
## Again, Welcome! ##""")
def test_delimiters(self):
renderer = Renderer()
actual = renderer.render(Delimiters())
self.assertString(actual, u"""\
* It worked the first time.
* And it worked the second time.
* Then, surprisingly, it worked the third time.
""")
def test_nested_context(self):
renderer = Renderer()
actual = renderer.render(NestedContext(renderer))
self.assertString(actual, u"one and foo and two")
def test_nested_context_is_available_in_view(self):
renderer = Renderer()
view = NestedContext(renderer)
view.template = '{{#herp}}{{#derp}}{{nested_context_in_view}}{{/derp}}{{/herp}}'
actual = renderer.render(view)
self.assertString(actual, u'it works!')
def test_partial_in_partial_has_access_to_grand_parent_context(self):
renderer = Renderer(search_dirs=EXAMPLES_DIR)
view = TemplatePartial(renderer=renderer)
view.template = '''{{>partial_in_partial}}'''
actual = renderer.render(view, {'prop': 'derp'})
self.assertEqual(actual, 'Hi derp!')
if __name__ == '__main__':
unittest.main()

209
third_party/python/pystache/pystache/tests/test_loader.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,209 @@
# encoding: utf-8
"""
Unit tests of loader.py.
"""
import os
import sys
import unittest
from pystache.tests.common import AssertStringMixin, DATA_DIR, SetupDefaults
from pystache import defaults
from pystache.loader import Loader
# We use the same directory as the locator tests for now.
LOADER_DATA_DIR = os.path.join(DATA_DIR, 'locator')
class LoaderTests(unittest.TestCase, AssertStringMixin, SetupDefaults):
def setUp(self):
self.setup_defaults()
def tearDown(self):
self.teardown_defaults()
def test_init__extension(self):
loader = Loader(extension='foo')
self.assertEqual(loader.extension, 'foo')
def test_init__extension__default(self):
# Test the default value.
loader = Loader()
self.assertEqual(loader.extension, 'mustache')
def test_init__file_encoding(self):
loader = Loader(file_encoding='bar')
self.assertEqual(loader.file_encoding, 'bar')
def test_init__file_encoding__default(self):
file_encoding = defaults.FILE_ENCODING
try:
defaults.FILE_ENCODING = 'foo'
loader = Loader()
self.assertEqual(loader.file_encoding, 'foo')
finally:
defaults.FILE_ENCODING = file_encoding
def test_init__to_unicode(self):
to_unicode = lambda x: x
loader = Loader(to_unicode=to_unicode)
self.assertEqual(loader.to_unicode, to_unicode)
def test_init__to_unicode__default(self):
loader = Loader()
self.assertRaises(TypeError, loader.to_unicode, u"abc")
decode_errors = defaults.DECODE_ERRORS
string_encoding = defaults.STRING_ENCODING
nonascii = u'abcdé'.encode('utf-8')
loader = Loader()
self.assertRaises(UnicodeDecodeError, loader.to_unicode, nonascii)
defaults.DECODE_ERRORS = 'ignore'
loader = Loader()
self.assertString(loader.to_unicode(nonascii), u'abcd')
defaults.STRING_ENCODING = 'utf-8'
loader = Loader()
self.assertString(loader.to_unicode(nonascii), u'abcdé')
def _get_path(self, filename):
return os.path.join(DATA_DIR, filename)
def test_unicode__basic__input_str(self):
"""
Test unicode(): default arguments with str input.
"""
loader = Loader()
actual = loader.unicode("foo")
self.assertString(actual, u"foo")
def test_unicode__basic__input_unicode(self):
"""
Test unicode(): default arguments with unicode input.
"""
loader = Loader()
actual = loader.unicode(u"foo")
self.assertString(actual, u"foo")
def test_unicode__basic__input_unicode_subclass(self):
"""
Test unicode(): default arguments with unicode-subclass input.
"""
class UnicodeSubclass(unicode):
pass
s = UnicodeSubclass(u"foo")
loader = Loader()
actual = loader.unicode(s)
self.assertString(actual, u"foo")
def test_unicode__to_unicode__attribute(self):
"""
Test unicode(): encoding attribute.
"""
loader = Loader()
non_ascii = u'abcdé'.encode('utf-8')
self.assertRaises(UnicodeDecodeError, loader.unicode, non_ascii)
def to_unicode(s, encoding=None):
if encoding is None:
encoding = 'utf-8'
return unicode(s, encoding)
loader.to_unicode = to_unicode
self.assertString(loader.unicode(non_ascii), u"abcdé")
def test_unicode__encoding_argument(self):
"""
Test unicode(): encoding argument.
"""
loader = Loader()
non_ascii = u'abcdé'.encode('utf-8')
self.assertRaises(UnicodeDecodeError, loader.unicode, non_ascii)
actual = loader.unicode(non_ascii, encoding='utf-8')
self.assertString(actual, u'abcdé')
# TODO: check the read() unit tests.
def test_read(self):
"""
Test read().
"""
loader = Loader()
path = self._get_path('ascii.mustache')
actual = loader.read(path)
self.assertString(actual, u'ascii: abc')
def test_read__file_encoding__attribute(self):
"""
Test read(): file_encoding attribute respected.
"""
loader = Loader()
path = self._get_path('non_ascii.mustache')
self.assertRaises(UnicodeDecodeError, loader.read, path)
loader.file_encoding = 'utf-8'
actual = loader.read(path)
self.assertString(actual, u'non-ascii: é')
def test_read__encoding__argument(self):
"""
Test read(): encoding argument respected.
"""
loader = Loader()
path = self._get_path('non_ascii.mustache')
self.assertRaises(UnicodeDecodeError, loader.read, path)
actual = loader.read(path, encoding='utf-8')
self.assertString(actual, u'non-ascii: é')
def test_read__to_unicode__attribute(self):
"""
Test read(): to_unicode attribute respected.
"""
loader = Loader()
path = self._get_path('non_ascii.mustache')
self.assertRaises(UnicodeDecodeError, loader.read, path)
#loader.decode_errors = 'ignore'
#actual = loader.read(path)
#self.assertString(actual, u'non-ascii: ')
def test_load_file(self):
loader = Loader(search_dirs=[DATA_DIR, LOADER_DATA_DIR])
template = loader.load_file('template.txt')
self.assertEqual(template, 'Test template file\n')
def test_load_name(self):
loader = Loader(search_dirs=[DATA_DIR, LOADER_DATA_DIR],
extension='txt')
template = loader.load_name('template')
self.assertEqual(template, 'Test template file\n')

179
third_party/python/pystache/pystache/tests/test_locator.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,179 @@
# encoding: utf-8
"""
Unit tests for locator.py.
"""
from datetime import datetime
import os
import sys
import unittest
# TODO: remove this alias.
from pystache.common import TemplateNotFoundError
from pystache.loader import Loader as Reader
from pystache.locator import Locator
from pystache.tests.common import DATA_DIR, EXAMPLES_DIR, AssertExceptionMixin
from pystache.tests.data.views import SayHello
LOCATOR_DATA_DIR = os.path.join(DATA_DIR, 'locator')
class LocatorTests(unittest.TestCase, AssertExceptionMixin):
def _locator(self):
return Locator(search_dirs=DATA_DIR)
def test_init__extension(self):
# Test the default value.
locator = Locator()
self.assertEqual(locator.template_extension, 'mustache')
locator = Locator(extension='txt')
self.assertEqual(locator.template_extension, 'txt')
locator = Locator(extension=False)
self.assertTrue(locator.template_extension is False)
def _assert_paths(self, actual, expected):
"""
Assert that two paths are the same.
"""
self.assertEqual(actual, expected)
def test_get_object_directory(self):
locator = Locator()
obj = SayHello()
actual = locator.get_object_directory(obj)
self._assert_paths(actual, DATA_DIR)
def test_get_object_directory__not_hasattr_module(self):
locator = Locator()
# Previously, we used a genuine object -- a datetime instance --
# because datetime instances did not have the __module__ attribute
# in CPython. See, for example--
#
# http://bugs.python.org/issue15223
#
# However, since datetime instances do have the __module__ attribute
# in PyPy, we needed to switch to something else once we added
# support for PyPi. This was so that our test runs would pass
# in all systems.
obj = "abc"
self.assertFalse(hasattr(obj, '__module__'))
self.assertEqual(locator.get_object_directory(obj), None)
self.assertFalse(hasattr(None, '__module__'))
self.assertEqual(locator.get_object_directory(None), None)
def test_make_file_name(self):
locator = Locator()
locator.template_extension = 'bar'
self.assertEqual(locator.make_file_name('foo'), 'foo.bar')
locator.template_extension = False
self.assertEqual(locator.make_file_name('foo'), 'foo')
locator.template_extension = ''
self.assertEqual(locator.make_file_name('foo'), 'foo.')
def test_make_file_name__template_extension_argument(self):
locator = Locator()
self.assertEqual(locator.make_file_name('foo', template_extension='bar'), 'foo.bar')
def test_find_file(self):
locator = Locator()
path = locator.find_file('template.txt', [LOCATOR_DATA_DIR])
expected_path = os.path.join(LOCATOR_DATA_DIR, 'template.txt')
self.assertEqual(path, expected_path)
def test_find_name(self):
locator = Locator()
path = locator.find_name(search_dirs=[EXAMPLES_DIR], template_name='simple')
self.assertEqual(os.path.basename(path), 'simple.mustache')
def test_find_name__using_list_of_paths(self):
locator = Locator()
path = locator.find_name(search_dirs=[EXAMPLES_DIR, 'doesnt_exist'], template_name='simple')
self.assertTrue(path)
def test_find_name__precedence(self):
"""
Test the order in which find_name() searches directories.
"""
locator = Locator()
dir1 = DATA_DIR
dir2 = LOCATOR_DATA_DIR
self.assertTrue(locator.find_name(search_dirs=[dir1], template_name='duplicate'))
self.assertTrue(locator.find_name(search_dirs=[dir2], template_name='duplicate'))
path = locator.find_name(search_dirs=[dir2, dir1], template_name='duplicate')
dirpath = os.path.dirname(path)
dirname = os.path.split(dirpath)[-1]
self.assertEqual(dirname, 'locator')
def test_find_name__non_existent_template_fails(self):
locator = Locator()
self.assertException(TemplateNotFoundError, "File 'doesnt_exist.mustache' not found in dirs: []",
locator.find_name, search_dirs=[], template_name='doesnt_exist')
def test_find_object(self):
locator = Locator()
obj = SayHello()
actual = locator.find_object(search_dirs=[], obj=obj, file_name='sample_view.mustache')
expected = os.path.join(DATA_DIR, 'sample_view.mustache')
self._assert_paths(actual, expected)
def test_find_object__none_file_name(self):
locator = Locator()
obj = SayHello()
actual = locator.find_object(search_dirs=[], obj=obj)
expected = os.path.join(DATA_DIR, 'say_hello.mustache')
self.assertEqual(actual, expected)
def test_find_object__none_object_directory(self):
locator = Locator()
obj = None
self.assertEqual(None, locator.get_object_directory(obj))
actual = locator.find_object(search_dirs=[DATA_DIR], obj=obj, file_name='say_hello.mustache')
expected = os.path.join(DATA_DIR, 'say_hello.mustache')
self.assertEqual(actual, expected)
def test_make_template_name(self):
"""
Test make_template_name().
"""
locator = Locator()
class FooBar(object):
pass
foo = FooBar()
self.assertEqual(locator.make_template_name(foo), 'foo_bar')

27
third_party/python/pystache/pystache/tests/test_parser.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,27 @@
# coding: utf-8
"""
Unit tests of parser.py.
"""
import unittest
from pystache.defaults import DELIMITERS
from pystache.parser import _compile_template_re as make_re
class RegularExpressionTestCase(unittest.TestCase):
"""Tests the regular expression returned by _compile_template_re()."""
def test_re(self):
"""
Test getting a key from a dictionary.
"""
re = make_re(DELIMITERS)
match = re.search("b {{test}}")
self.assertEqual(match.start(), 1)

127
third_party/python/pystache/pystache/tests/test_pystache.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,127 @@
# encoding: utf-8
import unittest
import pystache
from pystache import defaults
from pystache import renderer
from pystache.tests.common import html_escape
class PystacheTests(unittest.TestCase):
def setUp(self):
self.original_escape = defaults.TAG_ESCAPE
defaults.TAG_ESCAPE = html_escape
def tearDown(self):
defaults.TAG_ESCAPE = self.original_escape
def _assert_rendered(self, expected, template, context):
actual = pystache.render(template, context)
self.assertEqual(actual, expected)
def test_basic(self):
ret = pystache.render("Hi {{thing}}!", { 'thing': 'world' })
self.assertEqual(ret, "Hi world!")
def test_kwargs(self):
ret = pystache.render("Hi {{thing}}!", thing='world')
self.assertEqual(ret, "Hi world!")
def test_less_basic(self):
template = "It's a nice day for {{beverage}}, right {{person}}?"
context = { 'beverage': 'soda', 'person': 'Bob' }
self._assert_rendered("It's a nice day for soda, right Bob?", template, context)
def test_even_less_basic(self):
template = "I think {{name}} wants a {{thing}}, right {{name}}?"
context = { 'name': 'Jon', 'thing': 'racecar' }
self._assert_rendered("I think Jon wants a racecar, right Jon?", template, context)
def test_ignores_misses(self):
template = "I think {{name}} wants a {{thing}}, right {{name}}?"
context = { 'name': 'Jon' }
self._assert_rendered("I think Jon wants a , right Jon?", template, context)
def test_render_zero(self):
template = 'My value is {{value}}.'
context = { 'value': 0 }
self._assert_rendered('My value is 0.', template, context)
def test_comments(self):
template = "What {{! the }} what?"
actual = pystache.render(template)
self.assertEqual("What what?", actual)
def test_false_sections_are_hidden(self):
template = "Ready {{#set}}set {{/set}}go!"
context = { 'set': False }
self._assert_rendered("Ready go!", template, context)
def test_true_sections_are_shown(self):
template = "Ready {{#set}}set{{/set}} go!"
context = { 'set': True }
self._assert_rendered("Ready set go!", template, context)
non_strings_expected = """(123 & [&#x27;something&#x27;])(chris & 0.9)"""
def test_non_strings(self):
template = "{{#stats}}({{key}} & {{value}}){{/stats}}"
stats = []
stats.append({'key': 123, 'value': ['something']})
stats.append({'key': u"chris", 'value': 0.900})
context = { 'stats': stats }
self._assert_rendered(self.non_strings_expected, template, context)
def test_unicode(self):
template = 'Name: {{name}}; Age: {{age}}'
context = {'name': u'Henri Poincaré', 'age': 156 }
self._assert_rendered(u'Name: Henri Poincaré; Age: 156', template, context)
def test_sections(self):
template = """<ul>{{#users}}<li>{{name}}</li>{{/users}}</ul>"""
context = { 'users': [ {'name': 'Chris'}, {'name': 'Tom'}, {'name': 'PJ'} ] }
expected = """<ul><li>Chris</li><li>Tom</li><li>PJ</li></ul>"""
self._assert_rendered(expected, template, context)
def test_implicit_iterator(self):
template = """<ul>{{#users}}<li>{{.}}</li>{{/users}}</ul>"""
context = { 'users': [ 'Chris', 'Tom','PJ' ] }
expected = """<ul><li>Chris</li><li>Tom</li><li>PJ</li></ul>"""
self._assert_rendered(expected, template, context)
# The spec says that sections should not alter surrounding whitespace.
def test_surrounding_whitepace_not_altered(self):
template = "first{{#spacing}} second {{/spacing}}third"
context = {"spacing": True}
self._assert_rendered("first second third", template, context)
def test__section__non_false_value(self):
"""
Test when a section value is a (non-list) "non-false value".
From mustache(5):
When the value [of a section key] is non-false but not a list, it
will be used as the context for a single rendering of the block.
"""
template = """{{#person}}Hi {{name}}{{/person}}"""
context = {"person": {"name": "Jon"}}
self._assert_rendered("Hi Jon", template, context)
def test_later_list_section_with_escapable_character(self):
"""
This is a simple test case intended to cover issue #53.
The test case failed with markupsafe enabled, as follows:
AssertionError: Markup(u'foo &lt;') != 'foo <'
"""
template = """{{#s1}}foo{{/s1}} {{#s2}}<{{/s2}}"""
context = {'s1': True, 's2': [True]}
self._assert_rendered("foo <", template, context)

769
third_party/python/pystache/pystache/tests/test_renderengine.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,769 @@
# coding: utf-8
"""
Unit tests of renderengine.py.
"""
import sys
import unittest
from pystache.context import ContextStack, KeyNotFoundError
from pystache import defaults
from pystache.parser import ParsingError
from pystache.renderer import Renderer
from pystache.renderengine import context_get, RenderEngine
from pystache.tests.common import AssertStringMixin, AssertExceptionMixin, Attachable
def _get_unicode_char():
if sys.version_info < (3, ):
return 'u'
return ''
_UNICODE_CHAR = _get_unicode_char()
def mock_literal(s):
"""
For use as the literal keyword argument to the RenderEngine constructor.
Arguments:
s: a byte string or unicode string.
"""
if isinstance(s, unicode):
# Strip off unicode super classes, if present.
u = unicode(s)
else:
u = unicode(s, encoding='ascii')
# We apply upper() to make sure we are actually using our custom
# function in the tests
return u.upper()
class RenderEngineTestCase(unittest.TestCase):
"""Test the RenderEngine class."""
def test_init(self):
"""
Test that __init__() stores all of the arguments correctly.
"""
# In real-life, these arguments would be functions
engine = RenderEngine(resolve_partial="foo", literal="literal",
escape="escape", to_str="str")
self.assertEqual(engine.escape, "escape")
self.assertEqual(engine.literal, "literal")
self.assertEqual(engine.resolve_partial, "foo")
self.assertEqual(engine.to_str, "str")
class RenderTests(unittest.TestCase, AssertStringMixin, AssertExceptionMixin):
"""
Tests RenderEngine.render().
Explicit spec-test-like tests best go in this class since the
RenderEngine class contains all parsing logic. This way, the unit tests
will be more focused and fail "closer to the code".
"""
def _engine(self):
"""
Create and return a default RenderEngine for testing.
"""
renderer = Renderer(string_encoding='utf-8', missing_tags='strict')
engine = renderer._make_render_engine()
return engine
def _assert_render(self, expected, template, *context, **kwargs):
"""
Test rendering the given template using the given context.
"""
partials = kwargs.get('partials')
engine = kwargs.get('engine', self._engine())
if partials is not None:
engine.resolve_partial = lambda key: unicode(partials[key])
context = ContextStack(*context)
# RenderEngine.render() only accepts unicode template strings.
actual = engine.render(unicode(template), context)
self.assertString(actual=actual, expected=expected)
def test_render(self):
self._assert_render(u'Hi Mom', 'Hi {{person}}', {'person': 'Mom'})
def test__resolve_partial(self):
"""
Test that render() uses the load_template attribute.
"""
engine = self._engine()
partials = {'partial': u"{{person}}"}
engine.resolve_partial = lambda key: partials[key]
self._assert_render(u'Hi Mom', 'Hi {{>partial}}', {'person': 'Mom'}, engine=engine)
def test__literal(self):
"""
Test that render() uses the literal attribute.
"""
engine = self._engine()
engine.literal = lambda s: s.upper()
self._assert_render(u'BAR', '{{{foo}}}', {'foo': 'bar'}, engine=engine)
def test_literal__sigil(self):
template = "<h1>{{& thing}}</h1>"
context = {'thing': 'Bear > Giraffe'}
expected = u"<h1>Bear > Giraffe</h1>"
self._assert_render(expected, template, context)
def test__escape(self):
"""
Test that render() uses the escape attribute.
"""
engine = self._engine()
engine.escape = lambda s: "**" + s
self._assert_render(u'**bar', '{{foo}}', {'foo': 'bar'}, engine=engine)
def test__escape_does_not_call_literal(self):
"""
Test that render() does not call literal before or after calling escape.
"""
engine = self._engine()
engine.literal = lambda s: s.upper() # a test version
engine.escape = lambda s: "**" + s
template = 'literal: {{{foo}}} escaped: {{foo}}'
context = {'foo': 'bar'}
self._assert_render(u'literal: BAR escaped: **bar', template, context, engine=engine)
def test__escape_preserves_unicode_subclasses(self):
"""
Test that render() preserves unicode subclasses when passing to escape.
This is useful, for example, if one wants to respect whether a
variable value is markupsafe.Markup when escaping.
"""
class MyUnicode(unicode):
pass
def escape(s):
if type(s) is MyUnicode:
return "**" + s
else:
return s + "**"
engine = self._engine()
engine.escape = escape
template = '{{foo1}} {{foo2}}'
context = {'foo1': MyUnicode('bar'), 'foo2': 'bar'}
self._assert_render(u'**bar bar**', template, context, engine=engine)
# Custom to_str for testing purposes.
def _to_str(self, val):
if not val:
return ''
else:
return str(val)
def test_to_str(self):
"""Test the to_str attribute."""
engine = self._engine()
template = '{{value}}'
context = {'value': None}
self._assert_render(u'None', template, context, engine=engine)
engine.to_str = self._to_str
self._assert_render(u'', template, context, engine=engine)
def test_to_str__lambda(self):
"""Test the to_str attribute for a lambda."""
engine = self._engine()
template = '{{value}}'
context = {'value': lambda: None}
self._assert_render(u'None', template, context, engine=engine)
engine.to_str = self._to_str
self._assert_render(u'', template, context, engine=engine)
def test_to_str__section_list(self):
"""Test the to_str attribute for a section list."""
engine = self._engine()
template = '{{#list}}{{.}}{{/list}}'
context = {'list': [None, None]}
self._assert_render(u'NoneNone', template, context, engine=engine)
engine.to_str = self._to_str
self._assert_render(u'', template, context, engine=engine)
def test_to_str__section_lambda(self):
# TODO: add a test for a "method with an arity of 1".
pass
def test__non_basestring__literal_and_escaped(self):
"""
Test a context value that is not a basestring instance.
"""
engine = self._engine()
engine.escape = mock_literal
engine.literal = mock_literal
self.assertRaises(TypeError, engine.literal, 100)
template = '{{text}} {{int}} {{{int}}}'
context = {'int': 100, 'text': 'foo'}
self._assert_render(u'FOO 100 100', template, context, engine=engine)
def test_tag__output_not_interpolated(self):
"""
Context values should not be treated as templates (issue #44).
"""
template = '{{template}}: {{planet}}'
context = {'template': '{{planet}}', 'planet': 'Earth'}
self._assert_render(u'{{planet}}: Earth', template, context)
def test_tag__output_not_interpolated__section(self):
"""
Context values should not be treated as templates (issue #44).
"""
template = '{{test}}'
context = {'test': '{{#hello}}'}
self._assert_render(u'{{#hello}}', template, context)
## Test interpolation with "falsey" values
#
# In these test cases, we test the part of the spec that says that
# "data should be coerced into a string (and escaped, if appropriate)
# before interpolation." We test this for data that is "falsey."
def test_interpolation__falsey__zero(self):
template = '{{.}}'
context = 0
self._assert_render(u'0', template, context)
def test_interpolation__falsey__none(self):
template = '{{.}}'
context = None
self._assert_render(u'None', template, context)
def test_interpolation__falsey__zero(self):
template = '{{.}}'
context = False
self._assert_render(u'False', template, context)
# Built-in types:
#
# Confirm that we not treat instances of built-in types as objects,
# for example by calling a method on a built-in type instance when it
# has a method whose name matches the current key.
#
# Each test case puts an instance of a built-in type on top of the
# context stack before interpolating a tag whose key matches an
# attribute (method or property) of the instance.
#
def _assert_builtin_attr(self, item, attr_name, expected_attr):
self.assertTrue(hasattr(item, attr_name))
actual = getattr(item, attr_name)
if callable(actual):
actual = actual()
self.assertEqual(actual, expected_attr)
def _assert_builtin_type(self, item, attr_name, expected_attr, expected_template):
self._assert_builtin_attr(item, attr_name, expected_attr)
template = '{{#section}}{{%s}}{{/section}}' % attr_name
context = {'section': item, attr_name: expected_template}
self._assert_render(expected_template, template, context)
def test_interpolation__built_in_type__string(self):
"""
Check tag interpolation with a built-in type: string.
"""
self._assert_builtin_type('abc', 'upper', 'ABC', u'xyz')
def test_interpolation__built_in_type__integer(self):
"""
Check tag interpolation with a built-in type: integer.
"""
# Since public attributes weren't added to integers until Python 2.6
# (for example the "real" attribute of the numeric type hierarchy)--
#
# http://docs.python.org/library/numbers.html
#
# we need to resort to built-in attributes (double-underscored) on
# the integer type.
self._assert_builtin_type(15, '__neg__', -15, u'999')
def test_interpolation__built_in_type__list(self):
"""
Check tag interpolation with a built-in type: list.
"""
item = [[1, 2, 3]]
attr_name = 'pop'
# Make a copy to prevent changes to item[0].
self._assert_builtin_attr(list(item[0]), attr_name, 3)
template = '{{#section}}{{%s}}{{/section}}' % attr_name
context = {'section': item, attr_name: 7}
self._assert_render(u'7', template, context)
# This test is also important for testing 2to3.
def test_interpolation__nonascii_nonunicode(self):
"""
Test a tag whose value is a non-ascii, non-unicode string.
"""
template = '{{nonascii}}'
context = {'nonascii': u'abcdé'.encode('utf-8')}
self._assert_render(u'abcdé', template, context)
def test_implicit_iterator__literal(self):
"""
Test an implicit iterator in a literal tag.
"""
template = """{{#test}}{{{.}}}{{/test}}"""
context = {'test': ['<', '>']}
self._assert_render(u'<>', template, context)
def test_implicit_iterator__escaped(self):
"""
Test an implicit iterator in a normal tag.
"""
template = """{{#test}}{{.}}{{/test}}"""
context = {'test': ['<', '>']}
self._assert_render(u'&lt;&gt;', template, context)
def test_literal__in_section(self):
"""
Check that literals work in sections.
"""
template = '{{#test}}1 {{{less_than}}} 2{{/test}}'
context = {'test': {'less_than': '<'}}
self._assert_render(u'1 < 2', template, context)
def test_literal__in_partial(self):
"""
Check that literals work in partials.
"""
template = '{{>partial}}'
partials = {'partial': '1 {{{less_than}}} 2'}
context = {'less_than': '<'}
self._assert_render(u'1 < 2', template, context, partials=partials)
def test_partial(self):
partials = {'partial': "{{person}}"}
self._assert_render(u'Hi Mom', 'Hi {{>partial}}', {'person': 'Mom'}, partials=partials)
def test_partial__context_values(self):
"""
Test that escape and literal work on context values in partials.
"""
engine = self._engine()
template = '{{>partial}}'
partials = {'partial': 'unescaped: {{{foo}}} escaped: {{foo}}'}
context = {'foo': '<'}
self._assert_render(u'unescaped: < escaped: &lt;', template, context, engine=engine, partials=partials)
## Test cases related specifically to lambdas.
# This test is also important for testing 2to3.
def test_section__nonascii_nonunicode(self):
"""
Test a section whose value is a non-ascii, non-unicode string.
"""
template = '{{#nonascii}}{{.}}{{/nonascii}}'
context = {'nonascii': u'abcdé'.encode('utf-8')}
self._assert_render(u'abcdé', template, context)
# This test is also important for testing 2to3.
def test_lambda__returning_nonascii_nonunicode(self):
"""
Test a lambda tag value returning a non-ascii, non-unicode string.
"""
template = '{{lambda}}'
context = {'lambda': lambda: u'abcdé'.encode('utf-8')}
self._assert_render(u'abcdé', template, context)
## Test cases related specifically to sections.
def test_section__end_tag_with_no_start_tag(self):
"""
Check what happens if there is an end tag with no start tag.
"""
template = '{{/section}}'
try:
self._assert_render(None, template)
except ParsingError, err:
self.assertEqual(str(err), "Section end tag mismatch: section != None")
def test_section__end_tag_mismatch(self):
"""
Check what happens if the end tag doesn't match.
"""
template = '{{#section_start}}{{/section_end}}'
try:
self._assert_render(None, template)
except ParsingError, err:
self.assertEqual(str(err), "Section end tag mismatch: section_end != section_start")
def test_section__context_values(self):
"""
Test that escape and literal work on context values in sections.
"""
engine = self._engine()
template = '{{#test}}unescaped: {{{foo}}} escaped: {{foo}}{{/test}}'
context = {'test': {'foo': '<'}}
self._assert_render(u'unescaped: < escaped: &lt;', template, context, engine=engine)
def test_section__context_precedence(self):
"""
Check that items higher in the context stack take precedence.
"""
template = '{{entree}} : {{#vegetarian}}{{entree}}{{/vegetarian}}'
context = {'entree': 'chicken', 'vegetarian': {'entree': 'beans and rice'}}
self._assert_render(u'chicken : beans and rice', template, context)
def test_section__list_referencing_outer_context(self):
"""
Check that list items can access the parent context.
For sections whose value is a list, check that items in the list
have access to the values inherited from the parent context
when rendering.
"""
context = {
"greeting": "Hi",
"list": [{"name": "Al"}, {"name": "Bob"}],
}
template = "{{#list}}{{greeting}} {{name}}, {{/list}}"
self._assert_render(u"Hi Al, Hi Bob, ", template, context)
def test_section__output_not_interpolated(self):
"""
Check that rendered section output is not interpolated.
"""
template = '{{#section}}{{template}}{{/section}}: {{planet}}'
context = {'section': True, 'template': '{{planet}}', 'planet': 'Earth'}
self._assert_render(u'{{planet}}: Earth', template, context)
# TODO: have this test case added to the spec.
def test_section__string_values_not_lists(self):
"""
Check that string section values are not interpreted as lists.
"""
template = '{{#section}}foo{{/section}}'
context = {'section': '123'}
# If strings were interpreted as lists, this would give "foofoofoo".
self._assert_render(u'foo', template, context)
def test_section__nested_truthy(self):
"""
Check that "nested truthy" sections get rendered.
Test case for issue #24: https://github.com/defunkt/pystache/issues/24
This test is copied from the spec. We explicitly include it to
prevent regressions for those who don't pull down the spec tests.
"""
template = '| A {{#bool}}B {{#bool}}C{{/bool}} D{{/bool}} E |'
context = {'bool': True}
self._assert_render(u'| A B C D E |', template, context)
def test_section__nested_with_same_keys(self):
"""
Check a doubly-nested section with the same context key.
Test case for issue #36: https://github.com/defunkt/pystache/issues/36
"""
# Start with an easier, working case.
template = '{{#x}}{{#z}}{{y}}{{/z}}{{/x}}'
context = {'x': {'z': {'y': 1}}}
self._assert_render(u'1', template, context)
template = '{{#x}}{{#x}}{{y}}{{/x}}{{/x}}'
context = {'x': {'x': {'y': 1}}}
self._assert_render(u'1', template, context)
def test_section__lambda(self):
template = '{{#test}}Mom{{/test}}'
context = {'test': (lambda text: 'Hi %s' % text)}
self._assert_render(u'Hi Mom', template, context)
# This test is also important for testing 2to3.
def test_section__lambda__returning_nonascii_nonunicode(self):
"""
Test a lambda section value returning a non-ascii, non-unicode string.
"""
template = '{{#lambda}}{{/lambda}}'
context = {'lambda': lambda text: u'abcdé'.encode('utf-8')}
self._assert_render(u'abcdé', template, context)
def test_section__lambda__returning_nonstring(self):
"""
Test a lambda section value returning a non-string.
"""
template = '{{#lambda}}foo{{/lambda}}'
context = {'lambda': lambda text: len(text)}
self._assert_render(u'3', template, context)
def test_section__iterable(self):
"""
Check that objects supporting iteration (aside from dicts) behave like lists.
"""
template = '{{#iterable}}{{.}}{{/iterable}}'
context = {'iterable': (i for i in range(3))} # type 'generator'
self._assert_render(u'012', template, context)
context = {'iterable': xrange(4)} # type 'xrange'
self._assert_render(u'0123', template, context)
d = {'foo': 0, 'bar': 0}
# We don't know what order of keys we'll be given, but from the
# Python documentation:
# "If items(), keys(), values(), iteritems(), iterkeys(), and
# itervalues() are called with no intervening modifications to
# the dictionary, the lists will directly correspond."
expected = u''.join(d.keys())
context = {'iterable': d.iterkeys()} # type 'dictionary-keyiterator'
self._assert_render(expected, template, context)
def test_section__lambda__tag_in_output(self):
"""
Check that callable output is treated as a template string (issue #46).
The spec says--
When used as the data value for a Section tag, the lambda MUST
be treatable as an arity 1 function, and invoked as such (passing
a String containing the unprocessed section contents). The
returned value MUST be rendered against the current delimiters,
then interpolated in place of the section.
"""
template = '{{#test}}Hi {{person}}{{/test}}'
context = {'person': 'Mom', 'test': (lambda text: text + " :)")}
self._assert_render(u'Hi Mom :)', template, context)
def test_section__lambda__list(self):
"""
Check that lists of lambdas are processed correctly for sections.
This test case is equivalent to a test submitted to the Mustache spec here:
https://github.com/mustache/spec/pull/47 .
"""
template = '<{{#lambdas}}foo{{/lambdas}}>'
context = {'foo': 'bar',
'lambdas': [lambda text: "~{{%s}}~" % text,
lambda text: "#{{%s}}#" % text]}
self._assert_render(u'<~bar~#bar#>', template, context)
def test_section__lambda__mixed_list(self):
"""
Test a mixed list of lambdas and non-lambdas as a section value.
This test case is equivalent to a test submitted to the Mustache spec here:
https://github.com/mustache/spec/pull/47 .
"""
template = '<{{#lambdas}}foo{{/lambdas}}>'
context = {'foo': 'bar',
'lambdas': [lambda text: "~{{%s}}~" % text, 1]}
self._assert_render(u'<~bar~foo>', template, context)
def test_section__lambda__not_on_context_stack(self):
"""
Check that section lambdas are not pushed onto the context stack.
Even though the sections spec says that section data values should be
pushed onto the context stack prior to rendering, this does not apply
to lambdas. Lambdas obey their own special case.
This test case is equivalent to a test submitted to the Mustache spec here:
https://github.com/mustache/spec/pull/47 .
"""
context = {'foo': 'bar', 'lambda': (lambda text: "{{.}}")}
template = '{{#foo}}{{#lambda}}blah{{/lambda}}{{/foo}}'
self._assert_render(u'bar', template, context)
def test_section__lambda__no_reinterpolation(self):
"""
Check that section lambda return values are not re-interpolated.
This test is a sanity check that the rendered lambda return value
is not re-interpolated as could be construed by reading the
section part of the Mustache spec.
This test case is equivalent to a test submitted to the Mustache spec here:
https://github.com/mustache/spec/pull/47 .
"""
template = '{{#planet}}{{#lambda}}dot{{/lambda}}{{/planet}}'
context = {'planet': 'Earth', 'dot': '~{{.}}~', 'lambda': (lambda text: "#{{%s}}#" % text)}
self._assert_render(u'#~{{.}}~#', template, context)
def test_comment__multiline(self):
"""
Check that multiline comments are permitted.
"""
self._assert_render(u'foobar', 'foo{{! baz }}bar')
self._assert_render(u'foobar', 'foo{{! \nbaz }}bar')
def test_custom_delimiters__sections(self):
"""
Check that custom delimiters can be used to start a section.
Test case for issue #20: https://github.com/defunkt/pystache/issues/20
"""
template = '{{=[[ ]]=}}[[#foo]]bar[[/foo]]'
context = {'foo': True}
self._assert_render(u'bar', template, context)
def test_custom_delimiters__not_retroactive(self):
"""
Check that changing custom delimiters back is not "retroactive."
Test case for issue #35: https://github.com/defunkt/pystache/issues/35
"""
expected = u' {{foo}} '
self._assert_render(expected, '{{=$ $=}} {{foo}} ')
self._assert_render(expected, '{{=$ $=}} {{foo}} $={{ }}=$') # was yielding u' '.
def test_dot_notation(self):
"""
Test simple dot notation cases.
Check that we can use dot notation when the variable is a dict,
user-defined object, or combination of both.
"""
template = 'Hello, {{person.name}}. I see you are {{person.details.age}}.'
person = Attachable(name='Biggles', details={'age': 42})
context = {'person': person}
self._assert_render(u'Hello, Biggles. I see you are 42.', template, context)
def test_dot_notation__multiple_levels(self):
"""
Test dot notation with multiple levels.
"""
template = """Hello, Mr. {{person.name.lastname}}.
I see you're back from {{person.travels.last.country.city}}."""
expected = u"""Hello, Mr. Pither.
I see you're back from Cornwall."""
context = {'person': {'name': {'firstname': 'unknown', 'lastname': 'Pither'},
'travels': {'last': {'country': {'city': 'Cornwall'}}},
'details': {'public': 'likes cycling'}}}
self._assert_render(expected, template, context)
# It should also work with user-defined objects
context = {'person': Attachable(name={'firstname': 'unknown', 'lastname': 'Pither'},
travels=Attachable(last=Attachable(country=Attachable(city='Cornwall'))),
details=Attachable())}
self._assert_render(expected, template, context)
def test_dot_notation__missing_part_terminates_search(self):
"""
Test that dotted name resolution terminates on a later part not found.
Check that if a later dotted name part is not found in the result from
the former resolution, then name resolution terminates rather than
starting the search over with the next element of the context stack.
From the spec (interpolation section)--
5) If any name parts were retained in step 1, each should be resolved
against a context stack containing only the result from the former
resolution. If any part fails resolution, the result should be considered
falsey, and should interpolate as the empty string.
This test case is equivalent to the test case in the following pull
request:
https://github.com/mustache/spec/pull/48
"""
context = {'a': {'b': 'A.B'}, 'c': {'a': 'A'} }
template = '{{a.b}}'
self._assert_render(u'A.B', template, context)
template = '{{#c}}{{a}}{{/c}}'
self._assert_render(u'A', template, context)
template = '{{#c}}{{a.b}}{{/c}}'
self.assertException(KeyNotFoundError, "Key %(unicode)s'a.b' not found: missing %(unicode)s'b'" %
{'unicode': _UNICODE_CHAR},
self._assert_render, 'A.B :: (A :: )', template, context)

725
third_party/python/pystache/pystache/tests/test_renderer.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,725 @@
# coding: utf-8
"""
Unit tests of template.py.
"""
import codecs
import os
import sys
import unittest
from examples.simple import Simple
from pystache import Renderer
from pystache import TemplateSpec
from pystache.common import TemplateNotFoundError
from pystache.context import ContextStack, KeyNotFoundError
from pystache.loader import Loader
from pystache.tests.common import get_data_path, AssertStringMixin, AssertExceptionMixin
from pystache.tests.data.views import SayHello
def _make_renderer():
"""
Return a default Renderer instance for testing purposes.
"""
renderer = Renderer(string_encoding='ascii', file_encoding='ascii')
return renderer
def mock_unicode(b, encoding=None):
if encoding is None:
encoding = 'ascii'
u = unicode(b, encoding=encoding)
return u.upper()
class RendererInitTestCase(unittest.TestCase):
"""
Tests the Renderer.__init__() method.
"""
def test_partials__default(self):
"""
Test the default value.
"""
renderer = Renderer()
self.assertTrue(renderer.partials is None)
def test_partials(self):
"""
Test that the attribute is set correctly.
"""
renderer = Renderer(partials={'foo': 'bar'})
self.assertEqual(renderer.partials, {'foo': 'bar'})
def test_escape__default(self):
escape = Renderer().escape
self.assertEqual(escape(">"), "&gt;")
self.assertEqual(escape('"'), "&quot;")
# Single quotes are escaped only in Python 3.2 and later.
if sys.version_info < (3, 2):
expected = "'"
else:
expected = '&#x27;'
self.assertEqual(escape("'"), expected)
def test_escape(self):
escape = lambda s: "**" + s
renderer = Renderer(escape=escape)
self.assertEqual(renderer.escape("bar"), "**bar")
def test_decode_errors__default(self):
"""
Check the default value.
"""
renderer = Renderer()
self.assertEqual(renderer.decode_errors, 'strict')
def test_decode_errors(self):
"""
Check that the constructor sets the attribute correctly.
"""
renderer = Renderer(decode_errors="foo")
self.assertEqual(renderer.decode_errors, "foo")
def test_file_encoding__default(self):
"""
Check the file_encoding default.
"""
renderer = Renderer()
self.assertEqual(renderer.file_encoding, renderer.string_encoding)
def test_file_encoding(self):
"""
Check that the file_encoding attribute is set correctly.
"""
renderer = Renderer(file_encoding='foo')
self.assertEqual(renderer.file_encoding, 'foo')
def test_file_extension__default(self):
"""
Check the file_extension default.
"""
renderer = Renderer()
self.assertEqual(renderer.file_extension, 'mustache')
def test_file_extension(self):
"""
Check that the file_encoding attribute is set correctly.
"""
renderer = Renderer(file_extension='foo')
self.assertEqual(renderer.file_extension, 'foo')
def test_missing_tags(self):
"""
Check that the missing_tags attribute is set correctly.
"""
renderer = Renderer(missing_tags='foo')
self.assertEqual(renderer.missing_tags, 'foo')
def test_missing_tags__default(self):
"""
Check the missing_tags default.
"""
renderer = Renderer()
self.assertEqual(renderer.missing_tags, 'ignore')
def test_search_dirs__default(self):
"""
Check the search_dirs default.
"""
renderer = Renderer()
self.assertEqual(renderer.search_dirs, [os.curdir])
def test_search_dirs__string(self):
"""
Check that the search_dirs attribute is set correctly when a string.
"""
renderer = Renderer(search_dirs='foo')
self.assertEqual(renderer.search_dirs, ['foo'])
def test_search_dirs__list(self):
"""
Check that the search_dirs attribute is set correctly when a list.
"""
renderer = Renderer(search_dirs=['foo'])
self.assertEqual(renderer.search_dirs, ['foo'])
def test_string_encoding__default(self):
"""
Check the default value.
"""
renderer = Renderer()
self.assertEqual(renderer.string_encoding, sys.getdefaultencoding())
def test_string_encoding(self):
"""
Check that the constructor sets the attribute correctly.
"""
renderer = Renderer(string_encoding="foo")
self.assertEqual(renderer.string_encoding, "foo")
class RendererTests(unittest.TestCase, AssertStringMixin):
"""Test the Renderer class."""
def _renderer(self):
return Renderer()
## Test Renderer.unicode().
def test_unicode__string_encoding(self):
"""
Test that the string_encoding attribute is respected.
"""
renderer = self._renderer()
b = u"é".encode('utf-8')
renderer.string_encoding = "ascii"
self.assertRaises(UnicodeDecodeError, renderer.unicode, b)
renderer.string_encoding = "utf-8"
self.assertEqual(renderer.unicode(b), u"é")
def test_unicode__decode_errors(self):
"""
Test that the decode_errors attribute is respected.
"""
renderer = self._renderer()
renderer.string_encoding = "ascii"
b = u"déf".encode('utf-8')
renderer.decode_errors = "ignore"
self.assertEqual(renderer.unicode(b), "df")
renderer.decode_errors = "replace"
# U+FFFD is the official Unicode replacement character.
self.assertEqual(renderer.unicode(b), u'd\ufffd\ufffdf')
## Test the _make_loader() method.
def test__make_loader__return_type(self):
"""
Test that _make_loader() returns a Loader.
"""
renderer = self._renderer()
loader = renderer._make_loader()
self.assertEqual(type(loader), Loader)
def test__make_loader__attributes(self):
"""
Test that _make_loader() sets all attributes correctly..
"""
unicode_ = lambda x: x
renderer = self._renderer()
renderer.file_encoding = 'enc'
renderer.file_extension = 'ext'
renderer.unicode = unicode_
loader = renderer._make_loader()
self.assertEqual(loader.extension, 'ext')
self.assertEqual(loader.file_encoding, 'enc')
self.assertEqual(loader.to_unicode, unicode_)
## Test the render() method.
def test_render__return_type(self):
"""
Check that render() returns a string of type unicode.
"""
renderer = self._renderer()
rendered = renderer.render('foo')
self.assertEqual(type(rendered), unicode)
def test_render__unicode(self):
renderer = self._renderer()
actual = renderer.render(u'foo')
self.assertEqual(actual, u'foo')
def test_render__str(self):
renderer = self._renderer()
actual = renderer.render('foo')
self.assertEqual(actual, 'foo')
def test_render__non_ascii_character(self):
renderer = self._renderer()
actual = renderer.render(u'Poincaré')
self.assertEqual(actual, u'Poincaré')
def test_render__context(self):
"""
Test render(): passing a context.
"""
renderer = self._renderer()
self.assertEqual(renderer.render('Hi {{person}}', {'person': 'Mom'}), 'Hi Mom')
def test_render__context_and_kwargs(self):
"""
Test render(): passing a context and **kwargs.
"""
renderer = self._renderer()
template = 'Hi {{person1}} and {{person2}}'
self.assertEqual(renderer.render(template, {'person1': 'Mom'}, person2='Dad'), 'Hi Mom and Dad')
def test_render__kwargs_and_no_context(self):
"""
Test render(): passing **kwargs and no context.
"""
renderer = self._renderer()
self.assertEqual(renderer.render('Hi {{person}}', person='Mom'), 'Hi Mom')
def test_render__context_and_kwargs__precedence(self):
"""
Test render(): **kwargs takes precedence over context.
"""
renderer = self._renderer()
self.assertEqual(renderer.render('Hi {{person}}', {'person': 'Mom'}, person='Dad'), 'Hi Dad')
def test_render__kwargs_does_not_modify_context(self):
"""
Test render(): passing **kwargs does not modify the passed context.
"""
context = {}
renderer = self._renderer()
renderer.render('Hi {{person}}', context=context, foo="bar")
self.assertEqual(context, {})
def test_render__nonascii_template(self):
"""
Test passing a non-unicode template with non-ascii characters.
"""
renderer = _make_renderer()
template = u"déf".encode("utf-8")
# Check that decode_errors and string_encoding are both respected.
renderer.decode_errors = 'ignore'
renderer.string_encoding = 'ascii'
self.assertEqual(renderer.render(template), "df")
renderer.string_encoding = 'utf_8'
self.assertEqual(renderer.render(template), u"déf")
def test_make_resolve_partial(self):
"""
Test the _make_resolve_partial() method.
"""
renderer = Renderer()
renderer.partials = {'foo': 'bar'}
resolve_partial = renderer._make_resolve_partial()
actual = resolve_partial('foo')
self.assertEqual(actual, 'bar')
self.assertEqual(type(actual), unicode, "RenderEngine requires that "
"resolve_partial return unicode strings.")
def test_make_resolve_partial__unicode(self):
"""
Test _make_resolve_partial(): that resolve_partial doesn't "double-decode" Unicode.
"""
renderer = Renderer()
renderer.partials = {'partial': 'foo'}
resolve_partial = renderer._make_resolve_partial()
self.assertEqual(resolve_partial("partial"), "foo")
# Now with a value that is already unicode.
renderer.partials = {'partial': u'foo'}
resolve_partial = renderer._make_resolve_partial()
# If the next line failed, we would get the following error:
# TypeError: decoding Unicode is not supported
self.assertEqual(resolve_partial("partial"), "foo")
def test_render_name(self):
"""Test the render_name() method."""
data_dir = get_data_path()
renderer = Renderer(search_dirs=data_dir)
actual = renderer.render_name("say_hello", to='foo')
self.assertString(actual, u"Hello, foo")
def test_render_path(self):
"""
Test the render_path() method.
"""
renderer = Renderer()
path = get_data_path('say_hello.mustache')
actual = renderer.render_path(path, to='foo')
self.assertEqual(actual, "Hello, foo")
def test_render__object(self):
"""
Test rendering an object instance.
"""
renderer = Renderer()
say_hello = SayHello()
actual = renderer.render(say_hello)
self.assertEqual('Hello, World', actual)
actual = renderer.render(say_hello, to='Mars')
self.assertEqual('Hello, Mars', actual)
def test_render__template_spec(self):
"""
Test rendering a TemplateSpec instance.
"""
renderer = Renderer()
class Spec(TemplateSpec):
template = "hello, {{to}}"
to = 'world'
spec = Spec()
actual = renderer.render(spec)
self.assertString(actual, u'hello, world')
def test_render__view(self):
"""
Test rendering a View instance.
"""
renderer = Renderer()
view = Simple()
actual = renderer.render(view)
self.assertEqual('Hi pizza!', actual)
def test_custom_string_coercion_via_assignment(self):
"""
Test that string coercion can be customized via attribute assignment.
"""
renderer = self._renderer()
def to_str(val):
if not val:
return ''
else:
return str(val)
self.assertEqual(renderer.render('{{value}}', value=None), 'None')
renderer.str_coerce = to_str
self.assertEqual(renderer.render('{{value}}', value=None), '')
def test_custom_string_coercion_via_subclassing(self):
"""
Test that string coercion can be customized via subclassing.
"""
class MyRenderer(Renderer):
def str_coerce(self, val):
if not val:
return ''
else:
return str(val)
renderer1 = Renderer()
renderer2 = MyRenderer()
self.assertEqual(renderer1.render('{{value}}', value=None), 'None')
self.assertEqual(renderer2.render('{{value}}', value=None), '')
# By testing that Renderer.render() constructs the right RenderEngine,
# we no longer need to exercise all rendering code paths through
# the Renderer. It suffices to test rendering paths through the
# RenderEngine for the same amount of code coverage.
class Renderer_MakeRenderEngineTests(unittest.TestCase, AssertStringMixin, AssertExceptionMixin):
"""
Check the RenderEngine returned by Renderer._make_render_engine().
"""
def _make_renderer(self):
"""
Return a default Renderer instance for testing purposes.
"""
return _make_renderer()
## Test the engine's resolve_partial attribute.
def test__resolve_partial__returns_unicode(self):
"""
Check that resolve_partial returns unicode (and not a subclass).
"""
class MyUnicode(unicode):
pass
renderer = Renderer()
renderer.string_encoding = 'ascii'
renderer.partials = {'str': 'foo', 'subclass': MyUnicode('abc')}
engine = renderer._make_render_engine()
actual = engine.resolve_partial('str')
self.assertEqual(actual, "foo")
self.assertEqual(type(actual), unicode)
# Check that unicode subclasses are not preserved.
actual = engine.resolve_partial('subclass')
self.assertEqual(actual, "abc")
self.assertEqual(type(actual), unicode)
def test__resolve_partial__not_found(self):
"""
Check that resolve_partial returns the empty string when a template is not found.
"""
renderer = Renderer()
engine = renderer._make_render_engine()
resolve_partial = engine.resolve_partial
self.assertString(resolve_partial('foo'), u'')
def test__resolve_partial__not_found__missing_tags_strict(self):
"""
Check that resolve_partial provides a nice message when a template is not found.
"""
renderer = Renderer()
renderer.missing_tags = 'strict'
engine = renderer._make_render_engine()
resolve_partial = engine.resolve_partial
self.assertException(TemplateNotFoundError, "File 'foo.mustache' not found in dirs: ['.']",
resolve_partial, "foo")
def test__resolve_partial__not_found__partials_dict(self):
"""
Check that resolve_partial returns the empty string when a template is not found.
"""
renderer = Renderer()
renderer.partials = {}
engine = renderer._make_render_engine()
resolve_partial = engine.resolve_partial
self.assertString(resolve_partial('foo'), u'')
def test__resolve_partial__not_found__partials_dict__missing_tags_strict(self):
"""
Check that resolve_partial provides a nice message when a template is not found.
"""
renderer = Renderer()
renderer.missing_tags = 'strict'
renderer.partials = {}
engine = renderer._make_render_engine()
resolve_partial = engine.resolve_partial
# Include dict directly since str(dict) is different in Python 2 and 3:
# <type 'dict'> versus <class 'dict'>, respectively.
self.assertException(TemplateNotFoundError, "Name 'foo' not found in partials: %s" % dict,
resolve_partial, "foo")
## Test the engine's literal attribute.
def test__literal__uses_renderer_unicode(self):
"""
Test that literal uses the renderer's unicode function.
"""
renderer = self._make_renderer()
renderer.unicode = mock_unicode
engine = renderer._make_render_engine()
literal = engine.literal
b = u"foo".encode("ascii")
self.assertEqual(literal(b), "FOO")
def test__literal__handles_unicode(self):
"""
Test that literal doesn't try to "double decode" unicode.
"""
renderer = Renderer()
renderer.string_encoding = 'ascii'
engine = renderer._make_render_engine()
literal = engine.literal
self.assertEqual(literal(u"foo"), "foo")
def test__literal__returns_unicode(self):
"""
Test that literal returns unicode (and not a subclass).
"""
renderer = Renderer()
renderer.string_encoding = 'ascii'
engine = renderer._make_render_engine()
literal = engine.literal
self.assertEqual(type(literal("foo")), unicode)
class MyUnicode(unicode):
pass
s = MyUnicode("abc")
self.assertEqual(type(s), MyUnicode)
self.assertTrue(isinstance(s, unicode))
self.assertEqual(type(literal(s)), unicode)
## Test the engine's escape attribute.
def test__escape__uses_renderer_escape(self):
"""
Test that escape uses the renderer's escape function.
"""
renderer = Renderer()
renderer.escape = lambda s: "**" + s
engine = renderer._make_render_engine()
escape = engine.escape
self.assertEqual(escape("foo"), "**foo")
def test__escape__uses_renderer_unicode(self):
"""
Test that escape uses the renderer's unicode function.
"""
renderer = Renderer()
renderer.unicode = mock_unicode
engine = renderer._make_render_engine()
escape = engine.escape
b = u"foo".encode('ascii')
self.assertEqual(escape(b), "FOO")
def test__escape__has_access_to_original_unicode_subclass(self):
"""
Test that escape receives strings with the unicode subclass intact.
"""
renderer = Renderer()
renderer.escape = lambda s: unicode(type(s).__name__)
engine = renderer._make_render_engine()
escape = engine.escape
class MyUnicode(unicode):
pass
self.assertEqual(escape(u"foo".encode('ascii')), unicode.__name__)
self.assertEqual(escape(u"foo"), unicode.__name__)
self.assertEqual(escape(MyUnicode("foo")), MyUnicode.__name__)
def test__escape__returns_unicode(self):
"""
Test that literal returns unicode (and not a subclass).
"""
renderer = Renderer()
renderer.string_encoding = 'ascii'
engine = renderer._make_render_engine()
escape = engine.escape
self.assertEqual(type(escape("foo")), unicode)
# Check that literal doesn't preserve unicode subclasses.
class MyUnicode(unicode):
pass
s = MyUnicode("abc")
self.assertEqual(type(s), MyUnicode)
self.assertTrue(isinstance(s, unicode))
self.assertEqual(type(escape(s)), unicode)
## Test the missing_tags attribute.
def test__missing_tags__unknown_value(self):
"""
Check missing_tags attribute: setting an unknown value.
"""
renderer = Renderer()
renderer.missing_tags = 'foo'
self.assertException(Exception, "Unsupported 'missing_tags' value: 'foo'",
renderer._make_render_engine)
## Test the engine's resolve_context attribute.
def test__resolve_context(self):
"""
Check resolve_context(): default arguments.
"""
renderer = Renderer()
engine = renderer._make_render_engine()
stack = ContextStack({'foo': 'bar'})
self.assertEqual('bar', engine.resolve_context(stack, 'foo'))
self.assertString(u'', engine.resolve_context(stack, 'missing'))
def test__resolve_context__missing_tags_strict(self):
"""
Check resolve_context(): missing_tags 'strict'.
"""
renderer = Renderer()
renderer.missing_tags = 'strict'
engine = renderer._make_render_engine()
stack = ContextStack({'foo': 'bar'})
self.assertEqual('bar', engine.resolve_context(stack, 'foo'))
self.assertException(KeyNotFoundError, "Key 'missing' not found: first part",
engine.resolve_context, stack, 'missing')

83
third_party/python/pystache/pystache/tests/test_simple.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,83 @@
import unittest
import pystache
from pystache import Renderer
from examples.nested_context import NestedContext
from examples.complex import Complex
from examples.lambdas import Lambdas
from examples.template_partial import TemplatePartial
from examples.simple import Simple
from pystache.tests.common import EXAMPLES_DIR
from pystache.tests.common import AssertStringMixin
class TestSimple(unittest.TestCase, AssertStringMixin):
def test_nested_context(self):
renderer = Renderer()
view = NestedContext(renderer)
view.template = '{{#foo}}{{thing1}} and {{thing2}} and {{outer_thing}}{{/foo}}{{^foo}}Not foo!{{/foo}}'
actual = renderer.render(view)
self.assertString(actual, u"one and foo and two")
def test_looping_and_negation_context(self):
template = '{{#item}}{{header}}: {{name}} {{/item}}{{^item}} Shouldnt see me{{/item}}'
context = Complex()
renderer = Renderer()
actual = renderer.render(template, context)
self.assertEqual(actual, "Colors: red Colors: green Colors: blue ")
def test_empty_context(self):
template = '{{#empty_list}}Shouldnt see me {{/empty_list}}{{^empty_list}}Should see me{{/empty_list}}'
self.assertEqual(pystache.Renderer().render(template), "Should see me")
def test_callables(self):
view = Lambdas()
view.template = '{{#replace_foo_with_bar}}foo != bar. oh, it does!{{/replace_foo_with_bar}}'
renderer = Renderer()
actual = renderer.render(view)
self.assertString(actual, u'bar != bar. oh, it does!')
def test_rendering_partial(self):
renderer = Renderer(search_dirs=EXAMPLES_DIR)
view = TemplatePartial(renderer=renderer)
view.template = '{{>inner_partial}}'
actual = renderer.render(view)
self.assertString(actual, u'Again, Welcome!')
view.template = '{{#looping}}{{>inner_partial}} {{/looping}}'
actual = renderer.render(view)
self.assertString(actual, u"Again, Welcome! Again, Welcome! Again, Welcome! ")
def test_non_existent_value_renders_blank(self):
view = Simple()
template = '{{not_set}} {{blank}}'
self.assertEqual(pystache.Renderer().render(template), ' ')
def test_template_partial_extension(self):
"""
Side note:
From the spec--
Partial tags SHOULD be treated as standalone when appropriate.
In particular, this means that trailing newlines should be removed.
"""
renderer = Renderer(search_dirs=EXAMPLES_DIR, file_extension='txt')
view = TemplatePartial(renderer=renderer)
actual = renderer.render(view)
self.assertString(actual, u"""Welcome
-------
## Again, Welcome! ##""")

435
third_party/python/pystache/pystache/tests/test_specloader.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,435 @@
# coding: utf-8
"""
Unit tests for template_spec.py.
"""
import os.path
import sys
import unittest
import examples
from examples.simple import Simple
from examples.complex import Complex
from examples.lambdas import Lambdas
from examples.inverted import Inverted, InvertedLists
from pystache import Renderer
from pystache import TemplateSpec
from pystache.common import TemplateNotFoundError
from pystache.locator import Locator
from pystache.loader import Loader
from pystache.specloader import SpecLoader
from pystache.tests.common import DATA_DIR, EXAMPLES_DIR
from pystache.tests.common import AssertIsMixin, AssertStringMixin
from pystache.tests.data.views import SampleView
from pystache.tests.data.views import NonAscii
class Thing(object):
pass
class AssertPathsMixin:
"""A unittest.TestCase mixin to check path equality."""
def assertPaths(self, actual, expected):
self.assertEqual(actual, expected)
class ViewTestCase(unittest.TestCase, AssertStringMixin):
def test_template_rel_directory(self):
"""
Test that View.template_rel_directory is respected.
"""
class Tagless(TemplateSpec):
pass
view = Tagless()
renderer = Renderer()
self.assertRaises(TemplateNotFoundError, renderer.render, view)
# TODO: change this test to remove the following brittle line.
view.template_rel_directory = "examples"
actual = renderer.render(view)
self.assertEqual(actual, "No tags...")
def test_template_path_for_partials(self):
"""
Test that View.template_rel_path is respected for partials.
"""
spec = TemplateSpec()
spec.template = "Partial: {{>tagless}}"
renderer1 = Renderer()
renderer2 = Renderer(search_dirs=EXAMPLES_DIR)
actual = renderer1.render(spec)
self.assertString(actual, u"Partial: ")
actual = renderer2.render(spec)
self.assertEqual(actual, "Partial: No tags...")
def test_basic_method_calls(self):
renderer = Renderer()
actual = renderer.render(Simple())
self.assertString(actual, u"Hi pizza!")
def test_non_callable_attributes(self):
view = Simple()
view.thing = 'Chris'
renderer = Renderer()
actual = renderer.render(view)
self.assertEqual(actual, "Hi Chris!")
def test_complex(self):
renderer = Renderer()
actual = renderer.render(Complex())
self.assertString(actual, u"""\
<h1>Colors</h1>
<ul>
<li><strong>red</strong></li>
<li><a href="#Green">green</a></li>
<li><a href="#Blue">blue</a></li>
</ul>""")
def test_higher_order_replace(self):
renderer = Renderer()
actual = renderer.render(Lambdas())
self.assertEqual(actual, 'bar != bar. oh, it does!')
def test_higher_order_rot13(self):
view = Lambdas()
view.template = '{{#rot13}}abcdefghijklm{{/rot13}}'
renderer = Renderer()
actual = renderer.render(view)
self.assertString(actual, u'nopqrstuvwxyz')
def test_higher_order_lambda(self):
view = Lambdas()
view.template = '{{#sort}}zyxwvutsrqponmlkjihgfedcba{{/sort}}'
renderer = Renderer()
actual = renderer.render(view)
self.assertString(actual, u'abcdefghijklmnopqrstuvwxyz')
def test_partials_with_lambda(self):
view = Lambdas()
view.template = '{{>partial_with_lambda}}'
renderer = Renderer(search_dirs=EXAMPLES_DIR)
actual = renderer.render(view)
self.assertEqual(actual, u'nopqrstuvwxyz')
def test_hierarchical_partials_with_lambdas(self):
view = Lambdas()
view.template = '{{>partial_with_partial_and_lambda}}'
renderer = Renderer(search_dirs=EXAMPLES_DIR)
actual = renderer.render(view)
self.assertString(actual, u'nopqrstuvwxyznopqrstuvwxyz')
def test_inverted(self):
renderer = Renderer()
actual = renderer.render(Inverted())
self.assertString(actual, u"""one, two, three, empty list""")
def test_accessing_properties_on_parent_object_from_child_objects(self):
parent = Thing()
parent.this = 'derp'
parent.children = [Thing()]
view = Simple()
view.template = "{{#parent}}{{#children}}{{this}}{{/children}}{{/parent}}"
renderer = Renderer()
actual = renderer.render(view, {'parent': parent})
self.assertString(actual, u'derp')
def test_inverted_lists(self):
renderer = Renderer()
actual = renderer.render(InvertedLists())
self.assertString(actual, u"""one, two, three, empty list""")
def _make_specloader():
"""
Return a default SpecLoader instance for testing purposes.
"""
# Python 2 and 3 have different default encodings. Thus, to have
# consistent test results across both versions, we need to specify
# the string and file encodings explicitly rather than relying on
# the defaults.
def to_unicode(s, encoding=None):
"""
Raises a TypeError exception if the given string is already unicode.
"""
if encoding is None:
encoding = 'ascii'
return unicode(s, encoding, 'strict')
loader = Loader(file_encoding='ascii', to_unicode=to_unicode)
return SpecLoader(loader=loader)
class SpecLoaderTests(unittest.TestCase, AssertIsMixin, AssertStringMixin,
AssertPathsMixin):
"""
Tests template_spec.SpecLoader.
"""
def _make_specloader(self):
return _make_specloader()
def test_init__defaults(self):
spec_loader = SpecLoader()
# Check the loader attribute.
loader = spec_loader.loader
self.assertEqual(loader.extension, 'mustache')
self.assertEqual(loader.file_encoding, sys.getdefaultencoding())
# TODO: finish testing the other Loader attributes.
to_unicode = loader.to_unicode
def test_init__loader(self):
loader = Loader()
custom = SpecLoader(loader=loader)
self.assertIs(custom.loader, loader)
# TODO: rename to something like _assert_load().
def _assert_template(self, loader, custom, expected):
self.assertString(loader.load(custom), expected)
def test_load__template__type_str(self):
"""
Test the template attribute: str string.
"""
custom = TemplateSpec()
custom.template = "abc"
spec_loader = self._make_specloader()
self._assert_template(spec_loader, custom, u"abc")
def test_load__template__type_unicode(self):
"""
Test the template attribute: unicode string.
"""
custom = TemplateSpec()
custom.template = u"abc"
spec_loader = self._make_specloader()
self._assert_template(spec_loader, custom, u"abc")
def test_load__template__unicode_non_ascii(self):
"""
Test the template attribute: non-ascii unicode string.
"""
custom = TemplateSpec()
custom.template = u"é"
spec_loader = self._make_specloader()
self._assert_template(spec_loader, custom, u"é")
def test_load__template__with_template_encoding(self):
"""
Test the template attribute: with template encoding attribute.
"""
custom = TemplateSpec()
custom.template = u'é'.encode('utf-8')
spec_loader = self._make_specloader()
self.assertRaises(UnicodeDecodeError, self._assert_template, spec_loader, custom, u'é')
custom.template_encoding = 'utf-8'
self._assert_template(spec_loader, custom, u'é')
# TODO: make this test complete.
def test_load__template__correct_loader(self):
"""
Test that reader.unicode() is called correctly.
This test tests that the correct reader is called with the correct
arguments. This is a catch-all test to supplement the other
test cases. It tests SpecLoader.load() independent of reader.unicode()
being implemented correctly (and tested).
"""
class MockLoader(Loader):
def __init__(self):
self.s = None
self.encoding = None
# Overrides the existing method.
def unicode(self, s, encoding=None):
self.s = s
self.encoding = encoding
return u"foo"
loader = MockLoader()
custom_loader = SpecLoader()
custom_loader.loader = loader
view = TemplateSpec()
view.template = "template-foo"
view.template_encoding = "encoding-foo"
# Check that our unicode() above was called.
self._assert_template(custom_loader, view, u'foo')
self.assertEqual(loader.s, "template-foo")
self.assertEqual(loader.encoding, "encoding-foo")
def test_find__template_path(self):
"""Test _find() with TemplateSpec.template_path."""
loader = self._make_specloader()
custom = TemplateSpec()
custom.template_path = "path/foo"
actual = loader._find(custom)
self.assertPaths(actual, "path/foo")
# TODO: migrate these tests into the SpecLoaderTests class.
# TODO: rename the get_template() tests to test load().
# TODO: condense, reorganize, and rename the tests so that it is
# clear whether we have full test coverage (e.g. organized by
# TemplateSpec attributes or something).
class TemplateSpecTests(unittest.TestCase, AssertPathsMixin):
def _make_loader(self):
return _make_specloader()
def _assert_template_location(self, view, expected):
loader = self._make_loader()
actual = loader._find_relative(view)
self.assertEqual(actual, expected)
def test_find_relative(self):
"""
Test _find_relative(): default behavior (no attributes set).
"""
view = SampleView()
self._assert_template_location(view, (None, 'sample_view.mustache'))
def test_find_relative__template_rel_path__file_name_only(self):
"""
Test _find_relative(): template_rel_path attribute.
"""
view = SampleView()
view.template_rel_path = 'template.txt'
self._assert_template_location(view, ('', 'template.txt'))
def test_find_relative__template_rel_path__file_name_with_directory(self):
"""
Test _find_relative(): template_rel_path attribute.
"""
view = SampleView()
view.template_rel_path = 'foo/bar/template.txt'
self._assert_template_location(view, ('foo/bar', 'template.txt'))
def test_find_relative__template_rel_directory(self):
"""
Test _find_relative(): template_rel_directory attribute.
"""
view = SampleView()
view.template_rel_directory = 'foo'
self._assert_template_location(view, ('foo', 'sample_view.mustache'))
def test_find_relative__template_name(self):
"""
Test _find_relative(): template_name attribute.
"""
view = SampleView()
view.template_name = 'new_name'
self._assert_template_location(view, (None, 'new_name.mustache'))
def test_find_relative__template_extension(self):
"""
Test _find_relative(): template_extension attribute.
"""
view = SampleView()
view.template_extension = 'txt'
self._assert_template_location(view, (None, 'sample_view.txt'))
def test_find__with_directory(self):
"""
Test _find() with a view that has a directory specified.
"""
loader = self._make_loader()
view = SampleView()
view.template_rel_path = os.path.join('foo', 'bar.txt')
self.assertTrue(loader._find_relative(view)[0] is not None)
actual = loader._find(view)
expected = os.path.join(DATA_DIR, 'foo', 'bar.txt')
self.assertPaths(actual, expected)
def test_find__without_directory(self):
"""
Test _find() with a view that doesn't have a directory specified.
"""
loader = self._make_loader()
view = SampleView()
self.assertTrue(loader._find_relative(view)[0] is None)
actual = loader._find(view)
expected = os.path.join(DATA_DIR, 'sample_view.mustache')
self.assertPaths(actual, expected)
def _assert_get_template(self, custom, expected):
loader = self._make_loader()
actual = loader.load(custom)
self.assertEqual(type(actual), unicode)
self.assertEqual(actual, expected)
def test_get_template(self):
"""
Test get_template(): default behavior (no attributes set).
"""
view = SampleView()
self._assert_get_template(view, u"ascii: abc")
def test_get_template__template_encoding(self):
"""
Test get_template(): template_encoding attribute.
"""
view = NonAscii()
self.assertRaises(UnicodeDecodeError, self._assert_get_template, view, 'foo')
view.template_encoding = 'utf-8'
self._assert_get_template(view, u"non-ascii: é")

5
third_party/python/pystache/setup.cfg поставляемый Normal file
Просмотреть файл

@ -0,0 +1,5 @@
[egg_info]
tag_build =
tag_date = 0
tag_svn_revision = 0

1
third_party/python/requirements.in поставляемый
Просмотреть файл

@ -36,6 +36,7 @@ pip-tools==5.5.0
ply==3.10
pyasn1==0.4.8
pyasn1-modules==0.2.8
pystache==0.5.4
pytest==3.6.2
python-hglib==2.4
pytoml==0.1.10

3
third_party/python/requirements.txt поставляемый
Просмотреть файл

@ -214,6 +214,9 @@ pyasn1==0.4.8 \
pyrsistent==0.16.0 \
--hash=sha256:28669905fe725965daa16184933676547c5bb40a5153055a8dee2a4bd7933ad3
# via jsonschema
pystache==0.5.4 \
--hash=sha256:f7bbc265fb957b4d6c7c042b336563179444ab313fb93a719759111eabd3b85a
# via -r requirements-mach-vendor-python.in
pytest==3.6.2 \
--hash=sha256:8ea01fc4fcc8e1b1e305252b4bc80a1528019ab99fd3b88666c9dc38d754406c \
--hash=sha256:90898786b3d0b880b47645bae7b51aa9bbf1e9d1e4510c2cfd15dd65c70ea0cd