Merge branch 'main' into add-type-ignore-for-attr-defined-errors
This commit is contained in:
commit
7600243819
|
@ -27,7 +27,7 @@ jobs:
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: "3.8"
|
python-version: "3.11"
|
||||||
cache: pip
|
cache: pip
|
||||||
- name: requests-cache
|
- name: requests-cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
|
|
|
@ -5,7 +5,7 @@ repos:
|
||||||
- id: black
|
- id: black
|
||||||
args: [--safe, --quiet]
|
args: [--safe, --quiet]
|
||||||
- repo: https://github.com/asottile/blacken-docs
|
- repo: https://github.com/asottile/blacken-docs
|
||||||
rev: 1.15.0
|
rev: 1.16.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: blacken-docs
|
- id: blacken-docs
|
||||||
additional_dependencies: [black==23.7.0]
|
additional_dependencies: [black==23.7.0]
|
||||||
|
@ -56,7 +56,7 @@ repos:
|
||||||
hooks:
|
hooks:
|
||||||
- id: python-use-type-annotations
|
- id: python-use-type-annotations
|
||||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
rev: v1.5.0
|
rev: v1.5.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: mypy
|
- id: mypy
|
||||||
files: ^(src/|testing/)
|
files: ^(src/|testing/)
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Corrected the spelling of ``Config.ArgsSource.INVOCATION_DIR``.
|
||||||
|
The previous spelling ``INCOVATION_DIR`` remains as an alias.
|
|
@ -0,0 +1 @@
|
||||||
|
Removes unhelpful error message from assertion rewrite mechanism when exceptions raised in __iter__ methods, and instead treats them as un-iterable.
|
|
@ -34,7 +34,7 @@ a function/method call.
|
||||||
|
|
||||||
**Assert** is where we look at that resulting state and check if it looks how
|
**Assert** is where we look at that resulting state and check if it looks how
|
||||||
we'd expect after the dust has settled. It's where we gather evidence to say the
|
we'd expect after the dust has settled. It's where we gather evidence to say the
|
||||||
behavior does or does not aligns with what we expect. The ``assert`` in our test
|
behavior does or does not align with what we expect. The ``assert`` in our test
|
||||||
is where we take that measurement/observation and apply our judgement to it. If
|
is where we take that measurement/observation and apply our judgement to it. If
|
||||||
something should be green, we'd say ``assert thing == "green"``.
|
something should be green, we'd say ``assert thing == "green"``.
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1640,11 +1640,11 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||||
Additionally, ``pytest`` will attempt to intelligently identify and ignore a
|
Additionally, ``pytest`` will attempt to intelligently identify and ignore a
|
||||||
virtualenv by the presence of an activation script. Any directory deemed to
|
virtualenv by the presence of an activation script. Any directory deemed to
|
||||||
be the root of a virtual environment will not be considered during test
|
be the root of a virtual environment will not be considered during test
|
||||||
collection unless ``‑‑collect‑in‑virtualenv`` is given. Note also that
|
collection unless ``--collect-in-virtualenv`` is given. Note also that
|
||||||
``norecursedirs`` takes precedence over ``‑‑collect‑in‑virtualenv``; e.g. if
|
``norecursedirs`` takes precedence over ``--collect-in-virtualenv``; e.g. if
|
||||||
you intend to run tests in a virtualenv with a base directory that matches
|
you intend to run tests in a virtualenv with a base directory that matches
|
||||||
``'.*'`` you *must* override ``norecursedirs`` in addition to using the
|
``'.*'`` you *must* override ``norecursedirs`` in addition to using the
|
||||||
``‑‑collect‑in‑virtualenv`` flag.
|
``--collect-in-virtualenv`` flag.
|
||||||
|
|
||||||
|
|
||||||
.. confval:: python_classes
|
.. confval:: python_classes
|
||||||
|
|
|
@ -44,6 +44,7 @@ DEVELOPMENT_STATUS_CLASSIFIERS = (
|
||||||
)
|
)
|
||||||
ADDITIONAL_PROJECTS = { # set of additional projects to consider as plugins
|
ADDITIONAL_PROJECTS = { # set of additional projects to consider as plugins
|
||||||
"logassert",
|
"logassert",
|
||||||
|
"nuts",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,7 @@ def isiterable(obj: Any) -> bool:
|
||||||
try:
|
try:
|
||||||
iter(obj)
|
iter(obj)
|
||||||
return not istext(obj)
|
return not istext(obj)
|
||||||
except TypeError:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -953,7 +953,8 @@ class Config:
|
||||||
#: Command line arguments.
|
#: Command line arguments.
|
||||||
ARGS = enum.auto()
|
ARGS = enum.auto()
|
||||||
#: Invocation directory.
|
#: Invocation directory.
|
||||||
INCOVATION_DIR = enum.auto()
|
INVOCATION_DIR = enum.auto()
|
||||||
|
INCOVATION_DIR = INVOCATION_DIR # backwards compatibility alias
|
||||||
#: 'testpaths' configuration value.
|
#: 'testpaths' configuration value.
|
||||||
TESTPATHS = enum.auto()
|
TESTPATHS = enum.auto()
|
||||||
|
|
||||||
|
@ -1278,7 +1279,7 @@ class Config:
|
||||||
else:
|
else:
|
||||||
result = []
|
result = []
|
||||||
if not result:
|
if not result:
|
||||||
source = Config.ArgsSource.INCOVATION_DIR
|
source = Config.ArgsSource.INVOCATION_DIR
|
||||||
result = [str(invocation_dir)]
|
result = [str(invocation_dir)]
|
||||||
return result, source
|
return result, source
|
||||||
|
|
||||||
|
|
|
@ -829,7 +829,7 @@ class Pytester:
|
||||||
return self._makefile(ext, args, kwargs)
|
return self._makefile(ext, args, kwargs)
|
||||||
|
|
||||||
def makeconftest(self, source: str) -> Path:
|
def makeconftest(self, source: str) -> Path:
|
||||||
"""Write a contest.py file.
|
"""Write a conftest.py file.
|
||||||
|
|
||||||
:param source: The contents.
|
:param source: The contents.
|
||||||
:returns: The conftest.py file.
|
:returns: The conftest.py file.
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
# PYTHON_ARGCOMPLETE_OK
|
# PYTHON_ARGCOMPLETE_OK
|
||||||
"""pytest: unit and functional testing with Python."""
|
"""pytest: unit and functional testing with Python."""
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from _pytest import __version__
|
from _pytest import __version__
|
||||||
from _pytest import version_tuple
|
from _pytest import version_tuple
|
||||||
from _pytest._code import ExceptionInfo
|
from _pytest._code import ExceptionInfo
|
||||||
|
@ -165,6 +167,7 @@ __all__ = [
|
||||||
"yield_fixture",
|
"yield_fixture",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if not TYPE_CHECKING:
|
||||||
|
|
||||||
def __getattr__(name: str) -> object:
|
def __getattr__(name: str) -> object:
|
||||||
if name == "Instance":
|
if name == "Instance":
|
||||||
|
|
|
@ -272,7 +272,7 @@ def test_importing_instance_is_deprecated(pytester: Pytester) -> None:
|
||||||
pytest.PytestDeprecationWarning,
|
pytest.PytestDeprecationWarning,
|
||||||
match=re.escape("The pytest.Instance collector type is deprecated"),
|
match=re.escape("The pytest.Instance collector type is deprecated"),
|
||||||
):
|
):
|
||||||
pytest.Instance
|
pytest.Instance # type:ignore[attr-defined]
|
||||||
|
|
||||||
with pytest.warns(
|
with pytest.warns(
|
||||||
pytest.PytestDeprecationWarning,
|
pytest.PytestDeprecationWarning,
|
||||||
|
|
|
@ -685,6 +685,25 @@ class TestAssertionRewrite:
|
||||||
assert msg is not None
|
assert msg is not None
|
||||||
assert "<MY42 object> < 0" in msg
|
assert "<MY42 object> < 0" in msg
|
||||||
|
|
||||||
|
def test_assert_handling_raise_in__iter__(self, pytester: Pytester) -> None:
|
||||||
|
pytester.makepyfile(
|
||||||
|
"""\
|
||||||
|
class A:
|
||||||
|
def __iter__(self):
|
||||||
|
raise ValueError()
|
||||||
|
|
||||||
|
def __eq__(self, o: object) -> bool:
|
||||||
|
return self is o
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<A object>"
|
||||||
|
|
||||||
|
assert A() == A()
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
result = pytester.runpytest()
|
||||||
|
result.stdout.fnmatch_lines(["*E*assert <A object> == <A object>"])
|
||||||
|
|
||||||
def test_formatchar(self) -> None:
|
def test_formatchar(self) -> None:
|
||||||
def f() -> None:
|
def f() -> None:
|
||||||
assert "%test" == "test" # type: ignore[comparison-overlap]
|
assert "%test" == "test" # type: ignore[comparison-overlap]
|
||||||
|
|
|
@ -507,6 +507,24 @@ class TestParseIni:
|
||||||
result = pytester.runpytest("--foo=1")
|
result = pytester.runpytest("--foo=1")
|
||||||
result.stdout.fnmatch_lines("* no tests ran in *")
|
result.stdout.fnmatch_lines("* no tests ran in *")
|
||||||
|
|
||||||
|
def test_args_source_args(self, pytester: Pytester):
|
||||||
|
config = pytester.parseconfig("--", "test_filename.py")
|
||||||
|
assert config.args_source == Config.ArgsSource.ARGS
|
||||||
|
|
||||||
|
def test_args_source_invocation_dir(self, pytester: Pytester):
|
||||||
|
config = pytester.parseconfig()
|
||||||
|
assert config.args_source == Config.ArgsSource.INVOCATION_DIR
|
||||||
|
|
||||||
|
def test_args_source_testpaths(self, pytester: Pytester):
|
||||||
|
pytester.makeini(
|
||||||
|
"""
|
||||||
|
[pytest]
|
||||||
|
testpaths=*
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
config = pytester.parseconfig()
|
||||||
|
assert config.args_source == Config.ArgsSource.TESTPATHS
|
||||||
|
|
||||||
|
|
||||||
class TestConfigCmdlineParsing:
|
class TestConfigCmdlineParsing:
|
||||||
def test_parsing_again_fails(self, pytester: Pytester) -> None:
|
def test_parsing_again_fails(self, pytester: Pytester) -> None:
|
||||||
|
|
Loading…
Reference in New Issue