Skip to content

Commit

Permalink
Merge pull request #2096 from nicoddemus/merge-master-into-features
Browse files Browse the repository at this point in the history
Merge master into features
  • Loading branch information
RonnyPfannschmidt committed Nov 27, 2016
2 parents 5ce551e + b30a6d2 commit 36eb5b3
Show file tree
Hide file tree
Showing 18 changed files with 161 additions and 40 deletions.
4 changes: 4 additions & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ David Mohr
David Vierra
Diego Russo
Dmitry Dygalo
Duncan Betts
Edison Gustavo Muenz
Edoardo Batini
Eduardo Schettino
Expand Down Expand Up @@ -82,6 +83,7 @@ Kevin Cox
Lee Kamentsky
Lev Maximov
Lukas Bednar
Luke Murphy
Maciek Fijalkowski
Maho
Marc Schlaich
Expand All @@ -102,6 +104,8 @@ Michael Birtwell
Michael Droettboom
Michael Seifert
Mike Lundy
Ned Batchelder
Neven Mundar
Nicolas Delaby
Oleg Pidsadnyi
Oliver Bestwalter
Expand Down
32 changes: 30 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,45 @@ Changes
==========


* Add hint to error message hinting possible missing ``__init__.py`` (`#478`_). Thanks `@DuncanBetts`_.

*

*
* Provide ``:ref:`` targets for ``recwarn.rst`` so we can use intersphinx referencing.
Thanks to `@dupuy`_ for the report and `@lwm`_ for the PR.

* Using ``item.Function``, ``item.Module``, etc., is now issuing deprecation warnings, prefer
``pytest.Function``, ``pytest.Module``, etc., instead (`#2034`_).
Thanks `@nmundar`_ for the PR.

* An error message is now displayed if ``--confcutdir`` is not a valid directory, avoiding
subtle bugs (`#2078`_).
Thanks `@nicoddemus`_ for the PR.

* Fix error message using ``approx`` with complex numbers (`#2082`_).
Thanks `@adler-j`_ for the report and `@nicoddemus`_ for the PR.

*

* Cope gracefully with a .pyc file with no matching .py file (`#2038`_). Thanks
`@nedbat`_.

*

*

.. _@dupuy: https://bitbucket.org/dupuy/
.. _@lwm: https://github.com/lwm
.. _@adler-j: https://github.com/adler-j
.. _@DuncanBetts: https://github.com/DuncanBetts
.. _@nedbat: https://github.com/nedbat
.. _@nmundar: https://github.com/nmundar

.. _#478: https://github.com/pytest-dev/pytest/issues/478
.. _#2034: https://github.com/pytest-dev/pytest/issues/2034
.. _#2038: https://github.com/pytest-dev/pytest/issues/2038
.. _#2078: https://github.com/pytest-dev/pytest/issues/2078
.. _#2082: https://github.com/pytest-dev/pytest/issues/2082


3.0.4
=====
Expand Down
10 changes: 10 additions & 0 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,16 @@ Pytest could always use more documentation. What exactly is needed?
You can also edit documentation files directly in the GitHub web interface,
without using a local copy. This can be convenient for small fixes.

.. note::
Build the documentation locally with the following command:

.. code:: bash
$ tox -e docs
The built documentation should be available in the ``doc/en/_build/``.

Where 'en' refers to the documentation language.

.. _submitplugin:

Expand Down
16 changes: 8 additions & 8 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,31 @@ An example of a simple test:
.. code-block:: python
# content of test_sample.py
def func(x):
def inc(x):
return x + 1
def test_answer():
assert func(3) == 5
assert inc(3) == 5
To execute it::

$ pytest
======= test session starts ========
============================= test session starts =============================
collected 1 items

test_sample.py F

======= FAILURES ========
_______ test_answer ________
================================== FAILURES ===================================
_________________________________ test_answer _________________________________

def test_answer():
> assert func(3) == 5
> assert inc(3) == 5
E assert 4 == 5
E + where 4 = func(3)
E + where 4 = inc(3)

test_sample.py:5: AssertionError
======= 1 failed in 0.12 seconds ========
========================== 1 failed in 0.04 seconds ===========================


Due to ``pytest``'s detailed assertion introspection, only plain ``assert`` statements are used. See `getting-started <https://docs.pytest.org/en/latest/getting-started.html#our-first-test-run>`_ for more examples.
Expand Down
7 changes: 6 additions & 1 deletion _pytest/assertion/rewrite.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,12 @@ def find_module(self, name, path=None):
tp = desc[2]
if tp == imp.PY_COMPILED:
if hasattr(imp, "source_from_cache"):
fn = imp.source_from_cache(fn)
try:
fn = imp.source_from_cache(fn)
except ValueError:
# Python 3 doesn't like orphaned but still-importable
# .pyc files.
fn = fn[:-1]
else:
fn = fn[:-1]
elif tp != imp.PY_SOURCE:
Expand Down
6 changes: 5 additions & 1 deletion _pytest/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,7 @@ def _warn_about_missing_assertion(self, mode):
"(are you using python -O?)\n")

