Example #1
0
 def test_canonical_import(self, monkeypatch):
     mod = py.std.types.ModuleType("pytest_xyz")
     monkeypatch.setitem(py.std.sys.modules, 'pytest_xyz', mod)
     pp = PluginManager()
     pp.import_plugin('pytest_xyz')
     assert pp.getplugin('pytest_xyz') == mod
     assert pp.isregistered(mod)
Example #2
0
 def test_listattr(self):
     pluginmanager = PluginManager()
     class My2:
         x = 42
     pluginmanager.register(My2())
     assert not pluginmanager.listattr("hello")
     assert pluginmanager.listattr("x") == [42]
Example #3
0
 def test_consider_module(self, testdir):
     pluginmanager = PluginManager()
     testdir.syspathinsert()
     testdir.makepyfile(pytest_p1="#")
     testdir.makepyfile(pytest_p2="#")
     mod = py.std.types.ModuleType("temp")
     mod.pytest_plugins = ["pytest_p1", "pytest_p2"]
     pluginmanager.consider_module(mod)
     assert pluginmanager.getplugin("pytest_p1").__name__ == "pytest_p1"
     assert pluginmanager.getplugin("pytest_p2").__name__ == "pytest_p2"
Example #4
0
 def test_consider_module(self, testdir):
     pluginmanager = PluginManager()
     testdir.syspathinsert()
     testdir.makepyfile(pytest_p1="#")
     testdir.makepyfile(pytest_p2="#")
     mod = py.std.types.ModuleType("temp")
     mod.pytest_plugins = ["pytest_p1", "pytest_p2"]
     pluginmanager.consider_module(mod)
     assert pluginmanager.getplugin("pytest_p1").__name__ == "pytest_p1"
     assert pluginmanager.getplugin("pytest_p2").__name__ == "pytest_p2"
Example #5
0
    def test_import_plugin_dotted_name(self, testdir):
        pluginmanager = PluginManager()
        pytest.raises(ImportError, 'pluginmanager.import_plugin("qweqwex.y")')
        pytest.raises(ImportError, 'pluginmanager.import_plugin("pytest_qweqwex.y")')

        reset = testdir.syspathinsert()
        testdir.mkpydir("pkg").join("plug.py").write("x=3")
        pluginname = "pkg.plug"
        pluginmanager.import_plugin(pluginname)
        mod = pluginmanager.getplugin("pkg.plug")
        assert mod.x == 3
Example #6
0
    def test_import_plugin_dotted_name(self, testdir):
        pluginmanager = PluginManager()
        pytest.raises(ImportError, 'pluginmanager.import_plugin("qweqwex.y")')
        pytest.raises(ImportError,
                      'pluginmanager.import_plugin("pytest_qweqwex.y")')

        reset = testdir.syspathinsert()
        testdir.mkpydir("pkg").join("plug.py").write("x=3")
        pluginname = "pkg.plug"
        pluginmanager.import_plugin(pluginname)
        mod = pluginmanager.getplugin("pkg.plug")
        assert mod.x == 3
Example #7
0
 def test_consider_env_plugin_instantiation(self, testdir, monkeypatch):
     pluginmanager = PluginManager()
     testdir.syspathinsert()
     testdir.makepyfile(xy123="#")
     monkeypatch.setitem(os.environ, 'PYTEST_PLUGINS', 'xy123')
     l1 = len(pluginmanager.getplugins())
     pluginmanager.consider_env()
     l2 = len(pluginmanager.getplugins())
     assert l2 == l1 + 1
     assert pluginmanager.getplugin('xy123')
     pluginmanager.consider_env()
     l3 = len(pluginmanager.getplugins())
     assert l2 == l3
Example #8
0
    def test_listattr_tryfirst(self):
        class P1:
            @pytest.mark.tryfirst
            def m(self):
                return 17

        class P2:
            def m(self):
                return 23

        class P3:
            def m(self):
                return 19

        pluginmanager = PluginManager()
        p1 = P1()
        p2 = P2()
        p3 = P3()
        pluginmanager.register(p1)
        pluginmanager.register(p2)
        pluginmanager.register(p3)
        methods = pluginmanager.listattr('m')
        assert methods == [p2.m, p3.m, p1.m]
        # listattr keeps a cache and deleting
        # a function attribute requires clearing it
        pluginmanager._listattrcache.clear()
        del P1.m.__dict__['tryfirst']

        pytest.mark.trylast(getattr(P2.m, 'im_func', P2.m))
        methods = pluginmanager.listattr('m')
        assert methods == [p2.m, p1.m, p3.m]
Example #9
0
    def test_firstresult_definition(self):
        pm = PluginManager()
        class Api:
            def hello(self, arg):
                "api hook 1"
            hello.firstresult = True

        mcm = HookRelay(hookspecs=Api, pm=pm, prefix="he")
        class Plugin:
            def hello(self, arg):
                return arg + 1
        pm.register(Plugin())
        res = mcm.hello(arg=3)
        assert res == 4
Example #10
0
 def test_plugin_prevent_register(self):
     pluginmanager = PluginManager()
     pluginmanager.consider_preparse(["xyz", "-p", "no:abc"])
     l1 = pluginmanager.getplugins()
     pluginmanager.register(42, name="abc")
     l2 = pluginmanager.getplugins()
     assert len(l2) == len(l1)
Example #11
0
 def test_plugin_prevent_register_unregistered_alredy_registered(self):
     pluginmanager = PluginManager()
     pluginmanager.register(42, name="abc")
     l1 = pluginmanager.getplugins()
     assert 42 in l1
     pluginmanager.consider_preparse(["xyz", "-p", "no:abc"])
     l2 = pluginmanager.getplugins()
     assert 42 not in l2
Example #12
0
    def test_pm_ordering(self):
        pp = PluginManager()

        class A:
            pass

        a1, a2 = A(), A()
        pp.register(a1)
        pp.register(a2, "hello")
        l = pp.getplugins()
        assert l.index(a1) < l.index(a2)
        a3 = A()
        pp.register(a3, prepend=True)
        l = pp.getplugins()
        assert l.index(a3) == 0
Example #13
0
 def test_pm_ordering(self):
     pp = PluginManager()
     class A: pass
     a1, a2 = A(), A()
     pp.register(a1)
     pp.register(a2, "hello")
     l = pp.getplugins()
     assert l.index(a1) < l.index(a2)
     a3 = A()
     pp.register(a3, prepend=True)
     l = pp.getplugins()
     assert l.index(a3) == 0
Example #14
0
    def test_consider_module_import_module(self, testdir):
        mod = py.std.types.ModuleType("x")
        mod.pytest_plugins = "pytest_a"
        aplugin = testdir.makepyfile(pytest_a="#")
        pluginmanager = PluginManager()
        reprec = testdir.getreportrecorder(pluginmanager)
        #syspath.prepend(aplugin.dirpath())
        py.std.sys.path.insert(0, str(aplugin.dirpath()))
        pluginmanager.consider_module(mod)
        call = reprec.getcall(pluginmanager.hook.pytest_plugin_registered.name)
        assert call.plugin.__name__ == "pytest_a"

        # check that it is not registered twice
        pluginmanager.consider_module(mod)
        l = reprec.getcalls("pytest_plugin_registered")
        assert len(l) == 1
Example #15
0
def get_plugin_manager():
    try:
        from _pytest.config import get_plugin_manager
        return get_plugin_manager()
    except ImportError:
        from _pytest.core import PluginManager
        return PluginManager(load=True)
Example #16
0
    def test_happypath(self):
        pm = PluginManager()
        class Api:
            def hello(self, arg):
                "api hook 1"

        mcm = HookRelay(hookspecs=Api, pm=pm, prefix="he")
        assert hasattr(mcm, 'hello')
        assert repr(mcm.hello).find("hello") != -1
        class Plugin:
            def hello(self, arg):
                return arg + 1
        pm.register(Plugin())
        l = mcm.hello(arg=3)
        assert l == [4]
        assert not hasattr(mcm, 'world')
Example #17
0
 def test_consider_env_plugin_instantiation(self, testdir, monkeypatch):
     pluginmanager = PluginManager()
     testdir.syspathinsert()
     testdir.makepyfile(xy123="#")
     monkeypatch.setitem(os.environ, 'PYTEST_PLUGINS', 'xy123')
     l1 = len(pluginmanager.getplugins())
     pluginmanager.consider_env()
     l2 = len(pluginmanager.getplugins())
     assert l2 == l1 + 1
     assert pluginmanager.getplugin('xy123')
     pluginmanager.consider_env()
     l3 = len(pluginmanager.getplugins())
     assert l2 == l3
