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
Load Testing ML Microservices for Robustness and Scalability

The demo is aimed at getting started with load testing a microservice before taking it to production. We use FastAPI microservice (to predict weather) and Locust to load test the service (locally or

Emmanuel Raj 13 Jul 05, 2022
A grab-bag of nifty pytest plugins

A goody-bag of nifty plugins for pytest OS Build Coverage Plugin Description Supported OS pytest-server-fixtures Extensible server-running framework w

Man Group 492 Jan 03, 2023
Sixpack is a language-agnostic a/b-testing framework

Sixpack Sixpack is a framework to enable A/B testing across multiple programming languages. It does this by exposing a simple API for client libraries

1.7k Dec 24, 2022
The Penetration Testers Framework (PTF) is a way for modular support for up-to-date tools.

The PenTesters Framework (PTF) is a Python script designed for Debian/Ubuntu/ArchLinux based distributions to create a similar and familiar distribution for Penetration Testing

trustedsec 4.5k Dec 28, 2022
Tutorial for integrating Oxylabs' Residential Proxies with Selenium

Oxylabs’ Residential Proxies integration with Selenium Requirements For the integration to work, you'll need to install Selenium on your system. You c

Oxylabs.io 8 Dec 08, 2022
Public repo for automation scripts

Script_Quickies Public repo for automation scripts Dependencies Chrome webdriver .exe (make sure it matches the version of chrome you are using) Selen

CHR-onicles 1 Nov 04, 2021
0hh1 solver for the web (selenium) and also for mobile (adb)

0hh1 - Solver Aims to solve the '0hh1 puzzle' for all the sizes (4x4, 6x6, 8x8, 10x10 12x12). for both the web version (using selenium) and on android

Adwaith Rajesh 1 Nov 05, 2021
This package is a python library with tools for the Molecular Simulation - Software Gromos.

This package is a python library with tools for the Molecular Simulation - Software Gromos. It allows you to easily set up, manage and analyze simulations in python.

14 Sep 28, 2022
Donors data of Tamil Nadu Chief Ministers Relief Fund scrapped from https://ereceipt.tn.gov.in/cmprf/Interface/CMPRF/MonthWiseReport

Tamil Nadu Chief Minister's Relief Fund Donors Scrapped data from https://ereceipt.tn.gov.in/cmprf/Interface/CMPRF/MonthWiseReport Scrapper scrapper.p

Arunmozhi 5 May 18, 2021
A simple script to login into twitter using Selenium in python.

Quick Talk A simple script to login into twitter using Selenium in python. I was looking for a way to login into twitter using Selenium in python. Sin

Lzy-slh 4 Nov 20, 2022
create custom test databases that are populated with fake data

About Generate fake but valid data filled databases for test purposes using most popular patterns(AFAIK). Current support is sqlite, mysql, postgresql

Emir Ozer 2.2k Jan 04, 2023
pytest plugin for manipulating test data directories and files

pytest-datadir pytest plugin for manipulating test data directories and files. Usage pytest-datadir will look up for a directory with the name of your

Gabriel Reis 191 Dec 21, 2022
Pyramid debug toolbar

pyramid_debugtoolbar pyramid_debugtoolbar provides a debug toolbar useful while you're developing your Pyramid application. Note that pyramid_debugtoo

Pylons Project 95 Sep 17, 2022
This is a web test framework based on python+selenium

Basic thoughts for this framework There should have a BasePage.py to be the parent page and all the page object should inherit this class BasePage.py

Cactus 2 Mar 09, 2022
User-interest mock backend server implemnted using flask restful, and SQLAlchemy ORM confiugred with sqlite

Flask_Restful_SQLAlchemy_server User-interest mock backend server implemnted using flask restful, and SQLAlchemy ORM confiugred with sqlite. Backend b

Austin Weigel 1 Nov 17, 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
Fully functioning price detector built with selenium and python

Fully functioning price detector built with selenium and python

mark sikaundi 4 Mar 30, 2022
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
PoC getting concret intel with chardet and charset-normalizer

aiohttp with charset-normalizer Context aiohttp.TCPConnector(limit=16) alpine linux nginx 1.21 python 3.9 aiohttp dev-master chardet 4.0.0 (aiohttp-ch

TAHRI Ahmed R. 2 Nov 30, 2022