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
Bayesian A/B testing

bayesian_testing is a small package for a quick evaluation of A/B (or A/B/C/...) tests using Bayesian approach.

Matus Baniar 35 Dec 15, 2022
Find index entries in $INDEX_ALLOCATION attributes

INDXRipper Find index entries in $INDEX_ALLOCATION attributes Timeline created using mactime.pl on the combined output of INDXRipper and fls. See: sle

32 Nov 05, 2022
A folder automation made using Watch-dog, it only works in linux for now but I assume, it will be adaptable to mac and PC as well

folder-automation A folder automation made using Watch-dog, it only works in linux for now but I assume, it will be adaptable to mac and PC as well Th

Parag Jyoti Paul 31 May 28, 2021
Python version of the Playwright testing and automation library.

🎭 Playwright for Python Docs | API Playwright is a Python library to automate Chromium, Firefox and WebKit browsers with a single API. Playwright del

Microsoft 7.8k Jan 02, 2023
Obsei is a low code AI powered automation tool.

Obsei is a low code AI powered automation tool. It can be used in various business flows like social listening, AI based alerting, brand image analysis, comparative study and more .

Obsei 782 Dec 31, 2022
WEB PENETRATION TESTING TOOL 💥

N-WEB ADVANCE WEB PENETRATION TESTING TOOL Features 🎭 Admin Panel Finder Admin Scanner Dork Generator Advance Dork Finder Extract Links No Redirect H

56 Dec 23, 2022
Screenplay pattern base for Python automated UI test suites.

ScreenPy TITLE CARD: "ScreenPy" TITLE DISAPPEARS.

Perry Goy 39 Nov 15, 2022
Hamcrest matchers for Python

PyHamcrest Introduction PyHamcrest is a framework for writing matcher objects, allowing you to declaratively define "match" rules. There are a number

Hamcrest 684 Dec 29, 2022
Youtube Tool using selenium Python

YT-AutoLikeComment-AutoReportComment-AutoComment Youtube Tool using selenium Python Auto Comment Auto Like Comment Auto Report Comment Usage: 1. Insta

Rahul Joshua Damanik 1 Dec 13, 2021
Photostudio是一款能进行自动化检测网页存活并实时给网页拍照的工具,通过调用Fofa/Zoomeye/360qua/shodan等 Api快速准确查询资产并进行网页截图,从而实施进一步的信息筛查。

Photostudio-红队快速爬取网页快照工具 一、简介: 正如其名:这是一款能进行自动化检测,实时给网页拍照的工具 信息收集要求所收集到的信息要真实可靠。 当然,这个原则是信息收集工作的最基本的要求。为达到这样的要求,信息收集者就必须对收集到的信息反复核实,不断检验,力求把误差减少到最低限度。我

s7ck Team 41 Dec 11, 2022
a wrapper around pytest for executing tests to look for test flakiness and runtime regression

bubblewrap a wrapper around pytest for assessing flakiness and runtime regressions a cs implementations practice project How to Run: First, install de

Anna Nagy 1 Aug 05, 2021
A friendly wrapper for modern SQLAlchemy and Alembic

A friendly wrapper for modern SQLAlchemy (v1.4 or later) and Alembic. Documentation: https://jpsca.github.io/sqla-wrapper/ Includes: A SQLAlchemy wrap

Juan-Pablo Scaletti 129 Nov 28, 2022
DUCKSPLOIT - Windows Hacking FrameWork using Reverse Shell

Ducksploit Install Ducksploit Hacker setup raspberry pico Download https://githu

2 Jan 31, 2022
The pytest framework makes it easy to write small tests, yet scales to support complex functional testing

The pytest framework makes it easy to write small tests, yet scales to support complex functional testing for applications and libraries. An example o

pytest-dev 9.6k Jan 02, 2023
A python bot using the Selenium library to auto-buy specified sneakers on the nike.com website.

Sneaker-Bot-UK A python bot using the Selenium library to auto-buy specified sneakers on the nike.com website. This bot is still in development and is

Daniel Hinds 4 Dec 14, 2022
A collection of benchmarking tools.

Benchmark Utilities About A collection of benchmarking tools. PYPI Package Table of Contents Using the library Installing and using the library Manual

Kostas Georgiou 2 Jan 28, 2022
Descriptor Vector Exchange

Descriptor Vector Exchange This repo provides code for learning dense landmarks without supervision. Our approach is described in the ICCV 2019 paper

James Thewlis 74 Nov 29, 2022
tidevice can be used to communicate with iPhone device

tidevice can be used to communicate with iPhone device

Alibaba 1.8k Jan 08, 2023
Coverage plugin for pytest.

Overview docs tests package This plugin produces coverage reports. Compared to just using coverage run this plugin does some extras: Subprocess suppor

pytest-dev 1.4k Dec 29, 2022
Pytest-rich - Pytest + rich integration (proof of concept)

pytest-rich Leverage rich for richer test session output. This plugin is not pub

Bruno Oliveira 170 Dec 02, 2022