nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: pytest-dev/pluggy
Pull request #359 (2022-08-03 06:46:09)

Proposed fix for issue #358
Switch to `inspect.signature` instead of `inspect.getfullargspec` to properly support wrapper chains (decorated functions) - see details in issue #358 .

In the proposed change I tried to do the minimal required changes to `varnames`.


Patch:
diff --git a/src/pluggy/_hooks.py b/src/pluggy/_hooks.py
index 8316115..73f0e80 100644
--- a/src/pluggy/_hooks.py
+++ b/src/pluggy/_hooks.py
@@ -244,12 +244,33 @@ def varnames(func: object) -> Tuple[Tuple[str, ...], Tuple[str, ...]]:
         except Exception:
             return (), ()
 
-    try:  # func MUST be a function or method here or we won't parse any args
-        spec = inspect.getfullargspec(func)
+    try:
+        # func MUST be a function or method here or we won't parse any args.
+        sig = inspect.signature(
+            func.__func__ if inspect.ismethod(func) else func  # type:ignore[arg-type]
+        )
     except TypeError:
         return (), ()
 
-    args, defaults = tuple(spec.args), spec.defaults
+    _valid_param_kinds = (
+        inspect.Parameter.POSITIONAL_ONLY,
+        inspect.Parameter.POSITIONAL_OR_KEYWORD,
+    )
+    _valid_params = {
+        name: param
+        for name, param in sig.parameters.items()
+        if param.kind in _valid_param_kinds
+    }
+    args = tuple(_valid_params)
+    defaults = (
+        tuple(
+            param.default
+            for param in _valid_params.values()
+            if param.default is not param.empty
+        )
+        or None
+    )
+
     if defaults:
         index = -len(defaults)
         args, kwargs = args[:index], tuple(args[index:])


Test patch:
diff --git a/testing/test_helpers.py b/testing/test_helpers.py
index cf3f6d7..4ddd945 100644
--- a/testing/test_helpers.py
+++ b/testing/test_helpers.py
@@ -1,3 +1,5 @@
+from functools import wraps
+from typing import Any, Callable, TypeVar, cast
 from pluggy._hooks import varnames
 from pluggy._manager import _formatdef
 
@@ -82,3 +84,29 @@ def test_formatdef() -> None:
         pass
 
     assert _formatdef(function4) == "function4(arg1, *args, **kwargs)"
+
+
+def test_varnames_decorator() -> None:
+    F = TypeVar("F", bound=Callable[..., Any])
+
+    def my_decorator(func: F) -> F:
+        @wraps(func)
+        def wrapper(*args, **kwargs):
+            return func(*args, **kwargs)
+
+        return cast(F, wrapper)
+
+    @my_decorator
+    def example(a, b=123) -> None:
+        pass
+
+    class Example:
+        @my_decorator
+        def example_method(self, x, y=1) -> None:
+            pass
+
+    ex_inst = Example()
+
+    assert varnames(example) == (("a",), ("b",))
+    assert varnames(Example.example_method) == (("x",), ("y",))
+    assert varnames(ex_inst.example_method) == (("x",), ("y",))
Repository: pytest-dev/pluggy
Pull request #379 (2023-03-24 05:34:43)

Detailed error message on hook registration conflict
Hi! I've spent some time trying to nail down hook registration error:

```python
INTERNALERROR>     pluginmanager.add_hookspecs(Hookspec)
INTERNALERROR>   File "contrib/python/pluggy/py3/pluggy/_manager.py", line 175, in add_hookspecs
INTERNALERROR>     hc.set_specification(module_or_class, spec_opts)
INTERNALERROR>   File "contrib/python/pluggy/py3/pluggy/_hooks.py", line 200, in set_specification
INTERNALERROR>     assert not self.has_spec()
INTERNALERROR> AssertionError
```

This PR raises `RuntimeError` with detailed message which should ease developer's life a bit:

```python
E           RuntimeError: Hook 'conflict' is already registered within namespace <class 'test_hookcaller.test_hook_conflict.<locals>.Api1'>

src/pluggy/_hooks.py:341: RuntimeError
```


Patch:
diff --git a/src/pluggy/_hooks.py b/src/pluggy/_hooks.py
index 79dd9cb..6fe5a6a 100644
--- a/src/pluggy/_hooks.py
+++ b/src/pluggy/_hooks.py
@@ -337,7 +337,11 @@ class _HookCaller:
         specmodule_or_class: _Namespace,
         spec_opts: "_HookSpecOpts",
     ) -> None:
-        assert not self.has_spec()
+        if self.spec is not None:
+            raise ValueError(
+                f"Hook {self.spec.name!r} is already registered "
+                f"within namespace {self.spec.namespace}"
+            )
         self.spec = HookSpec(specmodule_or_class, self.name, spec_opts)
         if spec_opts.get("historic"):
             self._call_history = []


