Automated merge with ssh://team@pocoo.org/jinja2-main
[jinja2.git] / tests / conftest.py
1 # -*- coding: utf-8 -*-
2 """
3     conftest
4     ~~~~~~~~
5
6     Configure py.test for support stuff.
7
8     :copyright: 2007 by Armin Ronacher, Alexander Schremmer.
9     :license: BSD, see LICENSE for more details.
10 """
11
12 import os
13 import sys
14 sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
15
16 import py
17 from jinja2 import Environment
18 from jinja2.loaders import BaseLoader
19 from jinja2.exceptions import TemplateNotFound
20
21
22 try:
23     # This code adds support for coverage.py (see
24     # http://nedbatchelder.com/code/modules/coverage.html).
25     # It prints a coverage report for the modules specified in all
26     # module globals (of the test modules) named "coverage_modules".
27
28     import coverage, atexit
29
30     IGNORED_MODULES = ['jinja2._speedups', 'jinja2.defaults',
31                        'jinja2.translators']
32
33     def report_coverage():
34         coverage.stop()
35         module_list = [
36             mod for name, mod in sys.modules.copy().iteritems() if
37             getattr(mod, '__file__', None) and
38             name.startswith('jinja2.') and
39             name not in IGNORED_MODULES
40         ]
41         module_list.sort()
42         coverage.report(module_list)
43
44     def callback(option, opt_str, value, parser):
45         atexit.register(report_coverage)
46         coverage.erase()
47         coverage.start()
48
49     py.test.config.addoptions('Test options', py.test.config.Option('-C',
50         '--coverage', action='callback', callback=callback,
51         help='Output information about code coverage (slow!)'))
52
53 except ImportError:
54     coverage = None
55
56
57 class GlobalLoader(BaseLoader):
58     scope = globals()
59
60     def get_source(self, environment, name):
61         try:
62             return self.scope[name.upper() + 'TEMPLATE'], None, None
63         except KeyError:
64             raise TemplateNotFound(name)
65
66
67 loader = GlobalLoader()
68 simple_env = Environment(trim_blocks=True, loader=loader, cache_size=0)
69
70
71 class Directory(py.test.collect.Directory):
72
73     def run(self):
74         rv = super(Directory, self).run()
75         if self.fspath.basename == 'tests':
76             rv.append('doctests')
77         return rv
78
79     def join(self, name):
80         if name == 'doctests':
81             return JinjaDocTestModule(name, parent=self)
82         return super(Directory, self).join(name)
83
84
85 class Module(py.test.collect.Module):
86
87     def __init__(self, *args, **kwargs):
88         self.env = simple_env
89         super(Module, self).__init__(*args, **kwargs)
90
91     def makeitem(self, name, obj, usefilters=True):
92         if name.startswith('test_'):
93             if hasattr(obj, 'func_code'):
94                 return JinjaTestFunction(name, parent=self)
95             elif isinstance(obj, basestring):
96                 return JinjaDocTest(name, parent=self)
97
98
99 class JinjaTestFunction(py.test.collect.Function):
100
101     def execute(self, target, *args):
102         loader.scope = target.func_globals
103         co = target.func_code
104         if 'env' in co.co_varnames[:co.co_argcount]:
105             target(self.parent.env, *args)
106         else:
107             target(*args)
108
109
110 class JinjaDocTest(py.test.collect.Item):
111
112     def __init__(self, *args, **kwargs):
113         realmod = kwargs.pop('realmod', False)
114         super(JinjaDocTest, self).__init__(*args, **kwargs)
115         self.realmod = realmod
116
117     def run(self):
118         if self.realmod:
119             mod = __import__(self.name, None, None, [''])
120         else:
121             mod = py.std.types.ModuleType(self.name)
122             mod.__doc__ = self.obj
123             mod.env = self.parent.env
124             mod.MODULE = self.parent.obj
125         self.execute(mod)
126
127     def execute(self, mod):
128         failed, tot = py.compat.doctest.testmod(mod, verbose=True)
129         if failed:
130             py.test.fail('doctest %s: %s failed out of %s' % (
131                          self.fspath, failed, tot))
132
133
134 class JinjaDocTestModule(py.test.collect.Module):
135
136     def __init__(self, *args, **kwargs):
137         super(JinjaDocTestModule, self).__init__(*args, **kwargs)
138         self.doctest_modules = [
139             'jinja2.environment', 'jinja2.compiler', 'jinja2.parser',
140             'jinja2.lexer', 'jinja2.ext', 'jinja2.sandbox',
141             'jinja2.filters', 'jinja2.tests', 'jinja2.utils',
142             'jinja2.runtime'
143         ]
144
145     def run(self):
146         return self.doctest_modules
147
148     def join(self, name):
149         return JinjaDocTest(name, parent=self, realmod=True)