{"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":"validation","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/98b357f69e380da908740a212288d73b2ee06687/src/_pytest/monkeypatch.py#L252-L288","documentation":"Raised by MonkeyPatch.delattr when called with a single argument that is not a dotted import string. pytest supports delattr(target, name) for an object plus attribute name, or delattr(target) where target is a dotted path like \"pkg.mod.attr\". Passing a bare object with no name is ambiguous and is rejected with TypeError.","triggerScenarios":"Calling monkeypatch.delattr(some_module) or monkeypatch.delattr(obj) where obj is a module/class/instance and the second positional `name` argument is omitted. The single-argument form only accepts str.","commonSituations":"Developers conflate the builtin delattr(obj, name) signature with pytest's monkeypatch.delattr and omit the name; or attempt the dotted-string shortcut with an actual object reference.","solutions":["Pass the attribute name explicitly: monkeypatch.delattr(target, 'attr_name')","If you want the single-arg form, pass a dotted import string: monkeypatch.delattr('package.module.attr')"],"exampleFix":"// before\nmonkeypatch.delattr(some_module)\n// after\nmonkeypatch.delattr(some_module, 'attr_name')","handlingStrategy":"validation","validationCode":"def safe_delattr(mpatch, target, name=None):\n    import inspect\n    if name is None:\n        if not isinstance(target, str):\n            raise TypeError(\"single-arg delattr requires a dotted import string\")\n        mpatch.delattr(target)\n    else:\n        mpatch.delattr(target, name)","typeGuard":"def is_dotted_import_path(target) -> bool:\n    return isinstance(target, str) and '.' in target","tryCatchPattern":null,"preventionTips":["Always pass the explicit (target, name) pair to monkeypatch.delattr unless you genuinely need the dotted-string form","When using the single-arg form, assert the target is a str first"],"tags":["monkeypatch","api-misuse","pytest","delattr"],"analyzedSha":"98b357f69e380da908740a212288d73b2ee06687","analyzedAt":"2026-08-04T20:26:34.442Z","schemaVersion":2}