5
5
import os
6
6
import sys
7
7
8
- from _pytest .config import hookimpl
9
- from _pytest .monkeypatch import monkeypatch
10
8
from _pytest .assertion import util
9
+ from _pytest .assertion import rewrite
11
10
12
11
13
12
def pytest_addoption (parser ):
14
13
group = parser .getgroup ("debugconfig" )
15
14
group .addoption ('--assert' ,
16
15
action = "store" ,
17
16
dest = "assertmode" ,
18
- choices = ("rewrite" , "reinterp" , " plain" ,),
17
+ choices = ("rewrite" , "plain" ,),
19
18
default = "rewrite" ,
20
19
metavar = "MODE" ,
21
- help = """control assertion debugging tools. 'plain'
22
- performs no assertion debugging. 'reinterp'
23
- reinterprets assert statements after they failed
24
- to provide assertion expression information.
25
- 'rewrite' (the default) rewrites assert
26
- statements in test modules on import to
27
- provide assert expression information. """ )
20
+ help = """Control assertion debugging tools. 'plain'
21
+ performs no assertion debugging. 'rewrite'
22
+ (the default) rewrites assert statements in
23
+ test modules on import to provide assert
24
+ expression information.""" )
25
+
26
+
27
+ def pytest_namespace ():
28
+ return {'register_assert_rewrite' : register_assert_rewrite }
29
+
30
+
31
+ def register_assert_rewrite (* names ):
32
+ """Register a module name to be rewritten on import.
33
+
34
+ This function will make sure that the module will get it's assert
35
+ statements rewritten when it is imported. Thus you should make
36
+ sure to call this before the module is actually imported, usually
37
+ in your __init__.py if you are a plugin using a package.
38
+ """
39
+ for hook in sys .meta_path :
40
+ if isinstance (hook , rewrite .AssertionRewritingHook ):
41
+ importhook = hook
42
+ break
43
+ else :
44
+ importhook = DummyRewriteHook ()
45
+ importhook .mark_rewrite (* names )
46
+
47
+
48
+ class DummyRewriteHook (object ):
49
+ """A no-op import hook for when rewriting is disabled."""
50
+
51
+ def mark_rewrite (self , * names ):
52
+ pass
28
53
29
54
30
55
class AssertionState :
@@ -33,55 +58,37 @@ class AssertionState:
33
58
def __init__ (self , config , mode ):
34
59
self .mode = mode
35
60
self .trace = config .trace .root .get ("assertion" )
61
+ self .hook = None
62
+
36
63
64
+ def install_importhook (config ):
65
+ """Try to install the rewrite hook, raise SystemError if it fails."""
66
+ # Both Jython and CPython 2.6.0 have AST bugs that make the
67
+ # assertion rewriting hook malfunction.
68
+ if (sys .platform .startswith ('java' ) or
69
+ sys .version_info [:3 ] == (2 , 6 , 0 )):
70
+ raise SystemError ('rewrite not supported' )
37
71
38
- @hookimpl (tryfirst = True )
39
- def pytest_load_initial_conftests (early_config , parser , args ):
40
- ns , ns_unknown_args = parser .parse_known_and_unknown_args (args )
41
- mode = ns .assertmode
42
- if mode == "rewrite" :
43
- try :
44
- import ast # noqa
45
- except ImportError :
46
- mode = "reinterp"
47
- else :
48
- # Both Jython and CPython 2.6.0 have AST bugs that make the
49
- # assertion rewriting hook malfunction.
50
- if (sys .platform .startswith ('java' ) or
51
- sys .version_info [:3 ] == (2 , 6 , 0 )):
52
- mode = "reinterp"
53
-
54
- early_config ._assertstate = AssertionState (early_config , mode )
55
- warn_about_missing_assertion (mode , early_config .pluginmanager )
56
-
57
- if mode != "plain" :
58
- _load_modules (mode )
59
- m = monkeypatch ()
60
- early_config ._cleanup .append (m .undo )
61
- m .setattr (py .builtin .builtins , 'AssertionError' ,
62
- reinterpret .AssertionError ) # noqa
63
-
64
- hook = None
65
- if mode == "rewrite" :
66
- hook = rewrite .AssertionRewritingHook (early_config ) # noqa
67
- sys .meta_path .insert (0 , hook )
68
-
69
- early_config ._assertstate .hook = hook
70
- early_config ._assertstate .trace ("configured with mode set to %r" % (mode ,))
72
+ config ._assertstate = AssertionState (config , 'rewrite' )
73
+ config ._assertstate .hook = hook = rewrite .AssertionRewritingHook (config )
74
+ sys .meta_path .insert (0 , hook )
75
+ config ._assertstate .trace ('installed rewrite import hook' )
71
76
def undo ():
72
- hook = early_config ._assertstate .hook
77
+ hook = config ._assertstate .hook
73
78
if hook is not None and hook in sys .meta_path :
74
79
sys .meta_path .remove (hook )
75
- early_config .add_cleanup (undo )
80
+ config .add_cleanup (undo )
81
+ return hook
76
82
77
83
78
84
def pytest_collection (session ):
79
85
# this hook is only called when test modules are collected
80
86
# so for example not in the master process of pytest-xdist
81
87
# (which does not collect test modules)
82
- hook = session .config ._assertstate .hook
83
- if hook is not None :
84
- hook .set_session (session )
88
+ assertstate = getattr (session .config , '_assertstate' , None )
89
+ if assertstate :
90
+ if assertstate .hook is not None :
91
+ assertstate .hook .set_session (session )
85
92
86
93
87
94
def _running_on_ci ():
@@ -138,43 +145,10 @@ def pytest_runtest_teardown(item):
138
145
139
146
140
147
def pytest_sessionfinish (session ):
141
- hook = session .config ._assertstate .hook
142
- if hook is not None :
143
- hook .session = None
144
-
145
-
146
- def _load_modules (mode ):
147
- """Lazily import assertion related code."""
148
- global rewrite , reinterpret
149
- from _pytest .assertion import reinterpret # noqa
150
- if mode == "rewrite" :
151
- from _pytest .assertion import rewrite # noqa
152
-
153
-
154
- def warn_about_missing_assertion (mode , pluginmanager ):
155
- try :
156
- assert False
157
- except AssertionError :
158
- pass
159
- else :
160
- if mode == "rewrite" :
161
- specifically = ("assertions which are not in test modules "
162
- "will be ignored" )
163
- else :
164
- specifically = "failing tests may report as passing"
165
-
166
- # temporarily disable capture so we can print our warning
167
- capman = pluginmanager .getplugin ('capturemanager' )
168
- try :
169
- out , err = capman .suspendcapture ()
170
- sys .stderr .write ("WARNING: " + specifically +
171
- " because assert statements are not executed "
172
- "by the underlying Python interpreter "
173
- "(are you using python -O?)\n " )
174
- finally :
175
- capman .resumecapture ()
176
- sys .stdout .write (out )
177
- sys .stderr .write (err )
148
+ assertstate = getattr (session .config , '_assertstate' , None )
149
+ if assertstate :
150
+ if assertstate .hook is not None :
151
+ assertstate .hook .set_session (None )
178
152
179
153
180
154
# Expose this plugin's implementation for the pytest_assertrepr_compare hook
0 commit comments