pytest-dev/pytest · error · ValueError

pytester.makefile expects a file extension, try .{ext} inste

Error message

pytester.makefile expects a file extension, try .{ext} instead of {ext}

What it means

Raised by Pytester._makefile when ext is a non-empty string that does not begin with a dot. pytester.makefile expects the leading dot (e.g. '.py', '.ini') because it is passed verbatim to Path.with_suffix. The message suggests the corrected form '.{ext}' to guide the caller. An empty string ext is allowed (it means 'use the basename as-is').

Source

Thrown at src/_pytest/pytester.py:772

        This is done automatically upon instantiation.
        """
        self._monkeypatch.chdir(self.path)

    def _makefile(
        self,
        ext: str,
        lines: Sequence[Any | bytes],
        files: Mapping[str, _FileContent],
        encoding: str = "utf-8",
    ) -> Path:
        items = list(files.items())

        if ext is None:
            raise TypeError("ext must not be None")

        if ext and not ext.startswith("."):
            raise ValueError(
                f"pytester.makefile expects a file extension, try .{ext} instead of {ext}"
            )

        def to_text(s: Any | bytes) -> str:
            return s.decode(encoding) if isinstance(s, bytes) else str(s)

        if lines:
            source = "\n".join(to_text(x) for x in lines)
            basename = self._name
            items.insert(0, (basename, source))

        ret = None
        for basename, value in items:
            p = self.path.joinpath(basename).with_suffix(ext)
            p.parent.mkdir(parents=True, exist_ok=True)
            source_ = Source(value)
            source = "\n".join(to_text(line) for line in source_.lines)
            p.write_text(source.strip(), encoding=encoding)

View on GitHub (pinned to 98b357f69e)

Solutions

  1. Add the leading dot: pass '.py' instead of 'py'.
  2. Normalize ext before calling: ext = ext if ext.startswith('.') else '.' + ext.
  3. Use the dedicated helpers (makepyfile, makeini, maketoml) which handle the extension for you.

Example fix

// before
pytester.makefile("txt", data="hello")
// after
pytester.makefile(".txt", data="hello")
Defensive patterns

Strategy: validation

Validate before calling

def norm_ext(ext: str) -> str:
    if ext and not ext.startswith("."):
        ext = "." + ext
    return ext

pytester.makefile(norm_ext(ext), data=source)

Type guard

def is_dotted_ext(ext: object) -> bool:
    return isinstance(ext, str) and (ext == "" or ext.startswith("."))

Prevention

When it happens

Trigger: Calling pytester.makefile('py', ...) or makefile('ini', ...) without the leading dot; constructing ext dynamically and stripping the dot; misreading the docstring.

Common situations: Copy-pasting code that uses os.path.splitext semantics (which returns the extension without the dot); passing a value from config that omits the dot; new users unfamiliar with the leading-dot convention.

Related errors


AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04). Data as JSON: /data/errors/d199c507493fb2c0.json. Report an issue: GitHub.