Test patch:
diff --git a/testing/test_hookcaller.py b/testing/test_hookcaller.py
index 5e69a00..1f0c0a4 100644
--- a/testing/test_hookcaller.py
+++ b/testing/test_hookcaller.py
@@ -405,3 +405,23 @@ def test_hookrelay_registration_by_specname_raises(pm: PluginManager) -> None:
     pm.register(Plugin2())
     with pytest.raises(PluginValidationError):
         pm.check_pending()
+
+
+def test_hook_conflict(pm: PluginManager) -> None:
+    class Api1:
+        @hookspec
+        def conflict(self) -> None:
+            """Api1 hook"""
+
+    class Api2:
+        @hookspec
+        def conflict(self) -> None:
+            """Api2 hook"""
+
+    pm.add_hookspecs(Api1)
+    with pytest.raises(ValueError) as exc:
+        pm.add_hookspecs(Api2)
+    assert str(exc.value) == (
+        "Hook 'conflict' is already registered within namespace "
+        "<class 'test_hookcaller.test_hook_conflict.<locals>.Api1'>"
+    )
Repository: pytest-dev/pluggy
Pull request #481 (2024-02-19 19:00:37)

PluginManager.get_plugins no longer returns None for blocked plugins


Patch:
diff --git a/changelog/481.bugfix.rst b/changelog/481.bugfix.rst
new file mode 100644
index 0000000..4890c35
--- /dev/null
+++ b/changelog/481.bugfix.rst
@@ -0,0 +1,1 @@
+``PluginManager.get_plugins()`` no longer returns ``None`` for blocked plugins.
diff --git a/src/pluggy/_manager.py b/src/pluggy/_manager.py
index ce1e107..a9eb4a4 100644
--- a/src/pluggy/_manager.py
+++ b/src/pluggy/_manager.py
@@ -291,7 +291,7 @@ class PluginManager:
 
     def get_plugins(self) -> set[Any]:
         """Return a set of all registered plugin objects."""
-        return set(self._name2plugin.values())
+        return {x for x in self._name2plugin.values() if x is not None}
 
     def is_registered(self, plugin: _Plugin) -> bool:
         """Return whether the plugin is already registered."""


Test patch:
diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py
index d3bcac4..9b570f8 100644
--- a/testing/test_pluginmanager.py
+++ b/testing/test_pluginmanager.py
@@ -100,15 +100,19 @@ def test_set_blocked(pm: PluginManager) -> None:
     assert name is not None
     assert pm.is_registered(a1)
     assert not pm.is_blocked(name)
+    assert pm.get_plugins() == {a1}
+
     pm.set_blocked(name)
     assert pm.is_blocked(name)
     assert not pm.is_registered(a1)
+    assert pm.get_plugins() == set()
 
     pm.set_blocked("somename")
     assert pm.is_blocked("somename")
     assert not pm.register(A(), "somename")
     pm.unregister(name="somename")
     assert pm.is_blocked("somename")
+    assert pm.get_plugins() == set()
 
     # Unblock.
     assert not pm.unblock("someothername")
Repository: apiflask/apiflask
Pull request #339 (2022-08-13 05:17:59)

Set default Elements router to hash
So we don't need to handle the basePath value.


Patch:
diff --git a/CHANGES.md b/CHANGES.md
index 6349244..ee96755 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -6,6 +6,13 @@
 Released: -
 
 
+## Version 1.1.2
+
+Released: 2022/8/13
+
+- Set default Elements router to `hash` to fix incorrect path updates.
+
+
 ## Version 1.1.1
 
 Released: 2022/8/3
diff --git a/src/apiflask/ui_templates.py b/src/apiflask/ui_templates.py
index 8ec6821..da254c1 100644
--- a/src/apiflask/ui_templates.py
+++ b/src/apiflask/ui_templates.py
@@ -207,6 +207,12 @@ elements_template = """
   <elements-api
     apiDescriptionUrl="{{ url_for('openapi.spec') }}"
     layout="{{ config.ELEMENTS_LAYOUT }}"
+    {% if config.ELEMENTS_CONFIG and 'router' in config.ELEMENTS_CONFIG %}
+      {% set router = config.ELEMENTS_CONFIG['router'] %}
+    {% else %}
+      {% set router = 'hash' %}
+    {% endif %}
+    router={{ router | tojson }}
     {% if config.ELEMENTS_CONFIG %}
       {% for key, value in config.ELEMENTS_CONFIG.items() %}
         {{ key }}={{ value | tojson }}


Test patch:
diff --git a/tests/test_settings_api_docs.py b/tests/test_settings_api_docs.py
index aaa3ce0..258d854 100644
--- a/tests/test_settings_api_docs.py
+++ b/tests/test_settings_api_docs.py
@@ -92,6 +92,12 @@ def test_swagger_ui_oauth_config(app, client):
 
 def test_elements_config():
     app = APIFlask(__name__, docs_ui='elements')
+
+    rv = app.test_client().get('/docs')
+    assert rv.status_code == 200
+    # test default router
+    assert b'router="hash"' in rv.data
+
     app.config['ELEMENTS_CONFIG'] = {
         'hideTryIt': False,
         'router': 'memory'