def _preparse(self, args, addopts=True):
import pytest
self._initini(args)
if addopts:
args[:] = shlex.split(os.environ.get('PYTEST_ADDOPTS', '')) + args
Expand All @@ -1007,7 +1008,10 @@ def _preparse(self, args, addopts=True):
self.pluginmanager.load_setuptools_entrypoints(entrypoint_name)
self.pluginmanager.consider_env()
self.known_args_namespace = ns = self._parser.parse_known_args(args, namespace=self.option.copy())
if self.known_args_namespace.confcutdir is None and self.inifile:
confcutdir = self.known_args_namespace.confcutdir
if confcutdir and not os.path.isdir(confcutdir):
raise pytest.UsageError('--confcutdir must be a directory, given: {0}'.format(confcutdir))
if confcutdir is None and self.inifile:
confcutdir = py.path.local(self.inifile).dirname
self.known_args_namespace.confcutdir = confcutdir
try:
Expand Down
9 changes: 5 additions & 4 deletions _pytest/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,9 @@ def __getattr__(self, name):

def compatproperty(name):
def fget(self):
# deprecated - use pytest.name
import warnings
warnings.warn("This usage is deprecated, please use pytest.{0} instead".format(name),
PendingDeprecationWarning, stacklevel=2)
return getattr(pytest, name)

return property(fget)
Expand Down Expand Up @@ -700,10 +702,9 @@ def _parsearg(self, arg):
path = self.config.invocation_dir.join(relpath, abs=True)
if not path.check():
if self.config.option.pyargs:
msg = "file or package not found: "
raise pytest.UsageError("file or package not found: " + arg + " (missing __init__.py?)")
else:
msg = "file not found: "
raise pytest.UsageError(msg + arg)
raise pytest.UsageError("file not found: " + arg)
parts[0] = path
return parts

Expand Down
3 changes: 3 additions & 0 deletions _pytest/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -1414,6 +1414,9 @@ def __init__(self, expected, rel=None, abs=None):
self.rel = rel

def __repr__(self):
if isinstance(self.expected, complex):
return str(self.expected)

# Infinities aren't compared using tolerances, so don't show a
# tolerance.
if math.isinf(self.expected):
Expand Down
9 changes: 4 additions & 5 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ environment:
# https://www.appveyor.com/docs/build-configuration#secure-variables

matrix:
# coveralls is not in the default env list
- TOXENV: "coveralls"
# note: please use "tox --listenvs" to populate the build matrix below
- TOXENV: "linting"
- TOXENV: "py26"
Expand All @@ -29,14 +31,11 @@ install:
- echo Installed Pythons
- dir c:\Python*

- if "%TOXENV%" == "pypy" scripts\install-pypy.bat
- if "%TOXENV%" == "pypy" call scripts\install-pypy.bat

- C:\Python35\python -m pip install tox

build: false # Not a C# project, build stuff at the test step instead.

test_script:
- C:\Python35\python -m tox
# coveralls is not in tox's envlist, plus for PRs the secure variable
# is not defined so we have to check for it
- if defined COVERALLS_REPO_TOKEN C:\Python35\python -m tox -e coveralls
- call scripts\call-tox.bat
10 changes: 6 additions & 4 deletions doc/en/goodpractices.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ Conventions for Python test discovery
* If no arguments are specified then collection starts from :confval:`testpaths`
(if configured) or the current directory. Alternatively, command line arguments
can be used in any combination of directories, file names or node ids.
* recurse into directories, unless they match :confval:`norecursedirs`
* ``test_*.py`` or ``*_test.py`` files, imported by their `test package name`_.
* ``Test`` prefixed test classes (without an ``__init__`` method)
* ``test_`` prefixed test functions or methods are test items
* Recurse into directories, unless they match :confval:`norecursedirs`.
* In those directories, search for ``test_*.py`` or ``*_test.py`` files, imported by their `test package name`_.
* From those files, collect test items:

* ``test_`` prefixed test functions or methods outside of class
* ``test_`` prefixed test functions or methods inside ``Test`` prefixed test classes (without an ``__init__`` method)

For examples of how to customize your test discovery :doc:`example/pythoncollection`.

Expand Down
26 changes: 12 additions & 14 deletions doc/en/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,31 @@ An example of a simple test:
.. code-block:: python
# content of test_sample.py
def func(x):
def inc(x):
return x + 1
def test_answer():
assert func(3) == 5
assert inc(3) == 5
To execute it::

