Skip to content

Commit

Permalink
split tests into files and change flake8/pytest setup (#35)
Browse files Browse the repository at this point in the history
* extends tox and travis config to more python versions
* lines up closer with pep8
* fixes #32
  • Loading branch information
RonnyPfannschmidt authored Nov 18, 2016
1 parent aef418c commit 8e0c74d
Show file tree
Hide file tree
Showing 13 changed files with 1,249 additions and 1,157 deletions.
32 changes: 19 additions & 13 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
sudo: false
language: python
python:

- '2.6'
- '2.7'
- '3.3'
- '3.4'
- '3.5'
- '3.6-dev'
- pypy
- nightly
# command to install dependencies
install: "pip install -U tox"
# # command to run tests
env:
matrix:
- TESTENV=check
- TESTENV=py26-pytest27
- TESTENV=py26-pytest
- TESTENV=py27-pytest27
- TESTENV=py27-pytest
- TESTENV=py34-pytest27
- TESTENV=py34-pytest
- TESTENV=py35-pytest27
- TESTENV=py35-pytest
- TESTENV=pypy-pytest27
- TESTENV=pypy-pytest

script: tox --recreate -e $TESTENV
- TOXENV=py-pytest28
- TOXENV=py-pytest29
- TOXENV=py-pytest30
matrix:
include:
- python: '2.7'
env: TOXENV=check
- python: '3.5'
env: TOXENV=check
script:
- tox --recreate -e $TOXENV

notifications:
irc:
Expand Down
13 changes: 7 additions & 6 deletions pluggy.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def setattr_hookspec_opts(func):
if historic and firstresult:
raise ValueError("cannot have a historic firstresult hook")
setattr(func, self.project_name + "_spec",
dict(firstresult=firstresult, historic=historic))
dict(firstresult=firstresult, historic=historic))
return func

if function is not None:
Expand Down Expand Up @@ -150,8 +150,8 @@ def __call__(self, function=None, hookwrapper=False, optionalhook=False,
"""
def setattr_hookimpl_opts(func):
setattr(func, self.project_name + "_impl",
dict(hookwrapper=hookwrapper, optionalhook=optionalhook,
tryfirst=tryfirst, trylast=trylast))
dict(hookwrapper=hookwrapper, optionalhook=optionalhook,
tryfirst=tryfirst, trylast=trylast))
return func

if function is None:
Expand Down Expand Up @@ -232,7 +232,7 @@ def get(self, name):
def _raise_wrapfail(wrap_controller, msg):
co = wrap_controller.gi_code
raise RuntimeError("wrap_controller at %r %s:%d %s" %
(co.co_name, co.co_filename, co.co_firstlineno, msg))
(co.co_name, co.co_filename, co.co_firstlineno, msg))


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


if not _py3:
exec("""
def _reraise(cls, val, tb):
Expand Down Expand Up @@ -348,7 +349,7 @@ def register(self, plugin, name=None):
if self._name2plugin.get(plugin_name, -1) is None:
return # blocked plugin, return None to indicate no registration
raise ValueError("Plugin already registered: %s=%s\n%s" %
(plugin_name, plugin, self._name2plugin))
(plugin_name, plugin, self._name2plugin))

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

