{"record":{"id":"0e8525507e2b14fe","repo":"pytest-dev/pytest","slug":"use-delattr-target-name-or-delattr-target-with","errorCode":null,"errorMessage":"use delattr(target, name) or delattr(target) with target being a dotted import string","messagePattern":"use delattr\\(target, name\\) or delattr\\(target\\) with target being a dotted import string","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/_pytest/monkeypatch.py","lineNumber":270,"sourceCode":"        target: object | str,\n        name: str | NotSetType = NOTSET,\n        raising: bool = True,\n    ) -> None:\n        \"\"\"Delete attribute ``name`` from ``target``.\n\n        If no ``name`` is specified and ``target`` is a string\n        it will be interpreted as a dotted import path with the\n        last part being the attribute name.\n\n        Raises AttributeError it the attribute does not exist, unless\n        ``raising`` is set to False.\n        \"\"\"\n        __tracebackhide__ = True\n        import inspect\n\n        if name is NOTSET:\n            if not isinstance(target, str):\n                raise TypeError(\n                    \"use delattr(target, name) or \"\n                    \"delattr(target) with target being a dotted \"\n                    \"import string\"\n                )\n            name, target = derive_importpath(target, raising)\n\n        if not hasattr(target, name):\n            if raising:\n                raise AttributeError(name)\n        else:\n            oldval = getattr(target, name, NOTSET)\n            # Avoid class descriptors like staticmethod/classmethod.\n            if inspect.isclass(target):\n                oldval = target.__dict__.get(name, NOTSET)\n            self._setattr.append((target, name, oldval))\n            delattr(target, name)\n\n    def setitem(self, dic: Mapping[K, V], name: K, value: V) -> None:","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/monkeypatch.py#L252-L288","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass the attribute name explicitly: monkeypatch.delattr(target, 'attr_name').","If targeting a dotted import path, pass a string: monkeypatch.delattr('package.module.attr').","Check the call site: delattr needs exactly two positional args (target, name) unless target is a dotted import string."],"exampleFix":"// before\nmonkeypatch.delattr(my_module)\n// after\nmonkeypatch.delattr(my_module, 'attr_name')","handlingStrategy":"type-guard","validationCode":"if name is None and not isinstance(target, str):\n    raise TypeError('provide name, or pass a dotted import string as target')","typeGuard":"def _delattr_args_ok(target, name) -> bool:\n    return name is not None or isinstance(target, str)","tryCatchPattern":null,"preventionTips":["Always pass the explicit (target, name) pair unless using a dotted import string.","Lint call sites that call monkeypatch.delattr with a single non-string argument."],"tags":["pytest","monkeypatch","api-misuse","typeerror"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}