Mypy static type checker plugin for Pytest

Related tags

Testingpytest-mypy
Overview

pytest-mypy

Mypy static type checker plugin for pytest

See Latest Release on PyPI

Features

  • Runs the mypy static type checker on your source files as part of your pytest test runs.
  • Does for mypy what the pytest-flake8 plugin does for flake8.
  • This is a work in progress – pull requests appreciated.

Installation

You can install "pytest-mypy" via pip from PyPI:

$ pip install pytest-mypy

Usage

You can enable pytest-mypy with the --mypy flag:

$ py.test --mypy test_*.py

Mypy supports reading configuration settings from a mypy.ini file. Alternatively, the plugin can be configured in a conftest.py to invoke mypy with extra options:

def pytest_configure(config):
    plugin = config.pluginmanager.getplugin('mypy')
    plugin.mypy_argv.append('--check-untyped-defs')

You can restrict your test run to only perform mypy checks and not any other tests by using the -m option:

py.test --mypy -m mypy test_*.py

License

Distributed under the terms of the MIT license, "pytest-mypy" is free and open source software

Issues

If you encounter any problems, please file an issue along with a detailed description.

Meta

Daniel Bader – @dbader_orghttps://dbader.org[email protected]

https://github.com/dbader/pytest-mypy

Comments
  • Add support for 3.8

    Add support for 3.8

    Just a nice quick change hopefully. I've ran tox and the tests passed but really I'm just making sure when used with 3.8 it no longer pulls in the version of mypy which depends on typed_ast as that's been removed in 3.8.

    I'm not very familiar with tox so correct me if I've made an erroneous change to the tox.ini (I ran tox -e py38 inside a 3.8-dev interpreter)

    opened by naphta 10
  • 0.8.1: pytest is failing because cannot find module named `is_always_missing`

    0.8.1: pytest is failing because cannot find module named `is_always_missing`

    I'm trying to package your module as an rpm package. So I'm using the typical PEP517 based build, install and test cycle used on building packages from non-root account.

    • python3 -sBm build -w --no-isolation
    • install .whl file in </install/prefix>
    • run pytest with PYTHONPATH pointing to sitearch and sitelib inside </install/prefix>

    May I ask where I can find that is_always_missing module? I canmot find it on pypi :/ Here is pytest output:

    + PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mypy-0.8.1-2.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mypy-0.8.1-2.fc35.x86_64/usr/lib/python3.8/site-packages
    + /usr/bin/pytest -ra
    =========================================================================== test session starts ============================================================================
    platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
    rootdir: /home/tkloczko/rpmbuild/BUILD/pytest-mypy-0.8.1, configfile: tox.ini, testpaths: tests
    plugins: mypy-0.8.1, forked-1.4.0, xdist-2.5.0, cov-3.0.0, cases-3.6.7, flake8-1.0.7
    collected 50 items
    
    tests/test_pytest_mypy.py ............FFF...................................                                                                                         [100%]
    
    ================================================================================= FAILURES =================================================================================
    _________________________________________________________________ test_mypy_ignore_missings_imports[True] __________________________________________________________________
    
    testdir = <Testdir local('/tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports0')>, xdist_args = ['-n', 'auto']
    
        def test_mypy_ignore_missings_imports(testdir, xdist_args):
            """
            Verify that --mypy-ignore-missing-imports
            causes mypy to ignore missing imports.
            """
            module_name = "is_always_missing"
            testdir.makepyfile(
                """
                    try:
                        import {module_name}
                    except ImportError:
                        pass
                """.format(
                    module_name=module_name,
                ),
            )
            result = testdir.runpytest_subprocess("--mypy", *xdist_args)
            mypy_file_checks = 1
            mypy_status_check = 1
            mypy_checks = mypy_file_checks + mypy_status_check
            result.assert_outcomes(failed=mypy_checks)
    >       result.stdout.fnmatch_lines(
                [
                    "2: error: Cannot find *module named '{module_name}'".format(
                        module_name=module_name,
                    ),
                ],
            )
    E       Failed: nomatch: "2: error: Cannot find *module named 'is_always_missing'"
    E           and: '============================= test session starts =============================='
    E           and: 'platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0'
    E           and: 'rootdir: /tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports0'
    E           and: 'plugins: mypy-0.8.1, forked-1.4.0, xdist-2.5.0, cov-3.0.0, cases-3.6.7, flake8-1.0.7'
    E           and: 'gw0 I / gw1 I / gw2 I / gw3 I / gw4 I / gw5 I / gw6 I / gw7 I / gw8 I / gw9 I / gw10 I / gw11 I'
    E           and: 'gw0 [2] / gw1 [2] / gw2 [2] / gw3 [2] / gw4 [2] / gw5 [2] / gw6 [2] / gw7 [2] / gw8 [2] / gw9 [2] / gw10 [2] / gw11 [2]'
    E           and: ''
    E           and: 'FF                                                                       [100%]'
    E           and: '=================================== FAILURES ==================================='
    E           and: '_________________________________ test session _________________________________'
    E           and: '[gw1] linux -- Python 3.8.12 /usr/bin/python3'
    E           and: 'mypy exited with status 1.'
    E           and: '_____________________ test_mypy_ignore_missings_imports.py _____________________'
    E           and: '[gw0] linux -- Python 3.8.12 /usr/bin/python3'
    E           and: '2: error: Cannot find implementation or library stub for module named "is_always_missing"'
    E           and: '2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports'
    E           and: '===================================== mypy ====================================='
    E           and: 'Found 1 error in 1 file (checked 1 source file)'
    E           and: '=========================== short test summary info ============================'
    E           and: 'FAILED test_mypy_ignore_missings_imports.py::mypy-status'
    E           and: 'FAILED test_mypy_ignore_missings_imports.py::mypy'
    E           and: '============================== 2 failed in 13.08s =============================='
    E       remains unmatched: "2: error: Cannot find *module named 'is_always_missing'"
    
    /home/tkloczko/rpmbuild/BUILD/pytest-mypy-0.8.1/tests/test_pytest_mypy.py:119: Failed
    --------------------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------------------
    running: /usr/bin/python3 -mpytest --basetemp=/tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports0/runpytest-0 --mypy -n auto
         in: /tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports0
    ============================= test session starts ==============================
    platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
    rootdir: /tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports0
    plugins: mypy-0.8.1, forked-1.4.0, xdist-2.5.0, cov-3.0.0, cases-3.6.7, flake8-1.0.7
    gw0 I / gw1 I / gw2 I / gw3 I / gw4 I / gw5 I / gw6 I / gw7 I / gw8 I / gw9 I / gw10 I / gw11 I
    gw0 [2] / gw1 [2] / gw2 [2] / gw3 [2] / gw4 [2] / gw5 [2] / gw6 [2] / gw7 [2] / gw8 [2] / gw9 [2] / gw10 [2] / gw11 [2]
    
    FF                                                                       [100%]
    =================================== FAILURES ===================================
    _________________________________ test session _________________________________
    [gw1] linux -- Python 3.8.12 /usr/bin/python3
    mypy exited with status 1.
    _____________________ test_mypy_ignore_missings_imports.py _____________________
    [gw0] linux -- Python 3.8.12 /usr/bin/python3
    2: error: Cannot find implementation or library stub for module named "is_always_missing"
    2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
    ===================================== mypy =====================================
    Found 1 error in 1 file (checked 1 source file)
    =========================== short test summary info ============================
    FAILED test_mypy_ignore_missings_imports.py::mypy-status
    FAILED test_mypy_ignore_missings_imports.py::mypy
    ============================== 2 failed in 13.08s ==============================
    _________________________________________________________________ test_mypy_ignore_missings_imports[False] _________________________________________________________________
    
    testdir = <Testdir local('/tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports1')>, xdist_args = []
    
        def test_mypy_ignore_missings_imports(testdir, xdist_args):
            """
            Verify that --mypy-ignore-missing-imports
            causes mypy to ignore missing imports.
            """
            module_name = "is_always_missing"
            testdir.makepyfile(
                """
                    try:
                        import {module_name}
                    except ImportError:
                        pass
                """.format(
                    module_name=module_name,
                ),
            )
            result = testdir.runpytest_subprocess("--mypy", *xdist_args)
            mypy_file_checks = 1
            mypy_status_check = 1
            mypy_checks = mypy_file_checks + mypy_status_check
            result.assert_outcomes(failed=mypy_checks)
    >       result.stdout.fnmatch_lines(
                [
                    "2: error: Cannot find *module named '{module_name}'".format(
                        module_name=module_name,
                    ),
                ],
            )
    E       Failed: nomatch: "2: error: Cannot find *module named 'is_always_missing'"
    E           and: '============================= test session starts =============================='
    E           and: 'platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0'
    E           and: 'rootdir: /tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports1'
    E           and: 'plugins: mypy-0.8.1, forked-1.4.0, xdist-2.5.0, cov-3.0.0, cases-3.6.7, flake8-1.0.7'
    E           and: 'collected 2 items'
    E           and: ''
    E           and: 'test_mypy_ignore_missings_imports.py FF                                  [100%]'
    E           and: ''
    E           and: '=================================== FAILURES ==================================='
    E           and: '_____________________ test_mypy_ignore_missings_imports.py _____________________'
    E           and: '2: error: Cannot find implementation or library stub for module named "is_always_missing"'
    E           and: '2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports'
    E           and: '_________________________________ test session _________________________________'
    E           and: 'mypy exited with status 1.'
    E           and: '===================================== mypy ====================================='
    E           and: 'Found 1 error in 1 file (checked 1 source file)'
    E           and: '=========================== short test summary info ============================'
    E           and: 'FAILED test_mypy_ignore_missings_imports.py::mypy'
    E           and: 'FAILED test_mypy_ignore_missings_imports.py::mypy-status'
    E           and: '============================== 2 failed in 11.33s =============================='
    E       remains unmatched: "2: error: Cannot find *module named 'is_always_missing'"
    
    /home/tkloczko/rpmbuild/BUILD/pytest-mypy-0.8.1/tests/test_pytest_mypy.py:119: Failed
    --------------------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------------------
    running: /usr/bin/python3 -mpytest --basetemp=/tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports1/runpytest-0 --mypy
         in: /tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports1
    ============================= test session starts ==============================
    platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
    rootdir: /tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports1
    plugins: mypy-0.8.1, forked-1.4.0, xdist-2.5.0, cov-3.0.0, cases-3.6.7, flake8-1.0.7
    collected 2 items
    
    test_mypy_ignore_missings_imports.py FF                                  [100%]
    
    =================================== FAILURES ===================================
    _____________________ test_mypy_ignore_missings_imports.py _____________________
    2: error: Cannot find implementation or library stub for module named "is_always_missing"
    2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
    _________________________________ test session _________________________________
    mypy exited with status 1.
    ===================================== mypy =====================================
    Found 1 error in 1 file (checked 1 source file)
    =========================== short test summary info ============================
    FAILED test_mypy_ignore_missings_imports.py::mypy
    FAILED test_mypy_ignore_missings_imports.py::mypy-status
    ============================== 2 failed in 11.33s ==============================
    _________________________________________________________________ test_mypy_ignore_missings_imports[None] __________________________________________________________________
    
    testdir = <Testdir local('/tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports2')>, xdist_args = ['-p', 'no:xdist']
    
        def test_mypy_ignore_missings_imports(testdir, xdist_args):
            """
            Verify that --mypy-ignore-missing-imports
            causes mypy to ignore missing imports.
            """
            module_name = "is_always_missing"
            testdir.makepyfile(
                """
                    try:
                        import {module_name}
                    except ImportError:
                        pass
                """.format(
                    module_name=module_name,
                ),
            )
            result = testdir.runpytest_subprocess("--mypy", *xdist_args)
            mypy_file_checks = 1
            mypy_status_check = 1
            mypy_checks = mypy_file_checks + mypy_status_check
            result.assert_outcomes(failed=mypy_checks)
    >       result.stdout.fnmatch_lines(
                [
                    "2: error: Cannot find *module named '{module_name}'".format(
                        module_name=module_name,
                    ),
                ],
            )
    E       Failed: nomatch: "2: error: Cannot find *module named 'is_always_missing'"
    E           and: '============================= test session starts =============================='
    E           and: 'platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0'
    E           and: 'rootdir: /tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports2'
    E           and: 'plugins: mypy-0.8.1, forked-1.4.0, xdist-2.5.0, cov-3.0.0, cases-3.6.7, flake8-1.0.7'
    E           and: 'collected 2 items'
    E           and: ''
    E           and: 'test_mypy_ignore_missings_imports.py FF                                  [100%]'
    E           and: ''
    E           and: '=================================== FAILURES ==================================='
    E           and: '_____________________ test_mypy_ignore_missings_imports.py _____________________'
    E           and: '2: error: Cannot find implementation or library stub for module named "is_always_missing"'
    E           and: '2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports'
    E           and: '_________________________________ test session _________________________________'
    E           and: 'mypy exited with status 1.'
    E           and: '===================================== mypy ====================================='
    E           and: 'Found 1 error in 1 file (checked 1 source file)'
    E           and: '=========================== short test summary info ============================'
    E           and: 'FAILED test_mypy_ignore_missings_imports.py::mypy'
    E           and: 'FAILED test_mypy_ignore_missings_imports.py::mypy-status'
    E           and: '============================== 2 failed in 11.25s =============================='
    E       remains unmatched: "2: error: Cannot find *module named 'is_always_missing'"
    
    /home/tkloczko/rpmbuild/BUILD/pytest-mypy-0.8.1/tests/test_pytest_mypy.py:119: Failed
    --------------------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------------------
    running: /usr/bin/python3 -mpytest --basetemp=/tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports2/runpytest-0 --mypy -p no:xdist
         in: /tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports2
    ============================= test session starts ==============================
    platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
    rootdir: /tmp/pytest-of-tkloczko/pytest-551/test_mypy_ignore_missings_imports2
    plugins: mypy-0.8.1, forked-1.4.0, xdist-2.5.0, cov-3.0.0, cases-3.6.7, flake8-1.0.7
    collected 2 items
    
    test_mypy_ignore_missings_imports.py FF                                  [100%]
    
    =================================== FAILURES ===================================
    _____________________ test_mypy_ignore_missings_imports.py _____________________
    2: error: Cannot find implementation or library stub for module named "is_always_missing"
    2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
    _________________________________ test session _________________________________
    mypy exited with status 1.
    ===================================== mypy =====================================
    Found 1 error in 1 file (checked 1 source file)
    =========================== short test summary info ============================
    FAILED test_mypy_ignore_missings_imports.py::mypy
    FAILED test_mypy_ignore_missings_imports.py::mypy-status
    ============================== 2 failed in 11.25s ==============================
    ========================================================================= short test summary info ==========================================================================
    FAILED tests/test_pytest_mypy.py::test_mypy_ignore_missings_imports[True] - Failed: nomatch: "2: error: Cannot find *module named 'is_always_missing'"
    FAILED tests/test_pytest_mypy.py::test_mypy_ignore_missings_imports[False] - Failed: nomatch: "2: error: Cannot find *module named 'is_always_missing'"
    FAILED tests/test_pytest_mypy.py::test_mypy_ignore_missings_imports[None] - Failed: nomatch: "2: error: Cannot find *module named 'is_always_missing'"
    ================================================================= 3 failed, 47 passed in 588.13s (0:09:48) =================================================================
    
    opened by kloczek 9
  • Build requirements are too strict

    Build requirements are too strict

    I'd like to package pytest-mypy for OpenIndiana, but it is very hard to do so because build requirements for pytest-mypy are these (from pyproject.toml):

    [build-system]
    requires = ['setuptools ~= 50.3.0', 'setuptools-scm[toml] ~= 5.0.0', 'wheel ~= 0.36.0']
    build-backend = 'setuptools.build_meta'
    

    The latest acceptable versions of required tools are about two years old now.

    Could you please update pytest-mypy to relax its build requirements?

    Thank you.

    opened by mtelka 8
  • The exclude option is being ignored

    The exclude option is being ignored

    I am using pytest-mypy 0.8.0 to check ts_salobj (see link below). It had a generated version.py file that makes mypy unhappy so I am trying to exclude that (on branch tickets/DM-31000, see link below). My configuration works if I run mypy from the command line:

    mypy python tests
    

    but if run mypy using pytest-mypy then version.py is processed and the test fails:

    pytest -v -m mypy
    

    My configuration includes verbosity=1 and the output shows that version\.py is marked as excluded in both cases, but somehow pytest is pulling it in anyway.

    I am not sure how pytest is running mypy. Even with verbosity 2 I can't tell pytest-mypy tells mypy which files to test. I suspect that pytest-mypy is explicitly ordering mypy to test each file and am hoping there is some way to tell it to exclude version.py.

    The packages is here https://github.com/lsst-ts/ts_salobj/tree/tickets/DM-31000 and that ticket branch is the one with my attempted changes (including committing the offending version.py file, which normally is not in git).

    I admit that I am specifying the mypy config in setup.cfg and the pytest-mypy docs say to use mypy.ini. However, pytest-mypy is clearly using the configuration, based on the verbosity and the resulting log. Also moving or copying the mypy configuration to a new mypy.ini file makes no difference. Here is an excerpt from the printed output from pytest -v -m mypy:

    LOG:  Mypy Version:           0.812
    LOG:  Config File:            setup.cfg
    LOG:  Configured Executable:  /opt/lsst/software/stack/conda/miniconda3-py38_4.9.2/envs/lsst-scipipe-0.6.0/bin/python
    LOG:  Current Executable:     /opt/lsst/software/stack/conda/miniconda3-py38_4.9.2/envs/lsst-scipipe-0.6.0/bin/python
    LOG:  Cache Dir:              .mypy_cache
    LOG:  Compiled:               True
    LOG:  Exclude:                version\.py
    LOG:  Found source:           BuildSource(path='/home/saluser/tsrepos/ts_salobj/setup.py', module='setup', has_text=False, base_dir='/home/saluser/tsrepos/ts_salobj')
    ...
    LOG:  Found source:           BuildSource(path='/home/saluser/tsrepos/ts_salobj/python/lsst/ts/salobj/validator.py', module='salobj.validator', has_text=False, base_dir='/home/saluser/tsrepos/ts_salobj/python/lsst/ts')
    LOG:  Found source:           BuildSource(path='/home/saluser/tsrepos/ts_salobj/python/lsst/ts/salobj/version.py', module='salobj.version', has_text=False, base_dir='/home/saluser/tsrepos/ts_salobj/python/lsst/ts')
    LOG:  Found source:           BuildSource(path='/home/saluser/tsrepos/ts_salobj/python/lsst/ts/salobj/topics/__init__.py', module='salobj.topics', has_text=False, base_dir='/home/saluser/tsrepos/ts_salobj/python/lsst/ts')
    

    and a log from the command line:

    LOG:  Mypy Version:           0.812
    LOG:  Config File:            setup.cfg
    LOG:  Configured Executable:  /opt/lsst/software/stack/conda/miniconda3-py38_4.9.2/envs/lsst-scipipe-0.6.0/bin/python
    LOG:  Current Executable:     /opt/lsst/software/stack/conda/miniconda3-py38_4.9.2/envs/lsst-scipipe-0.6.0/bin/python
    LOG:  Cache Dir:              .mypy_cache
    LOG:  Compiled:               True
    LOG:  Exclude:                version\.py
    LOG:  Found source:           BuildSource(path='python/lsst/ts/salobj/__init__.py', module='salobj', has_text=False, base_dir='/home/saluser/tsrepos/ts_salobj/python/lsst/ts')
    ...
    LOG:  Found source:           BuildSource(path='python/lsst/ts/salobj/validator.py', module='salobj.validator', has_text=False, base_dir='/home/saluser/tsrepos/ts_salobj/python/lsst/ts')
    LOG:  Found source:           BuildSource(path='tests/data/minimal_salobj_controller.py', module='minimal_salobj_controller', has_text=False, base_dir='/home/saluser/tsrepos/ts_salobj/tests/data')
    LOG:  Found source:           BuildSource(path='/home/saluser/tsrepos/ts_salobj/python/lsst/ts/salobj/topics/__init__.py', module='salobj.topics', has_text=False, base_dir='/home/saluser/tsrepos/ts_salobj/python/lsst/ts')
    

    notice that version.py is not listed as a "Found source" in the second case.

    opened by r-owen 8
  • Update dependency from mypy-lang to mypy

    Update dependency from mypy-lang to mypy

    When trying to use a development snapshot of mypy (through pip install git+https://github.com/python/mypy.git\#egg\=mypy), the current setup.py is ignoring the existing mypy installation because it doesn't match mypy-lang, making such use impossible.

    Apparently mypy's maintainers managed to get access to mypy in PyPI, and their setup.py now builds using this very name.

    This fix consists of dropping the dependency on mypy-lang and adding a new one on mypy requiring version 0.470 or newer, which is the earliest version available on PyPI for this newly named package.

    opened by lastmikoi 8
  • Fix automatic release deployment

    Fix automatic release deployment

    Resolve #104

    This will not work until the project has repository secrets for PYPI_USERNAME and PYPI_PASSWORD: https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository

    I don't have permission to do that, so @dbader will have to do it.

    opened by dmtucker 7
  • Why not just use `mypy`and

    Why not just use `mypy`and "pytest`? What are the advantages of the "pytest-mypy" package?

    Sorry for my noob question, but what is the purpose of the package? I can run in a terminal locally or at a cloud's CI/CD the following two commands:

    >  mypy src/ && mypy tests/
    >  pytest tests/ 
    

    So why waste time on a new package development instead of just running two simple commands?

    opened by AIGeneratedUsername 7
  • AttributeError: 'MypyStatusItem' object has no attribute '_obj'

    AttributeError: 'MypyStatusItem' object has no attribute '_obj'

    Hey,

    I'm using both pytest-mypy and allure-pytest together and when I generate the report, I'm getting weird errors I don't know how to solve.

    Can you help me please?

    Test Code

    import allure
    
    
    def test_mypy1():
    
        def foo(arg: str) -> int:
            return arg
    
    
    @allure.severity(allure.severity_level.MINOR)
    def test_mypy2():
    
        def boo() -> int:
            return 10
    
    
    def test_mypy3():
    
        def boo() -> int:
            return 'I should have been an int'
    

    Error: AttributeError: 'MypyStatusItem' object has no attribute '_obj'

    cls = <class '_pytest.runner.CallInfo'>
    func = <function call_runtest_hook.<locals>.<lambda> at 0x7f855c16a3b0>
    when = 'setup'
    reraise = (<class '_pytest.outcomes.Exit'>, <class 'KeyboardInterrupt'>)
    
        @classmethod
        def from_call(
            cls,
            func: "Callable[[], TResult]",
            when: "Literal['collect', 'setup', 'call', 'teardown']",
            reraise: Optional[
                Union[Type[BaseException], Tuple[Type[BaseException], ...]]
            ] = None,
        ) -> "CallInfo[TResult]":
            excinfo = None
            start = timing.time()
            precise_start = timing.perf_counter()
            try:
    >           result: Optional[TResult] = func()
    
    .venv/lib/python3.7/site-packages/_pytest/runner.py:311: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    >       lambda: ihook(item=item, **kwds), when=when, reraise=reraise
        )
    
    .venv/lib/python3.7/site-packages/_pytest/runner.py:255: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    self = <_HookCaller 'pytest_runtest_setup'>, args = ()
    kwargs = {'item': <MypyStatusItem mypy>}, notincall = set()
    
        def __call__(self, *args, **kwargs):
            if args:
                raise TypeError("hook calling supports only keyword arguments")
            assert not self.is_historic()
            if self.spec and self.spec.argnames:
                notincall = (
                    set(self.spec.argnames) - set(["__multicall__"]) - set(kwargs.keys())
                )
                if notincall:
                    warnings.warn(
                        "Argument(s) {} which are declared in the hookspec "
                        "can not be found in this hook call".format(tuple(notincall)),
                        stacklevel=2,
                    )
    >       return self._hookexec(self, self.get_hookimpls(), kwargs)
    
    .venv/lib/python3.7/site-packages/pluggy/hooks.py:286: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    self = <_pytest.config.PytestPluginManager object at 0x7f8558758150>
    hook = <_HookCaller 'pytest_runtest_setup'>
    methods = [<HookImpl plugin_name='nose', plugin=<module '_pytest.nose' from '/Users/nusnus/dev/flask_tester/.venv/lib/python3.7/...855c013450>>, <HookImpl plugin_name='logging-plugin', plugin=<_pytest.logging.LoggingPlugin object at 0x7f855c034b90>>]
    kwargs = {'item': <MypyStatusItem mypy>}
    
        def _hookexec(self, hook, methods, kwargs):
            # called from all hookcaller instances.
            # enable_tracing will set its own wrapping function at self._inner_hookexec
    >       return self._inner_hookexec(hook, methods, kwargs)
    
    .venv/lib/python3.7/site-packages/pluggy/manager.py:93: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    hook = <_HookCaller 'pytest_runtest_setup'>
    methods = [<HookImpl plugin_name='nose', plugin=<module '_pytest.nose' from '/Users/nusnus/dev/flask_tester/.venv/lib/python3.7/...855c013450>>, <HookImpl plugin_name='logging-plugin', plugin=<_pytest.logging.LoggingPlugin object at 0x7f855c034b90>>]
    kwargs = {'item': <MypyStatusItem mypy>}
    
        self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall(
            methods,
            kwargs,
    >       firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
        )
    
    .venv/lib/python3.7/site-packages/pluggy/manager.py:87: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    hook_impls = [<HookImpl plugin_name='nose', plugin=<module '_pytest.nose' from '/Users/nusnus/dev/flask_tester/.venv/lib/python3.7/...855c013450>>, <HookImpl plugin_name='logging-plugin', plugin=<_pytest.logging.LoggingPlugin object at 0x7f855c034b90>>]
    caller_kwargs = {'item': <MypyStatusItem mypy>}, firstresult = False
    
        def _multicall(hook_impls, caller_kwargs, firstresult=False):
            """Execute a call into multiple python functions/methods and return the
            result(s).
        
            ``caller_kwargs`` comes from _HookCaller.__call__().
            """
            __tracebackhide__ = True
            results = []
            excinfo = None
            try:  # run impl and wrapper setup functions in a loop
                teardowns = []
                try:
                    for hook_impl in reversed(hook_impls):
                        try:
                            args = [caller_kwargs[argname] for argname in hook_impl.argnames]
                        except KeyError:
                            for argname in hook_impl.argnames:
                                if argname not in caller_kwargs:
                                    raise HookCallError(
                                        "hook call must provide argument %r" % (argname,)
                                    )
        
                        if hook_impl.hookwrapper:
                            try:
                                gen = hook_impl.function(*args)
                                next(gen)  # first yield
                                teardowns.append(gen)
                            except StopIteration:
                                _raise_wrapfail(gen, "did not yield")
                        else:
                            res = hook_impl.function(*args)
                            if res is not None:
                                results.append(res)
                                if firstresult:  # halt further impl calls
                                    break
                except BaseException:
                    excinfo = sys.exc_info()
            finally:
                if firstresult:  # first result hooks return a single value
                    outcome = _Result(results[0] if results else None, excinfo)
                else:
                    outcome = _Result(results, excinfo)
        
                # run all wrapper post-yield blocks
                for gen in reversed(teardowns):
                    try:
    >                   gen.send(outcome)
    
    .venv/lib/python3.7/site-packages/pluggy/callers.py:203: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    self = <allure_pytest.listener.AllureListener object at 0x7f855c013450>
    item = <MypyStatusItem mypy>
    
        @pytest.hookimpl(hookwrapper=True)
        def pytest_runtest_setup(self, item):
            if not self._cache.get(item.nodeid):
                uuid = self._cache.push(item.nodeid)
                test_result = TestResult(name=item.name, uuid=uuid, start=now(), stop=now())
                self.allure_logger.schedule_test(uuid, test_result)
        
            yield
        
            uuid = self._cache.get(item.nodeid)
            test_result = self.allure_logger.get_test(uuid)
            for fixturedef in _test_fixtures(item):
                group_uuid = self._cache.get(fixturedef)
                if not group_uuid:
                    group_uuid = self._cache.push(fixturedef)
                    group = TestResultContainer(uuid=group_uuid)
                    self.allure_logger.start_group(group_uuid, group)
                self.allure_logger.update_group(group_uuid, children=uuid)
            params = item.callspec.params if hasattr(item, 'callspec') else {}
        
    >       test_result.name = allure_name(item, params)
    
    .venv/lib/python3.7/site-packages/allure_pytest/listener.py:88: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    item = <MypyStatusItem mypy>, parameters = {}
    
        def allure_name(item, parameters):
            name = escape_name(item.name)
    >       title = allure_title(item)
    
    .venv/lib/python3.7/site-packages/allure_pytest/utils.py:110: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    item = <MypyStatusItem mypy>
    
        def allure_title(item):
    >       return getattr(item._obj, '__allure_display_name__', None)
    E       AttributeError: 'MypyStatusItem' object has no attribute '_obj'
    
    .venv/lib/python3.7/site-packages/allure_pytest/utils.py:34: AttributeError
    
    opened by Nusnus 7
  • False positives using when using pytest-xdist -f (--looponfail)

    False positives using when using pytest-xdist -f (--looponfail)

    When doing TDD, after the first mypy error, the plugin start emitting errors on collection.

    It will continue normally until you hit an actual mypy fail, then in the follow round (after mypy error is fixed) this warning is emitted forever until pytest is killed and restarted.

    Steps to Reproduce (assumes python 3.8 and pipenv available):

    1. mkdir ~/tmp20200412
    2. cd ~/tmp20200412
    3. git clone [email protected]:y2kbugger/test_driven_development_by_example_tdd_follow_along.git
    4. cd ./test*
    5. git checkout b0a2f56
    6. replicate versions exactly from Pipfile.lock pipenv sync
    7. put venv on PATH pipenv shell
    8. run pytest pytest --mypy -f money.py test_money.py

    In another terminal:

    1. cd ~/tmp20200412/test*
    2. cause mypy error echo 'lol: str = 2' >> money.py
    3. undo mypy error git checkout b0a2f56 -- .
    ###################################### waiting for changes #######################################
    ### Watching:   /home/y2k/devel/test_driven_development_by_example_tdd_follow_along
    # MODIFIED /home/y2k/devel/test_driven_development_by_example_tdd_follow_along/money.py
    ============================= test session starts ==============================
    platform linux -- Python 3.8.2, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
    rootdir: /home/y2k/devel/test_driven_development_by_example_tdd_follow_along
    plugins: forked-1.1.3, mypy-0.6.1, xdist-1.31.0, flake8-1.0.4
    collected 0 items / 1 error
    collected 0 items / 1 error
    
    ==================================== ERRORS ====================================
    ________________________ ERROR collecting test session _________________________
    ../../.local/share/virtualenvs/test_driven_development_by_example_tdd_fol-TPMT2dI5/lib/python3.8/site-packages/_pytest/runner.py:244: in from_call
        result = func()
    ../../.local/share/virtualenvs/test_driven_development_by_example_tdd_fol-TPMT2dI5/lib/python3.8/site-packages/_pytest/runner.py:264: in <lambda>
        call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
    ../../.local/share/virtualenvs/test_driven_development_by_example_tdd_fol-TPMT2dI5/lib/python3.8/site-packages/_pytest/main.py:498: in collect
        yield from self._collect(fspath, parts)
    ../../.local/share/virtualenvs/test_driven_development_by_example_tdd_fol-TPMT2dI5/lib/python3.8/site-packages/_pytest/main.py:537: in _collect
        assert not names, "invalid arg {!r}".format((argpath, names))
    E   AssertionError: invalid arg (local('/home/y2k/devel/test_driven_development_by_example_tdd_follow_along'), ['mypy'])
    =========================== short test summary info ============================
    ERROR  - AssertionError: invalid arg (local('/home/y2k/devel/test_driven_deve...
    !!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
    =============================== 1 error in 0.22s ===============================
    ######################################### LOOPONFAILING ##########################################
    money.py::mypy
    test_money.py::test_multiplication
    test_money.py::test_franc_multiplication
    test_money.py::test_equality
    test_money.py::test_currency
    ::mypy
    ###################################### waiting for changes #######################################
    ### Watching:   /home/y2k/devel/test_driven_development_by_example_tdd_follow_along
    

    Note I kill with keyboard interrupt here:

    ^C
    

    Then everything goes fine again:

    (test_driven_development_by_example_tdd_follow_along) [[email protected] test_driven_development_by_example_tdd_follow_along]
    $ pytest --mypy -f money.py test_money.py 
    ============================= test session starts ==============================
    platform linux -- Python 3.8.2, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
    rootdir: /home/y2k/devel/test_driven_development_by_example_tdd_follow_along
    plugins: forked-1.1.3, mypy-0.6.1, xdist-1.31.0, flake8-1.0.4
    collected 7 items
    collected 7 items
    
    money.py .                                                               [ 12%]
    test_money.py ......                                                     [ 87%]
    . .                                                                      [100%]. [100%]
    ===================================== mypy =====================================
    
    Success: no issues found in 2 source files
    ============================== 9 passed in 0.34s ===============================
    ###################################### waiting for changes #######################################
    ### Watching:   /home/y2k/devel/test_driven_development_by_example_tdd_follow_along
    
    opened by y2kbugger 6
  • Only depend on mypy.api

    Only depend on mypy.api

    Fixes #6

    I think we should strongly discourage such use of interfaces internal to mypy. The only public APIs are the command line and the mypy.api module. https://github.com/python/mypy/issues/4681#issuecomment-371037599

    opened by dmtucker 6
  • Add --mypy-config option

    Add --mypy-config option

    Hello! I have not found how to pass path to mypy config?

    I want something like: pytest --mypy --mypy-config tox.ini

    It's because mypy isn't read config from tox.

    opened by pbelskiy 4
  • Upgrading to 0.10.2 leads to `exceptiongroup` error

    Upgrading to 0.10.2 leads to `exceptiongroup` error

    After upgrading to v0.10.2 my CI system started failing, giving the following error:

    Traceback (most recent call last):
      File "/home/alex/code/FINESSE/.venv/bin/pytest", line 5, in <module>
        from pytest import console_main
      File "/home/alex/code/FINESSE/.venv/lib/python3.9/site-packages/pytest/__init__.py", line 5, in <module>
        from _pytest._code import ExceptionInfo
      File "/home/alex/code/FINESSE/.venv/lib/python3.9/site-packages/_pytest/_code/__init__.py", line 2, in <module>
        from .code import Code
      File "/home/alex/code/FINESSE/.venv/lib/python3.9/site-packages/_pytest/_code/code.py", line 60, in <module>
        from exceptiongroup import BaseExceptionGroup
    ModuleNotFoundError: No module named 'exceptiongroup'
    

    Full output here: https://github.com/ImperialCollegeLondon/FINESSE/pull/58

    It appears that the exceptiongroup package is not being installed via poetry, though it isn't obvious why.

    Any ideas?

    opened by alexdewar 1
  • Add --no-mypy option to disable mypy check

    Add --no-mypy option to disable mypy check

    Right now I have --mypy in my pytest.ini file so that mypy runs by default when my tests are run, both locally and in CI

    However, when I'm quickly iterating in testing a new feature, I would like to skip the mypy check since I first just want to make sure that the feature works.

    Having a --no-mypy option to pass through to pytest when running locally would be great, rather than having to just deal with the mypy run each time, or go and manually modify my pytest.ini file to comment out the --mypy option.

    The pytest-pylint and pytest-cov plugins provide this functionality:

    • https://github.com/carsongee/pytest-pylint/blob/781d6a8d67377b543756d0123c6259b8df77c0a8/pytest_pylint/plugin.py#L33-L38
    • https://github.com/pytest-dev/pytest-cov/blob/00713b3fec90cb8c98a9e4bfb3212e574c08e67b/src/pytest_cov/plugin.py#L110-L112

    I'm happy to add a PR if you agree that this is a worthwhile feature

    opened by pwildenhain 1
  • mypy exited with status 1 - no error messages shown

    mypy exited with status 1 - no error messages shown

    I have some type errors in my code, and would like to find them by running mypy via pytest-mypy. When I run pytest, I get:

    =========================================================================== test session starts ============================================================================
    platform linux -- Python 3.6.9, pytest-6.2.3, py-1.10.0, pluggy-0.13.1 -- <venv>
    cachedir: .pytest_cache
    rootdir: <project-root>, configfile: setup.cfg, testpaths: proof_of_concept, tests
    plugins: cov-2.11.1, pycodestyle-2.2.0, pydocstyle-2.2.0, mypy-0.8.1
    collected 154 items                                                                                                                                                        
    
    proof_of_concept/__init__.py::mypy PASSED
    proof_of_concept/__init__.py::mypy-status FAILED
    
    ================================================================================= FAILURES =================================================================================
    _______________________________________________________________________________ test session _______________________________________________________________________________
    mypy exited with status 1.
    

    This suggests that there were some errors, but it doesn't show what they were, so I cannot fix them. Running mypy separately reveals a bunch of issues in proof_of_concept/rest/registry_client.py.

    Looking at the pytest-mypy source, it seems that this can happen if mypy checks a file that has not been collected. I'm importing the problem file from the file under test, and mypy gives a bunch of errors about this imported file. I guess the ::mypy test passes anyway, because the errors are not in the file under test. However, pytest-mypy then generates an error using this second mypy-status result, because mypy returned a non-zero exit code.

    Ignoring the errors makes sense I think, they should show up later when the problem file itself is tested. Unfortunately, we never get to that point, because I'm running with -x, which stops the tests as soon as the first error is found, and no error messages are shown for the mypy-status failure, so I cannot fix them.

    I'm a bit confused about the current intent of the pytest-mypy code. There's a comment suggesting that the ::mypy test is intended to fail even if mypy only shows errors in files that weren't collected, and that that is why there's the ::mypy-status result. On the other hand, there used to be a test that checked that no MypyStatusItem was created unless there was at least one MypyFileItem, which I think means the opposite. That was removed in https://github.com/dbader/pytest-mypy/commit/cd459a48ce11d24e1bddf6877ef53f7d26cf3daf however, which also introduced this -status result.

    In my opinion, a mypy failure only because of errors in imported files should either be considered an error in the file under test, in which case the error should be printed, or it should not be considered an error in the file under test, in which case all tests related to that file should pass and the non-zero exit code ignored. The latter makes more sense to me.

    opened by LourensVeen 3
  • Recommended way to set report path?

    Recommended way to set report path?

    Hi, thanks for this excellent plugin! :heart:

    We are running pytest like so; pytest tests/unit_tests and this generates a bunch of reports. Then we also run pytest tests/component_tests, which also generates a bunch of (different) reports. I use a setup.cfg file to configure both pytest and mypy.

    Now, ideally, we want the mypy reports to be named accordingly ("unit" vs "component" respectively). Do you have a recommended approach on how to achieve this? Right now, I've created a simple pytest plugin which analyses pytest's config.args and determines which type of test is executing and then it does the following:

    plugin = config.pluginmanager.getplugin("mypy")
    plugin.mypy_argv.append(f"--html-report=reports/mypy/{test_type}")
    

    But to me, this seems both hacky and a little excessive. There must be some easier way to achieve this? Any ideas? 😃

    opened by fredrikaverpil 1
  • Expected mypy errors

    Expected mypy errors

    I'm working on a module specifically for use with typing, so I have tests that I expect to raise mypy warnings. It doesn't look like there's a way to mark tests as having expected errors.

    opened by dcbaker 3
Releases(v0.10.3)
Owner
Dan Bader
Full-stack Pythonista & Python Coach. Write Clean and Pythonic code with my free tutorials, books, and courses.
Dan Bader
pytest plugin for testing mypy types, stubs, and plugins

pytest plugin for testing mypy types, stubs, and plugins Installation This package is available on PyPI pip install pytest-mypy-plugins and conda-forg

TypedDjango 74 Dec 31, 2022
Whatsapp messages bulk sender using Python Selenium.

Whatsapp Sender Whatsapp Sender automates sending of messages via Whatsapp Web. The tool allows you to send whatsapp messages in bulk. This program re

Yap Yee Qiang 3 Jan 23, 2022
This repository contnains sample problems with test cases using Cormen-Lib

Cormen Lib Sample Problems Description This repository contnains sample problems with test cases using Cormen-Lib. These problems were made for the pu

Cormen Lib 3 Jun 30, 2022
Testinfra test your infrastructures

Testinfra test your infrastructure Latest documentation: https://testinfra.readthedocs.io/en/latest About With Testinfra you can write unit tests in P

pytest-dev 2.1k Jan 07, 2023
Automates hiketop+ crystal earning using python and appium

hikepy Works on poco x3 idk about your device deponds on resolution Prerquests Android sdk java adb Setup Go to https://appium.io/ Download and instal

4 Aug 26, 2022
The definitive testing tool for Python. Born under the banner of Behavior Driven Development (BDD).

mamba: the definitive test runner for Python mamba is the definitive test runner for Python. Born under the banner of behavior-driven development. Ins

Néstor Salceda 502 Dec 30, 2022
AllPairs is an open source test combinations generator written in Python

AllPairs is an open source test combinations generator written in Python

Robson Agapito Correa 5 Mar 05, 2022
Minimal example of getting Django + PyTest running on GitHub Actions

Minimal Django + Pytest + GitHub Actions example This minimal example shows you how you can runs pytest on your Django app on every commit using GitHu

Matt Segal 5 Sep 19, 2022
This file will contain a series of Python functions that use the Selenium library to search for elements in a web page while logging everything into a file

element_search with Selenium (Now With docstrings 😎 ) Just to mention, I'm a beginner to all this, so it it's very possible to make some mistakes The

2 Aug 12, 2021
Let your Python tests travel through time

FreezeGun: Let your Python tests travel through time FreezeGun is a library that allows your Python tests to travel through time by mocking the dateti

Steve Pulec 3.5k Dec 29, 2022
A modern API testing tool for web applications built with Open API and GraphQL specifications.

Schemathesis Schemathesis is a modern API testing tool for web applications built with Open API and GraphQL specifications. It reads the application s

Schemathesis.io 1.6k Jan 06, 2023
tidevice can be used to communicate with iPhone device

tidevice can be used to communicate with iPhone device

Alibaba 1.8k Jan 08, 2023
输入Google Hacking语句,自动调用Chrome浏览器爬取结果

Google-Hacking-Crawler 该脚本可输入Google Hacking语句,自动调用Chrome浏览器爬取结果 环境配置 python -m pip install -r requirements.txt 下载Chrome浏览器

Jarcis 4 Jun 21, 2022
A pure Python script to easily get a reverse shell

easy-shell A pure Python script to easily get a reverse shell. How it works? After sending a request, it generates a payload with different commands a

Cristian Souza 48 Dec 12, 2022
UUM Merit Form Filler is a web automation which helps automate entering a matric number to the UUM system in order for participants to obtain a merit

About UUM Merit Form Filler UUM Merit Form Filler is a web automation which helps automate entering a matric number to the UUM system in order for par

Ilham Rachmat 3 May 31, 2022
A cross-platform GUI automation Python module for human beings. Used to programmatically control the mouse & keyboard.

PyAutoGUI PyAutoGUI is a cross-platform GUI automation Python module for human beings. Used to programmatically control the mouse & keyboard. pip inst

Al Sweigart 7.5k Dec 31, 2022
Percy visual testing for Python Selenium

percy-selenium-python Percy visual testing for Python Selenium. Installation npm install @percy/cli: $ npm install --save-dev @percy/cli pip install P

Percy 9 Mar 24, 2022
Auto Click by pyautogui and excel operations.

Auto Click by pyautogui and excel operations.

Janney 2 Dec 21, 2021
User-oriented Web UI browser tests in Python

Selene - User-oriented Web UI browser tests in Python (Selenide port) Main features: User-oriented API for Selenium Webdriver (code like speak common

Iakiv Kramarenko 575 Jan 02, 2023
FakeDataGen is a Full Valid Fake Data Generator.

FakeDataGen is a Full Valid Fake Data Generator. This tool helps you to create fake accounts (in Spanish format) with fully valid data. Within this in

Joel GM 64 Dec 12, 2022