Example #18
0
    def test_register_mismatch_arg(self):
        pp = PluginManager(load=True)

        class hello:
            def pytest_configure(self, asd):
                pass

        excinfo = pytest.raises(Exception, "pp.register(hello())")
Example #19
0
    def test_register_mismatch_method(self):
        pp = PluginManager(load=True)

        class hello:
            def pytest_gurgel(self):
                pass

        pytest.raises(Exception, "pp.register(hello())")
Example #20
0
    def test_listattr_tryfirst(self):
        class P1:
            @pytest.mark.tryfirst
            def m(self):
                return 17

        class P2:
            def m(self):
                return 23
        class P3:
            def m(self):
                return 19

        pluginmanager = PluginManager()
        p1 = P1()
        p2 = P2()
        p3 = P3()
        pluginmanager.register(p1)
        pluginmanager.register(p2)
        pluginmanager.register(p3)
        methods = pluginmanager.listattr('m')
        assert methods == [p2.m, p3.m, p1.m]
        # listattr keeps a cache and deleting
        # a function attribute requires clearing it
        pluginmanager._listattrcache.clear()
        del P1.m.__dict__['tryfirst']

        pytest.mark.trylast(getattr(P2.m, 'im_func', P2.m))
        methods = pluginmanager.listattr('m')
        assert methods == [p2.m, p1.m, p3.m]
Example #21
0
 def test_plugin_prevent_register(self):
     pluginmanager = PluginManager()
     pluginmanager.consider_preparse(["xyz", "-p", "no:abc"])
     l1 = pluginmanager.getplugins()
     pluginmanager.register(42, name="abc")
     l2 = pluginmanager.getplugins()
     assert len(l2) == len(l1)
Example #22
0
    def test_import_plugin_importname(self, testdir):
        pluginmanager = PluginManager()
        pytest.raises(ImportError, 'pluginmanager.import_plugin("qweqwex.y")')
        pytest.raises(ImportError,
                      'pluginmanager.import_plugin("pytest_qweqwx.y")')

        reset = testdir.syspathinsert()
        pluginname = "pytest_hello"
        testdir.makepyfile(**{pluginname: ""})
        pluginmanager.import_plugin("pytest_hello")
        len1 = len(pluginmanager.getplugins())
        pluginmanager.import_plugin("pytest_hello")
        len2 = len(pluginmanager.getplugins())
        assert len1 == len2
        plugin1 = pluginmanager.getplugin("pytest_hello")
        assert plugin1.__name__.endswith('pytest_hello')
        plugin2 = pluginmanager.getplugin("pytest_hello")
        assert plugin2 is plugin1
Example #23
0
    def test_firstresult_definition(self):
        pm = PluginManager()

        class Api:
            def hello(self, arg):
                "api hook 1"

            hello.firstresult = True

        mcm = HookRelay(hookspecs=Api, pm=pm, prefix="he")

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

        pm.register(Plugin())
        res = mcm.hello(arg=3)
        assert res == 4
Example #24
0
    def test_consider_setuptools_instantiation(self, monkeypatch):
        pkg_resources = py.test.importorskip("pkg_resources")
        def my_iter(name):
            assert name == "pytest11"
            class EntryPoint:
                name = "pytest_mytestplugin"
                dist = None
                def load(self):
                    class PseudoPlugin:
                        x = 42
                    return PseudoPlugin()
            return iter([EntryPoint()])

        monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter)
        pluginmanager = PluginManager()
        pluginmanager.consider_setuptools_entrypoints()
        plugin = pluginmanager.getplugin("mytestplugin")
        assert plugin.x == 42
Example #25
0
    def test_only_kwargs(self):
        pm = PluginManager()

        class Api:
            def hello(self, arg):
                "api hook 1"

        mcm = HookRelay(hookspecs=Api, pm=pm, prefix="he")
        pytest.raises(TypeError, "mcm.hello(3)")
Example #26
0
 def test_plugin_prevent_register_unregistered_alredy_registered(self):
     pluginmanager = PluginManager()
     pluginmanager.register(42, name="abc")
     l1 = pluginmanager.getplugins()
     assert 42 in l1
     pluginmanager.consider_preparse(["xyz", "-p", "no:abc"])
     l2 = pluginmanager.getplugins()
     assert 42 not in l2
Example #27
0
def test_hookrecorder_basic_no_args_hook():
    rec = HookRecorder(PluginManager())
    apimod = type(os)('api')
    def pytest_xyz():
        "x"
    apimod.pytest_xyz = pytest_xyz
    rec.start_recording(apimod)
    rec.hook.pytest_xyz()
    call = rec.popcall("pytest_xyz")
    assert call._name == "pytest_xyz"
Example #28
0
    def test_happypath(self):
        pm = PluginManager()

        class Api:
            def hello(self, arg):
                "api hook 1"

        mcm = HookRelay(hookspecs=Api, pm=pm, prefix="he")
        assert hasattr(mcm, 'hello')
        assert repr(mcm.hello).find("hello") != -1

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

        pm.register(Plugin())
        l = mcm.hello(arg=3)
        assert l == [4]
        assert not hasattr(mcm, 'world')
Example #29
0
    def test_hook_tracing(self):
        pm = PluginManager()
        saveindent = []
        class api1:
            x = 41
            def pytest_plugin_registered(self, plugin):
                saveindent.append(pm.trace.root.indent)
                raise ValueError(42)
        l = []
        pm.trace.root.setwriter(l.append)
        indent = pm.trace.root.indent
        p = api1()
        pm.register(p)

        assert pm.trace.root.indent == indent
        assert len(l) == 1
        assert 'pytest_plugin_registered' in l[0]
        pytest.raises(ValueError, lambda: pm.register(api1()))
        assert pm.trace.root.indent == indent
        assert saveindent[0] > indent
Example #30
0
def test_hookrecorder_basic():
    rec = HookRecorder(PluginManager())
    class ApiClass:
        def pytest_xyz(self, arg):
            "x"
    rec.start_recording(ApiClass)
    rec.hook.pytest_xyz(arg=123)
    call = rec.popcall("pytest_xyz")
    assert call.arg == 123
    assert call._name == "pytest_xyz"
    pytest.raises(pytest.fail.Exception, "rec.popcall('abc')")
Example #31
0
    def test_import_plugin_importname(self, testdir):
        pluginmanager = PluginManager()
        pytest.raises(ImportError, 'pluginmanager.import_plugin("qweqwex.y")')
        pytest.raises(ImportError, 'pluginmanager.import_plugin("pytest_qweqwx.y")')

        reset = testdir.syspathinsert()
        pluginname = "pytest_hello"
        testdir.makepyfile(**{pluginname: ""})
        pluginmanager.import_plugin("pytest_hello")
        len1 = len(pluginmanager.getplugins())
        pluginmanager.import_plugin("pytest_hello")
        len2 = len(pluginmanager.getplugins())
        assert len1 == len2
        plugin1 = pluginmanager.getplugin("pytest_hello")
        assert plugin1.__name__.endswith('pytest_hello')
        plugin2 = pluginmanager.getplugin("pytest_hello")
        assert plugin2 is plugin1
Example #32
0
 def test_canonical_import(self, monkeypatch):
     mod = py.std.types.ModuleType("pytest_xyz")
     monkeypatch.setitem(py.std.sys.modules, 'pytest_xyz', mod)
     pp = PluginManager()
     pp.import_plugin('pytest_xyz')
     assert pp.getplugin('pytest_xyz') == mod
     assert pp.isregistered(mod)
Example #33
0
    def test_notify_exception(self, capfd):
        pp = PluginManager()
        excinfo = pytest.raises(ValueError, "raise ValueError(1)")
        pp.notify_exception(excinfo)
        out, err = capfd.readouterr()
        assert "ValueError" in err

        class A:
            def pytest_internalerror(self, excrepr):
                return True

        pp.register(A())
        pp.notify_exception(excinfo)
        out, err = capfd.readouterr()
        assert not err
