From 0a8e8d37897f3044ce6117d206666983d5dc5492 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Mon, 3 Feb 2020 11:18:06 +0100 Subject: [PATCH 1/3] docs: use sphinx-autodoc-typehints, minor typing improvements Ref: https://github.com/agronholm/sphinx-autodoc-typehints --- doc/en/conf.py | 5 +++++ doc/en/requirements.txt | 1 + src/_pytest/logging.py | 16 ++++++---------- src/_pytest/mark/structures.py | 13 ++++--------- src/_pytest/nodes.py | 13 ++++++++----- src/_pytest/python.py | 21 ++++++++++++--------- 6 files changed, 36 insertions(+), 33 deletions(-) diff --git a/doc/en/conf.py b/doc/en/conf.py index 85521309fb6..9f68aa9cd33 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -45,6 +45,7 @@ extensions = [ "pygments_pytest", "sphinx.ext.autodoc", + "sphinx_autodoc_typehints", "sphinx.ext.autosummary", "sphinx.ext.intersphinx", "sphinx.ext.todo", @@ -346,6 +347,10 @@ # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {"python": ("https://docs.python.org/3", None)} +# sphinx_autodoc_typehints +set_type_checking_flag = True +always_document_param_types = True + def configure_logging(app: "sphinx.application.Sphinx") -> None: """Configure Sphinx's WarningHandler to handle (expected) missing include.""" diff --git a/doc/en/requirements.txt b/doc/en/requirements.txt index be22b7db872..7ab967a0033 100644 --- a/doc/en/requirements.txt +++ b/doc/en/requirements.txt @@ -2,3 +2,4 @@ pygments-pytest>=1.1.0 sphinx>=1.8.2,<2.1 sphinxcontrib-trio sphinx-removed-in>=0.2.0 +sphinx_autodoc_typehints diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index df0da3daae5..f0017b1d201 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -326,27 +326,23 @@ def _finalize(self) -> None: logger.setLevel(level) @property - def handler(self): - """ - :rtype: LogCaptureHandler - """ - return self._item.catch_log_handler + def handler(self) -> LogCaptureHandler: + return self._item.catch_log_handler # type: ignore[no-any-return] # noqa: F723 - def get_records(self, when): + def get_records(self, when: str) -> List[logging.LogRecord]: """ Get the logging records for one of the possible test phases. - :param str when: + :param when: Which test phase to obtain the records from. Valid values are: "setup", "call" and "teardown". - :rtype: List[logging.LogRecord] :return: the list of captured records at the given stage .. versionadded:: 3.4 """ handler = self._item.catch_log_handlers.get(when) if handler: - return handler.records + return handler.records # type: ignore[no-any-return] # noqa: F723 else: return [] @@ -613,7 +609,7 @@ def _runtest_for(self, item, when): yield @contextmanager - def _runtest_for_main(self, item, when): + def _runtest_for_main(self, item, when: str) -> Generator[None, None, None]: """Implements the internals of pytest_runtest_xxx() hook.""" with catching_logs( LogCaptureHandler(), formatter=self.formatter, level=self.log_level diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 3002f8abc41..9a5bf8c2429 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -2,7 +2,9 @@ import warnings from collections import namedtuple from collections.abc import MutableMapping +from typing import List from typing import Set +from typing import Union import attr @@ -147,8 +149,6 @@ class Mark: def combined_with(self, other): """ :param other: the mark to combine with - :type other: Mark - :rtype: Mark combines by appending args and merging the mappings """ @@ -249,13 +249,8 @@ def get_unpacked_marks(obj): return normalize_mark_list(mark_list) -def normalize_mark_list(mark_list): - """ - normalizes marker decorating helpers to mark objects - - :type mark_list: List[Union[Mark, Markdecorator]] - :rtype: List[Mark] - """ +def normalize_mark_list(mark_list: List[Union[Mark, MarkDecorator]]) -> List[Mark]: + """normalizes marker decorating helpers to mark objects""" extracted = [ getattr(mark, "mark", mark) for mark in mark_list ] # unpack MarkDecorator diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 5447f254173..31d956f3784 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -333,18 +333,21 @@ def repr_failure( return self._repr_failure_py(excinfo, style) -def get_fslocation_from_item(item): +def get_fslocation_from_item( + item: "Item", +) -> Tuple[Union[str, py.path.local], Optional[int]]: """Tries to extract the actual location from an item, depending on available attributes: * "fslocation": a pair (path, lineno) * "obj": a Python object that the item wraps. * "fspath": just a path - :rtype: a tuple of (str|LocalPath, int) with filename and line number. + :return: filename and line number """ - result = getattr(item, "location", None) - if result is not None: - return result[:2] + try: + return item.location[:2] + except AttributeError: + pass obj = getattr(item, "obj", None) if obj is not None: return getfslineno(obj) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 65ef1272b78..da881d99e92 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -10,6 +10,7 @@ from collections.abc import Sequence from functools import partial from textwrap import dedent +from typing import Dict from typing import List from typing import Tuple from typing import Union @@ -36,8 +37,10 @@ from _pytest.config import hookimpl from _pytest.deprecated import FUNCARGNAMES from _pytest.mark import MARK_GEN +from _pytest.mark import ParameterSet from _pytest.mark.structures import get_unpacked_marks from _pytest.mark.structures import normalize_mark_list +from _pytest.nodes import Item from _pytest.outcomes import fail from _pytest.outcomes import skip from _pytest.pathlib import parts @@ -947,7 +950,6 @@ def parametrize(self, argnames, argvalues, indirect=False, ids=None, scope=None) to set a dynamic scope using test context or configuration. """ from _pytest.fixtures import scope2index - from _pytest.mark import ParameterSet argnames, parameters = ParameterSet._for_parametrize( argnames, @@ -996,15 +998,16 @@ def parametrize(self, argnames, argvalues, indirect=False, ids=None, scope=None) newcalls.append(newcallspec) self._calls = newcalls - def _resolve_arg_ids(self, argnames, ids, parameters, item): + def _resolve_arg_ids( + self, argnames: List[str], ids, parameters: List[ParameterSet], item: Item + ): """Resolves the actual ids for the given argnames, based on the ``ids`` parameter given to ``parametrize``. - :param List[str] argnames: list of argument names passed to ``parametrize()``. + :param argnames: list of argument names passed to ``parametrize()``. :param ids: the ids parameter of the parametrized call (see docs). - :param List[ParameterSet] parameters: the list of parameter values, same size as ``argnames``. - :param Item item: the item that generated this parametrized call. - :rtype: List[str] + :param parameters: the list of parameter values, same size as ``argnames``. + :param item: the item that generated this parametrized call. :return: the list of ids for each argname given """ from _pytest._io.saferepr import saferepr @@ -1028,13 +1031,13 @@ def _resolve_arg_ids(self, argnames, ids, parameters, item): ids = idmaker(argnames, parameters, idfn, ids, self.config, item=item) return ids - def _resolve_arg_value_types(self, argnames, indirect): + def _resolve_arg_value_types(self, argnames: List[str], indirect) -> Dict[str, str]: """Resolves if each parametrized argument must be considered a parameter to a fixture or a "funcarg" to the function, based on the ``indirect`` parameter of the parametrized() call. - :param List[str] argnames: list of argument names passed to ``parametrize()``. + :param argnames: list of argument names passed to ``parametrize()``. :param indirect: same ``indirect`` parameter of ``parametrize()``. - :rtype: Dict[str, str] + :return: A dict mapping each arg name to either: * "params" if the argname should be the parameter of a fixture of the same name. * "funcargs" if the argname should be a parameter to the parametrized test function. From 45b9bc364c26e07261a2e0ec24d2af6c066160d3 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Mon, 3 Feb 2020 11:27:02 +0100 Subject: [PATCH 2/3] docs: py38 --- .github/workflows/main.yml | 2 +- tox.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 242c2eb8356..62fe282bdc1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -116,7 +116,7 @@ jobs: os: ubuntu-latest tox_env: "linting" - name: "docs" - python: "3.7" + python: "3.8" os: ubuntu-latest tox_env: "docs" - name: "doctesting" diff --git a/tox.ini b/tox.ini index 65af0a4a86c..efbd53377a1 100644 --- a/tox.ini +++ b/tox.ini @@ -73,7 +73,7 @@ commands = diff-cover --fail-under=100 --compare-branch={env:DIFF_BRANCH:origin/{env:GITHUB_BASE_REF:master}} {envtmpdir}/cobertura.xml [testenv:docs] -basepython = python3 +basepython = python3.8 usedevelop = True deps = -r{toxinidir}/doc/en/requirements.txt From 7a7a1c0a139fbd73872a2aed22dde9249ae77a60 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Mon, 3 Feb 2020 11:27:38 +0100 Subject: [PATCH 3/3] TEMP: GHA: only docs --- .github/workflows/main.yml | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 62fe282bdc1..59de7394697 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,26 +25,7 @@ jobs: fail-fast: false matrix: name: [ - "windows-py35", - "windows-py36", - "windows-py37", - "windows-py37-pluggy", - "windows-py38", - - "ubuntu-py35", - "ubuntu-py36", - "ubuntu-py37", - "ubuntu-py37-pluggy", - "ubuntu-py37-freeze", - "ubuntu-py38", - "ubuntu-pypy3", - - "macos-py37", - "macos-py38", - - "linting", "docs", - "doctesting", ] include: