pytest-dev/pytest · error · TypeError
must be absolute import path string, not
Error message
must be absolute import path string, not {import_path!r} What it means
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.
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.
Example fix
# before
monkeypatch.setattr('ospath', new)
# after
monkeypatch.setattr('os.path', new) Defensive patterns
Strategy: type-guard
Validate before calling
def is_dotted_path(p) -> bool:
return isinstance(p, str) and '.' in p Type guard
def is_dotted_import_path(p) -> bool:
return isinstance(p, str) and '.' in p Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- import error in
- object at has no attribute
- use setattr(target, name, value) or setattr(target, value)…
- use setattr(target, name, value) with name being a string…
- `allow_unwrapped=True` bypasses the `match` and `check`…
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/9465c8efbc5fa489.
Report an issue: GitHub.
Appendix: source
Thrown at src/_pytest/monkeypatch.py:105
else:
raise ImportError(f"import error in {used}: {ex}") from ex
found = annotated_getattr(found, part, used)
return found
def annotated_getattr(obj: object, name: str, ann: str) -> object:
try:
obj = getattr(obj, name)
except AttributeError as e:
raise AttributeError(
f"{type(obj).__name__!r} object at {ann} has no attribute {name!r}"
) from e
return obj
def derive_importpath(import_path: str, raising: bool) -> tuple[str, object]:
if not isinstance(import_path, str) or "." not in import_path:
raise TypeError(f"must be absolute import path string, not {import_path!r}")
module, attr = import_path.rsplit(".", 1)
target = resolve(module)
if raising:
annotated_getattr(target, attr, ann=module)
return attr, target
@final
class MonkeyPatch:
"""Helper to conveniently monkeypatch attributes/items/environment
variables/syspath.
Returned by the :fixture:`monkeypatch` fixture.
.. versionchanged:: 6.2
Can now also be used directly as `pytest.MonkeyPatch()`, for when
the fixture is not available. In this case, use
:meth:`with MonkeyPatch.context() as mp: <context>` or remember to callView on GitHub (pinned to 0d6fbdeffa)