def check_pending(self):
""" Verify that all hooks which have not been verified against
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,6 @@ def main():
py_modules=['pluggy'],
)


if __name__ == '__main__':
main()
30 changes: 30 additions & 0 deletions testing/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import pytest


@pytest.fixture(
params=[
lambda spec: spec,
lambda spec: spec()
],
ids=[
"spec-is-class",
"spec-is-instance"
],
)
def he_pm(request, pm):
from pluggy import HookspecMarker
hookspec = HookspecMarker("example")

class Hooks:
@hookspec
def he_method1(self, arg):
return arg + 1

pm.add_hookspecs(request.param(Hooks))
return pm


@pytest.fixture
def pm():
from pluggy import PluginManager
return PluginManager("example")
64 changes: 64 additions & 0 deletions testing/test_details.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from pluggy import PluginManager, HookimplMarker, HookspecMarker


hookspec = HookspecMarker("example")
hookimpl = HookimplMarker("example")


def test_parse_hookimpl_override():
class MyPluginManager(PluginManager):
def parse_hookimpl_opts(self, module_or_class, name):
opts = PluginManager.parse_hookimpl_opts(
self, module_or_class, name)
if opts is None:
if name.startswith("x1"):
opts = {}
return opts

class Plugin:
def x1meth(self):
pass

@hookimpl(hookwrapper=True, tryfirst=True)
def x1meth2(self):
pass

class Spec:
@hookspec
def x1meth(self):
pass

@hookspec
def x1meth2(self):
pass

pm = MyPluginManager(hookspec.project_name)
pm.register(Plugin())
pm.add_hookspecs(Spec)
assert not pm.hook.x1meth._nonwrappers[0].hookwrapper
assert not pm.hook.x1meth._nonwrappers[0].tryfirst
assert not pm.hook.x1meth._nonwrappers[0].trylast
assert not pm.hook.x1meth._nonwrappers[0].optionalhook

assert pm.hook.x1meth2._wrappers[0].tryfirst
assert pm.hook.x1meth2._wrappers[0].hookwrapper


def test_plugin_getattr_raises_errors():
"""Pluggy must be able to handle plugins which raise weird exceptions
when getattr() gets called (#11).
"""
class DontTouchMe:
def __getattr__(self, x):
raise Exception('cant touch me')

class Module:
pass

module = Module()
module.x = DontTouchMe()

pm = PluginManager(hookspec.project_name)
# register() would raise an error
pm.register(module, 'donttouch')
assert pm.get_plugin('donttouch') is module
68 changes: 68 additions & 0 deletions testing/test_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from pluggy import _formatdef, varnames


def test_varnames():
def f(x):
i = 3 # noqa

class A:
def f(self, y):
pass

class B(object):
def __call__(self, z):
pass

assert varnames(f) == ("x",)
assert varnames(A().f) == ('y',)
assert varnames(B()) == ('z',)


def test_varnames_default():
def f(x, y=3):
pass

assert varnames(f) == ("x",)


def test_varnames_class():
class C:
def __init__(self, x):
pass

class D:
pass

class E(object):
def __init__(self, x):
pass

class F(object):
pass

assert varnames(C) == ("x",)
assert varnames(D) == ()
assert varnames(E) == ("x",)
assert varnames(F) == ()


def test_formatdef():
def function1():
pass

assert _formatdef(function1) == 'function1()'

def function2(arg1):
pass

assert _formatdef(function2) == "function2(arg1)"

def function3(arg1, arg2="qwe"):
pass

assert _formatdef(function3) == "function3(arg1, arg2='qwe')"

def function4(arg1, *args, **kwargs):
pass

assert _formatdef(function4) == "function4(arg1, *args, **kwargs)"
78 changes: 78 additions & 0 deletions testing/test_hookrelay.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import pytest
from pluggy import PluginValidationError, HookimplMarker, HookspecMarker


hookspec = HookspecMarker("example")
hookimpl = HookimplMarker("example")


def test_happypath(pm):
class Api:
@hookspec
def hello(self, arg):
"api hook 1"

pm.add_hookspecs(Api)
hook = pm.hook
assert hasattr(hook, 'hello')
assert repr(hook.hello).find("hello") != -1

class Plugin:
@hookimpl
def hello(self, arg):
return arg + 1

plugin = Plugin()
pm.register(plugin)
l = hook.hello(arg=3)
assert l == [4]
assert not hasattr(hook, 'world')
pm.unregister(plugin)
assert hook.hello(arg=3) == []


def test_argmismatch(pm):
class Api:
@hookspec
def hello(self, arg):
"api hook 1"

pm.add_hookspecs(Api)

class Plugin:
@hookimpl
def hello(self, argwrong):
pass

with pytest.raises(PluginValidationError) as exc:
pm.register(Plugin())

assert "argwrong" in str(exc.value)


def test_only_kwargs(pm):
class Api:
@hookspec
def hello(self, arg):
"api hook 1"

pm.add_hookspecs(Api)
pytest.raises(TypeError, lambda: pm.hook.hello(3))


def test_firstresult_definition(pm):
class Api:
@hookspec(firstresult=True)
def hello(self, arg):
"api hook 1"

pm.add_hookspecs(Api)

class Plugin:
@hookimpl
def hello(self, arg):
return arg + 1

pm.register(Plugin())
res = pm.hook.hello(arg=3)
assert res == 4
Loading

0 comments on commit 8e0c74d

Please sign in to comment.