pytest-dev/pytest · error · TypeError

use delattr(target, name) or delattr(target) with target…

Error message

use delattr(target, name) or delattr(target) with target being a dotted import string

What it means

Thrown by MonkeyPatch.delattr when the single-argument form is used (name omitted) but target is not a string. The delattr API supports two shapes: delattr(target, name) for an explicit object+attribute pair, or delattr('dotted.import.path') where the last segment becomes the attribute. Calling delattr(some_object) with a non-string object and no name is ambiguous and rejected at line 270 before any attribute lookup occurs.

Solutions

  1. Pass the attribute name explicitly: monkeypatch.delattr(target, 'attr_name').
  2. If targeting a dotted import path, pass a string: monkeypatch.delattr('package.module.attr').
  3. Check the call site: delattr needs exactly two positional args (target, name) unless target is a dotted import string.

Example fix

// before
monkeypatch.delattr(my_module)
// after
monkeypatch.delattr(my_module, 'attr_name')
Defensive patterns

Strategy: type-guard

Validate before calling

if name is None and not isinstance(target, str):
    raise TypeError('provide name, or pass a dotted import string as target')

Type guard

def _delattr_args_ok(target, name) -> bool:
    return name is not None or isinstance(target, str)

Prevention

When it happens

Trigger: monkeypatch.delattr(some_module) where some_module is a module/object instance and no name argument is supplied; monkeypatch.delattr(123) with a non-string scalar; passing an object that is neither a str nor paired with a name kwarg.

Common situations: Developers confuse pytest's monkeypatch.delattr with the builtin delattr and try to call monkeypatch.delattr(obj) expecting deletion of the whole object; refactoring code that previously used a dotted string into an object reference without adding the name parameter.

Related errors


AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11). Data as JSON: /api/errors/0e8525507e2b14fe. Report an issue: GitHub.

Appendix: source

Thrown at src/_pytest/monkeypatch.py:270

        target: object | str,
        name: str | NotSetType = NOTSET,
        raising: bool = True,
    ) -> None:
        """Delete attribute ``name`` from ``target``.

        If no ``name`` is specified and ``target`` is a string
        it will be interpreted as a dotted import path with the
        last part being the attribute name.

        Raises AttributeError it the attribute does not exist, unless
        ``raising`` is set to False.
        """
        __tracebackhide__ = True
        import inspect

        if name is NOTSET:
            if not isinstance(target, str):
                raise TypeError(
                    "use delattr(target, name) or "
                    "delattr(target) with target being a dotted "
                    "import string"
                )
            name, target = derive_importpath(target, raising)

        if not hasattr(target, name):
            if raising:
                raise AttributeError(name)
        else:
            oldval = getattr(target, name, NOTSET)
            # Avoid class descriptors like staticmethod/classmethod.
            if inspect.isclass(target):
                oldval = target.__dict__.get(name, NOTSET)
            self._setattr.append((target, name, oldval))
            delattr(target, name)

    def setitem(self, dic: Mapping[K, V], name: K, value: V) -> None:

View on GitHub (pinned to 0d6fbdeffa)