$ pytest
======= test session starts ========
platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
============================= test session starts =============================
collected 1 items

test_sample.py F
======= FAILURES ========
_______ test_answer ________

================================== FAILURES ===================================
_________________________________ test_answer _________________________________

def test_answer():
> assert func(3) == 5
> assert inc(3) == 5
E assert 4 == 5
E + where 4 = func(3)
E + where 4 = inc(3)

test_sample.py:5: AssertionError
======= 1 failed in 0.12 seconds ========
========================== 1 failed in 0.04 seconds ===========================

Due to ``pytest``'s detailed assertion introspection, only plain ``assert`` statements are used.
See :ref:`Getting Started <getstarted>` for more examples.
Expand Down
8 changes: 8 additions & 0 deletions doc/en/recwarn.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
.. _`asserting warnings`:

.. _assertwarnings:

Asserting Warnings
=====================================================

.. _`asserting warnings with the warns function`:

.. _warns:

Asserting warnings with the warns function
Expand Down Expand Up @@ -46,6 +50,8 @@ Alternatively, you can examine raised warnings in detail using the
``DeprecationWarning`` and ``PendingDeprecationWarning`` are treated
differently; see :ref:`ensuring_function_triggers`.

.. _`recording warnings`:

.. _recwarn:

Recording warnings
Expand Down Expand Up @@ -99,6 +105,8 @@ class of the warning. The ``message`` is the warning itself; calling
``DeprecationWarning`` and ``PendingDeprecationWarning`` are treated
differently; see :ref:`ensuring_function_triggers`.

.. _`ensuring a function triggers a deprecation warning`:

.. _ensuring_function_triggers:

Ensuring a function triggers a deprecation warning
Expand Down
8 changes: 8 additions & 0 deletions scripts/call-tox.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
REM skip "coveralls" run in PRs or forks
if "%TOXENV%" == "coveralls" (
if not defined COVERALLS_REPO_TOKEN (
echo skipping coveralls run because COVERALLS_REPO_TOKEN is not defined
exit /b 0
)
)
C:\Python35\python -m tox
1 change: 1 addition & 0 deletions testing/python/approx.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def test_repr_string(self):
print(approx(inf))
print(approx(1.0, rel=nan))
print(approx(1.0, rel=inf))
print(approx(1.0j, rel=inf))

def test_operator_overloading(self):
assert 1 == approx(1, rel=1e-6, abs=1e-12)
Expand Down
28 changes: 28 additions & 0 deletions testing/test_assertrewrite.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import glob
import os
import py_compile
import stat
import sys
import zipfile

import py
import pytest

Expand Down Expand Up @@ -573,6 +576,31 @@ def test_no_bytecode():
monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", "1")
assert testdir.runpytest_subprocess().ret == 0

def test_orphaned_pyc_file(self, testdir):
if sys.version_info < (3, 0) and hasattr(sys, 'pypy_version_info'):
pytest.skip("pypy2 doesn't run orphaned pyc files")

testdir.makepyfile("""
import orphan
def test_it():
assert orphan.value == 17
""")
testdir.makepyfile(orphan="""
value = 17
""")
py_compile.compile("orphan.py")
os.remove("orphan.py")

# Python 3 puts the .pyc files in a __pycache__ directory, and will
# not import from there without source. It will import a .pyc from
# the source location though.
if not os.path.exists("orphan.pyc"):
pycs = glob.glob("__pycache__/orphan.*.pyc")
assert len(pycs) == 1
os.rename(pycs[0], "orphan.pyc")

assert testdir.runpytest().ret == 0

@pytest.mark.skipif('"__pypy__" in sys.modules')
def test_pyc_vs_pyo(self, testdir, monkeypatch):
testdir.makepyfile("""
Expand Down
9 changes: 9 additions & 0 deletions testing/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,15 @@ def pytest_addoption(parser):
assert len(l) == 2
assert l == ["456", "123"]

def test_confcutdir_check_isdir(self, testdir):
"""Give an error if --confcutdir is not a valid directory (#2078)"""
with pytest.raises(pytest.UsageError):
testdir.parseconfig('--confcutdir', testdir.tmpdir.join('file').ensure(file=1))
with pytest.raises(pytest.UsageError):
testdir.parseconfig('--confcutdir', testdir.tmpdir.join('inexistant'))
config = testdir.parseconfig('--confcutdir', testdir.tmpdir.join('dir').ensure(dir=1))
assert config.getoption('confcutdir') == str(testdir.tmpdir.join('dir'))


class TestConfigFromdictargs:
def test_basic_behavior(self):
Expand Down
Loading

0 comments on commit 36eb5b3

Please sign in to comment.