{"id":"19aea25bbeb705a3","repo":"pytest-dev/pytest","slug":"use-setattr-target-name-value-or-setattr-target","errorCode":null,"errorMessage":"use setattr(target, name, value) or setattr(target, value) with target being a dotted import string","messagePattern":"use setattr\\(target, name, value\\) or setattr\\(target, value\\) with target being a dotted import string","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/_pytest/monkeypatch.py","lineNumber":225,"sourceCode":"        Raises :class:`AttributeError` if the attribute does not exist, unless\n        ``raising`` is set to False.\n\n        **Where to patch**\n\n        ``monkeypatch.setattr`` works by (temporarily) changing the object that a name points to with another one.\n        There can be many names pointing to any individual object, so for patching to work you must ensure\n        that you patch the name used by the system under test.\n\n        See the section :ref:`Where to patch <python:where-to-patch>` in the :mod:`unittest.mock`\n        docs for a complete explanation, which is meant for :func:`unittest.mock.patch` but\n        applies to ``monkeypatch.setattr`` as well.\n        \"\"\"\n        __tracebackhide__ = True\n        import inspect\n\n        if value is NOTSET:\n            if not isinstance(target, str):\n                raise TypeError(\n                    \"use setattr(target, name, value) or \"\n                    \"setattr(target, value) with target being a dotted \"\n                    \"import string\"\n                )\n            value = name\n            name, target = derive_importpath(target, raising)\n        else:\n            if not isinstance(name, str):\n                raise TypeError(\n                    \"use setattr(target, name, value) with name being a string or \"\n                    \"setattr(target, value) with target being a dotted \"\n                    \"import string\"\n                )\n\n        oldval = getattr(target, name, NOTSET)\n        if raising and oldval is NOTSET:\n            raise AttributeError(f\"{target!r} has no attribute {name!r}\")\n","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/pytest-dev/pytest/blob/98b357f69e380da908740a212288d73b2ee06687/src/_pytest/monkeypatch.py#L207-L243","documentation":"`monkeypatch.setattr` supports a short form `setattr(target, value)` where `target` is a dotted import string. If `value` was not provided (so the method treats the 2nd arg as `target` for the short form) but that target is not a `str`, the call is ambiguous and TypeError is raised telling you to either pass three args or use a dotted-string target.","triggerScenarios":"`monkeypatch.setattr(os, 'new')` — passing an object as first arg with only two positional args, instead of either `setattr('os.new', val)` or `setattr(os, 'new', val)`.","commonSituations":"Forgetting the third argument; mixing up the two-arg (string target) and three-arg (object target) overloads.","solutions":["If target is an object, pass three arguments: `setattr(obj, 'name', value)`.","If you want the short form, pass a dotted string: `setattr('module.attr', value)`."],"exampleFix":"# before\nmonkeypatch.setattr(os, fake)\n# after\nmonkeypatch.setattr(os, 'getcwd', fake)","handlingStrategy":"type-guard","validationCode":"def valid_setattr_short_form(target) -> bool:\n    return isinstance(target, str) and '.' in target","typeGuard":"def can_use_short_setattr(target: object) -> bool:\n    return isinstance(target, str) and '.' in target","tryCatchPattern":null,"preventionTips":["Pass three args when the target is an object.","Pass a dotted string when using only two args."],"tags":["pytest","monkeypatch","type-error","setattr","api-usage"],"analyzedSha":"98b357f69e380da908740a212288d73b2ee06687","analyzedAt":"2026-08-04T20:26:34.442Z","schemaVersion":2}