Skip to content

Writing Stub File for Dynamic Namespace #3282

@jambonrose

Description

@jambonrose

Hi,
I'm new to mypy and giving it a whirl for the first time.

I'm trying to lint a python file that is run as a test file by pytest.

import pytest
from roman_numerals import convert_to_numeral


@pytest.mark.parametrize("decimal_integer, expected_numeral", [
    (1, 'I'),
    (5, 'V'),
])
def test_numeral_conversion(decimal_integer: int, expected_numeral: str) -> None:
    assert convert_to_numeral(decimal_integer) == expected_numeral

When I run mypy, I am greeted with the error below.

test_ascii_to_numeral.py:2: error: No library stub file for module 'pytest'
test_ascii_to_numeral.py:2: note: (Stub files are from https://github.com/python/typeshed)

No problem! I can create a set of local stubs. I create the following directory structure and specify the directory in mypy.ini.

$ tree stubs/
stubs/
└── pytest
    ├── __init__.py
    └── mark.pyi

1 directory, 2 files

However, when I run mypy, I now get the error below, regardless of the contents of stubs/pytest/mark.pyi.

test_ascii_to_numeral.py:4: error: "module" has no attribute "mark"

It's worth noting that py.test is a little unusual. In my site packages, there is a pytest.py file that creates a custom namespace from a _pytest package, which in turn contains the mark.py module. _pytest/mark.py defines a MarkGenerator class, which when called dynamically creates the parametrize decorator. As such, the pytest.py module doesn't really have a mark.py module or a parametrizedecorator, but does allow for invocation of pytest.mark.parametrize.

  • Question 1: How do I debug the message above? Is this related to my stubs, or to py.test's handling of namespace?

  • Question 2: Is it possible to create a type stub for pytest.mark.parametrize even if it isn't explicitly defined? Effectively, can I create stubs (such as below) the follow the public API rather than the Python code?

# stubs/pytest/mark.pyi
from typing import Callable, List

def parametrize(parameter_names: str, arguments: List[tuple]) -> Callable: ...

(For the record, I tried to use stubgen to generate stubs for pytest, _pytest and _pytest/mark.py, all without any success, and the mypy error remained the same).

Thank you!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions