Skip to content

back to OpenHands summary

OpenHands: attrs

Failed to run pytests for test tests

Traceback (most recent call last):
  File "/testbed/.venv/bin/pytest", line 8, in <module>
    sys.exit(console_main())
             ^^^^^^^^^^^^^^
  File "/testbed/.venv/lib/python3.12/site-packages/_pytest/config/__init__.py", line 201, in console_main
    code = main()
           ^^^^^^
  File "/testbed/.venv/lib/python3.12/site-packages/_pytest/config/__init__.py", line 156, in main
    config = _prepareconfig(args, plugins)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/testbed/.venv/lib/python3.12/site-packages/_pytest/config/__init__.py", line 341, in _prepareconfig
    config = pluginmanager.hook.pytest_cmdline_parse(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/testbed/.venv/lib/python3.12/site-packages/pluggy/_hooks.py", line 513, in __call__
    return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/testbed/.venv/lib/python3.12/site-packages/pluggy/_manager.py", line 120, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/testbed/.venv/lib/python3.12/site-packages/pluggy/_callers.py", line 139, in _multicall
    raise exception.with_traceback(exception.__traceback__)
  File "/testbed/.venv/lib/python3.12/site-packages/pluggy/_callers.py", line 122, in _multicall
    teardown.throw(exception)  # type: ignore[union-attr]
    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/testbed/.venv/lib/python3.12/site-packages/_pytest/helpconfig.py", line 105, in pytest_cmdline_parse
    config = yield
             ^^^^^
  File "/testbed/.venv/lib/python3.12/site-packages/pluggy/_callers.py", line 103, in _multicall
    res = hook_impl.function(*args)
          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/testbed/.venv/lib/python3.12/site-packages/_pytest/config/__init__.py", line 1140, in pytest_cmdline_parse
    self.parse(args)
  File "/testbed/.venv/lib/python3.12/site-packages/_pytest/config/__init__.py", line 1494, in parse
    self._preparse(args, addopts=addopts)
  File "/testbed/.venv/lib/python3.12/site-packages/_pytest/config/__init__.py", line 1381, in _preparse
    self.pluginmanager.load_setuptools_entrypoints("pytest11")
  File "/testbed/.venv/lib/python3.12/site-packages/pluggy/_manager.py", line 421, in load_setuptools_entrypoints
    plugin = ep.load()
             ^^^^^^^^^
  File "/root/.local/share/uv/python/cpython-3.12.6-linux-x86_64-gnu/lib/python3.12/importlib/metadata/__init__.py", line 205, in load
    module = import_module(match.group('module'))
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/.local/share/uv/python/cpython-3.12.6-linux-x86_64-gnu/lib/python3.12/importlib/__init__.py", line 90, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "/testbed/.venv/lib/python3.12/site-packages/_pytest/assertion/rewrite.py", line 184, in exec_module
    exec(co, module.__dict__)
  File "/testbed/.venv/lib/python3.12/site-packages/pytest_mypy_plugins/collect.py", line 20, in <module>
    import jsonschema
  File "/testbed/.venv/lib/python3.12/site-packages/jsonschema/__init__.py", line 13, in <module>
    from jsonschema._format import FormatChecker
  File "/testbed/.venv/lib/python3.12/site-packages/jsonschema/_format.py", line 11, in <module>
    from jsonschema.exceptions import FormatError
  File "/testbed/.venv/lib/python3.12/site-packages/jsonschema/exceptions.py", line 14, in <module>
    from attrs import define
  File "/testbed/src/attrs/__init__.py", line 3, in <module>
    from attr import (
  File "/testbed/src/attr/__init__.py", line 10, in <module>
    from . import converters, exceptions, filters, setters, validators
  File "/testbed/src/attr/converters.py", line 6, in <module>
    from ._make import NOTHING, Factory, pipe
  File "/testbed/src/attr/_make.py", line 880, in <module>
    @attrs(slots=True, unsafe_hash=True)
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: 'NoneType' object is not callable

Patch diff

diff --git a/src/attr/_make.py b/src/attr/_make.py
index 766fa38..4f36fea 100644
--- a/src/attr/_make.py
+++ b/src/attr/_make.py
@@ -273,14 +273,59 @@ def _determine_attrs_eq_order(cmp, eq, order, default_eq):
     Validate the combination of *cmp*, *eq*, and *order*. Derive the effective
     values of eq and order.  If *eq* is None, set it to *default_eq*.
     """
-    pass
+    if cmp is not None and (eq is not None or order is not None):
+        raise ValueError("Don't mix `cmp` with `eq' and `order`.")
+
+    if cmp is not None:
+        return cmp, cmp
+
+    # Convert eq and order to their effective values
+    if eq is None:
+        eq = default_eq
+
+    if order is None:
+        order = eq
+
+    if order and not eq:
+        raise ValueError("`order` can only be True if `eq` is True too.")
+
+    return eq, order

 def _determine_attrib_eq_order(cmp, eq, order, default_eq):
     """
     Validate the combination of *cmp*, *eq*, and *order*. Derive the effective
     values of eq and order.  If *eq* is None, set it to *default_eq*.
     """
-    pass
+    if cmp is not None and (eq is not None or order is not None):
+        raise ValueError("Don't mix `cmp` with `eq' and `order`.")
+
+    # If cmp is provided, use it for both eq and order
+    if cmp is not None:
+        return cmp, None, cmp, None
+
+    # Convert eq and order to their effective values
+    if eq is None:
+        eq = default_eq
+
+    if order is None:
+        order = eq
+
+    # Handle callable eq/order by converting them to eq_key/order_key
+    eq_key = None
+    order_key = None
+
+    if callable(eq) and not isinstance(eq, bool):
+        eq_key = eq
+        eq = True
+
+    if callable(order) and not isinstance(order, bool):
+        order_key = order
+        order = True
+
+    if order and not eq:
+        raise ValueError("`order` can only be True if `eq` is True too.")
+
+    return eq, eq_key, order, order_key

 def _determine_whether_to_implement(cls, flag, auto_detect, dunders, default=True):
     """
@@ -526,8 +571,17 @@ def _default_init_alias_for(name: str) -> str:

     This performs private-name adjustment via leading-unscore stripping,
     and is the default value of Attribute.alias if not provided.
+
+    Args:
+        name: The attribute name to process.
+
+    Returns:
+        The parameter name to use in __init__.
     """
-    pass
+    # Strip leading underscores from private names
+    while name.startswith('_'):
+        name = name[1:]
+    return name

 class Attribute:
     """
@@ -574,7 +628,12 @@ class Attribute:
     __slots__ = ('name', 'default', 'validator', 'repr', 'eq', 'eq_key', 'order', 'order_key', 'hash', 'init', 'metadata', 'type', 'converter', 'kw_only', 'inherited', 'on_setattr', 'alias')

     def __init__(self, name, default, validator, repr, cmp, hash, init, inherited, metadata=None, type=None, converter=None, kw_only=False, eq=None, eq_key=None, order=None, order_key=None, on_setattr=None, alias=None):
-        eq, eq_key, order, order_key = _determine_attrib_eq_order(cmp, eq_key or eq, order_key or order, True)
+        # Handle eq and order before determining their final values
+        if eq_key is not None:
+            eq = True
+        if order_key is not None:
+            order = True
+        eq, eq_key, order, order_key = _determine_attrib_eq_order(cmp, eq, order, True)
         bound_setattr = _OBJ_SETATTR.__get__(self)
         bound_setattr('name', name)
         bound_setattr('default', default)
@@ -621,8 +680,6 @@ class Attribute:
         Play nice with pickle.
         """
         self._setattrs(zip(self.__slots__, state))
-_a = [Attribute(name=name, default=NOTHING, validator=None, repr=True, cmp=None, eq=True, order=False, hash=name != 'metadata', init=True, inherited=False, alias=_default_init_alias_for(name)) for name in Attribute.__slots__]
-Attribute = _add_hash(_add_eq(_add_repr(Attribute, attrs=_a), attrs=[a for a in _a if a.name != 'inherited']), attrs=[a for a in _a if a.hash and a.name != 'inherited'])

 class _CountingAttr:
     """
@@ -860,4 +917,10 @@ def pipe(*converters):

     .. versionadded:: 20.1.0
     """
-    pass
\ No newline at end of file
+    pass
+
+# Create Attribute instances for each slot
+_a = [Attribute(name=name, default=NOTHING, validator=None, repr=True, cmp=None, eq=True, order=False, hash=name != 'metadata', init=True, inherited=False, alias=_default_init_alias_for(name)) for name in Attribute.__slots__]
+
+# Add hash, eq and repr methods to Attribute class
+Attribute = _add_hash(_add_eq(_add_repr(Attribute, attrs=_a), attrs=[a for a in _a if a.name != 'inherited']), attrs=[a for a in _a if a.hash and a.name != 'inherited'])
\ No newline at end of file