Skip to content

Commit 0f7c7a9

Browse files
authored
Merge pull request #5281 from nicoddemus/merge-master-into-features
Merge master into features (make CI green again)
2 parents c0e53a6 + 041ea37 commit 0f7c7a9

File tree

15 files changed

+260
-143
lines changed

15 files changed

+260
-143
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ Here's a quick checklist that should be present in PRs.
55
(please delete this text from the final description, this is just a guideline)
66
-->
77

8-
- [ ] Create a new changelog file in the `changelog` folder, with a name like `<ISSUE NUMBER>.<TYPE>.rst`. See [changelog/README.rst](https://github.com/pytest-dev/pytest/blob/master/changelog/README.rst) for details.
98
- [ ] Target the `master` branch for bug fixes, documentation updates and trivial changes.
109
- [ ] Target the `features` branch for new features and removals/deprecations.
1110
- [ ] Include documentation when adding new features.
1211
- [ ] Include new tests or update existing tests when applicable.
1312

1413
Unless your change is trivial or a small documentation fix (e.g., a typo or reword of a small section) please:
1514

15+
- [ ] Create a new changelog file in the `changelog` folder, with a name like `<ISSUE NUMBER>.<TYPE>.rst`. See [changelog/README.rst](https://github.com/pytest-dev/pytest/blob/master/changelog/README.rst) for details.
1616
- [ ] Add yourself to `AUTHORS` in alphabetical order;

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ Endre Galaczi
8686
Eric Hunsberger
8787
Eric Siegerman
8888
Erik M. Bray
89+
Evan Kepner
8990
Fabien Zarifian
9091
Fabio Zadrozny
9192
Feng Ma

azure-pipelines.yml

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ trigger:
55
variables:
66
PYTEST_ADDOPTS: "--junitxml=build/test-results/$(tox.env).xml -vv"
77
python.needs_vc: False
8-
python.exe: "python"
98
COVERAGE_FILE: "$(Build.Repository.LocalPath)/.coverage"
109
COVERAGE_PROCESS_START: "$(Build.Repository.LocalPath)/.coveragerc"
1110
PYTEST_COVERAGE: '0'
@@ -42,15 +41,13 @@ jobs:
4241
# Also seen with py27-nobyte (using xdist), and py27-xdist.
4342
# But no exception with py27-pexpect,py27-twisted,py27-numpy.
4443
PYTEST_COVERAGE: '1'
45-
pypy:
46-
python.version: 'pypy2'
47-
tox.env: 'pypy'
48-
python.exe: 'pypy'
49-
# NOTE: pypy3 fails to install pip currently due to an internal error.
44+
# -- pypy2 and pypy3 are disabled for now: #5279 --
45+
# pypy:
46+
# python.version: 'pypy2'
47+
# tox.env: 'pypy'
5048
# pypy3:
5149
# python.version: 'pypy3'
5250
# tox.env: 'pypy3'
53-
# python.exe: 'pypy3'
5451
py34-xdist:
5552
python.version: '3.4'
5653
tox.env: 'py34-xdist'
@@ -94,12 +91,12 @@ jobs:
9491
condition: eq(variables['python.needs_vc'], True)
9592
displayName: 'Install VC for py27'
9693

97-
- script: $(python.exe) -m pip install --upgrade pip && $(python.exe) -m pip install tox
94+
- script: python -m pip install --upgrade pip && python -m pip install tox
9895
displayName: 'Install tox'
9996

10097
- script: |
10198
call scripts/setup-coverage-vars.bat || goto :eof
102-
$(python.exe) -m tox -e $(tox.env)
99+
python -m tox -e $(tox.env)
103100
displayName: 'Run tests'
104101
105102
- task: PublishTestResults@2
@@ -112,6 +109,5 @@ jobs:
112109
displayName: 'Report and upload coverage'
113110
condition: eq(variables['PYTEST_COVERAGE'], '1')
114111
env:
115-
PYTHON: $(python.exe)
116112
CODECOV_TOKEN: $(CODECOV_TOKEN)
117113
PYTEST_CODECOV_NAME: $(tox.env)

changelog/5250.doc.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Expand docs on use of ``setenv`` and ``delenv`` with ``monkeypatch``.

changelog/5256.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Handle internal error due to a lone surrogate unicode character not being representable in Jython.

changelog/5257.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Ensure that ``sys.stdout.mode`` does not include ``'b'`` as it is a text stream.

doc/en/example/markers.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
Working with custom markers
55
=================================================
66

7-
Here are some example using the :ref:`mark` mechanism.
7+
Here are some examples using the :ref:`mark` mechanism.
8+
9+
.. _`mark run`:
810

911
Marking test functions and selecting them for a run
1012
----------------------------------------------------

doc/en/historical-notes.rst

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,117 @@ Historical Notes
44
This page lists features or behavior from previous versions of pytest which have changed over the years. They are
55
kept here as a historical note so users looking at old code can find documentation related to them.
66

7+
8+
.. _marker-revamp:
9+
10+
Marker revamp and iteration
11+
---------------------------
12+
13+
.. versionchanged:: 3.6
14+
15+
pytest's marker implementation traditionally worked by simply updating the ``__dict__`` attribute of functions to cumulatively add markers. As a result, markers would unintentionally be passed along class hierarchies in surprising ways. Further, the API for retrieving them was inconsistent, as markers from parameterization would be stored differently than markers applied using the ``@pytest.mark`` decorator and markers added via ``node.add_marker``.
16+
17+
This state of things made it technically next to impossible to use data from markers correctly without having a deep understanding of the internals, leading to subtle and hard to understand bugs in more advanced usages.
18+
19+
Depending on how a marker got declared/changed one would get either a ``MarkerInfo`` which might contain markers from sibling classes,
20+
``MarkDecorators`` when marks came from parameterization or from a ``node.add_marker`` call, discarding prior marks. Also ``MarkerInfo`` acts like a single mark, when it in fact represents a merged view on multiple marks with the same name.
21+
22+
On top of that markers were not accessible in the same way for modules, classes, and functions/methods.
23+
In fact, markers were only accessible in functions, even if they were declared on classes/modules.
24+
25+
A new API to access markers has been introduced in pytest 3.6 in order to solve the problems with
26+
the initial design, providing the :func:`_pytest.nodes.Node.iter_markers` method to iterate over
27+
markers in a consistent manner and reworking the internals, which solved a great deal of problems
28+
with the initial design.
29+
30+
31+
.. _update marker code:
32+
33+
Updating code
34+
~~~~~~~~~~~~~
35+
36+
The old ``Node.get_marker(name)`` function is considered deprecated because it returns an internal ``MarkerInfo`` object
37+
which contains the merged name, ``*args`` and ``**kwargs`` of all the markers which apply to that node.
38+
39+
In general there are two scenarios on how markers should be handled:
40+
41+
1. Marks overwrite each other. Order matters but you only want to think of your mark as a single item. E.g.
42+
``log_level('info')`` at a module level can be overwritten by ``log_level('debug')`` for a specific test.
43+
44+
In this case, use ``Node.get_closest_marker(name)``:
45+
46+
.. code-block:: python
47+
48+
# replace this:
49+
marker = item.get_marker("log_level")
50+
if marker:
51+
level = marker.args[0]
52+
53+
# by this:
54+
marker = item.get_closest_marker("log_level")
55+
if marker:
56+
level = marker.args[0]
57+
58+
2. Marks compose in an additive manner. E.g. ``skipif(condition)`` marks mean you just want to evaluate all of them,
59+
order doesn't even matter. You probably want to think of your marks as a set here.
60+
61+
In this case iterate over each mark and handle their ``*args`` and ``**kwargs`` individually.
62+
63+
.. code-block:: python
64+
65+
# replace this
66+
skipif = item.get_marker("skipif")
67+
if skipif:
68+
for condition in skipif.args:
69+
# eval condition
70+
...
71+
72+
# by this:
73+
for skipif in item.iter_markers("skipif"):
74+
condition = skipif.args[0]
75+
# eval condition
76+
77+
78+
If you are unsure or have any questions, please consider opening
79+
`an issue <https://github.com/pytest-dev/pytest/issues>`_.
80+
81+
Related issues
82+
~~~~~~~~~~~~~~
83+
84+
Here is a non-exhaustive list of issues fixed by the new implementation:
85+
86+
* Marks don't pick up nested classes (`#199 <https://github.com/pytest-dev/pytest/issues/199>`_).
87+
88+
* Markers stain on all related classes (`#568 <https://github.com/pytest-dev/pytest/issues/568>`_).
89+
90+
* Combining marks - args and kwargs calculation (`#2897 <https://github.com/pytest-dev/pytest/issues/2897>`_).
91+
92+
* ``request.node.get_marker('name')`` returns ``None`` for markers applied in classes (`#902 <https://github.com/pytest-dev/pytest/issues/902>`_).
93+
94+
* Marks applied in parametrize are stored as markdecorator (`#2400 <https://github.com/pytest-dev/pytest/issues/2400>`_).
95+
96+
* Fix marker interaction in a backward incompatible way (`#1670 <https://github.com/pytest-dev/pytest/issues/1670>`_).
97+
98+
* Refactor marks to get rid of the current "marks transfer" mechanism (`#2363 <https://github.com/pytest-dev/pytest/issues/2363>`_).
99+
100+
* Introduce FunctionDefinition node, use it in generate_tests (`#2522 <https://github.com/pytest-dev/pytest/issues/2522>`_).
101+
102+
* Remove named marker attributes and collect markers in items (`#891 <https://github.com/pytest-dev/pytest/issues/891>`_).
103+
104+
* skipif mark from parametrize hides module level skipif mark (`#1540 <https://github.com/pytest-dev/pytest/issues/1540>`_).
105+
106+
* skipif + parametrize not skipping tests (`#1296 <https://github.com/pytest-dev/pytest/issues/1296>`_).
107+
108+
* Marker transfer incompatible with inheritance (`#535 <https://github.com/pytest-dev/pytest/issues/535>`_).
109+
110+
More details can be found in the `original PR <https://github.com/pytest-dev/pytest/pull/3317>`_.
111+
112+
.. note::
113+
114+
in a future major relase of pytest we will introduce class based markers,
115+
at which point markers will no longer be limited to instances of :py:class:`Mark`.
116+
117+
7118
cache plugin integrated into the core
8119
-------------------------------------
9120

doc/en/mark.rst

Lines changed: 35 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -15,151 +15,64 @@ some builtin markers, for example:
1515
to the same test function.
1616

1717
It's easy to create custom markers or to apply markers
18-
to whole test classes or modules. See :ref:`mark examples` for examples
19-
which also serve as documentation.
18+
to whole test classes or modules. Those markers can be used by plugins, and also
19+
are commonly used to :ref:`select tests <mark run>` on the command-line with the ``-m`` option.
20+
21+
See :ref:`mark examples` for examples which also serve as documentation.
2022

2123
.. note::
2224

2325
Marks can only be applied to tests, having no effect on
2426
:ref:`fixtures <fixtures>`.
2527

2628

27-
.. _unknown-marks:
28-
29-
Raising errors on unknown marks
30-
-------------------------------
29+
Registering marks
30+
-----------------
3131

32-
Unknown marks applied with the ``@pytest.mark.name_of_the_mark`` decorator
33-
will always emit a warning, in order to avoid silently doing something
34-
surprising due to mis-typed names. You can disable the warning for custom
35-
marks by registering them in ``pytest.ini`` like this:
32+
You can register custom marks in your ``pytest.ini`` file like this:
3633

3734
.. code-block:: ini
3835
3936
[pytest]
4037
markers =
41-
slow
38+
slow: marks tests as slow (deselect with '-m "not slow"')
4239
serial
4340
44-
When the ``--strict-markers`` command-line flag is passed, any unknown marks applied
45-
with the ``@pytest.mark.name_of_the_mark`` decorator will trigger an error.
46-
Marks added by pytest or by a plugin instead of the decorator will not trigger
47-
this error. To enforce validation of markers, add ``--strict-markers`` to ``addopts``:
48-
49-
.. code-block:: ini
50-
51-
[pytest]
52-
addopts = --strict-markers
53-
markers =
54-
slow
55-
serial
56-
57-
Third-party plugins should always :ref:`register their markers <registering-markers>`
58-
so that they appear in pytest's help text and do not emit warnings.
59-
60-
61-
.. _marker-revamp:
62-
63-
Marker revamp and iteration
64-
---------------------------
65-
66-
67-
68-
pytest's marker implementation traditionally worked by simply updating the ``__dict__`` attribute of functions to cumulatively add markers. As a result, markers would unintentionally be passed along class hierarchies in surprising ways. Further, the API for retrieving them was inconsistent, as markers from parameterization would be stored differently than markers applied using the ``@pytest.mark`` decorator and markers added via ``node.add_marker``.
69-
70-
This state of things made it technically next to impossible to use data from markers correctly without having a deep understanding of the internals, leading to subtle and hard to understand bugs in more advanced usages.
71-
72-
Depending on how a marker got declared/changed one would get either a ``MarkerInfo`` which might contain markers from sibling classes,
73-
``MarkDecorators`` when marks came from parameterization or from a ``node.add_marker`` call, discarding prior marks. Also ``MarkerInfo`` acts like a single mark, when it in fact represents a merged view on multiple marks with the same name.
74-
75-
On top of that markers were not accessible the same way for modules, classes, and functions/methods.
76-
In fact, markers were only accessible in functions, even if they were declared on classes/modules.
77-
78-
A new API to access markers has been introduced in pytest 3.6 in order to solve the problems with the initial design, providing :func:`_pytest.nodes.Node.iter_markers` method to iterate over markers in a consistent manner and reworking the internals, which solved great deal of problems with the initial design.
79-
80-
81-
.. _update marker code:
82-
83-
Updating code
84-
~~~~~~~~~~~~~
85-
86-
The old ``Node.get_marker(name)`` function is considered deprecated because it returns an internal ``MarkerInfo`` object
87-
which contains the merged name, ``*args`` and ``**kwargs`` of all the markers which apply to that node.
88-
89-
In general there are two scenarios on how markers should be handled:
41+
Note that everything after the ``:`` is an optional description.
9042

91-
1. Marks overwrite each other. Order matters but you only want to think of your mark as a single item. E.g.
92-
``log_level('info')`` at a module level can be overwritten by ``log_level('debug')`` for a specific test.
43+
Alternatively, you can register new markers programatically in a
44+
:ref:`pytest_configure <initialization-hooks>` hook:
9345

94-
In this case, use ``Node.get_closest_marker(name)``:
46+
.. code-block:: python
9547
96-
.. code-block:: python
48+
def pytest_configure(config):
49+
config.addinivalue_line(
50+
"markers", "env(name): mark test to run only on named environment"
51+
)
9752
98-
# replace this:
99-
marker = item.get_marker("log_level")
100-
if marker:
101-
level = marker.args[0]
10253
103-
# by this:
104-
marker = item.get_closest_marker("log_level")
105-
if marker:
106-
level = marker.args[0]
54+
Registered marks appear in pytest's help text and do not emit warnings (see the next section). It
55+
is recommended that third-party plugins always :ref:`register their markers <registering-markers>`.
10756

108-
2. Marks compose in an additive manner. E.g. ``skipif(condition)`` marks mean you just want to evaluate all of them,
109-
order doesn't even matter. You probably want to think of your marks as a set here.
110-
111-
In this case iterate over each mark and handle their ``*args`` and ``**kwargs`` individually.
112-
113-
.. code-block:: python
114-
115-
# replace this
116-
skipif = item.get_marker("skipif")
117-
if skipif:
118-
for condition in skipif.args:
119-
# eval condition
120-
...
121-
122-
# by this:
123-
for skipif in item.iter_markers("skipif"):
124-
condition = skipif.args[0]
125-
# eval condition
126-
127-
128-
If you are unsure or have any questions, please consider opening
129-
`an issue <https://github.com/pytest-dev/pytest/issues>`_.
130-
131-
Related issues
132-
~~~~~~~~~~~~~~
133-
134-
Here is a non-exhaustive list of issues fixed by the new implementation:
135-
136-
* Marks don't pick up nested classes (`#199 <https://github.com/pytest-dev/pytest/issues/199>`_).
137-
138-
* Markers stain on all related classes (`#568 <https://github.com/pytest-dev/pytest/issues/568>`_).
139-
140-
* Combining marks - args and kwargs calculation (`#2897 <https://github.com/pytest-dev/pytest/issues/2897>`_).
141-
142-
* ``request.node.get_marker('name')`` returns ``None`` for markers applied in classes (`#902 <https://github.com/pytest-dev/pytest/issues/902>`_).
143-
144-
* Marks applied in parametrize are stored as markdecorator (`#2400 <https://github.com/pytest-dev/pytest/issues/2400>`_).
145-
146-
* Fix marker interaction in a backward incompatible way (`#1670 <https://github.com/pytest-dev/pytest/issues/1670>`_).
147-
148-
* Refactor marks to get rid of the current "marks transfer" mechanism (`#2363 <https://github.com/pytest-dev/pytest/issues/2363>`_).
149-
150-
* Introduce FunctionDefinition node, use it in generate_tests (`#2522 <https://github.com/pytest-dev/pytest/issues/2522>`_).
151-
152-
* Remove named marker attributes and collect markers in items (`#891 <https://github.com/pytest-dev/pytest/issues/891>`_).
153-
154-
* skipif mark from parametrize hides module level skipif mark (`#1540 <https://github.com/pytest-dev/pytest/issues/1540>`_).
57+
.. _unknown-marks:
15558

156-
* skipif + parametrize not skipping tests (`#1296 <https://github.com/pytest-dev/pytest/issues/1296>`_).
59+
Raising errors on unknown marks
60+
-------------------------------
15761

158-
* Marker transfer incompatible with inheritance (`#535 <https://github.com/pytest-dev/pytest/issues/535>`_).
62+
Unregistered marks applied with the ``@pytest.mark.name_of_the_mark`` decorator
63+
will always emit a warning in order to avoid silently doing something
64+
surprising due to mis-typed names. As described in the previous section, you can disable
65+
the warning for custom marks by registering them in your ``pytest.ini`` file or
66+
using a custom ``pytest_configure`` hook.
15967

160-
More details can be found in the `original PR <https://github.com/pytest-dev/pytest/pull/3317>`_.
68+
When the ``--strict-markers`` command-line flag is passed, any unknown marks applied
69+
with the ``@pytest.mark.name_of_the_mark`` decorator will trigger an error. You can
70+
enforce this validation in your project by adding ``--strict-markers`` to ``addopts``:
16171

162-
.. note::
72+
.. code-block:: ini
16373
164-
in a future major relase of pytest we will introduce class based markers,
165-
at which point markers will no longer be limited to instances of :py:class:`Mark`.
74+
[pytest]
75+
addopts = --strict-markers
76+
markers =
77+
slow: marks tests as slow (deselect with '-m "not slow"')
78+
serial

0 commit comments

Comments
 (0)