Example #34
0
 def __init__(self, pluginmanager=None):
     #: command line option values, usually added via parser.addoption(...)
     #: or parser.getgroup(...).addoption(...) calls
     self.option = CmdOptions()
     self._parser = Parser(
         usage="usage: %prog [options] [file_or_dir] [file_or_dir] [...]",
         processopt=self._processopt,
     )
     #: a pluginmanager instance
     self.pluginmanager = pluginmanager or PluginManager(load=True)
     self.trace = self.pluginmanager.trace.root.get("config")
     self._conftest = Conftest(onimport=self._onimportconftest)
     self.hook = self.pluginmanager.hook
     self._inicache = {}
Example #35
0
    def test_consider_setuptools_instantiation(self, monkeypatch):
        pkg_resources = py.test.importorskip("pkg_resources")

        def my_iter(name):
            assert name == "pytest11"

            class EntryPoint:
                name = "pytest_mytestplugin"
                dist = None

                def load(self):
                    class PseudoPlugin:
                        x = 42

                    return PseudoPlugin()

            return iter([EntryPoint()])

        monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter)
        pluginmanager = PluginManager()
        pluginmanager.consider_setuptools_entrypoints()
        plugin = pluginmanager.getplugin("mytestplugin")
        assert plugin.x == 42
Example #36
0
    def test_hook_tracing(self):
        pm = PluginManager()
        saveindent = []

        class api1:
            x = 41

            def pytest_plugin_registered(self, plugin):
                saveindent.append(pm.trace.root.indent)
                raise ValueError(42)

        l = []
        pm.trace.root.setwriter(l.append)
        indent = pm.trace.root.indent
        p = api1()
        pm.register(p)

        assert pm.trace.root.indent == indent
        assert len(l) == 1
        assert 'pytest_plugin_registered' in l[0]
        pytest.raises(ValueError, lambda: pm.register(api1()))
        assert pm.trace.root.indent == indent
        assert saveindent[0] > indent
Example #37
0
    def test_listattr(self):
        pluginmanager = PluginManager()

        class My2:
            x = 42

        pluginmanager.register(My2())
        assert not pluginmanager.listattr("hello")
        assert pluginmanager.listattr("x") == [42]
Example #38
0
 def test_notify_exception(self, capfd):
     pp = PluginManager()
     excinfo = pytest.raises(ValueError, "raise ValueError(1)")
     pp.notify_exception(excinfo)
     out, err = capfd.readouterr()
     assert "ValueError" in err
     class A:
         def pytest_internalerror(self, excrepr):
             return True
     pp.register(A())
     pp.notify_exception(excinfo)
     out, err = capfd.readouterr()
     assert not err
Example #39
0
 def test_register_imported_modules(self):
     pp = PluginManager()
     mod = py.std.types.ModuleType("x.y.pytest_hello")
     pp.register(mod)
     assert pp.isregistered(mod)
     l = pp.getplugins()
     assert mod in l
     pytest.raises(ValueError, "pp.register(mod)")
     mod2 = py.std.types.ModuleType("pytest_hello")
     #pp.register(mod2) # double pm
     pytest.raises(ValueError, "pp.register(mod)")
     #assert not pp.isregistered(mod2)
     assert pp.getplugins() == l
Example #40
0
 def __init__(self, pluginmanager=None):
     #: access to command line option as attributes.
     #: (deprecated), use :py:func:`getoption() <_pytest.config.Config.getoption>` instead
     self.option = CmdOptions()
     self._parser = Parser(
         usage="usage: %prog [options] [file_or_dir] [file_or_dir] [...]",
         processopt=self._processopt,
     )
     #: a pluginmanager instance
     self.pluginmanager = pluginmanager or PluginManager(load=True)
     self.trace = self.pluginmanager.trace.root.get("config")
     self._conftest = Conftest(onimport=self._onimportconftest)
     self.hook = self.pluginmanager.hook
     self._inicache = {}
     self._opt2dest = {}
     self._cleanup = []
Example #41
0
 def test_register_imported_modules(self):
     pp = PluginManager()
     mod = py.std.types.ModuleType("x.y.pytest_hello")
     pp.register(mod)
     assert pp.isregistered(mod)
     l = pp.getplugins()
     assert mod in l
     pytest.raises(AssertionError, "pp.register(mod)")
     mod2 = py.std.types.ModuleType("pytest_hello")
     #pp.register(mod2) # double pm
     pytest.raises(AssertionError, "pp.register(mod)")
     #assert not pp.isregistered(mod2)
     assert pp.getplugins() == l
