Skip to content

Commit 8e0c74d

Browse files
split tests into files and change flake8/pytest setup (#35)
* extends tox and travis config to more python versions * lines up closer with pep8 * fixes #32
1 parent aef418c commit 8e0c74d

13 files changed

+1249
-1157
lines changed

.travis.yml

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,31 @@
11
sudo: false
22
language: python
33
python:
4+
5+
- '2.6'
6+
- '2.7'
7+
- '3.3'
8+
- '3.4'
49
- '3.5'
10+
- '3.6-dev'
11+
- pypy
12+
- nightly
513
# command to install dependencies
614
install: "pip install -U tox"
715
# # command to run tests
816
env:
917
matrix:
10-
- TESTENV=check
11-
- TESTENV=py26-pytest27
12-
- TESTENV=py26-pytest
13-
- TESTENV=py27-pytest27
14-
- TESTENV=py27-pytest
15-
- TESTENV=py34-pytest27
16-
- TESTENV=py34-pytest
17-
- TESTENV=py35-pytest27
18-
- TESTENV=py35-pytest
19-
- TESTENV=pypy-pytest27
20-
- TESTENV=pypy-pytest
21-
22-
script: tox --recreate -e $TESTENV
18+
- TOXENV=py-pytest28
19+
- TOXENV=py-pytest29
20+
- TOXENV=py-pytest30
21+
matrix:
22+
include:
23+
- python: '2.7'
24+
env: TOXENV=check
25+
- python: '3.5'
26+
env: TOXENV=check
27+
script:
28+
- tox --recreate -e $TOXENV
2329

2430
notifications:
2531
irc:

pluggy.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def setattr_hookspec_opts(func):
104104
if historic and firstresult:
105105
raise ValueError("cannot have a historic firstresult hook")
106106
setattr(func, self.project_name + "_spec",
107-
dict(firstresult=firstresult, historic=historic))
107+
dict(firstresult=firstresult, historic=historic))
108108
return func
109109

110110
if function is not None:
@@ -150,8 +150,8 @@ def __call__(self, function=None, hookwrapper=False, optionalhook=False,
150150
"""
151151
def setattr_hookimpl_opts(func):
152152
setattr(func, self.project_name + "_impl",
153-
dict(hookwrapper=hookwrapper, optionalhook=optionalhook,
154-
tryfirst=tryfirst, trylast=trylast))
153+
dict(hookwrapper=hookwrapper, optionalhook=optionalhook,
154+
tryfirst=tryfirst, trylast=trylast))
155155
return func
156156

157157
if function is None:
@@ -232,7 +232,7 @@ def get(self, name):
232232
def _raise_wrapfail(wrap_controller, msg):
233233
co = wrap_controller.gi_code
234234
raise RuntimeError("wrap_controller at %r %s:%d %s" %
235-
(co.co_name, co.co_filename, co.co_firstlineno, msg))
235+
(co.co_name, co.co_filename, co.co_firstlineno, msg))
236236

237237

238238
def _wrapped_call(wrap_controller, func):
@@ -279,6 +279,7 @@ def get_result(self):
279279
raise ex[1].with_traceback(ex[2])
280280
_reraise(*ex) # noqa
281281

282+
282283
if not _py3:
283284
exec("""
284285
def _reraise(cls, val, tb):
@@ -348,7 +349,7 @@ def register(self, plugin, name=None):
348349
if self._name2plugin.get(plugin_name, -1) is None:
349350
return # blocked plugin, return None to indicate no registration
350351
raise ValueError("Plugin already registered: %s=%s\n%s" %
351-
(plugin_name, plugin, self._name2plugin))
352+
(plugin_name, plugin, self._name2plugin))
352353

353354
# XXX if an error happens we should make sure no state has been
354355
# changed at point of return
@@ -484,7 +485,7 @@ def _verify_hook(self, hook, hookimpl):
484485
"plugin definition: %s\n"
485486
"available hookargs: %s" %
486487
(hookimpl.plugin_name, hook.name, arg,
487-
_formatdef(hookimpl.function), ", ".join(hook.argnames)))
488+
_formatdef(hookimpl.function), ", ".join(hook.argnames)))
488489

