{"record":{"id":"9465c8efbc5fa489","repo":"pytest-dev/pytest","slug":"must-be-absolute-import-path-string-not-import-p","errorCode":null,"errorMessage":"must be absolute import path string, not {import_path!r}","messagePattern":"must be absolute import path string, not (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/_pytest/monkeypatch.py","lineNumber":105,"sourceCode":"            else:\n                raise ImportError(f\"import error in {used}: {ex}\") from ex\n        found = annotated_getattr(found, part, used)\n    return found\n\n\ndef annotated_getattr(obj: object, name: str, ann: str) -> object:\n    try:\n        obj = getattr(obj, name)\n    except AttributeError as e:\n        raise AttributeError(\n            f\"{type(obj).__name__!r} object at {ann} has no attribute {name!r}\"\n        ) from e\n    return obj\n\n\ndef derive_importpath(import_path: str, raising: bool) -> tuple[str, object]:\n    if not isinstance(import_path, str) or \".\" not in import_path:\n        raise TypeError(f\"must be absolute import path string, not {import_path!r}\")\n    module, attr = import_path.rsplit(\".\", 1)\n    target = resolve(module)\n    if raising:\n        annotated_getattr(target, attr, ann=module)\n    return attr, target\n\n\n@final\nclass MonkeyPatch:\n    \"\"\"Helper to conveniently monkeypatch attributes/items/environment\n    variables/syspath.\n\n    Returned by the :fixture:`monkeypatch` fixture.\n\n    .. versionchanged:: 6.2\n        Can now also be used directly as `pytest.MonkeyPatch()`, for when\n        the fixture is not available. In this case, use\n        :meth:`with MonkeyPatch.context() as mp: <context>` or remember to call","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/monkeypatch.py#L87-L123","documentation":"A TypeError raised by derive_importpath when the import_path argument is not a string or does not contain a dot. pytest requires a dotted absolute import path (at least module.attribute) so it can split on the last dot into module and attribute. Non-strings (objects, None) and dot-less strings are rejected upfront.","triggerScenarios":"Calling `monkeypatch.setattr(123, value)`, `monkeypatch.setattr('nomodule', value)` (no dot), `monkeypatch.setattr(None, value)`, or `monkeypatch.delattr('justaname')`. The check `not isinstance(import_path, str) or '.' not in import_path` catches both cases.","commonSituations":"Confusing the two-arg and three-arg setattr forms; passing a module object where a dotted string is expected; forgetting the attribute portion when only a module name is given.","solutions":["Provide a fully qualified dotted path including the attribute: 'module.Class.attribute'.","If you have the object already, use the three-arg form: setattr(target_obj, 'name', value).","Ensure the path string contains at least one dot separating module from attribute."],"exampleFix":"# before\nmonkeypatch.setattr('ospath', new)\n# after\nmonkeypatch.setattr('os.path', new)","handlingStrategy":"type-guard","validationCode":"def is_dotted_path(p) -> bool:\n    return isinstance(p, str) and '.' in p","typeGuard":"def is_dotted_import_path(p) -> bool:\n    return isinstance(p, str) and '.' in p","tryCatchPattern":null,"preventionTips":["Always include at least one dot in dotted import paths.","Use the three-arg setattr form when you already hold the target object.","Validate paths built from dynamic data."],"tags":["pytest","monkeypatch","type-error","import-path","validation"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}