Example #42
0
 def test_listattr(self):
     plugins = PluginManager()
     class api1:
         x = 41
     class api2:
         x = 42
     class api3:
         x = 43
     plugins.register(api1())
     plugins.register(api2())
     plugins.register(api3())
     l = list(plugins.listattr('x'))
     assert l == [41, 42, 43]
Example #43
0
    def test_listattr(self):
        plugins = PluginManager()

        class api1:
            x = 41

        class api2:
            x = 42

        class api3:
            x = 43

        plugins.register(api1())
        plugins.register(api2())
        plugins.register(api3())
        l = list(plugins.listattr('x'))
        assert l == [41, 42, 43]
Example #44
0
    def test_consider_module_import_module(self, testdir):
        mod = py.std.types.ModuleType("x")
        mod.pytest_plugins = "pytest_a"
        aplugin = testdir.makepyfile(pytest_a="#")
        pluginmanager = PluginManager()
        reprec = testdir.getreportrecorder(pluginmanager)
        #syspath.prepend(aplugin.dirpath())
        py.std.sys.path.insert(0, str(aplugin.dirpath()))
        pluginmanager.consider_module(mod)
        call = reprec.getcall(pluginmanager.hook.pytest_plugin_registered.name)
        assert call.plugin.__name__ == "pytest_a"

        # check that it is not registered twice
        pluginmanager.consider_module(mod)
        l = reprec.getcalls("pytest_plugin_registered")
        assert len(l) == 1
Example #45
0
 def test_consider_setuptools_not_installed(self, monkeypatch):
     monkeypatch.setitem(py.std.sys.modules, 'pkg_resources',
                         py.std.types.ModuleType("pkg_resources"))
     pluginmanager = PluginManager()
     pluginmanager.consider_setuptools_entrypoints()
Example #46
0
    def test_register(self):
        pm = PluginManager(load=False)

        class MyPlugin:
            pass

        my = MyPlugin()
        pm.register(my)
        assert pm.getplugins()
        my2 = MyPlugin()
        pm.register(my2)
        assert pm.getplugins()[1:] == [my, my2]

        assert pm.isregistered(my)
        assert pm.isregistered(my2)
        pm.unregister(my)
        assert not pm.isregistered(my)
        assert pm.getplugins()[1:] == [my2]
Example #47
0
    def test_register(self):
        pm = PluginManager(load=False)
        class MyPlugin:
            pass
        my = MyPlugin()
        pm.register(my)
        assert pm.getplugins()
        my2 = MyPlugin()
        pm.register(my2)
        assert pm.getplugins()[1:] == [my, my2]

        assert pm.isregistered(my)
        assert pm.isregistered(my2)
        pm.unregister(my)
        assert not pm.isregistered(my)
        assert pm.getplugins()[1:] == [my2]
Example #48
0
 def test_consider_env_fails_to_import(self, monkeypatch):
     pluginmanager = PluginManager()
     monkeypatch.setenv('PYTEST_PLUGINS', 'nonexisting', prepend=",")
     pytest.raises(ImportError, "pluginmanager.consider_env()")
Example #49
0
 def test_consider_setuptools_not_installed(self, monkeypatch):
     monkeypatch.setitem(py.std.sys.modules, 'pkg_resources',
         py.std.types.ModuleType("pkg_resources"))
     pluginmanager = PluginManager()
     pluginmanager.consider_setuptools_entrypoints()
Example #50
0
 def test_plugin_double_register(self):
     pm = PluginManager()
     pm.register(42, name="abc")
     pytest.raises(ValueError, lambda: pm.register(42, name="abc"))
Example #51
0
 def test_plugin_double_register(self):
     pm = PluginManager()
     pm.register(42, name="abc")
     pytest.raises(ValueError, lambda: pm.register(42, name="abc"))
Example #52
0
 def test_pm(self):
     pp = PluginManager()
     class A: pass
     a1, a2 = A(), A()
     pp.register(a1)
     assert pp.isregistered(a1)
     pp.register(a2, "hello")
     assert pp.isregistered(a2)
     l = pp.getplugins()
     assert a1 in l
     assert a2 in l
     assert pp.getplugin('hello') == a2
     pp.unregister(a1)
     assert not pp.isregistered(a1)
     pp.unregister(name="hello")
     assert not pp.isregistered(a2)