489490
def check_pending(self):
490491
""" Verify that all hooks which have not been verified against

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,6 @@ def main():
4343
py_modules=['pluggy'],
4444
)
4545

46+
4647
if __name__ == '__main__':
4748
main()

testing/conftest.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import pytest
2+
3+
4+
@pytest.fixture(
5+
params=[
6+
lambda spec: spec,
7+
lambda spec: spec()
8+
],
9+
ids=[
10+
"spec-is-class",
11+
"spec-is-instance"
12+
],
13+
)
14+
def he_pm(request, pm):
15+
from pluggy import HookspecMarker
16+
hookspec = HookspecMarker("example")
17+
18+
class Hooks:
19+
@hookspec
20+
def he_method1(self, arg):
21+
return arg + 1
22+
23+
pm.add_hookspecs(request.param(Hooks))
24+
return pm
25+
26+
27+
@pytest.fixture
28+
def pm():
29+
from pluggy import PluginManager
30+
return PluginManager("example")

testing/test_details.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
from pluggy import PluginManager, HookimplMarker, HookspecMarker
2+
3+
4+
hookspec = HookspecMarker("example")
5+
hookimpl = HookimplMarker("example")
6+
7+
8+
def test_parse_hookimpl_override():
9+
class MyPluginManager(PluginManager):
10+
def parse_hookimpl_opts(self, module_or_class, name):
11+
opts = PluginManager.parse_hookimpl_opts(
12+
self, module_or_class, name)
13+
if opts is None:
14+
if name.startswith("x1"):
15+
opts = {}
16+
return opts
17+
18+
class Plugin:
19+
def x1meth(self):
20+
pass
21+
22+
@hookimpl(hookwrapper=True, tryfirst=True)
23+
def x1meth2(self):
24+
pass
25+
26+
class Spec:
27+
@hookspec
28+
def x1meth(self):
29+
pass
30+
31+
@hookspec
32+
def x1meth2(self):
33+
pass
34+
35+
pm = MyPluginManager(hookspec.project_name)
36+
pm.register(Plugin())
37+
pm.add_hookspecs(Spec)
38+
assert not pm.hook.x1meth._nonwrappers[0].hookwrapper
39+
assert not pm.hook.x1meth._nonwrappers[0].tryfirst
40+
assert not pm.hook.x1meth._nonwrappers[0].trylast
41+
assert not pm.hook.x1meth._nonwrappers[0].optionalhook
42+
43+
assert pm.hook.x1meth2._wrappers[0].tryfirst
44+
assert pm.hook.x1meth2._wrappers[0].hookwrapper
45+
46+
47+
def test_plugin_getattr_raises_errors():
48+
"""Pluggy must be able to handle plugins which raise weird exceptions
49+
when getattr() gets called (#11).
50+
"""
51+
class DontTouchMe:
52+
def __getattr__(self, x):
53+
raise Exception('cant touch me')
54+
55+
class Module:
56+
pass
57+
58+
module = Module()
59+
module.x = DontTouchMe()
60+
61+
pm = PluginManager(hookspec.project_name)
62+
# register() would raise an error
63+
pm.register(module, 'donttouch')
64+
assert pm.get_plugin('donttouch') is module

testing/test_helpers.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
from pluggy import _formatdef, varnames
2+
3+
4+
def test_varnames():
5+
def f(x):
6+
i = 3 # noqa
7+
8+
class A:
9+
def f(self, y):
10+
pass
11+
12+
class B(object):
13+
def __call__(self, z):
14+
pass
15+
16+
assert varnames(f) == ("x",)
17+
assert varnames(A().f) == ('y',)
18+
assert varnames(B()) == ('z',)
19+
20+
21+
def test_varnames_default():
22+
def f(x, y=3):
23+
pass
24+
25+
assert varnames(f) == ("x",)
26+
27+
28+
def test_varnames_class():
29+
class C:
30+
def __init__(self, x):
31+
pass
32+
33+
class D:
34+
pass
35+
36+
class E(object):
37+
def __init__(self, x):
38+
pass
39+
40+
class F(object):
41+
pass
42+
43+
assert varnames(C) == ("x",)
44+
assert varnames(D) == ()
45+
assert varnames(E) == ("x",)
46+
assert varnames(F) == ()
47+
48+
49+
def test_formatdef():
50+
def function1():
51+
pass
52+
53+
assert _formatdef(function1) == 'function1()'
54+
55+
def function2(arg1):
56+
pass
57+
58+
assert _formatdef(function2) == "function2(arg1)"
59+
60+
def function3(arg1, arg2="qwe"):
61+
pass
62+
63+
assert _formatdef(function3) == "function3(arg1, arg2='qwe')"
64+
65+
def function4(arg1, *args, **kwargs):
66+
pass
67+
68+
assert _formatdef(function4) == "function4(arg1, *args, **kwargs)"

testing/test_hookrelay.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import pytest
2+
from pluggy import PluginValidationError, HookimplMarker, HookspecMarker
3+
4+
5+
hookspec = HookspecMarker("example")
6+
hookimpl = HookimplMarker("example")
7+
8+
9+
def test_happypath(pm):
10+
class Api:
11+
@hookspec
12+
def hello(self, arg):
13+
"api hook 1"
14+
15+
pm.add_hookspecs(Api)
16+
hook = pm.hook
17+
assert hasattr(hook, 'hello')
18+
assert repr(hook.hello).find("hello") != -1
19+
20+
class Plugin:
21+
@hookimpl
22+
def hello(self, arg):
23+
return arg + 1
24+
25+
plugin = Plugin()
26+
pm.register(plugin)
27+
l = hook.hello(arg=3)
28+
assert l == [4]
29+
assert not hasattr(hook, 'world')
30+
pm.unregister(plugin)
31+
assert hook.hello(arg=3) == []
32+
33+
34+
def test_argmismatch(pm):
35+
class Api:
36+
@hookspec
37+
def hello(self, arg):
38+
"api hook 1"
39+
40+
pm.add_hookspecs(Api)
41+
42+
class Plugin:
43+
@hookimpl
44+
def hello(self, argwrong):
45+
pass
46+
47+
with pytest.raises(PluginValidationError) as exc:
48+
pm.register(Plugin())
49+
50+
assert "argwrong" in str(exc.value)
51+
52+
53+
def test_only_kwargs(pm):
54+
class Api:
55+
@hookspec
56+
def hello(self, arg):
57+
"api hook 1"
58+
59+
pm.add_hookspecs(Api)
60+
pytest.raises(TypeError, lambda: pm.hook.hello(3))
61+
62+
63+
def test_firstresult_definition(pm):
64+
class Api:
65+
@hookspec(firstresult=True)
66+
def hello(self, arg):
67+
"api hook 1"
68+
69+
pm.add_hookspecs(Api)
70+
71+
class Plugin:
72+
@hookimpl
73+
def hello(self, arg):
74+
return arg + 1
75+
76+
pm.register(Plugin())
77+
res = pm.hook.hello(arg=3)
78+
assert res == 4

0 commit comments

Comments
 (0)