WebDriver: auto-install pytest instead of importing it from wpt tools directory
https://bugs.webkit.org/show_bug.cgi?id=180243
Reviewed by Brian Burg.
Tools:
We don't really need the (old) version included in wpt tools dir, so we can simply remove it and use autoinstall
instead.
* Scripts/webkitpy/thirdparty/__init__.py:
(AutoinstallImportHook.find_module): Check pytest.
(AutoinstallImportHook._install_pytest): Install pytest.
* Scripts/webkitpy/webdriver_tests/webdriver_selenium_executor.py: Import autoinstalled pytest.
* Scripts/webkitpy/webdriver_tests/webdriver_test_runner_w3c.py:
(WebDriverTestRunnerW3C.run): Update the subtest path since the new pytest uses a different strategy for
rootdir.
* Scripts/webkitpy/webdriver_tests/webdriver_w3c_executor.py: Import autoinstalled pytest.
WebDriverTests:
* imported/selenium/py/conftest.py: Stop patching this to use yield_fixture, new pytest supports this.
* imported/selenium/py/setup.cfg: Stop patching this, since pytest supports tool:pytest as group name.
* imported/selenium/py/test/selenium/webdriver/common/alerts_tests.py: Stop patching this to use yield_fixture,
new pytest supports this.
* imported/selenium/py/test/selenium/webdriver/common/cookie_tests.py: Ditto.
* imported/selenium/py/test/selenium/webdriver/common/frame_switching_tests.py: Ditto.
* imported/selenium/py/test/selenium/webdriver/common/page_load_timeout_tests.py: Ditto.
* imported/selenium/py/test/selenium/webdriver/common/window_switching_tests.py: Ditto.
* imported/selenium/py/test/selenium/webdriver/safari/conftest.py: Ditto.
* imported/selenium/py/test/selenium/webdriver/support/event_firing_webdriver_tests.py: Ditto.
* imported/w3c/importer.json: Stop importing pytest.
* imported/w3c/pytest.ini: Added.
* imported/w3c/tools/pytest/: Removed.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@225447 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Tools/ChangeLog b/Tools/ChangeLog
index 61beeef..d1aadde 100644
--- a/Tools/ChangeLog
+++ b/Tools/ChangeLog
@@ -1,3 +1,22 @@
+2017-12-01 Carlos Garcia Campos <cgarcia@igalia.com>
+
+ WebDriver: auto-install pytest instead of importing it from wpt tools directory
+ https://bugs.webkit.org/show_bug.cgi?id=180243
+
+ Reviewed by Brian Burg.
+
+ We don't really need the (old) version included in wpt tools dir, so we can simply remove it and use autoinstall
+ instead.
+
+ * Scripts/webkitpy/thirdparty/__init__.py:
+ (AutoinstallImportHook.find_module): Check pytest.
+ (AutoinstallImportHook._install_pytest): Install pytest.
+ * Scripts/webkitpy/webdriver_tests/webdriver_selenium_executor.py: Import autoinstalled pytest.
+ * Scripts/webkitpy/webdriver_tests/webdriver_test_runner_w3c.py:
+ (WebDriverTestRunnerW3C.run): Update the subtest path since the new pytest uses a different strategy for
+ rootdir.
+ * Scripts/webkitpy/webdriver_tests/webdriver_w3c_executor.py: Import autoinstalled pytest.
+
2017-12-01 Dewei Zhu <dewei_zhu@apple.com>
Hardcoded python path is not compatible with virtual environment.
diff --git a/Tools/Scripts/webkitpy/thirdparty/__init__.py b/Tools/Scripts/webkitpy/thirdparty/__init__.py
index d70c1bf..b8ca086 100644
--- a/Tools/Scripts/webkitpy/thirdparty/__init__.py
+++ b/Tools/Scripts/webkitpy/thirdparty/__init__.py
@@ -112,6 +112,8 @@
self._install_mozprocess()
elif '.pytest_timeout' in fullname:
self._install_pytest_timeout()
+ elif '.pytest' in fullname:
+ self._install_pytest()
def _install_mechanize(self):
self._install("https://pypi.python.org/packages/source/m/mechanize/mechanize-0.2.5.tar.gz",
@@ -139,6 +141,12 @@
self._install("https://pypi.python.org/packages/cc/b7/b2a61365ea6b6d2e8881360ae7ed8dad0327ad2df89f2f0be4a02304deb2/pytest-timeout-1.2.0.tar.gz#md5=83607d91aa163562c7ee835da57d061d",
"pytest-timeout-1.2.0/pytest_timeout.py")
+ def _install_pytest(self):
+ self._install("https://pypi.python.org/packages/1f/f8/8cd74c16952163ce0db0bd95fdd8810cbf093c08be00e6e665ebf0dc3138/pytest-3.2.5.tar.gz#md5=6dbe9bb093883f75394a689a1426ac6f",
+ "pytest-3.2.5/_pytest")
+ self._install("https://pypi.python.org/packages/1f/f8/8cd74c16952163ce0db0bd95fdd8810cbf093c08be00e6e665ebf0dc3138/pytest-3.2.5.tar.gz#md5=6dbe9bb093883f75394a689a1426ac6f",
+ "pytest-3.2.5/pytest.py")
+
def _install_pylint(self):
self._ensure_autoinstalled_dir_is_in_sys_path()
if (not self._fs.exists(self._fs.join(_AUTOINSTALLED_DIR, "pylint")) or
diff --git a/Tools/Scripts/webkitpy/webdriver_tests/webdriver_selenium_executor.py b/Tools/Scripts/webkitpy/webdriver_tests/webdriver_selenium_executor.py
index e9e37d3..12a4953 100644
--- a/Tools/Scripts/webkitpy/webdriver_tests/webdriver_selenium_executor.py
+++ b/Tools/Scripts/webkitpy/webdriver_tests/webdriver_selenium_executor.py
@@ -27,6 +27,9 @@
from webkitpy.common.system.filesystem import FileSystem
from webkitpy.common.webkit_finder import WebKitFinder
import webkitpy.thirdparty.autoinstalled.mozlog
+import webkitpy.thirdparty.autoinstalled.pytest
+import webkitpy.thirdparty.autoinstalled.pytest_timeout
+import pytest
# Since W3C tests also use pytest, we use pytest and some other tools for selenium too.
w3c_tools_dir = WebKitFinder(FileSystem()).path_from_webkit_base('WebDriverTests', 'imported', 'w3c', 'tools')
@@ -35,11 +38,8 @@
def _ensure_directory_in_path(directory):
if not directory in sys.path:
sys.path.insert(0, directory)
-_ensure_directory_in_path(os.path.join(w3c_tools_dir, 'pytest'))
_ensure_directory_in_path(os.path.join(w3c_tools_dir, 'wptrunner'))
-import pytest
-import webkitpy.thirdparty.autoinstalled.pytest_timeout
from wptrunner.executors.pytestrunner.runner import HarnessResultRecorder, SubtestResultRecorder, TemporaryDirectory
_log = logging.getLogger(__name__)
diff --git a/Tools/Scripts/webkitpy/webdriver_tests/webdriver_test_runner_w3c.py b/Tools/Scripts/webkitpy/webdriver_tests/webdriver_test_runner_w3c.py
index 734a2d0..d248217 100644
--- a/Tools/Scripts/webkitpy/webdriver_tests/webdriver_test_runner_w3c.py
+++ b/Tools/Scripts/webkitpy/webdriver_tests/webdriver_test_runner_w3c.py
@@ -94,8 +94,8 @@
harness_result, test_results = executor.run(test)
result = WebDriverTestResult(test_name, *harness_result)
if harness_result[0] == 'OK':
- for test_result in test_results:
- result.add_subtest_results(*test_result)
+ for subtest, status, message, backtrace in test_results:
+ result.add_subtest_results(os.path.basename(subtest), status, message, backtrace)
else:
# FIXME: handle other results.
pass
diff --git a/Tools/Scripts/webkitpy/webdriver_tests/webdriver_w3c_executor.py b/Tools/Scripts/webkitpy/webdriver_tests/webdriver_w3c_executor.py
index 4804b2e..64634c48 100644
--- a/Tools/Scripts/webkitpy/webdriver_tests/webdriver_w3c_executor.py
+++ b/Tools/Scripts/webkitpy/webdriver_tests/webdriver_w3c_executor.py
@@ -28,6 +28,8 @@
from webkitpy.common.webkit_finder import WebKitFinder
import webkitpy.thirdparty.autoinstalled.mozlog
import webkitpy.thirdparty.autoinstalled.mozprocess
+import webkitpy.thirdparty.autoinstalled.pytest
+import webkitpy.thirdparty.autoinstalled.pytest_timeout
from mozlog import structuredlog
w3c_tools_dir = WebKitFinder(FileSystem()).path_from_webkit_base('WebDriverTests', 'imported', 'w3c', 'tools')
@@ -36,11 +38,9 @@
def _ensure_directory_in_path(directory):
if not directory in sys.path:
sys.path.insert(0, directory)
-_ensure_directory_in_path(os.path.join(w3c_tools_dir, 'pytest'))
_ensure_directory_in_path(os.path.join(w3c_tools_dir, 'webdriver'))
_ensure_directory_in_path(os.path.join(w3c_tools_dir, 'wptrunner'))
-import webkitpy.thirdparty.autoinstalled.pytest_timeout
from wptrunner.executors.base import WdspecExecutor, WebDriverProtocol
from wptrunner.webdriver_server import WebDriverServer
diff --git a/WebDriverTests/ChangeLog b/WebDriverTests/ChangeLog
index d03549c..1ad9d8e 100644
--- a/WebDriverTests/ChangeLog
+++ b/WebDriverTests/ChangeLog
@@ -1,3 +1,24 @@
+2017-12-01 Carlos Garcia Campos <cgarcia@igalia.com>
+
+ WebDriver: auto-install pytest instead of importing it from wpt tools directory
+ https://bugs.webkit.org/show_bug.cgi?id=180243
+
+ Reviewed by Brian Burg.
+
+ * imported/selenium/py/conftest.py: Stop patching this to use yield_fixture, new pytest supports this.
+ * imported/selenium/py/setup.cfg: Stop patching this, since pytest supports tool:pytest as group name.
+ * imported/selenium/py/test/selenium/webdriver/common/alerts_tests.py: Stop patching this to use yield_fixture,
+ new pytest supports this.
+ * imported/selenium/py/test/selenium/webdriver/common/cookie_tests.py: Ditto.
+ * imported/selenium/py/test/selenium/webdriver/common/frame_switching_tests.py: Ditto.
+ * imported/selenium/py/test/selenium/webdriver/common/page_load_timeout_tests.py: Ditto.
+ * imported/selenium/py/test/selenium/webdriver/common/window_switching_tests.py: Ditto.
+ * imported/selenium/py/test/selenium/webdriver/safari/conftest.py: Ditto.
+ * imported/selenium/py/test/selenium/webdriver/support/event_firing_webdriver_tests.py: Ditto.
+ * imported/w3c/importer.json: Stop importing pytest.
+ * imported/w3c/pytest.ini: Added.
+ * imported/w3c/tools/pytest/: Removed.
+
2017-11-30 Carlos Garcia Campos <cgarcia@igalia.com>
WebDriver: add support for importing and running selenium tests
diff --git a/WebDriverTests/imported/selenium/py/conftest.py b/WebDriverTests/imported/selenium/py/conftest.py
index 2eb9775..ef11e01 100644
--- a/WebDriverTests/imported/selenium/py/conftest.py
+++ b/WebDriverTests/imported/selenium/py/conftest.py
@@ -67,7 +67,7 @@
driver_instance = None
-@pytest.yield_fixture(scope='function')
+@pytest.fixture(scope='function')
def driver(request):
kwargs = {}
@@ -157,7 +157,7 @@
return Pages()
-@pytest.yield_fixture(autouse=True, scope='session')
+@pytest.fixture(autouse=True, scope='session')
def server(request):
drivers = request.config.getoption('drivers')
if drivers is None or 'Remote' not in drivers:
@@ -196,7 +196,7 @@
print('Selenium server has been terminated')
-@pytest.yield_fixture(autouse=True, scope='session')
+@pytest.fixture(autouse=True, scope='session')
def webserver():
webserver = SimpleWebServer(host=get_lan_ip())
webserver.start()
diff --git a/WebDriverTests/imported/selenium/py/setup.cfg b/WebDriverTests/imported/selenium/py/setup.cfg
index 8c986bb..1385258 100644
--- a/WebDriverTests/imported/selenium/py/setup.cfg
+++ b/WebDriverTests/imported/selenium/py/setup.cfg
@@ -5,7 +5,7 @@
exclude = .tox,docs/source/conf.py
ignore = E501
-[pytest]
+[tool:pytest]
addopts = -r=a
python_files = test_*.py *_tests.py
testpaths = test
diff --git a/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/alerts_tests.py b/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/alerts_tests.py
index cc496c3..16ab12c 100644
--- a/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/alerts_tests.py
+++ b/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/alerts_tests.py
@@ -29,7 +29,7 @@
WebDriverException)
-@pytest.yield_fixture(autouse=True)
+@pytest.fixture(autouse=True)
def close_alert(driver):
yield
try:
diff --git a/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/cookie_tests.py b/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/cookie_tests.py
index 908dcb3..ae080f5 100644
--- a/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/cookie_tests.py
+++ b/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/cookie_tests.py
@@ -33,7 +33,7 @@
return cookie
-@pytest.yield_fixture(autouse=True)
+@pytest.fixture(autouse=True)
def pages(request, driver, pages):
pages.load('simpleTest.html')
yield pages
diff --git a/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/frame_switching_tests.py b/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/frame_switching_tests.py
index 78e24bd..bd9cc5d 100644
--- a/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/frame_switching_tests.py
+++ b/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/frame_switching_tests.py
@@ -38,7 +38,7 @@
# ----------------------------------------------------------------------------------------------
-@pytest.yield_fixture(autouse=True)
+@pytest.fixture(autouse=True)
def restore_default_context(driver):
yield
driver.switch_to.default_content()
diff --git a/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/page_load_timeout_tests.py b/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/page_load_timeout_tests.py
index b1e3750..c311911 100644
--- a/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/page_load_timeout_tests.py
+++ b/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/page_load_timeout_tests.py
@@ -20,7 +20,7 @@
from selenium.common.exceptions import TimeoutException
-@pytest.yield_fixture(autouse=True)
+@pytest.fixture(autouse=True)
def reset_timeouts(driver):
yield
driver.set_page_load_timeout(300)
diff --git a/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/window_switching_tests.py b/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/window_switching_tests.py
index 1cbe385..77e91a3 100644
--- a/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/window_switching_tests.py
+++ b/WebDriverTests/imported/selenium/py/test/selenium/webdriver/common/window_switching_tests.py
@@ -24,7 +24,7 @@
from selenium.webdriver.support.ui import WebDriverWait
-@pytest.yield_fixture(autouse=True)
+@pytest.fixture(autouse=True)
def close_windows(driver):
main_windows_handle = driver.current_window_handle
yield
diff --git a/WebDriverTests/imported/selenium/py/test/selenium/webdriver/safari/conftest.py b/WebDriverTests/imported/selenium/py/test/selenium/webdriver/safari/conftest.py
index aad4e50..6aa8968 100644
--- a/WebDriverTests/imported/selenium/py/test/selenium/webdriver/safari/conftest.py
+++ b/WebDriverTests/imported/selenium/py/test/selenium/webdriver/safari/conftest.py
@@ -30,7 +30,7 @@
return {}
-@pytest.yield_fixture
+@pytest.fixture
def driver(driver_class, driver_kwargs):
driver = driver_class(**driver_kwargs)
yield driver
diff --git a/WebDriverTests/imported/selenium/py/test/selenium/webdriver/support/event_firing_webdriver_tests.py b/WebDriverTests/imported/selenium/py/test/selenium/webdriver/support/event_firing_webdriver_tests.py
index f437a44..1246d96 100644
--- a/WebDriverTests/imported/selenium/py/test/selenium/webdriver/support/event_firing_webdriver_tests.py
+++ b/WebDriverTests/imported/selenium/py/test/selenium/webdriver/support/event_firing_webdriver_tests.py
@@ -28,7 +28,7 @@
from selenium.webdriver.support.ui import WebDriverWait
-@pytest.yield_fixture
+@pytest.fixture
def log():
log = BytesIO()
yield log
diff --git a/WebDriverTests/imported/w3c/importer.json b/WebDriverTests/imported/w3c/importer.json
index dba6dc3..2715602 100644
--- a/WebDriverTests/imported/w3c/importer.json
+++ b/WebDriverTests/imported/w3c/importer.json
@@ -2,7 +2,6 @@
"repository": "https://github.com/w3c/web-platform-tests.git",
"revision": "2b50389ee72d89dd0be12bc6ca54a6e95c98d163",
"paths_to_import": [
- "tools/pytest",
"tools/webdriver",
"tools/wptrunner",
"webdriver"
diff --git a/WebDriverTests/imported/w3c/pytest.ini b/WebDriverTests/imported/w3c/pytest.ini
new file mode 100644
index 0000000..f4aabae
--- /dev/null
+++ b/WebDriverTests/imported/w3c/pytest.ini
@@ -0,0 +1,2 @@
+# Pytest config file. We don't have any special configuration for pytest,
+# but the existance of this file here determines the rootdir used by pytest.
diff --git a/WebDriverTests/imported/w3c/tools/pytest/.coveragerc b/WebDriverTests/imported/w3c/tools/pytest/.coveragerc
deleted file mode 100644
index 27db64e..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/.coveragerc
+++ /dev/null
@@ -1,7 +0,0 @@
-[run]
-omit =
- # standlonetemplate is read dynamically and tested by test_genscript
- *standalonetemplate.py
- # oldinterpret could be removed, as it is no longer used in py26+
- *oldinterpret.py
- vendored_packages
diff --git a/WebDriverTests/imported/w3c/tools/pytest/.gitattributes b/WebDriverTests/imported/w3c/tools/pytest/.gitattributes
deleted file mode 100644
index 242d3da..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/.gitattributes
+++ /dev/null
@@ -1 +0,0 @@
-CHANGELOG merge=union
diff --git a/WebDriverTests/imported/w3c/tools/pytest/.github/ISSUE_TEMPLATE.md b/WebDriverTests/imported/w3c/tools/pytest/.github/ISSUE_TEMPLATE.md
deleted file mode 100644
index bc62e8a..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/.github/ISSUE_TEMPLATE.md
+++ /dev/null
@@ -1,8 +0,0 @@
-Thanks for submitting an issue!
-
-Here's a quick checklist in what to include:
-
-- [ ] Include a detailed description of the bug or suggestion
-- [ ] `pip list` of the virtual environment you are using
-- [ ] py.test and operating system versions
-- [ ] Minimal example if possible
diff --git a/WebDriverTests/imported/w3c/tools/pytest/.github/PULL_REQUEST_TEMPLATE.md b/WebDriverTests/imported/w3c/tools/pytest/.github/PULL_REQUEST_TEMPLATE.md
deleted file mode 100644
index d09edce..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/.github/PULL_REQUEST_TEMPLATE.md
+++ /dev/null
@@ -1,8 +0,0 @@
-Thanks for submitting a PR, your contribution is really appreciated!
-
-Here's a quick checklist that should be present in PRs:
-
-- [ ] Target: for bug or doc fixes, target `master`; for new features, target `features`
-- [ ] Make sure to include one or more tests for your change
-- [ ] Add yourself to `AUTHORS`
-- [ ] Add a new entry to the `CHANGELOG` (choose any open position to avoid merge conflicts with other PRs)
diff --git a/WebDriverTests/imported/w3c/tools/pytest/.gitignore b/WebDriverTests/imported/w3c/tools/pytest/.gitignore
deleted file mode 100644
index e4355b8..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/.gitignore
+++ /dev/null
@@ -1,34 +0,0 @@
-# Automatically generated by `hgimportsvn`
-.svn
-.hgsvn
-
-# Ignore local virtualenvs
-lib/
-bin/
-include/
-.Python/
-
-# These lines are suggested according to the svn:ignore property
-# Feel free to enable them by uncommenting them
-*.pyc
-*.pyo
-*.swp
-*.class
-*.orig
-*~
-
-.eggs/
-
-doc/*/_build
-build/
-dist/
-*.egg-info
-issue/
-env/
-.env/
-3rdparty/
-.tox
-.cache
-.coverage
-.ropeproject
-.idea
diff --git a/WebDriverTests/imported/w3c/tools/pytest/.travis.yml b/WebDriverTests/imported/w3c/tools/pytest/.travis.yml
deleted file mode 100644
index 3a8f36e..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/.travis.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-sudo: false
-language: python
-python:
- - '3.5'
-# command to install dependencies
-install: "pip install -U tox"
-# # command to run tests
-env:
- matrix:
- # coveralls is not listed in tox's envlist, but should run in travis
- - TESTENV=coveralls
- # note: please use "tox --listenvs" to populate the build matrix below
- - TESTENV=linting
- - TESTENV=py26
- - TESTENV=py27
- - TESTENV=py33
- - TESTENV=py34
- - TESTENV=py35
- - TESTENV=pypy
- - TESTENV=py27-pexpect
- - TESTENV=py27-xdist
- - TESTENV=py27-trial
- - TESTENV=py35-pexpect
- - TESTENV=py35-xdist
- - TESTENV=py35-trial
- - TESTENV=py27-nobyte
- - TESTENV=doctesting
- - TESTENV=py27-cxfreeze
-
-script: tox --recreate -e $TESTENV
-
-notifications:
- irc:
- channels:
- - "chat.freenode.net#pytest"
- on_success: change
- on_failure: change
- skip_join: true
- email:
- - pytest-commit@python.org
diff --git a/WebDriverTests/imported/w3c/tools/pytest/AUTHORS b/WebDriverTests/imported/w3c/tools/pytest/AUTHORS
deleted file mode 100644
index dfc0a54..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/AUTHORS
+++ /dev/null
@@ -1,87 +0,0 @@
-Holger Krekel, holger at merlinux eu
-merlinux GmbH, Germany, office at merlinux eu
-
-Contributors include::
-
-Abhijeet Kasurde
-Anatoly Bubenkoff
-Andreas Zeidler
-Andy Freeland
-Anthon van der Neut
-Armin Rigo
-Aron Curzon
-Aviv Palivoda
-Benjamin Peterson
-Bob Ippolito
-Brian Dorsey
-Brian Okken
-Brianna Laugher
-Bruno Oliveira
-Carl Friedrich Bolz
-Charles Cloud
-Chris Lamb
-Christian Theunert
-Christian Tismer
-Christopher Gilling
-Daniel Grana
-Daniel Hahler
-Daniel Nuri
-Dave Hunt
-David Mohr
-David Vierra
-Edison Gustavo Muenz
-Eduardo Schettino
-Endre Galaczi
-Elizaveta Shashkova
-Eric Hunsberger
-Eric Siegerman
-Erik M. Bray
-Florian Bruhin
-Floris Bruynooghe
-Gabriel Reis
-Georgy Dyuldin
-Graham Horler
-Grig Gheorghiu
-Guido Wesdorp
-Harald Armin Massa
-Ian Bicking
-Jaap Broekhuizen
-Jan Balster
-Janne Vanhala
-Jason R. Coombs
-Joshua Bronson
-Jurko Gospodnetić
-Katarzyna Jachim
-Kevin Cox
-Lee Kamentsky
-Lukas Bednar
-Maciek Fijalkowski
-Maho
-Marc Schlaich
-Mark Abramowitz
-Markus Unterwaditzer
-Martijn Faassen
-Matt Bachmann
-Michael Aquilina
-Michael Birtwell
-Michael Droettboom
-Nicolas Delaby
-Pieter Mulder
-Piotr Banaszkiewicz
-Punyashloka Biswal
-Ralf Schmitt
-Raphael Pierzina
-Ronny Pfannschmidt
-Ross Lawley
-Ryan Wooden
-Samuele Pedroni
-Tom Viner
-Trevor Bekolay
-Wouter van Ackooy
-David Díaz-Barquero
-Eric Hunsberger
-Simon Gomizelj
-Russel Winder
-Ben Webb
-Alexei Kozlenok
-Cal Leeming
diff --git a/WebDriverTests/imported/w3c/tools/pytest/CHANGELOG.rst b/WebDriverTests/imported/w3c/tools/pytest/CHANGELOG.rst
deleted file mode 100644
index f18f646..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/CHANGELOG.rst
+++ /dev/null
@@ -1,2586 +0,0 @@
-2.9.1
-=====
-
-**Bug Fixes**
-
-* Improve error message when a plugin fails to load.
- Thanks `@nicoddemus`_ for the PR.
-
-* Fix (`#1178 <https://github.com/pytest-dev/pytest/issues/1178>`_):
- ``pytest.fail`` with non-ascii characters raises an internal pytest error.
- Thanks `@nicoddemus`_ for the PR.
-
-* Fix (`#469`_): junit parses report.nodeid incorrectly, when params IDs
- contain ``::``. Thanks `@tomviner`_ for the PR (`#1431`_).
-
-* Fix (`#578 <https://github.com/pytest-dev/pytest/issues/578>`_): SyntaxErrors
- containing non-ascii lines at the point of failure generated an internal
- py.test error.
- Thanks `@asottile`_ for the report and `@nicoddemus`_ for the PR.
-
-* Fix (`#1437`_): When passing in a bytestring regex pattern to parameterize
- attempt to decode it as utf-8 ignoring errors.
-
-* Fix (`#649`_): parametrized test nodes cannot be specified to run on the command line.
-
-
-.. _#1437: https://github.com/pytest-dev/pytest/issues/1437
-.. _#469: https://github.com/pytest-dev/pytest/issues/469
-.. _#1431: https://github.com/pytest-dev/pytest/pull/1431
-.. _#649: https://github.com/pytest-dev/pytest/issues/649
-
-.. _@asottile: https://github.com/asottile
-
-
-2.9.0
-=====
-
-**New Features**
-
-* New ``pytest.mark.skip`` mark, which unconditionally skips marked tests.
- Thanks `@MichaelAquilina`_ for the complete PR (`#1040`_).
-
-* ``--doctest-glob`` may now be passed multiple times in the command-line.
- Thanks `@jab`_ and `@nicoddemus`_ for the PR.
-
-* New ``-rp`` and ``-rP`` reporting options give the summary and full output
- of passing tests, respectively. Thanks to `@codewarrior0`_ for the PR.
-
-* ``pytest.mark.xfail`` now has a ``strict`` option, which makes ``XPASS``
- tests to fail the test suite (defaulting to ``False``). There's also a
- ``xfail_strict`` ini option that can be used to configure it project-wise.
- Thanks `@rabbbit`_ for the request and `@nicoddemus`_ for the PR (`#1355`_).
-
-* ``Parser.addini`` now supports options of type ``bool``.
- Thanks `@nicoddemus`_ for the PR.
-
-* New ``ALLOW_BYTES`` doctest option. This strips ``b`` prefixes from byte strings
- in doctest output (similar to ``ALLOW_UNICODE``).
- Thanks `@jaraco`_ for the request and `@nicoddemus`_ for the PR (`#1287`_).
-
-* Give a hint on ``KeyboardInterrupt`` to use the ``--fulltrace`` option to show the errors.
- Fixes `#1366`_.
- Thanks to `@hpk42`_ for the report and `@RonnyPfannschmidt`_ for the PR.
-
-* Catch ``IndexError`` exceptions when getting exception source location.
- Fixes a pytest internal error for dynamically generated code (fixtures and tests)
- where source lines are fake by intention.
-
-**Changes**
-
-* **Important**: `py.code <http://pylib.readthedocs.org/en/latest/code.html>`_ has been
- merged into the ``pytest`` repository as ``pytest._code``. This decision
- was made because ``py.code`` had very few uses outside ``pytest`` and the
- fact that it was in a different repository made it difficult to fix bugs on
- its code in a timely manner. The team hopes with this to be able to better
- refactor out and improve that code.
- This change shouldn't affect users, but it is useful to let users aware
- if they encounter any strange behavior.
-
- Keep in mind that the code for ``pytest._code`` is **private** and
- **experimental**, so you definitely should not import it explicitly!
-
- Please note that the original ``py.code`` is still available in
- `pylib <http://pylib.readthedocs.org>`_.
-
-* ``pytest_enter_pdb`` now optionally receives the pytest config object.
- Thanks `@nicoddemus`_ for the PR.
-
-* Removed code and documentation for Python 2.5 or lower versions,
- including removal of the obsolete ``_pytest.assertion.oldinterpret`` module.
- Thanks `@nicoddemus`_ for the PR (`#1226`_).
-
-* Comparisons now always show up in full when ``CI`` or ``BUILD_NUMBER`` is
- found in the environment, even when ``-vv`` isn't used.
- Thanks `@The-Compiler`_ for the PR.
-
-* ``--lf`` and ``--ff`` now support long names: ``--last-failed`` and
- ``--failed-first`` respectively.
- Thanks `@MichaelAquilina`_ for the PR.
-
-* Added expected exceptions to ``pytest.raises`` fail message.
-
-* Collection only displays progress ("collecting X items") when in a terminal.
- This avoids cluttering the output when using ``--color=yes`` to obtain
- colors in CI integrations systems (`#1397`_).
-
-**Bug Fixes**
-
-* The ``-s`` and ``-c`` options should now work under ``xdist``;
- ``Config.fromdictargs`` now represents its input much more faithfully.
- Thanks to `@bukzor`_ for the complete PR (`#680`_).
-
-* Fix (`#1290`_): support Python 3.5's ``@`` operator in assertion rewriting.
- Thanks `@Shinkenjoe`_ for report with test case and `@tomviner`_ for the PR.
-
-* Fix formatting utf-8 explanation messages (`#1379`_).
- Thanks `@biern`_ for the PR.
-
-* Fix `traceback style docs`_ to describe all of the available options
- (auto/long/short/line/native/no), with `auto` being the default since v2.6.
- Thanks `@hackebrot`_ for the PR.
-
-* Fix (`#1422`_): junit record_xml_property doesn't allow multiple records
- with same name.
-
-.. _`traceback style docs`: https://pytest.org/latest/usage.html#modifying-python-traceback-printing
-
-.. _#1422: https://github.com/pytest-dev/pytest/issues/1422
-.. _#1379: https://github.com/pytest-dev/pytest/issues/1379
-.. _#1366: https://github.com/pytest-dev/pytest/issues/1366
-.. _#1040: https://github.com/pytest-dev/pytest/pull/1040
-.. _#680: https://github.com/pytest-dev/pytest/issues/680
-.. _#1287: https://github.com/pytest-dev/pytest/pull/1287
-.. _#1226: https://github.com/pytest-dev/pytest/pull/1226
-.. _#1290: https://github.com/pytest-dev/pytest/pull/1290
-.. _#1355: https://github.com/pytest-dev/pytest/pull/1355
-.. _#1397: https://github.com/pytest-dev/pytest/issues/1397
-.. _@biern: https://github.com/biern
-.. _@MichaelAquilina: https://github.com/MichaelAquilina
-.. _@bukzor: https://github.com/bukzor
-.. _@hpk42: https://github.com/hpk42
-.. _@nicoddemus: https://github.com/nicoddemus
-.. _@jab: https://github.com/jab
-.. _@codewarrior0: https://github.com/codewarrior0
-.. _@jaraco: https://github.com/jaraco
-.. _@The-Compiler: https://github.com/The-Compiler
-.. _@Shinkenjoe: https://github.com/Shinkenjoe
-.. _@tomviner: https://github.com/tomviner
-.. _@RonnyPfannschmidt: https://github.com/RonnyPfannschmidt
-.. _@rabbbit: https://github.com/rabbbit
-.. _@hackebrot: https://github.com/hackebrot
-
-2.8.7
-=====
-
-- fix #1338: use predictable object resolution for monkeypatch
-
-2.8.6
-=====
-
-- fix #1259: allow for double nodeids in junitxml,
- this was a regression failing plugins combinations
- like pytest-pep8 + pytest-flakes
-
-- Workaround for exception that occurs in pyreadline when using
- ``--pdb`` with standard I/O capture enabled.
- Thanks Erik M. Bray for the PR.
-
-- fix #900: Better error message in case the target of a ``monkeypatch`` call
- raises an ``ImportError``.
-
-- fix #1292: monkeypatch calls (setattr, setenv, etc.) are now O(1).
- Thanks David R. MacIver for the report and Bruno Oliveira for the PR.
-
-- fix #1223: captured stdout and stderr are now properly displayed before
- entering pdb when ``--pdb`` is used instead of being thrown away.
- Thanks Cal Leeming for the PR.
-
-- fix #1305: pytest warnings emitted during ``pytest_terminal_summary`` are now
- properly displayed.
- Thanks Ionel Maries Cristian for the report and Bruno Oliveira for the PR.
-
-- fix #628: fixed internal UnicodeDecodeError when doctests contain unicode.
- Thanks Jason R. Coombs for the report and Bruno Oliveira for the PR.
-
-- fix #1334: Add captured stdout to jUnit XML report on setup error.
- Thanks Georgy Dyuldin for the PR.
-
-
-2.8.5
-=====
-
-- fix #1243: fixed issue where class attributes injected during collection could break pytest.
- PR by Alexei Kozlenok, thanks Ronny Pfannschmidt and Bruno Oliveira for the review and help.
-
-- fix #1074: precompute junitxml chunks instead of storing the whole tree in objects
- Thanks Bruno Oliveira for the report and Ronny Pfannschmidt for the PR
-
-- fix #1238: fix ``pytest.deprecated_call()`` receiving multiple arguments
- (Regression introduced in 2.8.4). Thanks Alex Gaynor for the report and
- Bruno Oliveira for the PR.
-
-
-2.8.4
-=====
-
-- fix #1190: ``deprecated_call()`` now works when the deprecated
- function has been already called by another test in the same
- module. Thanks Mikhail Chernykh for the report and Bruno Oliveira for the
- PR.
-
-- fix #1198: ``--pastebin`` option now works on Python 3. Thanks
- Mehdy Khoshnoody for the PR.
-
-- fix #1219: ``--pastebin`` now works correctly when captured output contains
- non-ascii characters. Thanks Bruno Oliveira for the PR.
-
-- fix #1204: another error when collecting with a nasty __getattr__().
- Thanks Florian Bruhin for the PR.
-
-- fix the summary printed when no tests did run.
- Thanks Florian Bruhin for the PR.
-- fix #1185 - ensure MANIFEST.in exactly matches what should go to a sdist
-
-- a number of documentation modernizations wrt good practices.
- Thanks Bruno Oliveira for the PR.
-
-2.8.3
-=====
-
-- fix #1169: add __name__ attribute to testcases in TestCaseFunction to
- support the @unittest.skip decorator on functions and methods.
- Thanks Lee Kamentsky for the PR.
-
-- fix #1035: collecting tests if test module level obj has __getattr__().
- Thanks Suor for the report and Bruno Oliveira / Tom Viner for the PR.
-
-- fix #331: don't collect tests if their failure cannot be reported correctly
- e.g. they are a callable instance of a class.
-
-- fix #1133: fixed internal error when filtering tracebacks where one entry
- belongs to a file which is no longer available.
- Thanks Bruno Oliveira for the PR.
-
-- enhancement made to highlight in red the name of the failing tests so
- they stand out in the output.
- Thanks Gabriel Reis for the PR.
-
-- add more talks to the documentation
-- extend documentation on the --ignore cli option
-- use pytest-runner for setuptools integration
-- minor fixes for interaction with OS X El Capitan
- system integrity protection (thanks Florian)
-
-
-2.8.2
-=====
-
-- fix #1085: proper handling of encoding errors when passing encoded byte
- strings to pytest.parametrize in Python 2.
- Thanks Themanwithoutaplan for the report and Bruno Oliveira for the PR.
-
-- fix #1087: handling SystemError when passing empty byte strings to
- pytest.parametrize in Python 3.
- Thanks Paul Kehrer for the report and Bruno Oliveira for the PR.
-
-- fix #995: fixed internal error when filtering tracebacks where one entry
- was generated by an exec() statement.
- Thanks Daniel Hahler, Ashley C Straw, Philippe Gauthier and Pavel Savchenko
- for contributing and Bruno Oliveira for the PR.
-
-- fix #1100 and #1057: errors when using autouse fixtures and doctest modules.
- Thanks Sergey B Kirpichev and Vital Kudzelka for contributing and Bruno
- Oliveira for the PR.
-
-2.8.1
-=====
-
-- fix #1034: Add missing nodeid on pytest_logwarning call in
- addhook. Thanks Simon Gomizelj for the PR.
-
-- 'deprecated_call' is now only satisfied with a DeprecationWarning or
- PendingDeprecationWarning. Before 2.8.0, it accepted any warning, and 2.8.0
- made it accept only DeprecationWarning (but not PendingDeprecationWarning).
- Thanks Alex Gaynor for the issue and Eric Hunsberger for the PR.
-
-- fix issue #1073: avoid calling __getattr__ on potential plugin objects.
- This fixes an incompatibility with pytest-django. Thanks Andreas Pelme,
- Bruno Oliveira and Ronny Pfannschmidt for contributing and Holger Krekel
- for the fix.
-
-- Fix issue #704: handle versionconflict during plugin loading more
- gracefully. Thanks Bruno Oliveira for the PR.
-
-- Fix issue #1064: ""--junitxml" regression when used with the
- "pytest-xdist" plugin, with test reports being assigned to the wrong tests.
- Thanks Daniel Grunwald for the report and Bruno Oliveira for the PR.
-
-- (experimental) adapt more SEMVER style versioning and change meaning of
- master branch in git repo: "master" branch now keeps the bugfixes, changes
- aimed for micro releases. "features" branch will only be be released
- with minor or major pytest releases.
-
-- Fix issue #766 by removing documentation references to distutils.
- Thanks Russel Winder.
-
-- Fix issue #1030: now byte-strings are escaped to produce item node ids
- to make them always serializable.
- Thanks Andy Freeland for the report and Bruno Oliveira for the PR.
-
-- Python 2: if unicode parametrized values are convertible to ascii, their
- ascii representation is used for the node id.
-
-- Fix issue #411: Add __eq__ method to assertion comparison example.
- Thanks Ben Webb.
-- Fix issue #653: deprecated_call can be used as context manager.
-
-- fix issue 877: properly handle assertion explanations with non-ascii repr
- Thanks Mathieu Agopian for the report and Ronny Pfannschmidt for the PR.
-
-- fix issue 1029: transform errors when writing cache values into pytest-warnings
-
-2.8.0
-=====
-
-- new ``--lf`` and ``-ff`` options to run only the last failing tests or
- "failing tests first" from the last run. This functionality is provided
- through porting the formerly external pytest-cache plugin into pytest core.
- BACKWARD INCOMPAT: if you used pytest-cache's functionality to persist
- data between test runs be aware that we don't serialize sets anymore.
- Thanks Ronny Pfannschmidt for most of the merging work.
-
-- "-r" option now accepts "a" to include all possible reports, similar
- to passing "fEsxXw" explicitly (isse960).
- Thanks Abhijeet Kasurde for the PR.
-
-- avoid python3.5 deprecation warnings by introducing version
- specific inspection helpers, thanks Michael Droettboom.
-
-- fix issue562: @nose.tools.istest now fully respected.
-
-- fix issue934: when string comparison fails and a diff is too large to display
- without passing -vv, still show a few lines of the diff.
- Thanks Florian Bruhin for the report and Bruno Oliveira for the PR.
-
-- fix issue736: Fix a bug where fixture params would be discarded when combined
- with parametrization markers.
- Thanks to Markus Unterwaditzer for the PR.
-
-- fix issue710: introduce ALLOW_UNICODE doctest option: when enabled, the
- ``u`` prefix is stripped from unicode strings in expected doctest output. This
- allows doctests which use unicode to run in Python 2 and 3 unchanged.
- Thanks Jason R. Coombs for the report and Bruno Oliveira for the PR.
-
-- parametrize now also generates meaningful test IDs for enum, regex and class
- objects (as opposed to class instances).
- Thanks to Florian Bruhin for the PR.
-
-- Add 'warns' to assert that warnings are thrown (like 'raises').
- Thanks to Eric Hunsberger for the PR.
-
-- Fix issue683: Do not apply an already applied mark. Thanks ojake for the PR.
-
-- Deal with capturing failures better so fewer exceptions get lost to
- /dev/null. Thanks David Szotten for the PR.
-
-- fix issue730: deprecate and warn about the --genscript option.
- Thanks Ronny Pfannschmidt for the report and Christian Pommranz for the PR.
-
-- fix issue751: multiple parametrize with ids bug if it parametrizes class with
- two or more test methods. Thanks Sergey Chipiga for reporting and Jan
- Bednarik for PR.
-
-- fix issue82: avoid loading conftest files from setup.cfg/pytest.ini/tox.ini
- files and upwards by default (--confcutdir can still be set to override this).
- Thanks Bruno Oliveira for the PR.
-
-- fix issue768: docstrings found in python modules were not setting up session
- fixtures. Thanks Jason R. Coombs for reporting and Bruno Oliveira for the PR.
-
-- added ``tmpdir_factory``, a session-scoped fixture that can be used to create
- directories under the base temporary directory. Previously this object was
- installed as a ``_tmpdirhandler`` attribute of the ``config`` object, but now it
- is part of the official API and using ``config._tmpdirhandler`` is
- deprecated.
- Thanks Bruno Oliveira for the PR.
-
-- fix issue808: pytest's internal assertion rewrite hook now implements the
- optional PEP302 get_data API so tests can access data files next to them.
- Thanks xmo-odoo for request and example and Bruno Oliveira for
- the PR.
-
-- rootdir and inifile are now displayed during usage errors to help
- users diagnose problems such as unexpected ini files which add
- unknown options being picked up by pytest. Thanks to Pavel Savchenko for
- bringing the problem to attention in #821 and Bruno Oliveira for the PR.
-
-- Summary bar now is colored yellow for warning
- situations such as: all tests either were skipped or xpass/xfailed,
- or no tests were run at all (this is a partial fix for issue500).
-
-- fix issue812: pytest now exits with status code 5 in situations where no
- tests were run at all, such as the directory given in the command line does
- not contain any tests or as result of a command line option filters
- all out all tests (-k for example).
- Thanks Eric Siegerman (issue812) and Bruno Oliveira for the PR.
-
-- Summary bar now is colored yellow for warning
- situations such as: all tests either were skipped or xpass/xfailed,
- or no tests were run at all (related to issue500).
- Thanks Eric Siegerman.
-
-- New ``testpaths`` ini option: list of directories to search for tests
- when executing pytest from the root directory. This can be used
- to speed up test collection when a project has well specified directories
- for tests, being usually more practical than configuring norecursedirs for
- all directories that do not contain tests.
- Thanks to Adrian for idea (#694) and Bruno Oliveira for the PR.
-
-- fix issue713: JUnit XML reports for doctest failures.
- Thanks Punyashloka Biswal.
-
-- fix issue970: internal pytest warnings now appear as "pytest-warnings" in
- the terminal instead of "warnings", so it is clear for users that those
- warnings are from pytest and not from the builtin "warnings" module.
- Thanks Bruno Oliveira.
-
-- Include setup and teardown in junitxml test durations.
- Thanks Janne Vanhala.
-
-- fix issue735: assertion failures on debug versions of Python 3.4+
-
-- new option ``--import-mode`` to allow to change test module importing
- behaviour to append to sys.path instead of prepending. This better allows
- to run test modules against installated versions of a package even if the
- package under test has the same import root. In this example::
-
- testing/__init__.py
- testing/test_pkg_under_test.py
- pkg_under_test/
-
- the tests will run against the installed version
- of pkg_under_test when ``--import-mode=append`` is used whereas
- by default they would always pick up the local version. Thanks Holger Krekel.
-
-- pytester: add method ``TmpTestdir.delete_loaded_modules()``, and call it
- from ``inline_run()`` to allow temporary modules to be reloaded.
- Thanks Eduardo Schettino.
-
-- internally refactor pluginmanager API and code so that there
- is a clear distinction between a pytest-agnostic rather simple
- pluginmanager and the PytestPluginManager which adds a lot of
- behaviour, among it handling of the local conftest files.
- In terms of documented methods this is a backward compatible
- change but it might still break 3rd party plugins which relied on
- details like especially the pluginmanager.add_shutdown() API.
- Thanks Holger Krekel.
-
-- pluginmanagement: introduce ``pytest.hookimpl`` and
- ``pytest.hookspec`` decorators for setting impl/spec
- specific parameters. This substitutes the previous
- now deprecated use of ``pytest.mark`` which is meant to
- contain markers for test functions only.
-
-- write/refine docs for "writing plugins" which now have their
- own page and are separate from the "using/installing plugins`` page.
-
-- fix issue732: properly unregister plugins from any hook calling
- sites allowing to have temporary plugins during test execution.
-
-- deprecate and warn about ``__multicall__`` argument in hook
- implementations. Use the ``hookwrapper`` mechanism instead already
- introduced with pytest-2.7.
-
-- speed up pytest's own test suite considerably by using inprocess
- tests by default (testrun can be modified with --runpytest=subprocess
- to create subprocesses in many places instead). The main
- APIs to run pytest in a test is "runpytest()" or "runpytest_subprocess"
- and "runpytest_inprocess" if you need a particular way of running
- the test. In all cases you get back a RunResult but the inprocess
- one will also have a "reprec" attribute with the recorded events/reports.
-
-- fix monkeypatch.setattr("x.y", raising=False) to actually not raise
- if "y" is not a pre-existing attribute. Thanks Florian Bruhin.
-
-- fix issue741: make running output from testdir.run copy/pasteable
- Thanks Bruno Oliveira.
-
-- add a new ``--noconftest`` argument which ignores all ``conftest.py`` files.
-
-- add ``file`` and ``line`` attributes to JUnit-XML output.
-
-- fix issue890: changed extension of all documentation files from ``txt`` to
- ``rst``. Thanks to Abhijeet for the PR.
-
-- fix issue714: add ability to apply indirect=True parameter on particular argnames.
- Thanks Elizaveta239.
-
-- fix issue890: changed extension of all documentation files from ``txt`` to
- ``rst``. Thanks to Abhijeet for the PR.
-
-- fix issue957: "# doctest: SKIP" option will now register doctests as SKIPPED
- rather than PASSED.
- Thanks Thomas Grainger for the report and Bruno Oliveira for the PR.
-
-- issue951: add new record_xml_property fixture, that supports logging
- additional information on xml output. Thanks David Diaz for the PR.
-
-- issue949: paths after normal options (for example ``-s``, ``-v``, etc) are now
- properly used to discover ``rootdir`` and ``ini`` files.
- Thanks Peter Lauri for the report and Bruno Oliveira for the PR.
-
-2.7.3 (compared to 2.7.2)
-=============================
-
-- Allow 'dev', 'rc', or other non-integer version strings in ``importorskip``.
- Thanks to Eric Hunsberger for the PR.
-
-- fix issue856: consider --color parameter in all outputs (for example
- --fixtures). Thanks Barney Gale for the report and Bruno Oliveira for the PR.
-
-- fix issue855: passing str objects as ``plugins`` argument to pytest.main
- is now interpreted as a module name to be imported and registered as a
- plugin, instead of silently having no effect.
- Thanks xmo-odoo for the report and Bruno Oliveira for the PR.
-
-- fix issue744: fix for ast.Call changes in Python 3.5+. Thanks
- Guido van Rossum, Matthias Bussonnier, Stefan Zimmermann and
- Thomas Kluyver.
-
-- fix issue842: applying markers in classes no longer propagate this markers
- to superclasses which also have markers.
- Thanks xmo-odoo for the report and Bruno Oliveira for the PR.
-
-- preserve warning functions after call to pytest.deprecated_call. Thanks
- Pieter Mulder for PR.
-
-- fix issue854: autouse yield_fixtures defined as class members of
- unittest.TestCase subclasses now work as expected.
- Thannks xmo-odoo for the report and Bruno Oliveira for the PR.
-
-- fix issue833: --fixtures now shows all fixtures of collected test files, instead of just the
- fixtures declared on the first one.
- Thanks Florian Bruhin for reporting and Bruno Oliveira for the PR.
-
-- fix issue863: skipped tests now report the correct reason when a skip/xfail
- condition is met when using multiple markers.
- Thanks Raphael Pierzina for reporting and Bruno Oliveira for the PR.
-
-- optimized tmpdir fixture initialization, which should make test sessions
- faster (specially when using pytest-xdist). The only visible effect
- is that now pytest uses a subdirectory in the $TEMP directory for all
- directories created by this fixture (defaults to $TEMP/pytest-$USER).
- Thanks Bruno Oliveira for the PR.
-
-2.7.2 (compared to 2.7.1)
-=============================
-
-- fix issue767: pytest.raises value attribute does not contain the exception
- instance on Python 2.6. Thanks Eric Siegerman for providing the test
- case and Bruno Oliveira for PR.
-
-- Automatically create directory for junitxml and results log.
- Thanks Aron Curzon.
-
-- fix issue713: JUnit XML reports for doctest failures.
- Thanks Punyashloka Biswal.
-
-- fix issue735: assertion failures on debug versions of Python 3.4+
- Thanks Benjamin Peterson.
-
-- fix issue114: skipif marker reports to internal skipping plugin;
- Thanks Floris Bruynooghe for reporting and Bruno Oliveira for the PR.
-
-- fix issue748: unittest.SkipTest reports to internal pytest unittest plugin.
- Thanks Thomas De Schampheleire for reporting and Bruno Oliveira for the PR.
-
-- fix issue718: failed to create representation of sets containing unsortable
- elements in python 2. Thanks Edison Gustavo Muenz.
-
-- fix issue756, fix issue752 (and similar issues): depend on py-1.4.29
- which has a refined algorithm for traceback generation.
-
-
-2.7.1 (compared to 2.7.0)
-=============================
-
-- fix issue731: do not get confused by the braces which may be present
- and unbalanced in an object's repr while collapsing False
- explanations. Thanks Carl Meyer for the report and test case.
-
-- fix issue553: properly handling inspect.getsourcelines failures in
- FixtureLookupError which would lead to to an internal error,
- obfuscating the original problem. Thanks talljosh for initial
- diagnose/patch and Bruno Oliveira for final patch.
-
-- fix issue660: properly report scope-mismatch-access errors
- independently from ordering of fixture arguments. Also
- avoid the pytest internal traceback which does not provide
- information to the user. Thanks Holger Krekel.
-
-- streamlined and documented release process. Also all versions
- (in setup.py and documentation generation) are now read
- from _pytest/__init__.py. Thanks Holger Krekel.
-
-- fixed docs to remove the notion that yield-fixtures are experimental.
- They are here to stay :) Thanks Bruno Oliveira.
-
-- Support building wheels by using environment markers for the
- requirements. Thanks Ionel Maries Cristian.
-
-- fixed regression to 2.6.4 which surfaced e.g. in lost stdout capture printing
- when tests raised SystemExit. Thanks Holger Krekel.
-
-- reintroduced _pytest fixture of the pytester plugin which is used
- at least by pytest-xdist.
-
-2.7.0 (compared to 2.6.4)
-=============================
-
-- fix issue435: make reload() work when assert rewriting is active.
- Thanks Daniel Hahler.
-
-- fix issue616: conftest.py files and their contained fixutres are now
- properly considered for visibility, independently from the exact
- current working directory and test arguments that are used.
- Many thanks to Eric Siegerman and his PR235 which contains
- systematic tests for conftest visibility and now passes.
- This change also introduces the concept of a ``rootdir`` which
- is printed as a new pytest header and documented in the pytest
- customize web page.
-
-- change reporting of "diverted" tests, i.e. tests that are collected
- in one file but actually come from another (e.g. when tests in a test class
- come from a base class in a different file). We now show the nodeid
- and indicate via a postfix the other file.
-
-- add ability to set command line options by environment variable PYTEST_ADDOPTS.
-
-- added documentation on the new pytest-dev teams on bitbucket and
- github. See https://pytest.org/latest/contributing.html .
- Thanks to Anatoly for pushing and initial work on this.
-
-- fix issue650: new option ``--docttest-ignore-import-errors`` which
- will turn import errors in doctests into skips. Thanks Charles Cloud
- for the complete PR.
-
-- fix issue655: work around different ways that cause python2/3
- to leak sys.exc_info into fixtures/tests causing failures in 3rd party code
-
-- fix issue615: assertion re-writing did not correctly escape % signs
- when formatting boolean operations, which tripped over mixing
- booleans with modulo operators. Thanks to Tom Viner for the report,
- triaging and fix.
-
-- implement issue351: add ability to specify parametrize ids as a callable
- to generate custom test ids. Thanks Brianna Laugher for the idea and
- implementation.
-
-- introduce and document new hookwrapper mechanism useful for plugins
- which want to wrap the execution of certain hooks for their purposes.
- This supersedes the undocumented ``__multicall__`` protocol which
- pytest itself and some external plugins use. Note that pytest-2.8
- is scheduled to drop supporting the old ``__multicall__``
- and only support the hookwrapper protocol.
-
-- majorly speed up invocation of plugin hooks
-
-- use hookwrapper mechanism in builtin pytest plugins.
-
-- add a doctest ini option for doctest flags, thanks Holger Peters.
-
-- add note to docs that if you want to mark a parameter and the
- parameter is a callable, you also need to pass in a reason to disambiguate
- it from the "decorator" case. Thanks Tom Viner.
-
-- "python_classes" and "python_functions" options now support glob-patterns
- for test discovery, as discussed in issue600. Thanks Ldiary Translations.
-
-- allow to override parametrized fixtures with non-parametrized ones and vice versa (bubenkoff).
-
-- fix issue463: raise specific error for 'parameterize' misspelling (pfctdayelise).
-
-- On failure, the ``sys.last_value``, ``sys.last_type`` and
- ``sys.last_traceback`` are set, so that a user can inspect the error
- via postmortem debugging (almarklein).
-
-2.6.4
-=====
-
-- Improve assertion failure reporting on iterables, by using ndiff and
- pprint.
-
-- removed outdated japanese docs from source tree.
-
-- docs for "pytest_addhooks" hook. Thanks Bruno Oliveira.
-
-- updated plugin index docs. Thanks Bruno Oliveira.
-
-- fix issue557: with "-k" we only allow the old style "-" for negation
- at the beginning of strings and even that is deprecated. Use "not" instead.
- This should allow to pick parametrized tests where "-" appeared in the parameter.
-
-- fix issue604: Escape % character in the assertion message.
-
-- fix issue620: add explanation in the --genscript target about what
- the binary blob means. Thanks Dinu Gherman.
-
-- fix issue614: fixed pastebin support.
-
-
-- fix issue620: add explanation in the --genscript target about what
- the binary blob means. Thanks Dinu Gherman.
-
-- fix issue614: fixed pastebin support.
-
-2.6.3
-=====
-
-- fix issue575: xunit-xml was reporting collection errors as failures
- instead of errors, thanks Oleg Sinyavskiy.
-
-- fix issue582: fix setuptools example, thanks Laszlo Papp and Ronny
- Pfannschmidt.
-
-- Fix infinite recursion bug when pickling capture.EncodedFile, thanks
- Uwe Schmitt.
-
-- fix issue589: fix bad interaction with numpy and others when showing
- exceptions. Check for precise "maximum recursion depth exceed" exception
- instead of presuming any RuntimeError is that one (implemented in py
- dep). Thanks Charles Cloud for analysing the issue.
-
-- fix conftest related fixture visibility issue: when running with a
- CWD outside a test package pytest would get fixture discovery wrong.
- Thanks to Wolfgang Schnerring for figuring out a reproducable example.
-
-- Introduce pytest_enter_pdb hook (needed e.g. by pytest_timeout to cancel the
- timeout when interactively entering pdb). Thanks Wolfgang Schnerring.
-
-- check xfail/skip also with non-python function test items. Thanks
- Floris Bruynooghe.
-
-2.6.2
-=====
-
-- Added function pytest.freeze_includes(), which makes it easy to embed
- pytest into executables using tools like cx_freeze.
- See docs for examples and rationale. Thanks Bruno Oliveira.
-
-- Improve assertion rewriting cache invalidation precision.
-
-- fixed issue561: adapt autouse fixture example for python3.
-
-- fixed issue453: assertion rewriting issue with __repr__ containing
- "\n{", "\n}" and "\n~".
-
-- fix issue560: correctly display code if an "else:" or "finally:" is
- followed by statements on the same line.
-
-- Fix example in monkeypatch documentation, thanks t-8ch.
-
-- fix issue572: correct tmpdir doc example for python3.
-
-- Do not mark as universal wheel because Python 2.6 is different from
- other builds due to the extra argparse dependency. Fixes issue566.
- Thanks sontek.
-
-- Implement issue549: user-provided assertion messages now no longer
- replace the py.test introspection message but are shown in addition
- to them.
-
-2.6.1
-=====
-
-- No longer show line numbers in the --verbose output, the output is now
- purely the nodeid. The line number is still shown in failure reports.
- Thanks Floris Bruynooghe.
-
-- fix issue437 where assertion rewriting could cause pytest-xdist slaves
- to collect different tests. Thanks Bruno Oliveira.
-
-- fix issue555: add "errors" attribute to capture-streams to satisfy
- some distutils and possibly other code accessing sys.stdout.errors.
-
-- fix issue547 capsys/capfd also work when output capturing ("-s") is disabled.
-
-- address issue170: allow pytest.mark.xfail(...) to specify expected exceptions via
- an optional "raises=EXC" argument where EXC can be a single exception
- or a tuple of exception classes. Thanks David Mohr for the complete
- PR.
-
-- fix integration of pytest with unittest.mock.patch decorator when
- it uses the "new" argument. Thanks Nicolas Delaby for test and PR.
-
-- fix issue with detecting conftest files if the arguments contain
- "::" node id specifications (copy pasted from "-v" output)
-
-- fix issue544 by only removing "@NUM" at the end of "::" separated parts
- and if the part has an ".py" extension
-
-- don't use py.std import helper, rather import things directly.
- Thanks Bruno Oliveira.
-
-2.6
-===
-
-- Cache exceptions from fixtures according to their scope (issue 467).
-
-- fix issue537: Avoid importing old assertion reinterpretation code by default.
-
-- fix issue364: shorten and enhance tracebacks representation by default.
- The new "--tb=auto" option (default) will only display long tracebacks
- for the first and last entry. You can get the old behaviour of printing
- all entries as long entries with "--tb=long". Also short entries by
- default are now printed very similarly to "--tb=native" ones.
-
-- fix issue514: teach assertion reinterpretation about private class attributes
-
-- change -v output to include full node IDs of tests. Users can copy
- a node ID from a test run, including line number, and use it as a
- positional argument in order to run only a single test.
-
-- fix issue 475: fail early and comprehensible if calling
- pytest.raises with wrong exception type.
-
-- fix issue516: tell in getting-started about current dependencies.
-
-- cleanup setup.py a bit and specify supported versions. Thanks Jurko
- Gospodnetic for the PR.
-
-- change XPASS colour to yellow rather then red when tests are run
- with -v.
-
-- fix issue473: work around mock putting an unbound method into a class
- dict when double-patching.
-
-- fix issue498: if a fixture finalizer fails, make sure that
- the fixture is still invalidated.
-
-- fix issue453: the result of the pytest_assertrepr_compare hook now gets
- it's newlines escaped so that format_exception does not blow up.
-
-- internal new warning system: pytest will now produce warnings when
- it detects oddities in your test collection or execution.
- Warnings are ultimately sent to a new pytest_logwarning hook which is
- currently only implemented by the terminal plugin which displays
- warnings in the summary line and shows more details when -rw (report on
- warnings) is specified.
-
-- change skips into warnings for test classes with an __init__ and
- callables in test modules which look like a test but are not functions.
-
-- fix issue436: improved finding of initial conftest files from command
- line arguments by using the result of parse_known_args rather than
- the previous flaky heuristics. Thanks Marc Abramowitz for tests
- and initial fixing approaches in this area.
-
-- fix issue #479: properly handle nose/unittest(2) SkipTest exceptions
- during collection/loading of test modules. Thanks to Marc Schlaich
- for the complete PR.
-
-- fix issue490: include pytest_load_initial_conftests in documentation
- and improve docstring.
-
-- fix issue472: clarify that ``pytest.config.getvalue()`` cannot work
- if it's triggered ahead of command line parsing.
-
-- merge PR123: improved integration with mock.patch decorator on tests.
-
-- fix issue412: messing with stdout/stderr FD-level streams is now
- captured without crashes.
-
-- fix issue483: trial/py33 works now properly. Thanks Daniel Grana for PR.
-
-- improve example for pytest integration with "python setup.py test"
- which now has a generic "-a" or "--pytest-args" option where you
- can pass additional options as a quoted string. Thanks Trevor Bekolay.
-
-- simplified internal capturing mechanism and made it more robust
- against tests or setups changing FD1/FD2, also better integrated
- now with pytest.pdb() in single tests.
-
-- improvements to pytest's own test-suite leakage detection, courtesy of PRs
- from Marc Abramowitz
-
-- fix issue492: avoid leak in test_writeorg. Thanks Marc Abramowitz.
-
-- fix issue493: don't run tests in doc directory with ``python setup.py test``
- (use tox -e doctesting for that)
-
-- fix issue486: better reporting and handling of early conftest loading failures
-
-- some cleanup and simplification of internal conftest handling.
-
-- work a bit harder to break reference cycles when catching exceptions.
- Thanks Jurko Gospodnetic.
-
-- fix issue443: fix skip examples to use proper comparison. Thanks Alex
- Groenholm.
-
-- support nose-style ``__test__`` attribute on modules, classes and
- functions, including unittest-style Classes. If set to False, the
- test will not be collected.
-
-- fix issue512: show "<notset>" for arguments which might not be set
- in monkeypatch plugin. Improves output in documentation.
-
-
-2.5.2
-=====
-
-- fix issue409 -- better interoperate with cx_freeze by not
- trying to import from collections.abc which causes problems
- for py27/cx_freeze. Thanks Wolfgang L. for reporting and tracking it down.
-
-- fixed docs and code to use "pytest" instead of "py.test" almost everywhere.
- Thanks Jurko Gospodnetic for the complete PR.
-
-- fix issue425: mention at end of "py.test -h" that --markers
- and --fixtures work according to specified test path (or current dir)
-
-- fix issue413: exceptions with unicode attributes are now printed
- correctly also on python2 and with pytest-xdist runs. (the fix
- requires py-1.4.20)
-
-- copy, cleanup and integrate py.io capture
- from pylib 1.4.20.dev2 (rev 13d9af95547e)
-
-- address issue416: clarify docs as to conftest.py loading semantics
-
-- fix issue429: comparing byte strings with non-ascii chars in assert
- expressions now work better. Thanks Floris Bruynooghe.
-
-- make capfd/capsys.capture private, its unused and shouldnt be exposed
-
-
-2.5.1
-=====
-
-- merge new documentation styling PR from Tobias Bieniek.
-
-- fix issue403: allow parametrize of multiple same-name functions within
- a collection node. Thanks Andreas Kloeckner and Alex Gaynor for reporting
- and analysis.
-
-- Allow parameterized fixtures to specify the ID of the parameters by
- adding an ids argument to pytest.fixture() and pytest.yield_fixture().
- Thanks Floris Bruynooghe.
-
-- fix issue404 by always using the binary xml escape in the junitxml
- plugin. Thanks Ronny Pfannschmidt.
-
-- fix issue407: fix addoption docstring to point to argparse instead of
- optparse. Thanks Daniel D. Wright.
-
-
-
-2.5.0
-=====
-
-- dropped python2.5 from automated release testing of pytest itself
- which means it's probably going to break soon (but still works
- with this release we believe).
-
-- simplified and fixed implementation for calling finalizers when
- parametrized fixtures or function arguments are involved. finalization
- is now performed lazily at setup time instead of in the "teardown phase".
- While this might sound odd at first, it helps to ensure that we are
- correctly handling setup/teardown even in complex code. User-level code
- should not be affected unless it's implementing the pytest_runtest_teardown
- hook and expecting certain fixture instances are torn down within (very
- unlikely and would have been unreliable anyway).
-
-- PR90: add --color=yes|no|auto option to force terminal coloring
- mode ("auto" is default). Thanks Marc Abramowitz.
-
-- fix issue319 - correctly show unicode in assertion errors. Many
- thanks to Floris Bruynooghe for the complete PR. Also means
- we depend on py>=1.4.19 now.
-
-- fix issue396 - correctly sort and finalize class-scoped parametrized
- tests independently from number of methods on the class.
-
-- refix issue323 in a better way -- parametrization should now never
- cause Runtime Recursion errors because the underlying algorithm
- for re-ordering tests per-scope/per-fixture is not recursive
- anymore (it was tail-call recursive before which could lead
- to problems for more than >966 non-function scoped parameters).
-
-- fix issue290 - there is preliminary support now for parametrizing
- with repeated same values (sometimes useful to to test if calling
- a second time works as with the first time).
-
-- close issue240 - document precisely how pytest module importing
- works, discuss the two common test directory layouts, and how it
- interacts with PEP420-namespace packages.
-
-- fix issue246 fix finalizer order to be LIFO on independent fixtures
- depending on a parametrized higher-than-function scoped fixture.
- (was quite some effort so please bear with the complexity of this sentence :)
- Thanks Ralph Schmitt for the precise failure example.
-
-- fix issue244 by implementing special index for parameters to only use
- indices for paramentrized test ids
-
-- fix issue287 by running all finalizers but saving the exception
- from the first failing finalizer and re-raising it so teardown will
- still have failed. We reraise the first failing exception because
- it might be the cause for other finalizers to fail.
-
-- fix ordering when mock.patch or other standard decorator-wrappings
- are used with test methods. This fixues issue346 and should
- help with random "xdist" collection failures. Thanks to
- Ronny Pfannschmidt and Donald Stufft for helping to isolate it.
-
-- fix issue357 - special case "-k" expressions to allow for
- filtering with simple strings that are not valid python expressions.
- Examples: "-k 1.3" matches all tests parametrized with 1.3.
- "-k None" filters all tests that have "None" in their name
- and conversely "-k 'not None'".
- Previously these examples would raise syntax errors.
-
-- fix issue384 by removing the trial support code
- since the unittest compat enhancements allow
- trial to handle it on its own
-
-- don't hide an ImportError when importing a plugin produces one.
- fixes issue375.
-
-- fix issue275 - allow usefixtures and autouse fixtures
- for running doctest text files.
-
-- fix issue380 by making --resultlog only rely on longrepr instead
- of the "reprcrash" attribute which only exists sometimes.
-
-- address issue122: allow @pytest.fixture(params=iterator) by exploding
- into a list early on.
-
-- fix pexpect-3.0 compatibility for pytest's own tests.
- (fixes issue386)
-
-- allow nested parametrize-value markers, thanks James Lan for the PR.
-
-- fix unicode handling with new monkeypatch.setattr(import_path, value)
- API. Thanks Rob Dennis. Fixes issue371.
-
-- fix unicode handling with junitxml, fixes issue368.
-
-- In assertion rewriting mode on Python 2, fix the detection of coding
- cookies. See issue #330.
-
-- make "--runxfail" turn imperative pytest.xfail calls into no ops
- (it already did neutralize pytest.mark.xfail markers)
-
-- refine pytest / pkg_resources interactions: The AssertionRewritingHook
- PEP302 compliant loader now registers itself with setuptools/pkg_resources
- properly so that the pkg_resources.resource_stream method works properly.
- Fixes issue366. Thanks for the investigations and full PR to Jason R. Coombs.
-
-- pytestconfig fixture is now session-scoped as it is the same object during the
- whole test run. Fixes issue370.
-
-- avoid one surprising case of marker malfunction/confusion::
-
- @pytest.mark.some(lambda arg: ...)
- def test_function():
-
- would not work correctly because pytest assumes @pytest.mark.some
- gets a function to be decorated already. We now at least detect if this
- arg is an lambda and thus the example will work. Thanks Alex Gaynor
- for bringing it up.
-
-- xfail a test on pypy that checks wrong encoding/ascii (pypy does
- not error out). fixes issue385.
-
-- internally make varnames() deal with classes's __init__,
- although it's not needed by pytest itself atm. Also
- fix caching. Fixes issue376.
-
-- fix issue221 - handle importing of namespace-package with no
- __init__.py properly.
-
-- refactor internal FixtureRequest handling to avoid monkeypatching.
- One of the positive user-facing effects is that the "request" object
- can now be used in closures.
-
-- fixed version comparison in pytest.importskip(modname, minverstring)
-
-- fix issue377 by clarifying in the nose-compat docs that pytest
- does not duplicate the unittest-API into the "plain" namespace.
-
-- fix verbose reporting for @mock'd test functions
-
-2.4.2
-=====
-
-- on Windows require colorama and a newer py lib so that py.io.TerminalWriter()
- now uses colorama instead of its own ctypes hacks. (fixes issue365)
- thanks Paul Moore for bringing it up.
-
-- fix "-k" matching of tests where "repr" and "attr" and other names would
- cause wrong matches because of an internal implementation quirk
- (don't ask) which is now properly implemented. fixes issue345.
-
-- avoid tmpdir fixture to create too long filenames especially
- when parametrization is used (issue354)
-
-- fix pytest-pep8 and pytest-flakes / pytest interactions
- (collection names in mark plugin was assuming an item always
- has a function which is not true for those plugins etc.)
- Thanks Andi Zeidler.
-
-- introduce node.get_marker/node.add_marker API for plugins
- like pytest-pep8 and pytest-flakes to avoid the messy
- details of the node.keywords pseudo-dicts. Adapted
- docs.
-
-- remove attempt to "dup" stdout at startup as it's icky.
- the normal capturing should catch enough possibilities
- of tests messing up standard FDs.
-
-- add pluginmanager.do_configure(config) as a link to
- config.do_configure() for plugin-compatibility
-
-2.4.1
-=====
-
-- When using parser.addoption() unicode arguments to the
- "type" keyword should also be converted to the respective types.
- thanks Floris Bruynooghe, @dnozay. (fixes issue360 and issue362)
-
-- fix dotted filename completion when using argcomplete
- thanks Anthon van der Neuth. (fixes issue361)
-
-- fix regression when a 1-tuple ("arg",) is used for specifying
- parametrization (the values of the parametrization were passed
- nested in a tuple). Thanks Donald Stufft.
-
-- merge doc typo fixes, thanks Andy Dirnberger
-
-2.4
-===
-
-known incompatibilities:
-
-- if calling --genscript from python2.7 or above, you only get a
- standalone script which works on python2.7 or above. Use Python2.6
- to also get a python2.5 compatible version.
-
-- all xunit-style teardown methods (nose-style, pytest-style,
- unittest-style) will not be called if the corresponding setup method failed,
- see issue322 below.
-
-- the pytest_plugin_unregister hook wasn't ever properly called
- and there is no known implementation of the hook - so it got removed.
-
-- pytest.fixture-decorated functions cannot be generators (i.e. use
- yield) anymore. This change might be reversed in 2.4.1 if it causes
- unforeseen real-life issues. However, you can always write and return
- an inner function/generator and change the fixture consumer to iterate
- over the returned generator. This change was done in lieu of the new
- ``pytest.yield_fixture`` decorator, see below.
-
-new features:
-
-- experimentally introduce a new ``pytest.yield_fixture`` decorator
- which accepts exactly the same parameters as pytest.fixture but
- mandates a ``yield`` statement instead of a ``return statement`` from
- fixture functions. This allows direct integration with "with-style"
- context managers in fixture functions and generally avoids registering
- of finalization callbacks in favour of treating the "after-yield" as
- teardown code. Thanks Andreas Pelme, Vladimir Keleshev, Floris
- Bruynooghe, Ronny Pfannschmidt and many others for discussions.
-
-- allow boolean expression directly with skipif/xfail
- if a "reason" is also specified. Rework skipping documentation
- to recommend "condition as booleans" because it prevents surprises
- when importing markers between modules. Specifying conditions
- as strings will remain fully supported.
-
-- reporting: color the last line red or green depending if
- failures/errors occurred or everything passed. thanks Christian
- Theunert.
-
-- make "import pdb ; pdb.set_trace()" work natively wrt capturing (no
- "-s" needed anymore), making ``pytest.set_trace()`` a mere shortcut.
-
-- fix issue181: --pdb now also works on collect errors (and
- on internal errors) . This was implemented by a slight internal
- refactoring and the introduction of a new hook
- ``pytest_exception_interact`` hook (see next item).
-
-- fix issue341: introduce new experimental hook for IDEs/terminals to
- intercept debugging: ``pytest_exception_interact(node, call, report)``.
-
-- new monkeypatch.setattr() variant to provide a shorter
- invocation for patching out classes/functions from modules:
-
- monkeypatch.setattr("requests.get", myfunc)
-
- will replace the "get" function of the "requests" module with ``myfunc``.
-
-- fix issue322: tearDownClass is not run if setUpClass failed. Thanks
- Mathieu Agopian for the initial fix. Also make all of pytest/nose
- finalizer mimick the same generic behaviour: if a setupX exists and
- fails, don't run teardownX. This internally introduces a new method
- "node.addfinalizer()" helper which can only be called during the setup
- phase of a node.
-
-- simplify pytest.mark.parametrize() signature: allow to pass a
- CSV-separated string to specify argnames. For example:
- ``pytest.mark.parametrize("input,expected", [(1,2), (2,3)])``
- works as well as the previous:
- ``pytest.mark.parametrize(("input", "expected"), ...)``.
-
-- add support for setUpModule/tearDownModule detection, thanks Brian Okken.
-
-- integrate tab-completion on options through use of "argcomplete".
- Thanks Anthon van der Neut for the PR.
-
-- change option names to be hyphen-separated long options but keep the
- old spelling backward compatible. py.test -h will only show the
- hyphenated version, for example "--collect-only" but "--collectonly"
- will remain valid as well (for backward-compat reasons). Many thanks to
- Anthon van der Neut for the implementation and to Hynek Schlawack for
- pushing us.
-
-- fix issue 308 - allow to mark/xfail/skip individual parameter sets
- when parametrizing. Thanks Brianna Laugher.
-
-- call new experimental pytest_load_initial_conftests hook to allow
- 3rd party plugins to do something before a conftest is loaded.
-
-Bug fixes:
-
-- fix issue358 - capturing options are now parsed more properly
- by using a new parser.parse_known_args method.
-
-- pytest now uses argparse instead of optparse (thanks Anthon) which
- means that "argparse" is added as a dependency if installing into python2.6
- environments or below.
-
-- fix issue333: fix a case of bad unittest/pytest hook interaction.
-
-- PR27: correctly handle nose.SkipTest during collection. Thanks
- Antonio Cuni, Ronny Pfannschmidt.
-
-- fix issue355: junitxml puts name="pytest" attribute to testsuite tag.
-
-- fix issue336: autouse fixture in plugins should work again.
-
-- fix issue279: improve object comparisons on assertion failure
- for standard datatypes and recognise collections.abc. Thanks to
- Brianna Laugher and Mathieu Agopian.
-
-- fix issue317: assertion rewriter support for the is_package method
-
-- fix issue335: document py.code.ExceptionInfo() object returned
- from pytest.raises(), thanks Mathieu Agopian.
-
-- remove implicit distribute_setup support from setup.py.
-
-- fix issue305: ignore any problems when writing pyc files.
-
-- SO-17664702: call fixture finalizers even if the fixture function
- partially failed (finalizers would not always be called before)
-
-- fix issue320 - fix class scope for fixtures when mixed with
- module-level functions. Thanks Anatloy Bubenkoff.
-
-- you can specify "-q" or "-qq" to get different levels of "quieter"
- reporting (thanks Katarzyna Jachim)
-
-- fix issue300 - Fix order of conftest loading when starting py.test
- in a subdirectory.
-
-- fix issue323 - sorting of many module-scoped arg parametrizations
-
-- make sessionfinish hooks execute with the same cwd-context as at
- session start (helps fix plugin behaviour which write output files
- with relative path such as pytest-cov)
-
-- fix issue316 - properly reference collection hooks in docs
-
-- fix issue 306 - cleanup of -k/-m options to only match markers/test
- names/keywords respectively. Thanks Wouter van Ackooy.
-
-- improved doctest counting for doctests in python modules --
- files without any doctest items will not show up anymore
- and doctest examples are counted as separate test items.
- thanks Danilo Bellini.
-
-- fix issue245 by depending on the released py-1.4.14
- which fixes py.io.dupfile to work with files with no
- mode. Thanks Jason R. Coombs.
-
-- fix junitxml generation when test output contains control characters,
- addressing issue267, thanks Jaap Broekhuizen
-
-- fix issue338: honor --tb style for setup/teardown errors as well. Thanks Maho.
-
-- fix issue307 - use yaml.safe_load in example, thanks Mark Eichin.
-
-- better parametrize error messages, thanks Brianna Laugher
-
-- pytest_terminal_summary(terminalreporter) hooks can now use
- ".section(title)" and ".line(msg)" methods to print extra
- information at the end of a test run.
-
-2.3.5
-=====
-
-- fix issue169: respect --tb=style with setup/teardown errors as well.
-
-- never consider a fixture function for test function collection
-
-- allow re-running of test items / helps to fix pytest-reruntests plugin
- and also help to keep less fixture/resource references alive
-
-- put captured stdout/stderr into junitxml output even for passing tests
- (thanks Adam Goucher)
-
-- Issue 265 - integrate nose setup/teardown with setupstate
- so it doesnt try to teardown if it did not setup
-
-- issue 271 - dont write junitxml on slave nodes
-
-- Issue 274 - dont try to show full doctest example
- when doctest does not know the example location
-
-- issue 280 - disable assertion rewriting on buggy CPython 2.6.0
-
-- inject "getfixture()" helper to retrieve fixtures from doctests,
- thanks Andreas Zeidler
-
-- issue 259 - when assertion rewriting, be consistent with the default
- source encoding of ASCII on Python 2
-
-- issue 251 - report a skip instead of ignoring classes with init
-
-- issue250 unicode/str mixes in parametrization names and values now works
-
-- issue257, assertion-triggered compilation of source ending in a
- comment line doesn't blow up in python2.5 (fixed through py>=1.4.13.dev6)
-
-- fix --genscript option to generate standalone scripts that also
- work with python3.3 (importer ordering)
-
-- issue171 - in assertion rewriting, show the repr of some
- global variables
-
-- fix option help for "-k"
-
-- move long description of distribution into README.rst
-
-- improve docstring for metafunc.parametrize()
-
-- fix bug where using capsys with pytest.set_trace() in a test
- function would break when looking at capsys.readouterr()
-
-- allow to specify prefixes starting with "_" when
- customizing python_functions test discovery. (thanks Graham Horler)
-
-- improve PYTEST_DEBUG tracing output by puting
- extra data on a new lines with additional indent
-
-- ensure OutcomeExceptions like skip/fail have initialized exception attributes
-
-- issue 260 - don't use nose special setup on plain unittest cases
-
-- fix issue134 - print the collect errors that prevent running specified test items
-
-- fix issue266 - accept unicode in MarkEvaluator expressions
-
-2.3.4
-=====
-
-- yielded test functions will now have autouse-fixtures active but
- cannot accept fixtures as funcargs - it's anyway recommended to
- rather use the post-2.0 parametrize features instead of yield, see:
- http://pytest.org/latest/example/parametrize.html
-- fix autouse-issue where autouse-fixtures would not be discovered
- if defined in a a/conftest.py file and tests in a/tests/test_some.py
-- fix issue226 - LIFO ordering for fixture teardowns
-- fix issue224 - invocations with >256 char arguments now work
-- fix issue91 - add/discuss package/directory level setups in example
-- allow to dynamically define markers via
- item.keywords[...]=assignment integrating with "-m" option
-- make "-k" accept an expressions the same as with "-m" so that one
- can write: -k "name1 or name2" etc. This is a slight incompatibility
- if you used special syntax like "TestClass.test_method" which you now
- need to write as -k "TestClass and test_method" to match a certain
- method in a certain test class.
-
-2.3.3
-=====
-
-- fix issue214 - parse modules that contain special objects like e. g.
- flask's request object which blows up on getattr access if no request
- is active. thanks Thomas Waldmann.
-
-- fix issue213 - allow to parametrize with values like numpy arrays that
- do not support an __eq__ operator
-
-- fix issue215 - split test_python.org into multiple files
-
-- fix issue148 - @unittest.skip on classes is now recognized and avoids
- calling setUpClass/tearDownClass, thanks Pavel Repin
-
-- fix issue209 - reintroduce python2.4 support by depending on newer
- pylib which re-introduced statement-finding for pre-AST interpreters
-
-- nose support: only call setup if its a callable, thanks Andrew
- Taumoefolau
-
-- fix issue219 - add py2.4-3.3 classifiers to TROVE list
-
-- in tracebacks *,** arg values are now shown next to normal arguments
- (thanks Manuel Jacob)
-
-- fix issue217 - support mock.patch with pytest's fixtures - note that
- you need either mock-1.0.1 or the python3.3 builtin unittest.mock.
-
-- fix issue127 - improve documentation for pytest_addoption() and
- add a ``config.getoption(name)`` helper function for consistency.
-
-2.3.2
-=====
-
-- fix issue208 and fix issue29 use new py version to avoid long pauses
- when printing tracebacks in long modules
-
-- fix issue205 - conftests in subdirs customizing
- pytest_pycollect_makemodule and pytest_pycollect_makeitem
- now work properly
-
-- fix teardown-ordering for parametrized setups
-
-- fix issue127 - better documentation for pytest_addoption
- and related objects.
-
-- fix unittest behaviour: TestCase.runtest only called if there are
- test methods defined
-
-- improve trial support: don't collect its empty
- unittest.TestCase.runTest() method
-
-- "python setup.py test" now works with pytest itself
-
-- fix/improve internal/packaging related bits:
-
- - exception message check of test_nose.py now passes on python33 as well
-
- - issue206 - fix test_assertrewrite.py to work when a global
- PYTHONDONTWRITEBYTECODE=1 is present
-
- - add tox.ini to pytest distribution so that ignore-dirs and others config
- bits are properly distributed for maintainers who run pytest-own tests
-
-2.3.1
-=====
-
-- fix issue202 - fix regression: using "self" from fixture functions now
- works as expected (it's the same "self" instance that a test method
- which uses the fixture sees)
-
-- skip pexpect using tests (test_pdb.py mostly) on freebsd* systems
- due to pexpect not supporting it properly (hanging)
-
-- link to web pages from --markers output which provides help for
- pytest.mark.* usage.
-
-2.3.0
-=====
-
-- fix issue202 - better automatic names for parametrized test functions
-- fix issue139 - introduce @pytest.fixture which allows direct scoping
- and parametrization of funcarg factories.
-- fix issue198 - conftest fixtures were not found on windows32 in some
- circumstances with nested directory structures due to path manipulation issues
-- fix issue193 skip test functions with were parametrized with empty
- parameter sets
-- fix python3.3 compat, mostly reporting bits that previously depended
- on dict ordering
-- introduce re-ordering of tests by resource and parametrization setup
- which takes precedence to the usual file-ordering
-- fix issue185 monkeypatching time.time does not cause pytest to fail
-- fix issue172 duplicate call of pytest.fixture decoratored setup_module
- functions
-- fix junitxml=path construction so that if tests change the
- current working directory and the path is a relative path
- it is constructed correctly from the original current working dir.
-- fix "python setup.py test" example to cause a proper "errno" return
-- fix issue165 - fix broken doc links and mention stackoverflow for FAQ
-- catch unicode-issues when writing failure representations
- to terminal to prevent the whole session from crashing
-- fix xfail/skip confusion: a skip-mark or an imperative pytest.skip
- will now take precedence before xfail-markers because we
- can't determine xfail/xpass status in case of a skip. see also:
- http://stackoverflow.com/questions/11105828/in-py-test-when-i-explicitly-skip-a-test-that-is-marked-as-xfail-how-can-i-get
-
-- always report installed 3rd party plugins in the header of a test run
-
-- fix issue160: a failing setup of an xfail-marked tests should
- be reported as xfail (not xpass)
-
-- fix issue128: show captured output when capsys/capfd are used
-
-- fix issue179: propperly show the dependency chain of factories
-
-- pluginmanager.register(...) now raises ValueError if the
- plugin has been already registered or the name is taken
-
-- fix issue159: improve http://pytest.org/latest/faq.html
- especially with respect to the "magic" history, also mention
- pytest-django, trial and unittest integration.
-
-- make request.keywords and node.keywords writable. All descendant
- collection nodes will see keyword values. Keywords are dictionaries
- containing markers and other info.
-
-- fix issue 178: xml binary escapes are now wrapped in py.xml.raw
-
-- fix issue 176: correctly catch the builtin AssertionError
- even when we replaced AssertionError with a subclass on the
- python level
-
-- factory discovery no longer fails with magic global callables
- that provide no sane __code__ object (mock.call for example)
-
-- fix issue 182: testdir.inprocess_run now considers passed plugins
-
-- fix issue 188: ensure sys.exc_info is clear on python2
- before calling into a test
-
-- fix issue 191: add unittest TestCase runTest method support
-- fix issue 156: monkeypatch correctly handles class level descriptors
-
-- reporting refinements:
-
- - pytest_report_header now receives a "startdir" so that
- you can use startdir.bestrelpath(yourpath) to show
- nice relative path
-
- - allow plugins to implement both pytest_report_header and
- pytest_sessionstart (sessionstart is invoked first).
-
- - don't show deselected reason line if there is none
-
- - py.test -vv will show all of assert comparisations instead of truncating
-
-2.2.4
-=====
-
-- fix error message for rewritten assertions involving the % operator
-- fix issue 126: correctly match all invalid xml characters for junitxml
- binary escape
-- fix issue with unittest: now @unittest.expectedFailure markers should
- be processed correctly (you can also use @pytest.mark markers)
-- document integration with the extended distribute/setuptools test commands
-- fix issue 140: propperly get the real functions
- of bound classmethods for setup/teardown_class
-- fix issue #141: switch from the deceased paste.pocoo.org to bpaste.net
-- fix issue #143: call unconfigure/sessionfinish always when
- configure/sessionstart where called
-- fix issue #144: better mangle test ids to junitxml classnames
-- upgrade distribute_setup.py to 0.6.27
-
-2.2.3
-=====
-
-- fix uploaded package to only include neccesary files
-
-2.2.2
-=====
-
-- fix issue101: wrong args to unittest.TestCase test function now
- produce better output
-- fix issue102: report more useful errors and hints for when a
- test directory was renamed and some pyc/__pycache__ remain
-- fix issue106: allow parametrize to be applied multiple times
- e.g. from module, class and at function level.
-- fix issue107: actually perform session scope finalization
-- don't check in parametrize if indirect parameters are funcarg names
-- add chdir method to monkeypatch funcarg
-- fix crash resulting from calling monkeypatch undo a second time
-- fix issue115: make --collectonly robust against early failure
- (missing files/directories)
-- "-qq --collectonly" now shows only files and the number of tests in them
-- "-q --collectonly" now shows test ids
-- allow adding of attributes to test reports such that it also works
- with distributed testing (no upgrade of pytest-xdist needed)
-
-2.2.1
-=====
-
-- fix issue99 (in pytest and py) internallerrors with resultlog now
- produce better output - fixed by normalizing pytest_internalerror
- input arguments.
-- fix issue97 / traceback issues (in pytest and py) improve traceback output
- in conjunction with jinja2 and cython which hack tracebacks
-- fix issue93 (in pytest and pytest-xdist) avoid "delayed teardowns":
- the final test in a test node will now run its teardown directly
- instead of waiting for the end of the session. Thanks Dave Hunt for
- the good reporting and feedback. The pytest_runtest_protocol as well
- as the pytest_runtest_teardown hooks now have "nextitem" available
- which will be None indicating the end of the test run.
-- fix collection crash due to unknown-source collected items, thanks
- to Ralf Schmitt (fixed by depending on a more recent pylib)
-
-2.2.0
-=====
-
-- fix issue90: introduce eager tearing down of test items so that
- teardown function are called earlier.
-- add an all-powerful metafunc.parametrize function which allows to
- parametrize test function arguments in multiple steps and therefore
- from indepdenent plugins and palces.
-- add a @pytest.mark.parametrize helper which allows to easily
- call a test function with different argument values
-- Add examples to the "parametrize" example page, including a quick port
- of Test scenarios and the new parametrize function and decorator.
-- introduce registration for "pytest.mark.*" helpers via ini-files
- or through plugin hooks. Also introduce a "--strict" option which
- will treat unregistered markers as errors
- allowing to avoid typos and maintain a well described set of markers
- for your test suite. See exaples at http://pytest.org/latest/mark.html
- and its links.
-- issue50: introduce "-m marker" option to select tests based on markers
- (this is a stricter and more predictable version of '-k' in that "-m"
- only matches complete markers and has more obvious rules for and/or
- semantics.
-- new feature to help optimizing the speed of your tests:
- --durations=N option for displaying N slowest test calls
- and setup/teardown methods.
-- fix issue87: --pastebin now works with python3
-- fix issue89: --pdb with unexpected exceptions in doctest work more sensibly
-- fix and cleanup pytest's own test suite to not leak FDs
-- fix issue83: link to generated funcarg list
-- fix issue74: pyarg module names are now checked against imp.find_module false positives
-- fix compatibility with twisted/trial-11.1.0 use cases
-- simplify Node.listchain
-- simplify junitxml output code by relying on py.xml
-- add support for skip properties on unittest classes and functions
-
-2.1.3
-=====
-
-- fix issue79: assertion rewriting failed on some comparisons in boolops
-- correctly handle zero length arguments (a la pytest '')
-- fix issue67 / junitxml now contains correct test durations, thanks ronny
-- fix issue75 / skipping test failure on jython
-- fix issue77 / Allow assertrepr_compare hook to apply to a subset of tests
-
-2.1.2
-=====
-
-- fix assertion rewriting on files with windows newlines on some Python versions
-- refine test discovery by package/module name (--pyargs), thanks Florian Mayer
-- fix issue69 / assertion rewriting fixed on some boolean operations
-- fix issue68 / packages now work with assertion rewriting
-- fix issue66: use different assertion rewriting caches when the -O option is passed
-- don't try assertion rewriting on Jython, use reinterp
-
-2.1.1
-=====
-
-- fix issue64 / pytest.set_trace now works within pytest_generate_tests hooks
-- fix issue60 / fix error conditions involving the creation of __pycache__
-- fix issue63 / assertion rewriting on inserts involving strings containing '%'
-- fix assertion rewriting on calls with a ** arg
-- don't cache rewritten modules if bytecode generation is disabled
-- fix assertion rewriting in read-only directories
-- fix issue59: provide system-out/err tags for junitxml output
-- fix issue61: assertion rewriting on boolean operations with 3 or more operands
-- you can now build a man page with "cd doc ; make man"
-
-2.1.0
-=====
-
-- fix issue53 call nosestyle setup functions with correct ordering
-- fix issue58 and issue59: new assertion code fixes
-- merge Benjamin's assertionrewrite branch: now assertions
- for test modules on python 2.6 and above are done by rewriting
- the AST and saving the pyc file before the test module is imported.
- see doc/assert.txt for more info.
-- fix issue43: improve doctests with better traceback reporting on
- unexpected exceptions
-- fix issue47: timing output in junitxml for test cases is now correct
-- fix issue48: typo in MarkInfo repr leading to exception
-- fix issue49: avoid confusing error when initizaliation partially fails
-- fix issue44: env/username expansion for junitxml file path
-- show releaselevel information in test runs for pypy
-- reworked doc pages for better navigation and PDF generation
-- report KeyboardInterrupt even if interrupted during session startup
-- fix issue 35 - provide PDF doc version and download link from index page
-
-2.0.3
-=====
-
-- fix issue38: nicer tracebacks on calls to hooks, particularly early
- configure/sessionstart ones
-
-- fix missing skip reason/meta information in junitxml files, reported
- via http://lists.idyll.org/pipermail/testing-in-python/2011-March/003928.html
-
-- fix issue34: avoid collection failure with "test" prefixed classes
- deriving from object.
-
-- don't require zlib (and other libs) for genscript plugin without
- --genscript actually being used.
-
-- speed up skips (by not doing a full traceback represenation
- internally)
-
-- fix issue37: avoid invalid characters in junitxml's output
-
-2.0.2
-=====
-
-- tackle issue32 - speed up test runs of very quick test functions
- by reducing the relative overhead
-
-- fix issue30 - extended xfail/skipif handling and improved reporting.
- If you have a syntax error in your skip/xfail
- expressions you now get nice error reports.
-
- Also you can now access module globals from xfail/skipif
- expressions so that this for example works now::
-
- import pytest
- import mymodule
- @pytest.mark.skipif("mymodule.__version__[0] == "1")
- def test_function():
- pass
-
- This will not run the test function if the module's version string
- does not start with a "1". Note that specifying a string instead
- of a boolean expressions allows py.test to report meaningful information
- when summarizing a test run as to what conditions lead to skipping
- (or xfail-ing) tests.
-
-- fix issue28 - setup_method and pytest_generate_tests work together
- The setup_method fixture method now gets called also for
- test function invocations generated from the pytest_generate_tests
- hook.
-
-- fix issue27 - collectonly and keyword-selection (-k) now work together
- Also, if you do "py.test --collectonly -q" you now get a flat list
- of test ids that you can use to paste to the py.test commandline
- in order to execute a particular test.
-
-- fix issue25 avoid reported problems with --pdb and python3.2/encodings output
-
-- fix issue23 - tmpdir argument now works on Python3.2 and WindowsXP
- Starting with Python3.2 os.symlink may be supported. By requiring
- a newer py lib version the py.path.local() implementation acknowledges
- this.
-
-- fixed typos in the docs (thanks Victor Garcia, Brianna Laugher) and particular
- thanks to Laura Creighton who also revieved parts of the documentation.
-
-- fix slighly wrong output of verbose progress reporting for classes
- (thanks Amaury)
-
-- more precise (avoiding of) deprecation warnings for node.Class|Function accesses
-
-- avoid std unittest assertion helper code in tracebacks (thanks Ronny)
-
-2.0.1
-=====
-
-- refine and unify initial capturing so that it works nicely
- even if the logging module is used on an early-loaded conftest.py
- file or plugin.
-- allow to omit "()" in test ids to allow for uniform test ids
- as produced by Alfredo's nice pytest.vim plugin.
-- fix issue12 - show plugin versions with "--version" and
- "--traceconfig" and also document how to add extra information
- to reporting test header
-- fix issue17 (import-* reporting issue on python3) by
- requiring py>1.4.0 (1.4.1 is going to include it)
-- fix issue10 (numpy arrays truth checking) by refining
- assertion interpretation in py lib
-- fix issue15: make nose compatibility tests compatible
- with python3 (now that nose-1.0 supports python3)
-- remove somewhat surprising "same-conftest" detection because
- it ignores conftest.py when they appear in several subdirs.
-- improve assertions ("not in"), thanks Floris Bruynooghe
-- improve behaviour/warnings when running on top of "python -OO"
- (assertions and docstrings are turned off, leading to potential
- false positives)
-- introduce a pytest_cmdline_processargs(args) hook
- to allow dynamic computation of command line arguments.
- This fixes a regression because py.test prior to 2.0
- allowed to set command line options from conftest.py
- files which so far pytest-2.0 only allowed from ini-files now.
-- fix issue7: assert failures in doctest modules.
- unexpected failures in doctests will not generally
- show nicer, i.e. within the doctest failing context.
-- fix issue9: setup/teardown functions for an xfail-marked
- test will report as xfail if they fail but report as normally
- passing (not xpassing) if they succeed. This only is true
- for "direct" setup/teardown invocations because teardown_class/
- teardown_module cannot closely relate to a single test.
-- fix issue14: no logging errors at process exit
-- refinements to "collecting" output on non-ttys
-- refine internal plugin registration and --traceconfig output
-- introduce a mechanism to prevent/unregister plugins from the
- command line, see http://pytest.org/plugins.html#cmdunregister
-- activate resultlog plugin by default
-- fix regression wrt yielded tests which due to the
- collection-before-running semantics were not
- setup as with pytest 1.3.4. Note, however, that
- the recommended and much cleaner way to do test
- parametraization remains the "pytest_generate_tests"
- mechanism, see the docs.
-
-2.0.0
-=====
-
-- pytest-2.0 is now its own package and depends on pylib-2.0
-- new ability: python -m pytest / python -m pytest.main ability
-- new python invcation: pytest.main(args, plugins) to load
- some custom plugins early.
-- try harder to run unittest test suites in a more compatible manner
- by deferring setup/teardown semantics to the unittest package.
- also work harder to run twisted/trial and Django tests which
- should now basically work by default.
-- introduce a new way to set config options via ini-style files,
- by default setup.cfg and tox.ini files are searched. The old
- ways (certain environment variables, dynamic conftest.py reading
- is removed).
-- add a new "-q" option which decreases verbosity and prints a more
- nose/unittest-style "dot" output.
-- fix issue135 - marks now work with unittest test cases as well
-- fix issue126 - introduce py.test.set_trace() to trace execution via
- PDB during the running of tests even if capturing is ongoing.
-- fix issue123 - new "python -m py.test" invocation for py.test
- (requires Python 2.5 or above)
-- fix issue124 - make reporting more resilient against tests opening
- files on filedescriptor 1 (stdout).
-- fix issue109 - sibling conftest.py files will not be loaded.
- (and Directory collectors cannot be customized anymore from a Directory's
- conftest.py - this needs to happen at least one level up).
-- introduce (customizable) assertion failure representations and enhance
- output on assertion failures for comparisons and other cases (Floris Bruynooghe)
-- nose-plugin: pass through type-signature failures in setup/teardown
- functions instead of not calling them (Ed Singleton)
-- remove py.test.collect.Directory (follows from a major refactoring
- and simplification of the collection process)
-- majorly reduce py.test core code, shift function/python testing to own plugin
-- fix issue88 (finding custom test nodes from command line arg)
-- refine 'tmpdir' creation, will now create basenames better associated
- with test names (thanks Ronny)
-- "xpass" (unexpected pass) tests don't cause exitcode!=0
-- fix issue131 / issue60 - importing doctests in __init__ files used as namespace packages
-- fix issue93 stdout/stderr is captured while importing conftest.py
-- fix bug: unittest collected functions now also can have "pytestmark"
- applied at class/module level
-- add ability to use "class" level for cached_setup helper
-- fix strangeness: mark.* objects are now immutable, create new instances
-
-1.3.4
-=====
-
-- fix issue111: improve install documentation for windows
-- fix issue119: fix custom collectability of __init__.py as a module
-- fix issue116: --doctestmodules work with __init__.py files as well
-- fix issue115: unify internal exception passthrough/catching/GeneratorExit
-- fix issue118: new --tb=native for presenting cpython-standard exceptions
-
-1.3.3
-=====
-
-- fix issue113: assertion representation problem with triple-quoted strings
- (and possibly other cases)
-- make conftest loading detect that a conftest file with the same
- content was already loaded, avoids surprises in nested directory structures
- which can be produced e.g. by Hudson. It probably removes the need to use
- --confcutdir in most cases.
-- fix terminal coloring for win32
- (thanks Michael Foord for reporting)
-- fix weirdness: make terminal width detection work on stdout instead of stdin
- (thanks Armin Ronacher for reporting)
-- remove trailing whitespace in all py/text distribution files
-
-1.3.2
-=====
-
-**New features**
-
-- fix issue103: introduce py.test.raises as context manager, examples::
-
- with py.test.raises(ZeroDivisionError):
- x = 0
- 1 / x
-
- with py.test.raises(RuntimeError) as excinfo:
- call_something()
-
- # you may do extra checks on excinfo.value|type|traceback here
-
- (thanks Ronny Pfannschmidt)
-
-- Funcarg factories can now dynamically apply a marker to a
- test invocation. This is for example useful if a factory
- provides parameters to a test which are expected-to-fail::
-
- def pytest_funcarg__arg(request):
- request.applymarker(py.test.mark.xfail(reason="flaky config"))
- ...
-
- def test_function(arg):
- ...
-
-- improved error reporting on collection and import errors. This makes
- use of a more general mechanism, namely that for custom test item/collect
- nodes ``node.repr_failure(excinfo)`` is now uniformly called so that you can
- override it to return a string error representation of your choice
- which is going to be reported as a (red) string.
-
-- introduce '--junitprefix=STR' option to prepend a prefix
- to all reports in the junitxml file.
-
-**Bug fixes**
-
-- make tests and the ``pytest_recwarn`` plugin in particular fully compatible
- to Python2.7 (if you use the ``recwarn`` funcarg warnings will be enabled so that
- you can properly check for their existence in a cross-python manner).
-- refine --pdb: ignore xfailed tests, unify its TB-reporting and
- don't display failures again at the end.
-- fix assertion interpretation with the ** operator (thanks Benjamin Peterson)
-- fix issue105 assignment on the same line as a failing assertion (thanks Benjamin Peterson)
-- fix issue104 proper escaping for test names in junitxml plugin (thanks anonymous)
-- fix issue57 -f|--looponfail to work with xpassing tests (thanks Ronny)
-- fix issue92 collectonly reporter and --pastebin (thanks Benjamin Peterson)
-- fix py.code.compile(source) to generate unique filenames
-- fix assertion re-interp problems on PyPy, by defering code
- compilation to the (overridable) Frame.eval class. (thanks Amaury Forgeot)
-- fix py.path.local.pyimport() to work with directories
-- streamline py.path.local.mkdtemp implementation and usage
-- don't print empty lines when showing junitxml-filename
-- add optional boolean ignore_errors parameter to py.path.local.remove
-- fix terminal writing on win32/python2.4
-- py.process.cmdexec() now tries harder to return properly encoded unicode objects
- on all python versions
-- install plain py.test/py.which scripts also for Jython, this helps to
- get canonical script paths in virtualenv situations
-- make path.bestrelpath(path) return ".", note that when calling
- X.bestrelpath the assumption is that X is a directory.
-- make initial conftest discovery ignore "--" prefixed arguments
-- fix resultlog plugin when used in an multicpu/multihost xdist situation
- (thanks Jakub Gustak)
-- perform distributed testing related reporting in the xdist-plugin
- rather than having dist-related code in the generic py.test
- distribution
-- fix homedir detection on Windows
-- ship distribute_setup.py version 0.6.13
-
-1.3.1
-=====
-
-**New features**
-
-- issue91: introduce new py.test.xfail(reason) helper
- to imperatively mark a test as expected to fail. Can
- be used from within setup and test functions. This is
- useful especially for parametrized tests when certain
- configurations are expected-to-fail. In this case the
- declarative approach with the @py.test.mark.xfail cannot
- be used as it would mark all configurations as xfail.
-
-- issue102: introduce new --maxfail=NUM option to stop
- test runs after NUM failures. This is a generalization
- of the '-x' or '--exitfirst' option which is now equivalent
- to '--maxfail=1'. Both '-x' and '--maxfail' will
- now also print a line near the end indicating the Interruption.
-
-- issue89: allow py.test.mark decorators to be used on classes
- (class decorators were introduced with python2.6) and
- also allow to have multiple markers applied at class/module level
- by specifying a list.
-
-- improve and refine letter reporting in the progress bar:
- . pass
- f failed test
- s skipped tests (reminder: use for dependency/platform mismatch only)
- x xfailed test (test that was expected to fail)
- X xpassed test (test that was expected to fail but passed)
-
- You can use any combination of 'fsxX' with the '-r' extended
- reporting option. The xfail/xpass results will show up as
- skipped tests in the junitxml output - which also fixes
- issue99.
-
-- make py.test.cmdline.main() return the exitstatus instead of raising
- SystemExit and also allow it to be called multiple times. This of
- course requires that your application and tests are properly teared
- down and don't have global state.
-
-**Bug Fixes**
-
-- improved traceback presentation:
- - improved and unified reporting for "--tb=short" option
- - Errors during test module imports are much shorter, (using --tb=short style)
- - raises shows shorter more relevant tracebacks
- - --fulltrace now more systematically makes traces longer / inhibits cutting
-
-- improve support for raises and other dynamically compiled code by
- manipulating python's linecache.cache instead of the previous
- rather hacky way of creating custom code objects. This makes
- it seemlessly work on Jython and PyPy where it previously didn't.
-
-- fix issue96: make capturing more resilient against Control-C
- interruptions (involved somewhat substantial refactoring
- to the underlying capturing functionality to avoid race
- conditions).
-
-- fix chaining of conditional skipif/xfail decorators - so it works now
- as expected to use multiple @py.test.mark.skipif(condition) decorators,
- including specific reporting which of the conditions lead to skipping.
-
-- fix issue95: late-import zlib so that it's not required
- for general py.test startup.
-
-- fix issue94: make reporting more robust against bogus source code
- (and internally be more careful when presenting unexpected byte sequences)
-
-
-1.3.0
-=====
-
-- deprecate --report option in favour of a new shorter and easier to
- remember -r option: it takes a string argument consisting of any
- combination of 'xfsX' characters. They relate to the single chars
- you see during the dotted progress printing and will print an extra line
- per test at the end of the test run. This extra line indicates the exact
- position or test ID that you directly paste to the py.test cmdline in order
- to re-run a particular test.
-
-- allow external plugins to register new hooks via the new
- pytest_addhooks(pluginmanager) hook. The new release of
- the pytest-xdist plugin for distributed and looponfailing
- testing requires this feature.
-
-- add a new pytest_ignore_collect(path, config) hook to allow projects and
- plugins to define exclusion behaviour for their directory structure -
- for example you may define in a conftest.py this method::
-
- def pytest_ignore_collect(path):
- return path.check(link=1)
-
- to prevent even a collection try of any tests in symlinked dirs.
-
-- new pytest_pycollect_makemodule(path, parent) hook for
- allowing customization of the Module collection object for a
- matching test module.
-
-- extend and refine xfail mechanism:
- ``@py.test.mark.xfail(run=False)`` do not run the decorated test
- ``@py.test.mark.xfail(reason="...")`` prints the reason string in xfail summaries
- specifiying ``--runxfail`` on command line virtually ignores xfail markers
-
-- expose (previously internal) commonly useful methods:
- py.io.get_terminal_with() -> return terminal width
- py.io.ansi_print(...) -> print colored/bold text on linux/win32
- py.io.saferepr(obj) -> return limited representation string
-
-- expose test outcome related exceptions as py.test.skip.Exception,
- py.test.raises.Exception etc., useful mostly for plugins
- doing special outcome interpretation/tweaking
-
-- (issue85) fix junitxml plugin to handle tests with non-ascii output
-
-- fix/refine python3 compatibility (thanks Benjamin Peterson)
-
-- fixes for making the jython/win32 combination work, note however:
- jython2.5.1/win32 does not provide a command line launcher, see
- http://bugs.jython.org/issue1491 . See pylib install documentation
- for how to work around.
-
-- fixes for handling of unicode exception values and unprintable objects
-
-- (issue87) fix unboundlocal error in assertionold code
-
-- (issue86) improve documentation for looponfailing
-
-- refine IO capturing: stdin-redirect pseudo-file now has a NOP close() method
-
-- ship distribute_setup.py version 0.6.10
-
-- added links to the new capturelog and coverage plugins
-
-
-1.2.0
-=====
-
-- refined usage and options for "py.cleanup"::
-
- py.cleanup # remove "*.pyc" and "*$py.class" (jython) files
- py.cleanup -e .swp -e .cache # also remove files with these extensions
- py.cleanup -s # remove "build" and "dist" directory next to setup.py files
- py.cleanup -d # also remove empty directories
- py.cleanup -a # synonym for "-s -d -e 'pip-log.txt'"
- py.cleanup -n # dry run, only show what would be removed
-
-- add a new option "py.test --funcargs" which shows available funcargs
- and their help strings (docstrings on their respective factory function)
- for a given test path
-
-- display a short and concise traceback if a funcarg lookup fails
-
-- early-load "conftest.py" files in non-dot first-level sub directories.
- allows to conveniently keep and access test-related options in a ``test``
- subdir and still add command line options.
-
-- fix issue67: new super-short traceback-printing option: "--tb=line" will print a single line for each failing (python) test indicating its filename, lineno and the failure value
-
-- fix issue78: always call python-level teardown functions even if the
- according setup failed. This includes refinements for calling setup_module/class functions
- which will now only be called once instead of the previous behaviour where they'd be called
- multiple times if they raise an exception (including a Skipped exception). Any exception
- will be re-corded and associated with all tests in the according module/class scope.
-
-- fix issue63: assume <40 columns to be a bogus terminal width, default to 80
-
-- fix pdb debugging to be in the correct frame on raises-related errors
-
-- update apipkg.py to fix an issue where recursive imports might
- unnecessarily break importing
-
-- fix plugin links
-
-1.1.1
-=====
-
-- moved dist/looponfailing from py.test core into a new
- separately released pytest-xdist plugin.
-
-- new junitxml plugin: --junitxml=path will generate a junit style xml file
- which is processable e.g. by the Hudson CI system.
-
-- new option: --genscript=path will generate a standalone py.test script
- which will not need any libraries installed. thanks to Ralf Schmitt.
-
-- new option: --ignore will prevent specified path from collection.
- Can be specified multiple times.
-
-- new option: --confcutdir=dir will make py.test only consider conftest
- files that are relative to the specified dir.
-
-- new funcarg: "pytestconfig" is the pytest config object for access
- to command line args and can now be easily used in a test.
-
-- install ``py.test`` and ``py.which`` with a ``-$VERSION`` suffix to
- disambiguate between Python3, python2.X, Jython and PyPy installed versions.
-
-- new "pytestconfig" funcarg allows access to test config object
-
-- new "pytest_report_header" hook can return additional lines
- to be displayed at the header of a test run.
-
-- (experimental) allow "py.test path::name1::name2::..." for pointing
- to a test within a test collection directly. This might eventually
- evolve as a full substitute to "-k" specifications.
-
-- streamlined plugin loading: order is now as documented in
- customize.html: setuptools, ENV, commandline, conftest.
- also setuptools entry point names are turned to canonical namees ("pytest_*")
-
-- automatically skip tests that need 'capfd' but have no os.dup
-
-- allow pytest_generate_tests to be defined in classes as well
-
-- deprecate usage of 'disabled' attribute in favour of pytestmark
-- deprecate definition of Directory, Module, Class and Function nodes
- in conftest.py files. Use pytest collect hooks instead.
-
-- collection/item node specific runtest/collect hooks are only called exactly
- on matching conftest.py files, i.e. ones which are exactly below
- the filesystem path of an item
-
-- change: the first pytest_collect_directory hook to return something
- will now prevent further hooks to be called.
-
-- change: figleaf plugin now requires --figleaf to run. Also
- change its long command line options to be a bit shorter (see py.test -h).
-
-- change: pytest doctest plugin is now enabled by default and has a
- new option --doctest-glob to set a pattern for file matches.
-
-- change: remove internal py._* helper vars, only keep py._pydir
-
-- robustify capturing to survive if custom pytest_runtest_setup
- code failed and prevented the capturing setup code from running.
-
-- make py.test.* helpers provided by default plugins visible early -
- works transparently both for pydoc and for interactive sessions
- which will regularly see e.g. py.test.mark and py.test.importorskip.
-
-- simplify internal plugin manager machinery
-- simplify internal collection tree by introducing a RootCollector node
-
-- fix assert reinterpreation that sees a call containing "keyword=..."
-
-- fix issue66: invoke pytest_sessionstart and pytest_sessionfinish
- hooks on slaves during dist-testing, report module/session teardown
- hooks correctly.
-
-- fix issue65: properly handle dist-testing if no
- execnet/py lib installed remotely.
-
-- skip some install-tests if no execnet is available
-
-- fix docs, fix internal bin/ script generation
-
-
-1.1.0
-=====
-
-- introduce automatic plugin registration via 'pytest11'
- entrypoints via setuptools' pkg_resources.iter_entry_points
-
-- fix py.test dist-testing to work with execnet >= 1.0.0b4
-
-- re-introduce py.test.cmdline.main() for better backward compatibility
-
-- svn paths: fix a bug with path.check(versioned=True) for svn paths,
- allow '%' in svn paths, make svnwc.update() default to interactive mode
- like in 1.0.x and add svnwc.update(interactive=False) to inhibit interaction.
-
-- refine distributed tarball to contain test and no pyc files
-
-- try harder to have deprecation warnings for py.compat.* accesses
- report a correct location
-
-1.0.3
-=====
-
-* adjust and improve docs
-
-* remove py.rest tool and internal namespace - it was
- never really advertised and can still be used with
- the old release if needed. If there is interest
- it could be revived into its own tool i guess.
-
-* fix issue48 and issue59: raise an Error if the module
- from an imported test file does not seem to come from
- the filepath - avoids "same-name" confusion that has
- been reported repeatedly
-
-* merged Ronny's nose-compatibility hacks: now
- nose-style setup_module() and setup() functions are
- supported
-
-* introduce generalized py.test.mark function marking
-
-* reshuffle / refine command line grouping
-
-* deprecate parser.addgroup in favour of getgroup which creates option group
-
-* add --report command line option that allows to control showing of skipped/xfailed sections
-
-* generalized skipping: a new way to mark python functions with skipif or xfail
- at function, class and modules level based on platform or sys-module attributes.
-
-* extend py.test.mark decorator to allow for positional args
-
-* introduce and test "py.cleanup -d" to remove empty directories
-
-* fix issue #59 - robustify unittest test collection
-
-* make bpython/help interaction work by adding an __all__ attribute
- to ApiModule, cleanup initpkg
-
-* use MIT license for pylib, add some contributors
-
-* remove py.execnet code and substitute all usages with 'execnet' proper
-
-* fix issue50 - cached_setup now caches more to expectations
- for test functions with multiple arguments.
-
-* merge Jarko's fixes, issue #45 and #46
-
-* add the ability to specify a path for py.lookup to search in
-
-* fix a funcarg cached_setup bug probably only occuring
- in distributed testing and "module" scope with teardown.
-
-* many fixes and changes for making the code base python3 compatible,
- many thanks to Benjamin Peterson for helping with this.
-
-* consolidate builtins implementation to be compatible with >=2.3,
- add helpers to ease keeping 2 and 3k compatible code
-
-* deprecate py.compat.doctest|subprocess|textwrap|optparse
-
-* deprecate py.magic.autopath, remove py/magic directory
-
-* move pytest assertion handling to py/code and a pytest_assertion
- plugin, add "--no-assert" option, deprecate py.magic namespaces
- in favour of (less) py.code ones.
-
-* consolidate and cleanup py/code classes and files
-
-* cleanup py/misc, move tests to bin-for-dist
-
-* introduce delattr/delitem/delenv methods to py.test's monkeypatch funcarg
-
-* consolidate py.log implementation, remove old approach.
-
-* introduce py.io.TextIO and py.io.BytesIO for distinguishing between
- text/unicode and byte-streams (uses underlying standard lib io.*
- if available)
-
-* make py.unittest_convert helper script available which converts "unittest.py"
- style files into the simpler assert/direct-test-classes py.test/nosetests
- style. The script was written by Laura Creighton.
-
-* simplified internal localpath implementation
-
-1.0.2
-=====
-
-* fixing packaging issues, triggered by fedora redhat packaging,
- also added doc, examples and contrib dirs to the tarball.
-
-* added a documentation link to the new django plugin.
-
-1.0.1
-=====
-
-* added a 'pytest_nose' plugin which handles nose.SkipTest,
- nose-style function/method/generator setup/teardown and
- tries to report functions correctly.
-
-* capturing of unicode writes or encoded strings to sys.stdout/err
- work better, also terminalwriting was adapted and somewhat
- unified between windows and linux.
-
-* improved documentation layout and content a lot
-
-* added a "--help-config" option to show conftest.py / ENV-var names for
- all longopt cmdline options, and some special conftest.py variables.
- renamed 'conf_capture' conftest setting to 'option_capture' accordingly.
-
-* fix issue #27: better reporting on non-collectable items given on commandline
- (e.g. pyc files)
-
-* fix issue #33: added --version flag (thanks Benjamin Peterson)
-
-* fix issue #32: adding support for "incomplete" paths to wcpath.status()
-
-* "Test" prefixed classes are *not* collected by default anymore if they
- have an __init__ method
-
-* monkeypatch setenv() now accepts a "prepend" parameter
-
-* improved reporting of collection error tracebacks
-
-* simplified multicall mechanism and plugin architecture,
- renamed some internal methods and argnames
-
-1.0.0
-=====
-
-* more terse reporting try to show filesystem path relatively to current dir
-* improve xfail output a bit
-
-1.0.0b9
-=======
-
-* cleanly handle and report final teardown of test setup
-
-* fix svn-1.6 compat issue with py.path.svnwc().versioned()
- (thanks Wouter Vanden Hove)
-
-* setup/teardown or collection problems now show as ERRORs
- or with big "E"'s in the progress lines. they are reported
- and counted separately.
-
-* dist-testing: properly handle test items that get locally
- collected but cannot be collected on the remote side - often
- due to platform/dependency reasons
-
-* simplified py.test.mark API - see keyword plugin documentation
-
-* integrate better with logging: capturing now by default captures
- test functions and their immediate setup/teardown in a single stream
-
-* capsys and capfd funcargs now have a readouterr() and a close() method
- (underlyingly py.io.StdCapture/FD objects are used which grew a
- readouterr() method as well to return snapshots of captured out/err)
-
-* make assert-reinterpretation work better with comparisons not
- returning bools (reported with numpy from thanks maciej fijalkowski)
-
-* reworked per-test output capturing into the pytest_iocapture.py plugin
- and thus removed capturing code from config object
-
-* item.repr_failure(excinfo) instead of item.repr_failure(excinfo, outerr)
-
-
-1.0.0b8
-=======
-
-* pytest_unittest-plugin is now enabled by default
-
-* introduced pytest_keyboardinterrupt hook and
- refined pytest_sessionfinish hooked, added tests.
-
-* workaround a buggy logging module interaction ("closing already closed
- files"). Thanks to Sridhar Ratnakumar for triggering.
-
-* if plugins use "py.test.importorskip" for importing
- a dependency only a warning will be issued instead
- of exiting the testing process.
-
-* many improvements to docs:
- - refined funcargs doc , use the term "factory" instead of "provider"
- - added a new talk/tutorial doc page
- - better download page
- - better plugin docstrings
- - added new plugins page and automatic doc generation script
-
-* fixed teardown problem related to partially failing funcarg setups
- (thanks MrTopf for reporting), "pytest_runtest_teardown" is now
- always invoked even if the "pytest_runtest_setup" failed.
-
-* tweaked doctest output for docstrings in py modules,
- thanks Radomir.
-
-1.0.0b7
-=======
-
-* renamed py.test.xfail back to py.test.mark.xfail to avoid
- two ways to decorate for xfail
-
-* re-added py.test.mark decorator for setting keywords on functions
- (it was actually documented so removing it was not nice)
-
-* remove scope-argument from request.addfinalizer() because
- request.cached_setup has the scope arg. TOOWTDI.
-
-* perform setup finalization before reporting failures
-
-* apply modified patches from Andreas Kloeckner to allow
- test functions to have no func_code (#22) and to make
- "-k" and function keywords work (#20)
-
-* apply patch from Daniel Peolzleithner (issue #23)
-
-* resolve issue #18, multiprocessing.Manager() and
- redirection clash
-
-* make __name__ == "__channelexec__" for remote_exec code
-
-1.0.0b3
-=======
-
-* plugin classes are removed: one now defines
- hooks directly in conftest.py or global pytest_*.py
- files.
-
-* added new pytest_namespace(config) hook that allows
- to inject helpers directly to the py.test.* namespace.
-
-* documented and refined many hooks
-
-* added new style of generative tests via
- pytest_generate_tests hook that integrates
- well with function arguments.
-
-
-1.0.0b1
-=======
-
-* introduced new "funcarg" setup method,
- see doc/test/funcarg.txt
-
-* introduced plugin architecture and many
- new py.test plugins, see
- doc/test/plugins.txt
-
-* teardown_method is now guaranteed to get
- called after a test method has run.
-
-* new method: py.test.importorskip(mod,minversion)
- will either import or call py.test.skip()
-
-* completely revised internal py.test architecture
-
-* new py.process.ForkedFunc object allowing to
- fork execution of a function to a sub process
- and getting a result back.
-
-XXX lots of things missing here XXX
-
-0.9.2
-=====
-
-* refined installation and metadata, created new setup.py,
- now based on setuptools/ez_setup (thanks to Ralf Schmitt
- for his support).
-
-* improved the way of making py.* scripts available in
- windows environments, they are now added to the
- Scripts directory as ".cmd" files.
-
-* py.path.svnwc.status() now is more complete and
- uses xml output from the 'svn' command if available
- (Guido Wesdorp)
-
-* fix for py.path.svn* to work with svn 1.5
- (Chris Lamb)
-
-* fix path.relto(otherpath) method on windows to
- use normcase for checking if a path is relative.
-
-* py.test's traceback is better parseable from editors
- (follows the filenames:LINENO: MSG convention)
- (thanks to Osmo Salomaa)
-
-* fix to javascript-generation, "py.test --runbrowser"
- should work more reliably now
-
-* removed previously accidentally added
- py.test.broken and py.test.notimplemented helpers.
-
-* there now is a py.__version__ attribute
-
-0.9.1
-=====
-
-This is a fairly complete list of v0.9.1, which can
-serve as a reference for developers.
-
-* allowing + signs in py.path.svn urls [39106]
-* fixed support for Failed exceptions without excinfo in py.test [39340]
-* added support for killing processes for Windows (as well as platforms that
- support os.kill) in py.misc.killproc [39655]
-* added setup/teardown for generative tests to py.test [40702]
-* added detection of FAILED TO LOAD MODULE to py.test [40703, 40738, 40739]
-* fixed problem with calling .remove() on wcpaths of non-versioned files in
- py.path [44248]
-* fixed some import and inheritance issues in py.test [41480, 44648, 44655]
-* fail to run greenlet tests when pypy is available, but without stackless
- [45294]
-* small fixes in rsession tests [45295]
-* fixed issue with 2.5 type representations in py.test [45483, 45484]
-* made that internal reporting issues displaying is done atomically in py.test
- [45518]
-* made that non-existing files are igored by the py.lookup script [45519]
-* improved exception name creation in py.test [45535]
-* made that less threads are used in execnet [merge in 45539]
-* removed lock required for atomical reporting issue displaying in py.test
- [45545]
-* removed globals from execnet [45541, 45547]
-* refactored cleanup mechanics, made that setDaemon is set to 1 to make atexit
- get called in 2.5 (py.execnet) [45548]
-* fixed bug in joining threads in py.execnet's servemain [45549]
-* refactored py.test.rsession tests to not rely on exact output format anymore
- [45646]
-* using repr() on test outcome [45647]
-* added 'Reason' classes for py.test.skip() [45648, 45649]
-* killed some unnecessary sanity check in py.test.collect [45655]
-* avoid using os.tmpfile() in py.io.fdcapture because on Windows it's only
- usable by Administrators [45901]
-* added support for locking and non-recursive commits to py.path.svnwc [45994]
-* locking files in py.execnet to prevent CPython from segfaulting [46010]
-* added export() method to py.path.svnurl
-* fixed -d -x in py.test [47277]
-* fixed argument concatenation problem in py.path.svnwc [49423]
-* restore py.test behaviour that it exits with code 1 when there are failures
- [49974]
-* don't fail on html files that don't have an accompanying .txt file [50606]
-* fixed 'utestconvert.py < input' [50645]
-* small fix for code indentation in py.code.source [50755]
-* fix _docgen.py documentation building [51285]
-* improved checks for source representation of code blocks in py.test [51292]
-* added support for passing authentication to py.path.svn* objects [52000,
- 52001]
-* removed sorted() call for py.apigen tests in favour of [].sort() to support
- Python 2.3 [52481]
diff --git a/WebDriverTests/imported/w3c/tools/pytest/CONTRIBUTING.rst b/WebDriverTests/imported/w3c/tools/pytest/CONTRIBUTING.rst
deleted file mode 100644
index 75ee3ec..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/CONTRIBUTING.rst
+++ /dev/null
@@ -1,253 +0,0 @@
-============================
-Contribution getting started
-============================
-
-Contributions are highly welcomed and appreciated. Every little help counts,
-so do not hesitate!
-
-.. contents:: Contribution links
- :depth: 2
-
-
-.. _submitfeedback:
-
-Feature requests and feedback
------------------------------
-
-Do you like pytest? Share some love on Twitter or in your blog posts!
-
-We'd also like to hear about your propositions and suggestions. Feel free to
-`submit them as issues <https://github.com/pytest-dev/pytest/issues>`_ and:
-
-* Explain in detail how they should work.
-* Keep the scope as narrow as possible. This will make it easier to implement.
-
-
-.. _reportbugs:
-
-Report bugs
------------
-
-Report bugs for pytest in the `issue tracker <https://github.com/pytest-dev/pytest/issues>`_.
-
-If you are reporting a bug, please include:
-
-* Your operating system name and version.
-* Any details about your local setup that might be helpful in troubleshooting,
- specifically Python interpreter version,
- installed libraries and pytest version.
-* Detailed steps to reproduce the bug.
-
-If you can write a demonstration test that currently fails but should pass (xfail),
-that is a very useful commit to make as well, even if you can't find how
-to fix the bug yet.
-
-
-.. _fixbugs:
-
-Fix bugs
---------
-
-Look through the GitHub issues for bugs. Here is sample filter you can use:
-https://github.com/pytest-dev/pytest/labels/bug
-
-:ref:`Talk <contact>` to developers to find out how you can fix specific bugs.
-
-Don't forget to check the issue trackers of your favourite plugins, too!
-
-.. _writeplugins:
-
-Implement features
-------------------
-
-Look through the GitHub issues for enhancements. Here is sample filter you
-can use:
-https://github.com/pytest-dev/pytest/labels/enhancement
-
-:ref:`Talk <contact>` to developers to find out how you can implement specific
-features.
-
-Write documentation
--------------------
-
-pytest could always use more documentation. What exactly is needed?
-
-* More complementary documentation. Have you perhaps found something unclear?
-* Documentation translations. We currently have only English.
-* Docstrings. There can never be too many of them.
-* Blog posts, articles and such -- they're all very appreciated.
-
-You can also edit documentation files directly in the Github web interface
-without needing to make a fork and local copy. This can be convenient for
-small fixes.
-
-
-.. _submitplugin:
-
-Submitting Plugins to pytest-dev
---------------------------------
-
-Pytest development of the core, some plugins and support code happens
-in repositories living under the ``pytest-dev`` organisations:
-
-- `pytest-dev on GitHub <https://github.com/pytest-dev>`_
-
-- `pytest-dev on Bitbucket <https://bitbucket.org/pytest-dev>`_
-
-All pytest-dev Contributors team members have write access to all contained
-repositories. pytest core and plugins are generally developed
-using `pull requests`_ to respective repositories.
-
-The objectives of the ``pytest-dev`` organisation are:
-
-* Having a central location for popular pytest plugins
-* Sharing some of the maintenance responsibility (in case a maintainer no longer whishes to maintain a plugin)
-
-You can submit your plugin by subscribing to the `pytest-dev mail list
-<https://mail.python.org/mailman/listinfo/pytest-dev>`_ and writing a
-mail pointing to your existing pytest plugin repository which must have
-the following:
-
-- PyPI presence with a ``setup.py`` that contains a license, ``pytest-``
- prefixed name, version number, authors, short and long description.
-
-- a ``tox.ini`` for running tests using `tox <http://tox.testrun.org>`_.
-
-- a ``README.txt`` describing how to use the plugin and on which
- platforms it runs.
-
-- a ``LICENSE.txt`` file or equivalent containing the licensing
- information, with matching info in ``setup.py``.
-
-- an issue tracker for bug reports and enhancement requests.
-
-If no contributor strongly objects and two agree, the repository can then be
-transferred to the ``pytest-dev`` organisation.
-
-Here's a rundown of how a repository transfer usually proceeds
-(using a repository named ``joedoe/pytest-xyz`` as example):
-
-* One of the ``pytest-dev`` administrators creates:
-
- - ``pytest-xyz-admin`` team, with full administration rights to
- ``pytest-dev/pytest-xyz``.
- - ``pytest-xyz-developers`` team, with write access to
- ``pytest-dev/pytest-xyz``.
-
-* ``joedoe`` is invited to the ``pytest-xyz-admin`` team;
-
-* After accepting the invitation, ``joedoe`` transfers the repository from its
- original location to ``pytest-dev/pytest-xyz`` (A nice feature is that GitHub handles URL redirection from
- the old to the new location automatically).
-
-* ``joedoe`` is free to add any other collaborators to the
- ``pytest-xyz-admin`` or ``pytest-xyz-developers`` team as desired.
-
-The ``pytest-dev/Contributors`` team has write access to all projects, and
-every project administrator is in it. We recommend that each plugin has at least three
-people who have the right to release to PyPI.
-
-Repository owners can be assured that no ``pytest-dev`` administrator will ever make
-releases of your repository or take ownership in any way, except in rare cases
-where someone becomes unresponsive after months of contact attempts.
-As stated, the objective is to share maintenance and avoid "plugin-abandon".
-
-
-.. _`pull requests`:
-.. _pull-requests:
-
-Preparing Pull Requests on GitHub
----------------------------------
-
-There's an excellent tutorial on how Pull Requests work in the
-`GitHub Help Center <https://help.github.com/articles/using-pull-requests/>`_
-
-
-.. note::
- What is a "pull request"? It informs project's core developers about the
- changes you want to review and merge. Pull requests are stored on
- `GitHub servers <https://github.com/pytest-dev/pytest/pulls>`_.
- Once you send pull request, we can discuss it's potential modifications and
- even add more commits to it later on.
-
-There's an excellent tutorial on how Pull Requests work in the
-`GitHub Help Center <https://help.github.com/articles/using-pull-requests/>`_,
-but here is a simple overview:
-
-#. Fork the
- `pytest GitHub repository <https://github.com/pytest-dev/pytest>`__. It's
- fine to use ``pytest`` as your fork repository name because it will live
- under your user.
-
-#. Clone your fork locally using `git <https://git-scm.com/>`_ and create a branch::
-
- $ git clone git@github.com:YOUR_GITHUB_USERNAME/pytest.git
- $ cd pytest
- # now, to fix a bug create your own branch off "master":
-
- $ git checkout -b your-bugfix-branch-name master
-
- # or to instead add a feature create your own branch off "features":
-
- $ git checkout -b your-feature-branch-name features
-
- Given we have "major.minor.micro" version numbers, bugfixes will usually
- be released in micro releases whereas features will be released in
- minor releases and incompatible changes in major releases.
-
- If you need some help with Git, follow this quick start
- guide: https://git.wiki.kernel.org/index.php/QuickStart
-
-#. Install tox
-
- Tox is used to run all the tests and will automatically setup virtualenvs
- to run the tests in.
- (will implicitly use http://www.virtualenv.org/en/latest/)::
-
- $ pip install tox
-
-#. Run all the tests
-
- You need to have Python 2.7 and 3.5 available in your system. Now
- running tests is as simple as issuing this command::
-
- $ python runtox.py -e linting,py27,py35
-
- This command will run tests via the "tox" tool against Python 2.7 and 3.5
- and also perform "lint" coding-style checks. ``runtox.py`` is
- a thin wrapper around ``tox`` which installs from a development package
- index where newer (not yet released to pypi) versions of dependencies
- (especially ``py``) might be present.
-
-#. You can now edit your local working copy.
-
- You can now make the changes you want and run the tests again as necessary.
-
- To run tests on py27 and pass options to pytest (e.g. enter pdb on failure)
- to pytest you can do::
-
- $ python runtox.py -e py27 -- --pdb
-
- or to only run tests in a particular test module on py35::
-
- $ python runtox.py -e py35 -- testing/test_config.py
-
-#. Commit and push once your tests pass and you are happy with your change(s)::
-
- $ git commit -a -m "<commit message>"
- $ git push -u
-
- Make sure you add a CHANGELOG message, and add yourself to AUTHORS. If you
- are unsure about either of these steps, submit your pull request and we'll
- help you fix it up.
-
-#. Finally, submit a pull request through the GitHub website using this data::
-
- head-fork: YOUR_GITHUB_USERNAME/pytest
- compare: your-branch-name
-
- base-fork: pytest-dev/pytest
- base: master # if it's a bugfix
- base: feature # if it's a feature
-
-
diff --git a/WebDriverTests/imported/w3c/tools/pytest/HOWTORELEASE.rst b/WebDriverTests/imported/w3c/tools/pytest/HOWTORELEASE.rst
deleted file mode 100644
index 3ebfa28..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/HOWTORELEASE.rst
+++ /dev/null
@@ -1,92 +0,0 @@
-How to release pytest
---------------------------------------------
-
-Note: this assumes you have already registered on pypi.
-
-0. create the branch release-VERSION
- use features as base for minor/major releases
- and master as base for bugfix releases
-
-1. Bump version numbers in _pytest/__init__.py (setup.py reads it)
-
-2. Check and finalize CHANGELOG
-
-3. Write doc/en/announce/release-VERSION.txt and include
- it in doc/en/announce/index.txt::
-
- git log 2.8.2..HEAD --format='%aN' | sort -u # lists the names of authors involved
-
-4. Use devpi for uploading a release tarball to a staging area::
-
- devpi use https://devpi.net/USER/dev
- devpi upload --formats sdist,bdist_wheel
-
-5. Run from multiple machines::
-
- devpi use https://devpi.net/USER/dev
- devpi test pytest==VERSION
-
-6. Check that tests pass for relevant combinations with::
-
- devpi list pytest
-
- or look at failures with "devpi list -f pytest".
-
-7. Regenerate the docs examples using tox, and check for regressions::
-
- tox -e regen
- git diff
-
-
-8. Build the docs, you need a virtualenv with py and sphinx
- installed::
-
- cd doc/en
- make html
-
- Commit any changes before tagging the release.
-
-9. Tag the release::
-
- git tag VERSION
- git push
-
-10. Upload the docs using doc/en/Makefile::
-
- cd doc/en
- make install # or "installall" if you have LaTeX installed for PDF
-
- This requires ssh-login permission on pytest.org because it uses
- rsync.
- Note that the ``install`` target of ``doc/en/Makefile`` defines where the
- rsync goes to, typically to the "latest" section of pytest.org.
-
- If you are making a minor release (e.g. 5.4), you also need to manually
- create a symlink for "latest"::
-
- ssh pytest-dev@pytest.org
- ln -s 5.4 latest
-
- Browse to pytest.org to verify.
-
-11. Publish to pypi::
-
- devpi push pytest-VERSION pypi:NAME
-
- where NAME is the name of pypi.python.org as configured in your ``~/.pypirc``
- file `for devpi <http://doc.devpi.net/latest/quickstart-releaseprocess.html?highlight=pypirc#devpi-push-releasing-to-an-external-index>`_.
-
-
-12. Send release announcement to mailing lists:
-
- - pytest-dev
- - testing-in-python
- - python-announce-list@python.org
-
-
-13. **after the release** Bump the version number in ``_pytest/__init__.py``,
- to the next Minor release version (i.e. if you released ``pytest-2.8.0``,
- set it to ``pytest-2.9.0.dev1``).
-
-14. merge the actual release into the master branch and do a pull request against it
-15. merge from master to features
diff --git a/WebDriverTests/imported/w3c/tools/pytest/ISSUES.txt b/WebDriverTests/imported/w3c/tools/pytest/ISSUES.txt
deleted file mode 100644
index 081d727..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/ISSUES.txt
+++ /dev/null
@@ -1,365 +0,0 @@
-
-
-recorder = monkeypatch.function(".......")
--------------------------------------------------------------
-tags: nice feature
-
-Like monkeypatch.replace but sets a mock-like call recorder:
-
- recorder = monkeypatch.function("os.path.abspath")
- recorder.set_return("/hello")
- os.path.abspath("hello")
- call, = recorder.calls
- assert call.args.path == "hello"
- assert call.returned == "/hello"
- ...
-
-Unlike mock, "args.path" acts on the parsed auto-spec'ed ``os.path.abspath``
-so it's independent from if the client side called "os.path.abspath(path=...)"
-or "os.path.abspath('positional')".
-
-
-refine parametrize API
--------------------------------------------------------------
-tags: critical feature
-
-extend metafunc.parametrize to directly support indirection, example:
-
- def setupdb(request, config):
- # setup "resource" based on test request and the values passed
- # in to parametrize. setupfunc is called for each such value.
- # you may use request.addfinalizer() or request.cached_setup ...
- return dynamic_setup_database(val)
-
- @pytest.mark.parametrize("db", ["pg", "mysql"], setupfunc=setupdb)
- def test_heavy_functional_test(db):
- ...
-
-There would be no need to write or explain funcarg factories and
-their special __ syntax.
-
-The examples and improvements should also show how to put the parametrize
-decorator to a class, to a module or even to a directory. For the directory
-part a conftest.py content like this::
-
- pytestmark = [
- @pytest.mark.parametrize_setup("db", ...),
- ]
-
-probably makes sense in order to keep the declarative nature. This mirrors
-the marker-mechanism with respect to a test module but puts it to a directory
-scale.
-
-When doing larger scoped parametrization it probably becomes necessary
-to allow parametrization to be ignored if the according parameter is not
-used (currently any parametrized argument that is not present in a function will cause a ValueError). Example:
-
- @pytest.mark.parametrize("db", ..., mustmatch=False)
-
-means to not raise an error but simply ignore the parametrization
-if the signature of a decorated function does not match. XXX is it
-not sufficient to always allow non-matches?
-
-
-allow parametrized attributes on classes
---------------------------------------------------
-
-tags: wish 2.4
-
-example:
-
- @pytest.mark.parametrize_attr("db", setupfunc, [1,2,3], scope="class")
- @pytest.mark.parametrize_attr("tmp", setupfunc, scope="...")
- class TestMe:
- def test_hello(self):
- access self.db ...
-
-this would run the test_hello() function three times with three
-different values for self.db. This could also work with unittest/nose
-style tests, i.e. it leverages existing test suites without needing
-to rewrite them. Together with the previously mentioned setup_test()
-maybe the setupfunc could be omitted?
-
-optimizations
----------------------------------------------------------------
-tags: 2.4 core
-
-- look at ihook optimization such that all lookups for
- hooks relating to the same fspath are cached.
-
-fix start/finish partial finailization problem
----------------------------------------------------------------
-tags: bug core
-
-if a configure/runtest_setup/sessionstart/... hook invocation partially
-fails the sessionfinishes is not called. Each hook implementation
-should better be repsonsible for registering a cleanup/finalizer
-appropriately to avoid this issue. Moreover/Alternatively, we could
-record which implementations of a hook succeeded and only call their
-teardown.
-
-
-relax requirement to have tests/testing contain an __init__
-----------------------------------------------------------------
-tags: feature
-bb: http://bitbucket.org/hpk42/py-trunk/issue/64
-
-A local test run of a "tests" directory may work
-but a remote one fail because the tests directory
-does not contain an "__init__.py". Either give
-an error or make it work without the __init__.py
-i.e. port the nose-logic of unloading a test module.
-
-customize test function collection
--------------------------------------------------------
-tags: feature
-
-- introduce pytest.mark.nocollect for not considering a function for
- test collection at all. maybe also introduce a pytest.mark.test to
- explicitly mark a function to become a tested one. Lookup JUnit ways
- of tagging tests.
-
-introduce pytest.mark.importorskip
--------------------------------------------------------
-tags: feature
-
-in addition to the imperative pytest.importorskip also introduce
-a pytest.mark.importorskip so that the test count is more correct.
-
-
-introduce pytest.mark.platform
--------------------------------------------------------
-tags: feature
-
-Introduce nice-to-spell platform-skipping, examples:
-
- @pytest.mark.platform("python3")
- @pytest.mark.platform("not python3")
- @pytest.mark.platform("win32 and not python3")
- @pytest.mark.platform("darwin")
- @pytest.mark.platform("not (jython and win32)")
- @pytest.mark.platform("not (jython and win32)", xfail=True)
-
-etc. Idea is to allow Python expressions which can operate
-on common spellings for operating systems and python
-interpreter versions.
-
-pytest.mark.xfail signature change
--------------------------------------------------------
-tags: feature
-
-change to pytest.mark.xfail(reason, (optional)condition)
-to better implement the word meaning. It also signals
-better that we always have some kind of an implementation
-reason that can be formualated.
-Compatibility? how to introduce a new name/keep compat?
-
-allow to non-intrusively apply skipfs/xfail/marks
----------------------------------------------------
-tags: feature
-
-use case: mark a module or directory structures
-to be skipped on certain platforms (i.e. no import
-attempt will be made).
-
-consider introducing a hook/mechanism that allows to apply marks
-from conftests or plugins. (See extended parametrization)
-
-
-explicit referencing of conftest.py files
------------------------------------------
-tags: feature
-
-allow to name conftest.py files (in sub directories) that should
-be imported early, as to include command line options.
-
-improve central pytest ini file
--------------------------------
-tags: feature
-
-introduce more declarative configuration options:
-- (to-be-collected test directories)
-- required plugins
-- test func/class/file matching patterns
-- skip/xfail (non-intrusive)
-- pytest.ini and tox.ini and setup.cfg configuration in the same file
-
-new documentation
-----------------------------------
-tags: feature
-
-- logo pytest
-- examples for unittest or functional testing
-- resource management for functional testing
-- patterns: page object
-
-have imported module mismatch honour relative paths
---------------------------------------------------------
-tags: bug
-
-With 1.1.1 pytest fails at least on windows if an import
-is relative and compared against an absolute conftest.py
-path. Normalize.
-
-consider globals: pytest.ensuretemp and config
---------------------------------------------------------------
-tags: experimental-wish
-
-consider deprecating pytest.ensuretemp and pytest.config
-to further reduce pytest globality. Also consider
-having pytest.config and ensuretemp coming from
-a plugin rather than being there from the start.
-
-
-consider pytest_addsyspath hook
------------------------------------------
-tags: wish
-
-pytest could call a new pytest_addsyspath() in order to systematically
-allow manipulation of sys.path and to inhibit it via --no-addsyspath
-in order to more easily run against installed packages.
-
-Alternatively it could also be done via the config object
-and pytest_configure.
-
-
-
-deprecate global pytest.config usage
-----------------------------------------------------------------
-tags: feature
-
-pytest.ensuretemp and pytest.config are probably the last
-objects containing global state. Often using them is not
-necessary. This is about trying to get rid of them, i.e.
-deprecating them and checking with PyPy's usages as well
-as others.
-
-remove deprecated bits in collect.py
--------------------------------------------------------------------
-tags: feature
-
-In an effort to further simplify code, review and remove deprecated bits
-in collect.py. Probably good:
-- inline consider_file/dir methods, no need to have them
- subclass-overridable because of hooks
-
-implement fslayout decorator
----------------------------------
-tags: feature
-
-Improve the way how tests can work with pre-made examples,
-keeping the layout close to the test function:
-
-@pytest.mark.fslayout("""
- conftest.py:
- # empty
- tests/
- test_%(NAME)s: # becomes test_run1.py
- def test_function(self):
- pass
-""")
-def test_run(pytester, fslayout):
- p = fslayout.findone("test_*.py")
- result = pytester.runpytest(p)
- assert result.ret == 0
- assert result.passed == 1
-
-Another idea is to allow to define a full scenario including the run
-in one content string::
-
- runscenario("""
- test_{TESTNAME}.py:
- import pytest
- @pytest.mark.xfail
- def test_that_fails():
- assert 0
-
- @pytest.mark.skipif("True")
- def test_hello():
- pass
-
- conftest.py:
- import pytest
- def pytest_runsetup_setup(item):
- pytest.skip("abc")
-
- runpytest -rsxX
- *SKIP*{TESTNAME}*
- *1 skipped*
- """)
-
-This could be run with at least three different ways to invoke pytest:
-through the shell, through "python -m pytest" and inlined. As inlined
-would be the fastest it could be run first (or "--fast" mode).
-
-
-Create isolate plugin
----------------------
-tags: feature
-
-The idea is that you can e.g. import modules in a test and afterwards
-sys.modules, sys.meta_path etc would be reverted. It can go further
-then just importing however, e.g. current working directory, file
-descriptors, ...
-
-This would probably be done by marking::
-
- @pytest.mark.isolate(importing=True, cwd=True, fds=False)
- def test_foo():
- ...
-
-With the possibility of doing this globally in an ini-file.
-
-
-fnmatch for test names
-----------------------
-tags: feature-wish
-
-various testsuites use suffixes instead of prefixes for test classes
-also it lends itself to bdd style test names::
-
- class UserBehaviour:
- def anonymous_should_not_have_inbox(user):
- ...
- def registred_should_have_inbox(user):
- ..
-
-using the following in pytest.ini::
-
- [pytest]
- python_classes = Test *Behaviour *Test
- python_functions = test *_should_*
-
-
-mechanism for running named parts of tests with different reporting behaviour
-------------------------------------------------------------------------------
-tags: feature-wish-incomplete
-
-a few use-cases come to mind:
-
-* fail assertions and record that without stopping a complete test
-
- * this is in particular hepfull if a small bit of a test is known to fail/xfail::
-
- def test_fun():
- with pytest.section('fdcheck, marks=pytest.mark.xfail_if(...)):
- breaks_on_windows()
-
-* divide functional/acceptance tests into sections
-* provide a different mechanism for generators, maybe something like::
-
- def pytest_runtest_call(item)
- if not generator:
- ...
- prepare_check = GeneratorCheckprepare()
-
- gen = item.obj(**fixtures)
- for check in gen
- id, call = prepare_check(check)
- # bubble should only prevent exception propagation after a failure
- # the whole test should still fail
- # there might be need for a lower level api and taking custom markers into account
- with pytest.section(id, bubble=False):
- call()
-
-
diff --git a/WebDriverTests/imported/w3c/tools/pytest/LICENSE b/WebDriverTests/imported/w3c/tools/pytest/LICENSE
deleted file mode 100644
index 9e27bd78..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2004-2016 Holger Krekel and others
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/WebDriverTests/imported/w3c/tools/pytest/MANIFEST.in b/WebDriverTests/imported/w3c/tools/pytest/MANIFEST.in
deleted file mode 100644
index 266a918..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/MANIFEST.in
+++ /dev/null
@@ -1,34 +0,0 @@
-include CHANGELOG.rst
-include LICENSE
-include AUTHORS
-
-include README.rst
-include CONTRIBUTING.rst
-
-include tox.ini
-include setup.py
-
-include .coveragerc
-
-include plugin-test.sh
-include requirements-docs.txt
-include runtox.py
-
-recursive-include bench *.py
-recursive-include extra *.py
-
-graft testing
-graft doc
-
-exclude _pytest/impl
-
-graft _pytest/vendored_packages
-
-recursive-exclude * *.pyc *.pyo
-
-exclude appveyor/install.ps1
-exclude appveyor.yml
-exclude appveyor
-
-exclude ISSUES.txt
-exclude HOWTORELEASE.rst
diff --git a/WebDriverTests/imported/w3c/tools/pytest/README.rst b/WebDriverTests/imported/w3c/tools/pytest/README.rst
deleted file mode 100644
index 68fc922..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/README.rst
+++ /dev/null
@@ -1,102 +0,0 @@
-.. image:: http://pytest.org/latest/_static/pytest1.png
- :target: http://pytest.org
- :align: center
- :alt: pytest
-
-------
-
-.. image:: https://img.shields.io/pypi/v/pytest.svg
- :target: https://pypi.python.org/pypi/pytest
-.. image:: https://img.shields.io/pypi/pyversions/pytest.svg
- :target: https://pypi.python.org/pypi/pytest
-.. image:: https://img.shields.io/coveralls/pytest-dev/pytest/master.svg
- :target: https://coveralls.io/r/pytest-dev/pytest
-.. image:: https://travis-ci.org/pytest-dev/pytest.svg?branch=master
- :target: https://travis-ci.org/pytest-dev/pytest
-.. image:: https://ci.appveyor.com/api/projects/status/mrgbjaua7t33pg6b?svg=true
- :target: https://ci.appveyor.com/project/pytestbot/pytest
-
-The ``pytest`` framework makes it easy to write small tests, yet
-scales to support complex functional testing for applications and libraries.
-
-An example of a simple test:
-
-.. code-block:: python
-
- # content of test_sample.py
- def func(x):
- return x + 1
-
- def test_answer():
- assert func(3) == 5
-
-
-To execute it::
-
- $ py.test
- ======= test session starts ========
- platform linux -- Python 3.4.3, pytest-2.8.5, py-1.4.31, pluggy-0.3.1
- collected 1 items
-
- test_sample.py F
-
- ======= FAILURES ========
- _______ test_answer ________
-
- def test_answer():
- > assert func(3) == 5
- E assert 4 == 5
- E + where 4 = func(3)
-
- test_sample.py:5: AssertionError
- ======= 1 failed in 0.12 seconds ========
-
-Due to ``py.test``'s detailed assertion introspection, only plain ``assert`` statements are used. See `getting-started <http://pytest.org/latest/getting-started.html#our-first-test-run>`_ for more examples.
-
-
-Features
---------
-
-- Detailed info on failing `assert statements <http://pytest.org/latest/assert.html>`_ (no need to remember ``self.assert*`` names);
-
-- `Auto-discovery
- <http://pytest.org/latest/goodpractices.html#python-test-discovery>`_
- of test modules and functions;
-
-- `Modular fixtures <http://pytest.org/latest/fixture.html>`_ for
- managing small or parametrized long-lived test resources;
-
-- Can run `unittest <http://pytest.org/latest/unittest.html>`_ (or trial),
- `nose <http://pytest.org/latest/nose.html>`_ test suites out of the box;
-
-- Python2.6+, Python3.2+, PyPy-2.3, Jython-2.5 (untested);
-
-- Rich plugin architecture, with over 150+ `external plugins <http://pytest.org/latest/plugins.html#installing-external-plugins-searching>`_ and thriving community;
-
-
-Documentation
--------------
-
-For full documentation, including installation, tutorials and PDF documents, please see http://pytest.org.
-
-
-Bugs/Requests
--------------
-
-Please use the `GitHub issue tracker <https://github.com/pytest-dev/pytest/issues>`_ to submit bugs or request features.
-
-
-Changelog
----------
-
-Consult the `Changelog <http://pytest.org/latest/changelog.html>`_ page for fixes and enhancements of each version.
-
-
-License
--------
-
-Copyright Holger Krekel and others, 2004-2016.
-
-Distributed under the terms of the `MIT`_ license, pytest is free and open source software.
-
-.. _`MIT`: https://github.com/pytest-dev/pytest/blob/master/LICENSE
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/__init__.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/__init__.py
deleted file mode 100644
index 723fb9e..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-#
-__version__ = '2.9.1'
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/_argcomplete.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/_argcomplete.py
deleted file mode 100644
index 955855a..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/_argcomplete.py
+++ /dev/null
@@ -1,101 +0,0 @@
-
-"""allow bash-completion for argparse with argcomplete if installed
-needs argcomplete>=0.5.6 for python 3.2/3.3 (older versions fail
-to find the magic string, so _ARGCOMPLETE env. var is never set, and
-this does not need special code.
-
-argcomplete does not support python 2.5 (although the changes for that
-are minor).
-
-Function try_argcomplete(parser) should be called directly before
-the call to ArgumentParser.parse_args().
-
-The filescompleter is what you normally would use on the positional
-arguments specification, in order to get "dirname/" after "dirn<TAB>"
-instead of the default "dirname ":
-
- optparser.add_argument(Config._file_or_dir, nargs='*'
- ).completer=filescompleter
-
-Other, application specific, completers should go in the file
-doing the add_argument calls as they need to be specified as .completer
-attributes as well. (If argcomplete is not installed, the function the
-attribute points to will not be used).
-
-SPEEDUP
-=======
-The generic argcomplete script for bash-completion
-(/etc/bash_completion.d/python-argcomplete.sh )
-uses a python program to determine startup script generated by pip.
-You can speed up completion somewhat by changing this script to include
- # PYTHON_ARGCOMPLETE_OK
-so the the python-argcomplete-check-easy-install-script does not
-need to be called to find the entry point of the code and see if that is
-marked with PYTHON_ARGCOMPLETE_OK
-
-INSTALL/DEBUGGING
-=================
-To include this support in another application that has setup.py generated
-scripts:
-- add the line:
- # PYTHON_ARGCOMPLETE_OK
- near the top of the main python entry point
-- include in the file calling parse_args():
- from _argcomplete import try_argcomplete, filescompleter
- , call try_argcomplete just before parse_args(), and optionally add
- filescompleter to the positional arguments' add_argument()
-If things do not work right away:
-- switch on argcomplete debugging with (also helpful when doing custom
- completers):
- export _ARC_DEBUG=1
-- run:
- python-argcomplete-check-easy-install-script $(which appname)
- echo $?
- will echo 0 if the magic line has been found, 1 if not
-- sometimes it helps to find early on errors using:
- _ARGCOMPLETE=1 _ARC_DEBUG=1 appname
- which should throw a KeyError: 'COMPLINE' (which is properly set by the
- global argcomplete script).
-"""
-
-import sys
-import os
-from glob import glob
-
-class FastFilesCompleter:
- 'Fast file completer class'
- def __init__(self, directories=True):
- self.directories = directories
-
- def __call__(self, prefix, **kwargs):
- """only called on non option completions"""
- if os.path.sep in prefix[1:]: #
- prefix_dir = len(os.path.dirname(prefix) + os.path.sep)
- else:
- prefix_dir = 0
- completion = []
- globbed = []
- if '*' not in prefix and '?' not in prefix:
- if prefix[-1] == os.path.sep: # we are on unix, otherwise no bash
- globbed.extend(glob(prefix + '.*'))
- prefix += '*'
- globbed.extend(glob(prefix))
- for x in sorted(globbed):
- if os.path.isdir(x):
- x += '/'
- # append stripping the prefix (like bash, not like compgen)
- completion.append(x[prefix_dir:])
- return completion
-
-if os.environ.get('_ARGCOMPLETE'):
- try:
- import argcomplete.completers
- except ImportError:
- sys.exit(-1)
- filescompleter = FastFilesCompleter()
-
- def try_argcomplete(parser):
- argcomplete.autocomplete(parser)
-else:
- def try_argcomplete(parser): pass
- filescompleter = None
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/_code/__init__.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/_code/__init__.py
deleted file mode 100644
index c046b97..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/_code/__init__.py
+++ /dev/null
@@ -1,12 +0,0 @@
-""" python inspection/code generation API """
-from .code import Code # noqa
-from .code import ExceptionInfo # noqa
-from .code import Frame # noqa
-from .code import Traceback # noqa
-from .code import getrawcode # noqa
-from .code import patch_builtins # noqa
-from .code import unpatch_builtins # noqa
-from .source import Source # noqa
-from .source import compile_ as compile # noqa
-from .source import getfslineno # noqa
-
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/_code/_py2traceback.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/_code/_py2traceback.py
deleted file mode 100644
index a830d98..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/_code/_py2traceback.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# copied from python-2.7.3's traceback.py
-# CHANGES:
-# - some_str is replaced, trying to create unicode strings
-#
-import types
-
-def format_exception_only(etype, value):
- """Format the exception part of a traceback.
-
- The arguments are the exception type and value such as given by
- sys.last_type and sys.last_value. The return value is a list of
- strings, each ending in a newline.
-
- Normally, the list contains a single string; however, for
- SyntaxError exceptions, it contains several lines that (when
- printed) display detailed information about where the syntax
- error occurred.
-
- The message indicating which exception occurred is always the last
- string in the list.
-
- """
-
- # An instance should not have a meaningful value parameter, but
- # sometimes does, particularly for string exceptions, such as
- # >>> raise string1, string2 # deprecated
- #
- # Clear these out first because issubtype(string1, SyntaxError)
- # would throw another exception and mask the original problem.
- if (isinstance(etype, BaseException) or
- isinstance(etype, types.InstanceType) or
- etype is None or type(etype) is str):
- return [_format_final_exc_line(etype, value)]
-
- stype = etype.__name__
-
- if not issubclass(etype, SyntaxError):
- return [_format_final_exc_line(stype, value)]
-
- # It was a syntax error; show exactly where the problem was found.
- lines = []
- try:
- msg, (filename, lineno, offset, badline) = value.args
- except Exception:
- pass
- else:
- filename = filename or "<string>"
- lines.append(' File "%s", line %d\n' % (filename, lineno))
- if badline is not None:
- if isinstance(badline, bytes): # python 2 only
- badline = badline.decode('utf-8', 'replace')
- lines.append(u' %s\n' % badline.strip())
- if offset is not None:
- caretspace = badline.rstrip('\n')[:offset].lstrip()
- # non-space whitespace (likes tabs) must be kept for alignment
- caretspace = ((c.isspace() and c or ' ') for c in caretspace)
- # only three spaces to account for offset1 == pos 0
- lines.append(' %s^\n' % ''.join(caretspace))
- value = msg
-
- lines.append(_format_final_exc_line(stype, value))
- return lines
-
-def _format_final_exc_line(etype, value):
- """Return a list of a single line -- normal case for format_exception_only"""
- valuestr = _some_str(value)
- if value is None or not valuestr:
- line = "%s\n" % etype
- else:
- line = "%s: %s\n" % (etype, valuestr)
- return line
-
-def _some_str(value):
- try:
- return unicode(value)
- except Exception:
- try:
- return str(value)
- except Exception:
- pass
- return '<unprintable %s object>' % type(value).__name__
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/_code/code.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/_code/code.py
deleted file mode 100644
index bc68aac..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/_code/code.py
+++ /dev/null
@@ -1,795 +0,0 @@
-import sys
-from inspect import CO_VARARGS, CO_VARKEYWORDS
-
-import py
-
-builtin_repr = repr
-
-reprlib = py.builtin._tryimport('repr', 'reprlib')
-
-if sys.version_info[0] >= 3:
- from traceback import format_exception_only
-else:
- from ._py2traceback import format_exception_only
-
-class Code(object):
- """ wrapper around Python code objects """
- def __init__(self, rawcode):
- if not hasattr(rawcode, "co_filename"):
- rawcode = getrawcode(rawcode)
- try:
- self.filename = rawcode.co_filename
- self.firstlineno = rawcode.co_firstlineno - 1
- self.name = rawcode.co_name
- except AttributeError:
- raise TypeError("not a code object: %r" %(rawcode,))
- self.raw = rawcode
-
- def __eq__(self, other):
- return self.raw == other.raw
-
- def __ne__(self, other):
- return not self == other
-
- @property
- def path(self):
- """ return a path object pointing to source code (note that it
- might not point to an actually existing file). """
- p = py.path.local(self.raw.co_filename)
- # maybe don't try this checking
- if not p.check():
- # XXX maybe try harder like the weird logic
- # in the standard lib [linecache.updatecache] does?
- p = self.raw.co_filename
- return p
-
- @property
- def fullsource(self):
- """ return a _pytest._code.Source object for the full source file of the code
- """
- from _pytest._code import source
- full, _ = source.findsource(self.raw)
- return full
-
- def source(self):
- """ return a _pytest._code.Source object for the code object's source only
- """
- # return source only for that part of code
- import _pytest._code
- return _pytest._code.Source(self.raw)
-
- def getargs(self, var=False):
- """ return a tuple with the argument names for the code object
-
- if 'var' is set True also return the names of the variable and
- keyword arguments when present
- """
- # handfull shortcut for getting args
- raw = self.raw
- argcount = raw.co_argcount
- if var:
- argcount += raw.co_flags & CO_VARARGS
- argcount += raw.co_flags & CO_VARKEYWORDS
- return raw.co_varnames[:argcount]
-
-class Frame(object):
- """Wrapper around a Python frame holding f_locals and f_globals
- in which expressions can be evaluated."""
-
- def __init__(self, frame):
- self.lineno = frame.f_lineno - 1
- self.f_globals = frame.f_globals
- self.f_locals = frame.f_locals
- self.raw = frame
- self.code = Code(frame.f_code)
-
- @property
- def statement(self):
- """ statement this frame is at """
- import _pytest._code
- if self.code.fullsource is None:
- return _pytest._code.Source("")
- return self.code.fullsource.getstatement(self.lineno)
-
- def eval(self, code, **vars):
- """ evaluate 'code' in the frame
-
- 'vars' are optional additional local variables
-
- returns the result of the evaluation
- """
- f_locals = self.f_locals.copy()
- f_locals.update(vars)
- return eval(code, self.f_globals, f_locals)
-
- def exec_(self, code, **vars):
- """ exec 'code' in the frame
-
- 'vars' are optiona; additional local variables
- """
- f_locals = self.f_locals.copy()
- f_locals.update(vars)
- py.builtin.exec_(code, self.f_globals, f_locals )
-
- def repr(self, object):
- """ return a 'safe' (non-recursive, one-line) string repr for 'object'
- """
- return py.io.saferepr(object)
-
- def is_true(self, object):
- return object
-
- def getargs(self, var=False):
- """ return a list of tuples (name, value) for all arguments
-
- if 'var' is set True also include the variable and keyword
- arguments when present
- """
- retval = []
- for arg in self.code.getargs(var):
- try:
- retval.append((arg, self.f_locals[arg]))
- except KeyError:
- pass # this can occur when using Psyco
- return retval
-
-class TracebackEntry(object):
- """ a single entry in a traceback """
-
- _repr_style = None
- exprinfo = None
-
- def __init__(self, rawentry):
- self._rawentry = rawentry
- self.lineno = rawentry.tb_lineno - 1
-
- def set_repr_style(self, mode):
- assert mode in ("short", "long")
- self._repr_style = mode
-
- @property
- def frame(self):
- import _pytest._code
- return _pytest._code.Frame(self._rawentry.tb_frame)
-
- @property
- def relline(self):
- return self.lineno - self.frame.code.firstlineno
-
- def __repr__(self):
- return "<TracebackEntry %s:%d>" %(self.frame.code.path, self.lineno+1)
-
- @property
- def statement(self):
- """ _pytest._code.Source object for the current statement """
- source = self.frame.code.fullsource
- return source.getstatement(self.lineno)
-
- @property
- def path(self):
- """ path to the source code """
- return self.frame.code.path
-
- def getlocals(self):
- return self.frame.f_locals
- locals = property(getlocals, None, None, "locals of underlaying frame")
-
- def reinterpret(self):
- """Reinterpret the failing statement and returns a detailed information
- about what operations are performed."""
- from _pytest.assertion.reinterpret import reinterpret
- if self.exprinfo is None:
- source = py.builtin._totext(self.statement).strip()
- x = reinterpret(source, self.frame, should_fail=True)
- if not py.builtin._istext(x):
- raise TypeError("interpret returned non-string %r" % (x,))
- self.exprinfo = x
- return self.exprinfo
-
- def getfirstlinesource(self):
- # on Jython this firstlineno can be -1 apparently
- return max(self.frame.code.firstlineno, 0)
-
- def getsource(self, astcache=None):
- """ return failing source code. """
- # we use the passed in astcache to not reparse asttrees
- # within exception info printing
- from _pytest._code.source import getstatementrange_ast
- source = self.frame.code.fullsource
- if source is None:
- return None
- key = astnode = None
- if astcache is not None:
- key = self.frame.code.path
- if key is not None:
- astnode = astcache.get(key, None)
- start = self.getfirstlinesource()
- try:
- astnode, _, end = getstatementrange_ast(self.lineno, source,
- astnode=astnode)
- except SyntaxError:
- end = self.lineno + 1
- else:
- if key is not None:
- astcache[key] = astnode
- return source[start:end]
-
- source = property(getsource)
-
- def ishidden(self):
- """ return True if the current frame has a var __tracebackhide__
- resolving to True
-
- mostly for internal use
- """
- try:
- return self.frame.f_locals['__tracebackhide__']
- except KeyError:
- try:
- return self.frame.f_globals['__tracebackhide__']
- except KeyError:
- return False
-
- def __str__(self):
- try:
- fn = str(self.path)
- except py.error.Error:
- fn = '???'
- name = self.frame.code.name
- try:
- line = str(self.statement).lstrip()
- except KeyboardInterrupt:
- raise
- except:
- line = "???"
- return " File %r:%d in %s\n %s\n" %(fn, self.lineno+1, name, line)
-
- def name(self):
- return self.frame.code.raw.co_name
- name = property(name, None, None, "co_name of underlaying code")
-
-class Traceback(list):
- """ Traceback objects encapsulate and offer higher level
- access to Traceback entries.
- """
- Entry = TracebackEntry
- def __init__(self, tb):
- """ initialize from given python traceback object. """
- if hasattr(tb, 'tb_next'):
- def f(cur):
- while cur is not None:
- yield self.Entry(cur)
- cur = cur.tb_next
- list.__init__(self, f(tb))
- else:
- list.__init__(self, tb)
-
- def cut(self, path=None, lineno=None, firstlineno=None, excludepath=None):
- """ return a Traceback instance wrapping part of this Traceback
-
- by provding any combination of path, lineno and firstlineno, the
- first frame to start the to-be-returned traceback is determined
-
- this allows cutting the first part of a Traceback instance e.g.
- for formatting reasons (removing some uninteresting bits that deal
- with handling of the exception/traceback)
- """
- for x in self:
- code = x.frame.code
- codepath = code.path
- if ((path is None or codepath == path) and
- (excludepath is None or not hasattr(codepath, 'relto') or
- not codepath.relto(excludepath)) and
- (lineno is None or x.lineno == lineno) and
- (firstlineno is None or x.frame.code.firstlineno == firstlineno)):
- return Traceback(x._rawentry)
- return self
-
- def __getitem__(self, key):
- val = super(Traceback, self).__getitem__(key)
- if isinstance(key, type(slice(0))):
- val = self.__class__(val)
- return val
-
- def filter(self, fn=lambda x: not x.ishidden()):
- """ return a Traceback instance with certain items removed
-
- fn is a function that gets a single argument, a TracebackItem
- instance, and should return True when the item should be added
- to the Traceback, False when not
-
- by default this removes all the TracebackItems which are hidden
- (see ishidden() above)
- """
- return Traceback(filter(fn, self))
-
- def getcrashentry(self):
- """ return last non-hidden traceback entry that lead
- to the exception of a traceback.
- """
- for i in range(-1, -len(self)-1, -1):
- entry = self[i]
- if not entry.ishidden():
- return entry
- return self[-1]
-
- def recursionindex(self):
- """ return the index of the frame/TracebackItem where recursion
- originates if appropriate, None if no recursion occurred
- """
- cache = {}
- for i, entry in enumerate(self):
- # id for the code.raw is needed to work around
- # the strange metaprogramming in the decorator lib from pypi
- # which generates code objects that have hash/value equality
- #XXX needs a test
- key = entry.frame.code.path, id(entry.frame.code.raw), entry.lineno
- #print "checking for recursion at", key
- l = cache.setdefault(key, [])
- if l:
- f = entry.frame
- loc = f.f_locals
- for otherloc in l:
- if f.is_true(f.eval(co_equal,
- __recursioncache_locals_1=loc,
- __recursioncache_locals_2=otherloc)):
- return i
- l.append(entry.frame.f_locals)
- return None
-
-co_equal = compile('__recursioncache_locals_1 == __recursioncache_locals_2',
- '?', 'eval')
-
-class ExceptionInfo(object):
- """ wraps sys.exc_info() objects and offers
- help for navigating the traceback.
- """
- _striptext = ''
- def __init__(self, tup=None, exprinfo=None):
- import _pytest._code
- if tup is None:
- tup = sys.exc_info()
- if exprinfo is None and isinstance(tup[1], AssertionError):
- exprinfo = getattr(tup[1], 'msg', None)
- if exprinfo is None:
- exprinfo = str(tup[1])
- if exprinfo and exprinfo.startswith('assert '):
- self._striptext = 'AssertionError: '
- self._excinfo = tup
- #: the exception class
- self.type = tup[0]
- #: the exception instance
- self.value = tup[1]
- #: the exception raw traceback
- self.tb = tup[2]
- #: the exception type name
- self.typename = self.type.__name__
- #: the exception traceback (_pytest._code.Traceback instance)
- self.traceback = _pytest._code.Traceback(self.tb)
-
- def __repr__(self):
- return "<ExceptionInfo %s tblen=%d>" % (self.typename, len(self.traceback))
-
- def exconly(self, tryshort=False):
- """ return the exception as a string
-
- when 'tryshort' resolves to True, and the exception is a
- _pytest._code._AssertionError, only the actual exception part of
- the exception representation is returned (so 'AssertionError: ' is
- removed from the beginning)
- """
- lines = format_exception_only(self.type, self.value)
- text = ''.join(lines)
- text = text.rstrip()
- if tryshort:
- if text.startswith(self._striptext):
- text = text[len(self._striptext):]
- return text
-
- def errisinstance(self, exc):
- """ return True if the exception is an instance of exc """
- return isinstance(self.value, exc)
-
- def _getreprcrash(self):
- exconly = self.exconly(tryshort=True)
- entry = self.traceback.getcrashentry()
- path, lineno = entry.frame.code.raw.co_filename, entry.lineno
- return ReprFileLocation(path, lineno+1, exconly)
-
- def getrepr(self, showlocals=False, style="long",
- abspath=False, tbfilter=True, funcargs=False):
- """ return str()able representation of this exception info.
- showlocals: show locals per traceback entry
- style: long|short|no|native traceback style
- tbfilter: hide entries (where __tracebackhide__ is true)
-
- in case of style==native, tbfilter and showlocals is ignored.
- """
- if style == 'native':
- return ReprExceptionInfo(ReprTracebackNative(
- py.std.traceback.format_exception(
- self.type,
- self.value,
- self.traceback[0]._rawentry,
- )), self._getreprcrash())
-
- fmt = FormattedExcinfo(showlocals=showlocals, style=style,
- abspath=abspath, tbfilter=tbfilter, funcargs=funcargs)
- return fmt.repr_excinfo(self)
-
- def __str__(self):
- entry = self.traceback[-1]
- loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
- return str(loc)
-
- def __unicode__(self):
- entry = self.traceback[-1]
- loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
- return unicode(loc)
-
-
-class FormattedExcinfo(object):
- """ presenting information about failing Functions and Generators. """
- # for traceback entries
- flow_marker = ">"
- fail_marker = "E"
-
- def __init__(self, showlocals=False, style="long", abspath=True, tbfilter=True, funcargs=False):
- self.showlocals = showlocals
- self.style = style
- self.tbfilter = tbfilter
- self.funcargs = funcargs
- self.abspath = abspath
- self.astcache = {}
-
- def _getindent(self, source):
- # figure out indent for given source
- try:
- s = str(source.getstatement(len(source)-1))
- except KeyboardInterrupt:
- raise
- except:
- try:
- s = str(source[-1])
- except KeyboardInterrupt:
- raise
- except:
- return 0
- return 4 + (len(s) - len(s.lstrip()))
-
- def _getentrysource(self, entry):
- source = entry.getsource(self.astcache)
- if source is not None:
- source = source.deindent()
- return source
-
- def _saferepr(self, obj):
- return py.io.saferepr(obj)
-
- def repr_args(self, entry):
- if self.funcargs:
- args = []
- for argname, argvalue in entry.frame.getargs(var=True):
- args.append((argname, self._saferepr(argvalue)))
- return ReprFuncArgs(args)
-
- def get_source(self, source, line_index=-1, excinfo=None, short=False):
- """ return formatted and marked up source lines. """
- import _pytest._code
- lines = []
- if source is None or line_index >= len(source.lines):
- source = _pytest._code.Source("???")
- line_index = 0
- if line_index < 0:
- line_index += len(source)
- space_prefix = " "
- if short:
- lines.append(space_prefix + source.lines[line_index].strip())
- else:
- for line in source.lines[:line_index]:
- lines.append(space_prefix + line)
- lines.append(self.flow_marker + " " + source.lines[line_index])
- for line in source.lines[line_index+1:]:
- lines.append(space_prefix + line)
- if excinfo is not None:
- indent = 4 if short else self._getindent(source)
- lines.extend(self.get_exconly(excinfo, indent=indent, markall=True))
- return lines
-
- def get_exconly(self, excinfo, indent=4, markall=False):
- lines = []
- indent = " " * indent
- # get the real exception information out
- exlines = excinfo.exconly(tryshort=True).split('\n')
- failindent = self.fail_marker + indent[1:]
- for line in exlines:
- lines.append(failindent + line)
- if not markall:
- failindent = indent
- return lines
-
- def repr_locals(self, locals):
- if self.showlocals:
- lines = []
- keys = [loc for loc in locals if loc[0] != "@"]
- keys.sort()
- for name in keys:
- value = locals[name]
- if name == '__builtins__':
- lines.append("__builtins__ = <builtins>")
- else:
- # This formatting could all be handled by the
- # _repr() function, which is only reprlib.Repr in
- # disguise, so is very configurable.
- str_repr = self._saferepr(value)
- #if len(str_repr) < 70 or not isinstance(value,
- # (list, tuple, dict)):
- lines.append("%-10s = %s" %(name, str_repr))
- #else:
- # self._line("%-10s =\\" % (name,))
- # # XXX
- # py.std.pprint.pprint(value, stream=self.excinfowriter)
- return ReprLocals(lines)
-
- def repr_traceback_entry(self, entry, excinfo=None):
- import _pytest._code
- source = self._getentrysource(entry)
- if source is None:
- source = _pytest._code.Source("???")
- line_index = 0
- else:
- # entry.getfirstlinesource() can be -1, should be 0 on jython
- line_index = entry.lineno - max(entry.getfirstlinesource(), 0)
-
- lines = []
- style = entry._repr_style
- if style is None:
- style = self.style
- if style in ("short", "long"):
- short = style == "short"
- reprargs = self.repr_args(entry) if not short else None
- s = self.get_source(source, line_index, excinfo, short=short)
- lines.extend(s)
- if short:
- message = "in %s" %(entry.name)
- else:
- message = excinfo and excinfo.typename or ""
- path = self._makepath(entry.path)
- filelocrepr = ReprFileLocation(path, entry.lineno+1, message)
- localsrepr = None
- if not short:
- localsrepr = self.repr_locals(entry.locals)
- return ReprEntry(lines, reprargs, localsrepr, filelocrepr, style)
- if excinfo:
- lines.extend(self.get_exconly(excinfo, indent=4))
- return ReprEntry(lines, None, None, None, style)
-
- def _makepath(self, path):
- if not self.abspath:
- try:
- np = py.path.local().bestrelpath(path)
- except OSError:
- return path
- if len(np) < len(str(path)):
- path = np
- return path
-
- def repr_traceback(self, excinfo):
- traceback = excinfo.traceback
- if self.tbfilter:
- traceback = traceback.filter()
- recursionindex = None
- if excinfo.errisinstance(RuntimeError):
- if "maximum recursion depth exceeded" in str(excinfo.value):
- recursionindex = traceback.recursionindex()
- last = traceback[-1]
- entries = []
- extraline = None
- for index, entry in enumerate(traceback):
- einfo = (last == entry) and excinfo or None
- reprentry = self.repr_traceback_entry(entry, einfo)
- entries.append(reprentry)
- if index == recursionindex:
- extraline = "!!! Recursion detected (same locals & position)"
- break
- return ReprTraceback(entries, extraline, style=self.style)
-
- def repr_excinfo(self, excinfo):
- reprtraceback = self.repr_traceback(excinfo)
- reprcrash = excinfo._getreprcrash()
- return ReprExceptionInfo(reprtraceback, reprcrash)
-
-class TerminalRepr:
- def __str__(self):
- s = self.__unicode__()
- if sys.version_info[0] < 3:
- s = s.encode('utf-8')
- return s
-
- def __unicode__(self):
- # FYI this is called from pytest-xdist's serialization of exception
- # information.
- io = py.io.TextIO()
- tw = py.io.TerminalWriter(file=io)
- self.toterminal(tw)
- return io.getvalue().strip()
-
- def __repr__(self):
- return "<%s instance at %0x>" %(self.__class__, id(self))
-
-
-class ReprExceptionInfo(TerminalRepr):
- def __init__(self, reprtraceback, reprcrash):
- self.reprtraceback = reprtraceback
- self.reprcrash = reprcrash
- self.sections = []
-
- def addsection(self, name, content, sep="-"):
- self.sections.append((name, content, sep))
-
- def toterminal(self, tw):
- self.reprtraceback.toterminal(tw)
- for name, content, sep in self.sections:
- tw.sep(sep, name)
- tw.line(content)
-
-class ReprTraceback(TerminalRepr):
- entrysep = "_ "
-
- def __init__(self, reprentries, extraline, style):
- self.reprentries = reprentries
- self.extraline = extraline
- self.style = style
-
- def toterminal(self, tw):
- # the entries might have different styles
- for i, entry in enumerate(self.reprentries):
- if entry.style == "long":
- tw.line("")
- entry.toterminal(tw)
- if i < len(self.reprentries) - 1:
- next_entry = self.reprentries[i+1]
- if entry.style == "long" or \
- entry.style == "short" and next_entry.style == "long":
- tw.sep(self.entrysep)
-
- if self.extraline:
- tw.line(self.extraline)
-
-class ReprTracebackNative(ReprTraceback):
- def __init__(self, tblines):
- self.style = "native"
- self.reprentries = [ReprEntryNative(tblines)]
- self.extraline = None
-
-class ReprEntryNative(TerminalRepr):
- style = "native"
-
- def __init__(self, tblines):
- self.lines = tblines
-
- def toterminal(self, tw):
- tw.write("".join(self.lines))
-
-class ReprEntry(TerminalRepr):
- localssep = "_ "
-
- def __init__(self, lines, reprfuncargs, reprlocals, filelocrepr, style):
- self.lines = lines
- self.reprfuncargs = reprfuncargs
- self.reprlocals = reprlocals
- self.reprfileloc = filelocrepr
- self.style = style
-
- def toterminal(self, tw):
- if self.style == "short":
- self.reprfileloc.toterminal(tw)
- for line in self.lines:
- red = line.startswith("E ")
- tw.line(line, bold=True, red=red)
- #tw.line("")
- return
- if self.reprfuncargs:
- self.reprfuncargs.toterminal(tw)
- for line in self.lines:
- red = line.startswith("E ")
- tw.line(line, bold=True, red=red)
- if self.reprlocals:
- #tw.sep(self.localssep, "Locals")
- tw.line("")
- self.reprlocals.toterminal(tw)
- if self.reprfileloc:
- if self.lines:
- tw.line("")
- self.reprfileloc.toterminal(tw)
-
- def __str__(self):
- return "%s\n%s\n%s" % ("\n".join(self.lines),
- self.reprlocals,
- self.reprfileloc)
-
-class ReprFileLocation(TerminalRepr):
- def __init__(self, path, lineno, message):
- self.path = str(path)
- self.lineno = lineno
- self.message = message
-
- def toterminal(self, tw):
- # filename and lineno output for each entry,
- # using an output format that most editors unterstand
- msg = self.message
- i = msg.find("\n")
- if i != -1:
- msg = msg[:i]
- tw.line("%s:%s: %s" %(self.path, self.lineno, msg))
-
-class ReprLocals(TerminalRepr):
- def __init__(self, lines):
- self.lines = lines
-
- def toterminal(self, tw):
- for line in self.lines:
- tw.line(line)
-
-class ReprFuncArgs(TerminalRepr):
- def __init__(self, args):
- self.args = args
-
- def toterminal(self, tw):
- if self.args:
- linesofar = ""
- for name, value in self.args:
- ns = "%s = %s" %(name, value)
- if len(ns) + len(linesofar) + 2 > tw.fullwidth:
- if linesofar:
- tw.line(linesofar)
- linesofar = ns
- else:
- if linesofar:
- linesofar += ", " + ns
- else:
- linesofar = ns
- if linesofar:
- tw.line(linesofar)
- tw.line("")
-
-
-
-oldbuiltins = {}
-
-def patch_builtins(assertion=True, compile=True):
- """ put compile and AssertionError builtins to Python's builtins. """
- if assertion:
- from _pytest.assertion import reinterpret
- l = oldbuiltins.setdefault('AssertionError', [])
- l.append(py.builtin.builtins.AssertionError)
- py.builtin.builtins.AssertionError = reinterpret.AssertionError
- if compile:
- import _pytest._code
- l = oldbuiltins.setdefault('compile', [])
- l.append(py.builtin.builtins.compile)
- py.builtin.builtins.compile = _pytest._code.compile
-
-def unpatch_builtins(assertion=True, compile=True):
- """ remove compile and AssertionError builtins from Python builtins. """
- if assertion:
- py.builtin.builtins.AssertionError = oldbuiltins['AssertionError'].pop()
- if compile:
- py.builtin.builtins.compile = oldbuiltins['compile'].pop()
-
-def getrawcode(obj, trycall=True):
- """ return code object for given function. """
- try:
- return obj.__code__
- except AttributeError:
- obj = getattr(obj, 'im_func', obj)
- obj = getattr(obj, 'func_code', obj)
- obj = getattr(obj, 'f_code', obj)
- obj = getattr(obj, '__code__', obj)
- if trycall and not hasattr(obj, 'co_firstlineno'):
- if hasattr(obj, '__call__') and not py.std.inspect.isclass(obj):
- x = getrawcode(obj.__call__, trycall=False)
- if hasattr(x, 'co_firstlineno'):
- return x
- return obj
-
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/_code/source.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/_code/source.py
deleted file mode 100644
index a1521f8..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/_code/source.py
+++ /dev/null
@@ -1,421 +0,0 @@
-from __future__ import generators
-
-from bisect import bisect_right
-import sys
-import inspect, tokenize
-import py
-from types import ModuleType
-cpy_compile = compile
-
-try:
- import _ast
- from _ast import PyCF_ONLY_AST as _AST_FLAG
-except ImportError:
- _AST_FLAG = 0
- _ast = None
-
-
-class Source(object):
- """ a immutable object holding a source code fragment,
- possibly deindenting it.
- """
- _compilecounter = 0
- def __init__(self, *parts, **kwargs):
- self.lines = lines = []
- de = kwargs.get('deindent', True)
- rstrip = kwargs.get('rstrip', True)
- for part in parts:
- if not part:
- partlines = []
- if isinstance(part, Source):
- partlines = part.lines
- elif isinstance(part, (tuple, list)):
- partlines = [x.rstrip("\n") for x in part]
- elif isinstance(part, py.builtin._basestring):
- partlines = part.split('\n')
- if rstrip:
- while partlines:
- if partlines[-1].strip():
- break
- partlines.pop()
- else:
- partlines = getsource(part, deindent=de).lines
- if de:
- partlines = deindent(partlines)
- lines.extend(partlines)
-
- def __eq__(self, other):
- try:
- return self.lines == other.lines
- except AttributeError:
- if isinstance(other, str):
- return str(self) == other
- return False
-
- def __getitem__(self, key):
- if isinstance(key, int):
- return self.lines[key]
- else:
- if key.step not in (None, 1):
- raise IndexError("cannot slice a Source with a step")
- return self.__getslice__(key.start, key.stop)
-
- def __len__(self):
- return len(self.lines)
-
- def __getslice__(self, start, end):
- newsource = Source()
- newsource.lines = self.lines[start:end]
- return newsource
-
- def strip(self):
- """ return new source object with trailing
- and leading blank lines removed.
- """
- start, end = 0, len(self)
- while start < end and not self.lines[start].strip():
- start += 1
- while end > start and not self.lines[end-1].strip():
- end -= 1
- source = Source()
- source.lines[:] = self.lines[start:end]
- return source
-
- def putaround(self, before='', after='', indent=' ' * 4):
- """ return a copy of the source object with
- 'before' and 'after' wrapped around it.
- """
- before = Source(before)
- after = Source(after)
- newsource = Source()
- lines = [ (indent + line) for line in self.lines]
- newsource.lines = before.lines + lines + after.lines
- return newsource
-
- def indent(self, indent=' ' * 4):
- """ return a copy of the source object with
- all lines indented by the given indent-string.
- """
- newsource = Source()
- newsource.lines = [(indent+line) for line in self.lines]
- return newsource
-
- def getstatement(self, lineno, assertion=False):
- """ return Source statement which contains the
- given linenumber (counted from 0).
- """
- start, end = self.getstatementrange(lineno, assertion)
- return self[start:end]
-
- def getstatementrange(self, lineno, assertion=False):
- """ return (start, end) tuple which spans the minimal
- statement region which containing the given lineno.
- """
- if not (0 <= lineno < len(self)):
- raise IndexError("lineno out of range")
- ast, start, end = getstatementrange_ast(lineno, self)
- return start, end
-
- def deindent(self, offset=None):
- """ return a new source object deindented by offset.
- If offset is None then guess an indentation offset from
- the first non-blank line. Subsequent lines which have a
- lower indentation offset will be copied verbatim as
- they are assumed to be part of multilines.
- """
- # XXX maybe use the tokenizer to properly handle multiline
- # strings etc.pp?
- newsource = Source()
- newsource.lines[:] = deindent(self.lines, offset)
- return newsource
-
- def isparseable(self, deindent=True):
- """ return True if source is parseable, heuristically
- deindenting it by default.
- """
- try:
- import parser
- except ImportError:
- syntax_checker = lambda x: compile(x, 'asd', 'exec')
- else:
- syntax_checker = parser.suite
-
- if deindent:
- source = str(self.deindent())
- else:
- source = str(self)
- try:
- #compile(source+'\n', "x", "exec")
- syntax_checker(source+'\n')
- except KeyboardInterrupt:
- raise
- except Exception:
- return False
- else:
- return True
-
- def __str__(self):
- return "\n".join(self.lines)
-
- def compile(self, filename=None, mode='exec',
- flag=generators.compiler_flag,
- dont_inherit=0, _genframe=None):
- """ return compiled code object. if filename is None
- invent an artificial filename which displays
- the source/line position of the caller frame.
- """
- if not filename or py.path.local(filename).check(file=0):
- if _genframe is None:
- _genframe = sys._getframe(1) # the caller
- fn,lineno = _genframe.f_code.co_filename, _genframe.f_lineno
- base = "<%d-codegen " % self._compilecounter
- self.__class__._compilecounter += 1
- if not filename:
- filename = base + '%s:%d>' % (fn, lineno)
- else:
- filename = base + '%r %s:%d>' % (filename, fn, lineno)
- source = "\n".join(self.lines) + '\n'
- try:
- co = cpy_compile(source, filename, mode, flag)
- except SyntaxError:
- ex = sys.exc_info()[1]
- # re-represent syntax errors from parsing python strings
- msglines = self.lines[:ex.lineno]
- if ex.offset:
- msglines.append(" "*ex.offset + '^')
- msglines.append("(code was compiled probably from here: %s)" % filename)
- newex = SyntaxError('\n'.join(msglines))
- newex.offset = ex.offset
- newex.lineno = ex.lineno
- newex.text = ex.text
- raise newex
- else:
- if flag & _AST_FLAG:
- return co
- lines = [(x + "\n") for x in self.lines]
- if sys.version_info[0] >= 3:
- # XXX py3's inspect.getsourcefile() checks for a module
- # and a pep302 __loader__ ... we don't have a module
- # at code compile-time so we need to fake it here
- m = ModuleType("_pycodecompile_pseudo_module")
- py.std.inspect.modulesbyfile[filename] = None
- py.std.sys.modules[None] = m
- m.__loader__ = 1
- py.std.linecache.cache[filename] = (1, None, lines, filename)
- return co
-
-#
-# public API shortcut functions
-#
-
-def compile_(source, filename=None, mode='exec', flags=
- generators.compiler_flag, dont_inherit=0):
- """ compile the given source to a raw code object,
- and maintain an internal cache which allows later
- retrieval of the source code for the code object
- and any recursively created code objects.
- """
- if _ast is not None and isinstance(source, _ast.AST):
- # XXX should Source support having AST?
- return cpy_compile(source, filename, mode, flags, dont_inherit)
- _genframe = sys._getframe(1) # the caller
- s = Source(source)
- co = s.compile(filename, mode, flags, _genframe=_genframe)
- return co
-
-
-def getfslineno(obj):
- """ Return source location (path, lineno) for the given object.
- If the source cannot be determined return ("", -1)
- """
- import _pytest._code
- try:
- code = _pytest._code.Code(obj)
- except TypeError:
- try:
- fn = (py.std.inspect.getsourcefile(obj) or
- py.std.inspect.getfile(obj))
- except TypeError:
- return "", -1
-
- fspath = fn and py.path.local(fn) or None
- lineno = -1
- if fspath:
- try:
- _, lineno = findsource(obj)
- except IOError:
- pass
- else:
- fspath = code.path
- lineno = code.firstlineno
- assert isinstance(lineno, int)
- return fspath, lineno
-
-#
-# helper functions
-#
-
-def findsource(obj):
- try:
- sourcelines, lineno = py.std.inspect.findsource(obj)
- except py.builtin._sysex:
- raise
- except:
- return None, -1
- source = Source()
- source.lines = [line.rstrip() for line in sourcelines]
- return source, lineno
-
-def getsource(obj, **kwargs):
- import _pytest._code
- obj = _pytest._code.getrawcode(obj)
- try:
- strsrc = inspect.getsource(obj)
- except IndentationError:
- strsrc = "\"Buggy python version consider upgrading, cannot get source\""
- assert isinstance(strsrc, str)
- return Source(strsrc, **kwargs)
-
-def deindent(lines, offset=None):
- if offset is None:
- for line in lines:
- line = line.expandtabs()
- s = line.lstrip()
- if s:
- offset = len(line)-len(s)
- break
- else:
- offset = 0
- if offset == 0:
- return list(lines)
- newlines = []
- def readline_generator(lines):
- for line in lines:
- yield line + '\n'
- while True:
- yield ''
-
- it = readline_generator(lines)
-
- try:
- for _, _, (sline, _), (eline, _), _ in tokenize.generate_tokens(lambda: next(it)):
- if sline > len(lines):
- break # End of input reached
- if sline > len(newlines):
- line = lines[sline - 1].expandtabs()
- if line.lstrip() and line[:offset].isspace():
- line = line[offset:] # Deindent
- newlines.append(line)
-
- for i in range(sline, eline):
- # Don't deindent continuing lines of
- # multiline tokens (i.e. multiline strings)
- newlines.append(lines[i])
- except (IndentationError, tokenize.TokenError):
- pass
- # Add any lines we didn't see. E.g. if an exception was raised.
- newlines.extend(lines[len(newlines):])
- return newlines
-
-
-def get_statement_startend2(lineno, node):
- import ast
- # flatten all statements and except handlers into one lineno-list
- # AST's line numbers start indexing at 1
- l = []
- for x in ast.walk(node):
- if isinstance(x, _ast.stmt) or isinstance(x, _ast.ExceptHandler):
- l.append(x.lineno - 1)
- for name in "finalbody", "orelse":
- val = getattr(x, name, None)
- if val:
- # treat the finally/orelse part as its own statement
- l.append(val[0].lineno - 1 - 1)
- l.sort()
- insert_index = bisect_right(l, lineno)
- start = l[insert_index - 1]
- if insert_index >= len(l):
- end = None
- else:
- end = l[insert_index]
- return start, end
-
-
-def getstatementrange_ast(lineno, source, assertion=False, astnode=None):
- if astnode is None:
- content = str(source)
- if sys.version_info < (2,7):
- content += "\n"
- try:
- astnode = compile(content, "source", "exec", 1024) # 1024 for AST
- except ValueError:
- start, end = getstatementrange_old(lineno, source, assertion)
- return None, start, end
- start, end = get_statement_startend2(lineno, astnode)
- # we need to correct the end:
- # - ast-parsing strips comments
- # - there might be empty lines
- # - we might have lesser indented code blocks at the end
- if end is None:
- end = len(source.lines)
-
- if end > start + 1:
- # make sure we don't span differently indented code blocks
- # by using the BlockFinder helper used which inspect.getsource() uses itself
- block_finder = inspect.BlockFinder()
- # if we start with an indented line, put blockfinder to "started" mode
- block_finder.started = source.lines[start][0].isspace()
- it = ((x + "\n") for x in source.lines[start:end])
- try:
- for tok in tokenize.generate_tokens(lambda: next(it)):
- block_finder.tokeneater(*tok)
- except (inspect.EndOfBlock, IndentationError):
- end = block_finder.last + start
- except Exception:
- pass
-
- # the end might still point to a comment or empty line, correct it
- while end:
- line = source.lines[end - 1].lstrip()
- if line.startswith("#") or not line:
- end -= 1
- else:
- break
- return astnode, start, end
-
-
-def getstatementrange_old(lineno, source, assertion=False):
- """ return (start, end) tuple which spans the minimal
- statement region which containing the given lineno.
- raise an IndexError if no such statementrange can be found.
- """
- # XXX this logic is only used on python2.4 and below
- # 1. find the start of the statement
- from codeop import compile_command
- for start in range(lineno, -1, -1):
- if assertion:
- line = source.lines[start]
- # the following lines are not fully tested, change with care
- if 'super' in line and 'self' in line and '__init__' in line:
- raise IndexError("likely a subclass")
- if "assert" not in line and "raise" not in line:
- continue
- trylines = source.lines[start:lineno+1]
- # quick hack to prepare parsing an indented line with
- # compile_command() (which errors on "return" outside defs)
- trylines.insert(0, 'def xxx():')
- trysource = '\n '.join(trylines)
- # ^ space here
- try:
- compile_command(trysource)
- except (SyntaxError, OverflowError, ValueError):
- continue
-
- # 2. find the end of the statement
- for end in range(lineno+1, len(source)+1):
- trysource = source[start:end]
- if trysource.isparseable():
- return start, end
- raise SyntaxError("no valid source range around line %d " % (lineno,))
-
-
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/_pluggy.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/_pluggy.py
deleted file mode 100644
index 87d32cf..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/_pluggy.py
+++ /dev/null
@@ -1,11 +0,0 @@
-"""
-imports symbols from vendored "pluggy" if available, otherwise
-falls back to importing "pluggy" from the default namespace.
-"""
-
-try:
- from _pytest.vendored_packages.pluggy import * # noqa
- from _pytest.vendored_packages.pluggy import __version__ # noqa
-except ImportError:
- from pluggy import * # noqa
- from pluggy import __version__ # noqa
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/assertion/__init__.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/assertion/__init__.py
deleted file mode 100644
index 6921deb..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/assertion/__init__.py
+++ /dev/null
@@ -1,176 +0,0 @@
-"""
-support for presenting detailed information in failing assertions.
-"""
-import py
-import os
-import sys
-from _pytest.monkeypatch import monkeypatch
-from _pytest.assertion import util
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("debugconfig")
- group.addoption('--assert',
- action="store",
- dest="assertmode",
- choices=("rewrite", "reinterp", "plain",),
- default="rewrite",
- metavar="MODE",
- help="""control assertion debugging tools. 'plain'
- performs no assertion debugging. 'reinterp'
- reinterprets assert statements after they failed
- to provide assertion expression information.
- 'rewrite' (the default) rewrites assert
- statements in test modules on import to
- provide assert expression information. """)
- group.addoption('--no-assert',
- action="store_true",
- default=False,
- dest="noassert",
- help="DEPRECATED equivalent to --assert=plain")
- group.addoption('--nomagic', '--no-magic',
- action="store_true",
- default=False,
- help="DEPRECATED equivalent to --assert=plain")
-
-
-class AssertionState:
- """State for the assertion plugin."""
-
- def __init__(self, config, mode):
- self.mode = mode
- self.trace = config.trace.root.get("assertion")
-
-
-def pytest_configure(config):
- mode = config.getvalue("assertmode")
- if config.getvalue("noassert") or config.getvalue("nomagic"):
- mode = "plain"
- if mode == "rewrite":
- try:
- import ast # noqa
- except ImportError:
- mode = "reinterp"
- else:
- # Both Jython and CPython 2.6.0 have AST bugs that make the
- # assertion rewriting hook malfunction.
- if (sys.platform.startswith('java') or
- sys.version_info[:3] == (2, 6, 0)):
- mode = "reinterp"
- if mode != "plain":
- _load_modules(mode)
- m = monkeypatch()
- config._cleanup.append(m.undo)
- m.setattr(py.builtin.builtins, 'AssertionError',
- reinterpret.AssertionError) # noqa
- hook = None
- if mode == "rewrite":
- hook = rewrite.AssertionRewritingHook() # noqa
- sys.meta_path.insert(0, hook)
- warn_about_missing_assertion(mode)
- config._assertstate = AssertionState(config, mode)
- config._assertstate.hook = hook
- config._assertstate.trace("configured with mode set to %r" % (mode,))
- def undo():
- hook = config._assertstate.hook
- if hook is not None and hook in sys.meta_path:
- sys.meta_path.remove(hook)
- config.add_cleanup(undo)
-
-
-def pytest_collection(session):
- # this hook is only called when test modules are collected
- # so for example not in the master process of pytest-xdist
- # (which does not collect test modules)
- hook = session.config._assertstate.hook
- if hook is not None:
- hook.set_session(session)
-
-
-def _running_on_ci():
- """Check if we're currently running on a CI system."""
- env_vars = ['CI', 'BUILD_NUMBER']
- return any(var in os.environ for var in env_vars)
-
-
-def pytest_runtest_setup(item):
- """Setup the pytest_assertrepr_compare hook
-
- The newinterpret and rewrite modules will use util._reprcompare if
- it exists to use custom reporting via the
- pytest_assertrepr_compare hook. This sets up this custom
- comparison for the test.
- """
- def callbinrepr(op, left, right):
- """Call the pytest_assertrepr_compare hook and prepare the result
-
- This uses the first result from the hook and then ensures the
- following:
- * Overly verbose explanations are dropped unless -vv was used or
- running on a CI.
- * Embedded newlines are escaped to help util.format_explanation()
- later.
- * If the rewrite mode is used embedded %-characters are replaced
- to protect later % formatting.
-
- The result can be formatted by util.format_explanation() for
- pretty printing.
- """
- hook_result = item.ihook.pytest_assertrepr_compare(
- config=item.config, op=op, left=left, right=right)
- for new_expl in hook_result:
- if new_expl:
- if (sum(len(p) for p in new_expl[1:]) > 80*8 and
- item.config.option.verbose < 2 and
- not _running_on_ci()):
- show_max = 10
- truncated_lines = len(new_expl) - show_max
- new_expl[show_max:] = [py.builtin._totext(
- 'Detailed information truncated (%d more lines)'
- ', use "-vv" to show' % truncated_lines)]
- new_expl = [line.replace("\n", "\\n") for line in new_expl]
- res = py.builtin._totext("\n~").join(new_expl)
- if item.config.getvalue("assertmode") == "rewrite":
- res = res.replace("%", "%%")
- return res
- util._reprcompare = callbinrepr
-
-
-def pytest_runtest_teardown(item):
- util._reprcompare = None
-
-
-def pytest_sessionfinish(session):
- hook = session.config._assertstate.hook
- if hook is not None:
- hook.session = None
-
-
-def _load_modules(mode):
- """Lazily import assertion related code."""
- global rewrite, reinterpret
- from _pytest.assertion import reinterpret # noqa
- if mode == "rewrite":
- from _pytest.assertion import rewrite # noqa
-
-
-def warn_about_missing_assertion(mode):
- try:
- assert False
- except AssertionError:
- pass
- else:
- if mode == "rewrite":
- specifically = ("assertions which are not in test modules "
- "will be ignored")
- else:
- specifically = "failing tests may report as passing"
-
- sys.stderr.write("WARNING: " + specifically +
- " because assert statements are not executed "
- "by the underlying Python interpreter "
- "(are you using python -O?)\n")
-
-
-# Expose this plugin's implementation for the pytest_assertrepr_compare hook
-pytest_assertrepr_compare = util.assertrepr_compare
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/assertion/reinterpret.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/assertion/reinterpret.py
deleted file mode 100644
index f4262c3a..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/assertion/reinterpret.py
+++ /dev/null
@@ -1,407 +0,0 @@
-"""
-Find intermediate evalutation results in assert statements through builtin AST.
-"""
-import ast
-import sys
-
-import _pytest._code
-import py
-from _pytest.assertion import util
-u = py.builtin._totext
-
-
-class AssertionError(util.BuiltinAssertionError):
- def __init__(self, *args):
- util.BuiltinAssertionError.__init__(self, *args)
- if args:
- # on Python2.6 we get len(args)==2 for: assert 0, (x,y)
- # on Python2.7 and above we always get len(args) == 1
- # with args[0] being the (x,y) tuple.
- if len(args) > 1:
- toprint = args
- else:
- toprint = args[0]
- try:
- self.msg = u(toprint)
- except Exception:
- self.msg = u(
- "<[broken __repr__] %s at %0xd>"
- % (toprint.__class__, id(toprint)))
- else:
- f = _pytest._code.Frame(sys._getframe(1))
- try:
- source = f.code.fullsource
- if source is not None:
- try:
- source = source.getstatement(f.lineno, assertion=True)
- except IndexError:
- source = None
- else:
- source = str(source.deindent()).strip()
- except py.error.ENOENT:
- source = None
- # this can also occur during reinterpretation, when the
- # co_filename is set to "<run>".
- if source:
- self.msg = reinterpret(source, f, should_fail=True)
- else:
- self.msg = "<could not determine information>"
- if not self.args:
- self.args = (self.msg,)
-
-if sys.version_info > (3, 0):
- AssertionError.__module__ = "builtins"
-
-if sys.platform.startswith("java"):
- # See http://bugs.jython.org/issue1497
- _exprs = ("BoolOp", "BinOp", "UnaryOp", "Lambda", "IfExp", "Dict",
- "ListComp", "GeneratorExp", "Yield", "Compare", "Call",
- "Repr", "Num", "Str", "Attribute", "Subscript", "Name",
- "List", "Tuple")
- _stmts = ("FunctionDef", "ClassDef", "Return", "Delete", "Assign",
- "AugAssign", "Print", "For", "While", "If", "With", "Raise",
- "TryExcept", "TryFinally", "Assert", "Import", "ImportFrom",
- "Exec", "Global", "Expr", "Pass", "Break", "Continue")
- _expr_nodes = set(getattr(ast, name) for name in _exprs)
- _stmt_nodes = set(getattr(ast, name) for name in _stmts)
- def _is_ast_expr(node):
- return node.__class__ in _expr_nodes
- def _is_ast_stmt(node):
- return node.__class__ in _stmt_nodes
-else:
- def _is_ast_expr(node):
- return isinstance(node, ast.expr)
- def _is_ast_stmt(node):
- return isinstance(node, ast.stmt)
-
-try:
- _Starred = ast.Starred
-except AttributeError:
- # Python 2. Define a dummy class so isinstance() will always be False.
- class _Starred(object): pass
-
-
-class Failure(Exception):
- """Error found while interpreting AST."""
-
- def __init__(self, explanation=""):
- self.cause = sys.exc_info()
- self.explanation = explanation
-
-
-def reinterpret(source, frame, should_fail=False):
- mod = ast.parse(source)
- visitor = DebugInterpreter(frame)
- try:
- visitor.visit(mod)
- except Failure:
- failure = sys.exc_info()[1]
- return getfailure(failure)
- if should_fail:
- return ("(assertion failed, but when it was re-run for "
- "printing intermediate values, it did not fail. Suggestions: "
- "compute assert expression before the assert or use --assert=plain)")
-
-def run(offending_line, frame=None):
- if frame is None:
- frame = _pytest._code.Frame(sys._getframe(1))
- return reinterpret(offending_line, frame)
-
-def getfailure(e):
- explanation = util.format_explanation(e.explanation)
- value = e.cause[1]
- if str(value):
- lines = explanation.split('\n')
- lines[0] += " << %s" % (value,)
- explanation = '\n'.join(lines)
- text = "%s: %s" % (e.cause[0].__name__, explanation)
- if text.startswith('AssertionError: assert '):
- text = text[16:]
- return text
-
-operator_map = {
- ast.BitOr : "|",
- ast.BitXor : "^",
- ast.BitAnd : "&",
- ast.LShift : "<<",
- ast.RShift : ">>",
- ast.Add : "+",
- ast.Sub : "-",
- ast.Mult : "*",
- ast.Div : "/",
- ast.FloorDiv : "//",
- ast.Mod : "%",
- ast.Eq : "==",
- ast.NotEq : "!=",
- ast.Lt : "<",
- ast.LtE : "<=",
- ast.Gt : ">",
- ast.GtE : ">=",
- ast.Pow : "**",
- ast.Is : "is",
- ast.IsNot : "is not",
- ast.In : "in",
- ast.NotIn : "not in"
-}
-
-unary_map = {
- ast.Not : "not %s",
- ast.Invert : "~%s",
- ast.USub : "-%s",
- ast.UAdd : "+%s"
-}
-
-
-class DebugInterpreter(ast.NodeVisitor):
- """Interpret AST nodes to gleam useful debugging information. """
-
- def __init__(self, frame):
- self.frame = frame
-
- def generic_visit(self, node):
- # Fallback when we don't have a special implementation.
- if _is_ast_expr(node):
- mod = ast.Expression(node)
- co = self._compile(mod)
- try:
- result = self.frame.eval(co)
- except Exception:
- raise Failure()
- explanation = self.frame.repr(result)
- return explanation, result
- elif _is_ast_stmt(node):
- mod = ast.Module([node])
- co = self._compile(mod, "exec")
- try:
- self.frame.exec_(co)
- except Exception:
- raise Failure()
- return None, None
- else:
- raise AssertionError("can't handle %s" %(node,))
-
- def _compile(self, source, mode="eval"):
- return compile(source, "<assertion interpretation>", mode)
-
- def visit_Expr(self, expr):
- return self.visit(expr.value)
-
- def visit_Module(self, mod):
- for stmt in mod.body:
- self.visit(stmt)
-
- def visit_Name(self, name):
- explanation, result = self.generic_visit(name)
- # See if the name is local.
- source = "%r in locals() is not globals()" % (name.id,)
- co = self._compile(source)
- try:
- local = self.frame.eval(co)
- except Exception:
- # have to assume it isn't
- local = None
- if local is None or not self.frame.is_true(local):
- return name.id, result
- return explanation, result
-
- def visit_Compare(self, comp):
- left = comp.left
- left_explanation, left_result = self.visit(left)
- for op, next_op in zip(comp.ops, comp.comparators):
- next_explanation, next_result = self.visit(next_op)
- op_symbol = operator_map[op.__class__]
- explanation = "%s %s %s" % (left_explanation, op_symbol,
- next_explanation)
- source = "__exprinfo_left %s __exprinfo_right" % (op_symbol,)
- co = self._compile(source)
- try:
- result = self.frame.eval(co, __exprinfo_left=left_result,
- __exprinfo_right=next_result)
- except Exception:
- raise Failure(explanation)
- try:
- if not self.frame.is_true(result):
- break
- except KeyboardInterrupt:
- raise
- except:
- break
- left_explanation, left_result = next_explanation, next_result
-
- if util._reprcompare is not None:
- res = util._reprcompare(op_symbol, left_result, next_result)
- if res:
- explanation = res
- return explanation, result
-
- def visit_BoolOp(self, boolop):
- is_or = isinstance(boolop.op, ast.Or)
- explanations = []
- for operand in boolop.values:
- explanation, result = self.visit(operand)
- explanations.append(explanation)
- if result == is_or:
- break
- name = is_or and " or " or " and "
- explanation = "(" + name.join(explanations) + ")"
- return explanation, result
-
- def visit_UnaryOp(self, unary):
- pattern = unary_map[unary.op.__class__]
- operand_explanation, operand_result = self.visit(unary.operand)
- explanation = pattern % (operand_explanation,)
- co = self._compile(pattern % ("__exprinfo_expr",))
- try:
- result = self.frame.eval(co, __exprinfo_expr=operand_result)
- except Exception:
- raise Failure(explanation)
- return explanation, result
-
- def visit_BinOp(self, binop):
- left_explanation, left_result = self.visit(binop.left)
- right_explanation, right_result = self.visit(binop.right)
- symbol = operator_map[binop.op.__class__]
- explanation = "(%s %s %s)" % (left_explanation, symbol,
- right_explanation)
- source = "__exprinfo_left %s __exprinfo_right" % (symbol,)
- co = self._compile(source)
- try:
- result = self.frame.eval(co, __exprinfo_left=left_result,
- __exprinfo_right=right_result)
- except Exception:
- raise Failure(explanation)
- return explanation, result
-
- def visit_Call(self, call):
- func_explanation, func = self.visit(call.func)
- arg_explanations = []
- ns = {"__exprinfo_func" : func}
- arguments = []
- for arg in call.args:
- arg_explanation, arg_result = self.visit(arg)
- if isinstance(arg, _Starred):
- arg_name = "__exprinfo_star"
- ns[arg_name] = arg_result
- arguments.append("*%s" % (arg_name,))
- arg_explanations.append("*%s" % (arg_explanation,))
- else:
- arg_name = "__exprinfo_%s" % (len(ns),)
- ns[arg_name] = arg_result
- arguments.append(arg_name)
- arg_explanations.append(arg_explanation)
- for keyword in call.keywords:
- arg_explanation, arg_result = self.visit(keyword.value)
- if keyword.arg:
- arg_name = "__exprinfo_%s" % (len(ns),)
- keyword_source = "%s=%%s" % (keyword.arg)
- arguments.append(keyword_source % (arg_name,))
- arg_explanations.append(keyword_source % (arg_explanation,))
- else:
- arg_name = "__exprinfo_kwds"
- arguments.append("**%s" % (arg_name,))
- arg_explanations.append("**%s" % (arg_explanation,))
-
- ns[arg_name] = arg_result
-
- if getattr(call, 'starargs', None):
- arg_explanation, arg_result = self.visit(call.starargs)
- arg_name = "__exprinfo_star"
- ns[arg_name] = arg_result
- arguments.append("*%s" % (arg_name,))
- arg_explanations.append("*%s" % (arg_explanation,))
-
- if getattr(call, 'kwargs', None):
- arg_explanation, arg_result = self.visit(call.kwargs)
- arg_name = "__exprinfo_kwds"
- ns[arg_name] = arg_result
- arguments.append("**%s" % (arg_name,))
- arg_explanations.append("**%s" % (arg_explanation,))
- args_explained = ", ".join(arg_explanations)
- explanation = "%s(%s)" % (func_explanation, args_explained)
- args = ", ".join(arguments)
- source = "__exprinfo_func(%s)" % (args,)
- co = self._compile(source)
- try:
- result = self.frame.eval(co, **ns)
- except Exception:
- raise Failure(explanation)
- pattern = "%s\n{%s = %s\n}"
- rep = self.frame.repr(result)
- explanation = pattern % (rep, rep, explanation)
- return explanation, result
-
- def _is_builtin_name(self, name):
- pattern = "%r not in globals() and %r not in locals()"
- source = pattern % (name.id, name.id)
- co = self._compile(source)
- try:
- return self.frame.eval(co)
- except Exception:
- return False
-
- def visit_Attribute(self, attr):
- if not isinstance(attr.ctx, ast.Load):
- return self.generic_visit(attr)
- source_explanation, source_result = self.visit(attr.value)
- explanation = "%s.%s" % (source_explanation, attr.attr)
- source = "__exprinfo_expr.%s" % (attr.attr,)
- co = self._compile(source)
- try:
- try:
- result = self.frame.eval(co, __exprinfo_expr=source_result)
- except AttributeError:
- # Maybe the attribute name needs to be mangled?
- if not attr.attr.startswith("__") or attr.attr.endswith("__"):
- raise
- source = "getattr(__exprinfo_expr.__class__, '__name__', '')"
- co = self._compile(source)
- class_name = self.frame.eval(co, __exprinfo_expr=source_result)
- mangled_attr = "_" + class_name + attr.attr
- source = "__exprinfo_expr.%s" % (mangled_attr,)
- co = self._compile(source)
- result = self.frame.eval(co, __exprinfo_expr=source_result)
- except Exception:
- raise Failure(explanation)
- explanation = "%s\n{%s = %s.%s\n}" % (self.frame.repr(result),
- self.frame.repr(result),
- source_explanation, attr.attr)
- # Check if the attr is from an instance.
- source = "%r in getattr(__exprinfo_expr, '__dict__', {})"
- source = source % (attr.attr,)
- co = self._compile(source)
- try:
- from_instance = self.frame.eval(co, __exprinfo_expr=source_result)
- except Exception:
- from_instance = None
- if from_instance is None or self.frame.is_true(from_instance):
- rep = self.frame.repr(result)
- pattern = "%s\n{%s = %s\n}"
- explanation = pattern % (rep, rep, explanation)
- return explanation, result
-
- def visit_Assert(self, assrt):
- test_explanation, test_result = self.visit(assrt.test)
- explanation = "assert %s" % (test_explanation,)
- if not self.frame.is_true(test_result):
- try:
- raise util.BuiltinAssertionError
- except Exception:
- raise Failure(explanation)
- return explanation, test_result
-
- def visit_Assign(self, assign):
- value_explanation, value_result = self.visit(assign.value)
- explanation = "... = %s" % (value_explanation,)
- name = ast.Name("__exprinfo_expr", ast.Load(),
- lineno=assign.value.lineno,
- col_offset=assign.value.col_offset)
- new_assign = ast.Assign(assign.targets, name, lineno=assign.lineno,
- col_offset=assign.col_offset)
- mod = ast.Module([new_assign])
- co = self._compile(mod, "exec")
- try:
- self.frame.exec_(co, __exprinfo_expr=value_result)
- except Exception:
- raise Failure(explanation)
- return explanation, value_result
-
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/assertion/rewrite.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/assertion/rewrite.py
deleted file mode 100644
index 14b8e49..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/assertion/rewrite.py
+++ /dev/null
@@ -1,885 +0,0 @@
-"""Rewrite assertion AST to produce nice error messages"""
-
-import ast
-import errno
-import itertools
-import imp
-import marshal
-import os
-import re
-import struct
-import sys
-import types
-
-import py
-from _pytest.assertion import util
-
-
-# pytest caches rewritten pycs in __pycache__.
-if hasattr(imp, "get_tag"):
- PYTEST_TAG = imp.get_tag() + "-PYTEST"
-else:
- if hasattr(sys, "pypy_version_info"):
- impl = "pypy"
- elif sys.platform == "java":
- impl = "jython"
- else:
- impl = "cpython"
- ver = sys.version_info
- PYTEST_TAG = "%s-%s%s-PYTEST" % (impl, ver[0], ver[1])
- del ver, impl
-
-PYC_EXT = ".py" + (__debug__ and "c" or "o")
-PYC_TAIL = "." + PYTEST_TAG + PYC_EXT
-
-REWRITE_NEWLINES = sys.version_info[:2] != (2, 7) and sys.version_info < (3, 2)
-ASCII_IS_DEFAULT_ENCODING = sys.version_info[0] < 3
-
-if sys.version_info >= (3,5):
- ast_Call = ast.Call
-else:
- ast_Call = lambda a,b,c: ast.Call(a, b, c, None, None)
-
-
-class AssertionRewritingHook(object):
- """PEP302 Import hook which rewrites asserts."""
-
- def __init__(self):
- self.session = None
- self.modules = {}
- self._register_with_pkg_resources()
-
- def set_session(self, session):
- self.fnpats = session.config.getini("python_files")
- self.session = session
-
- def find_module(self, name, path=None):
- if self.session is None:
- return None
- sess = self.session
- state = sess.config._assertstate
- state.trace("find_module called for: %s" % name)
- names = name.rsplit(".", 1)
- lastname = names[-1]
- pth = None
- if path is not None:
- # Starting with Python 3.3, path is a _NamespacePath(), which
- # causes problems if not converted to list.
- path = list(path)
- if len(path) == 1:
- pth = path[0]
- if pth is None:
- try:
- fd, fn, desc = imp.find_module(lastname, path)
- except ImportError:
- return None
- if fd is not None:
- fd.close()
- tp = desc[2]
- if tp == imp.PY_COMPILED:
- if hasattr(imp, "source_from_cache"):
- fn = imp.source_from_cache(fn)
- else:
- fn = fn[:-1]
- elif tp != imp.PY_SOURCE:
- # Don't know what this is.
- return None
- else:
- fn = os.path.join(pth, name.rpartition(".")[2] + ".py")
- fn_pypath = py.path.local(fn)
- # Is this a test file?
- if not sess.isinitpath(fn):
- # We have to be very careful here because imports in this code can
- # trigger a cycle.
- self.session = None
- try:
- for pat in self.fnpats:
- if fn_pypath.fnmatch(pat):
- state.trace("matched test file %r" % (fn,))
- break
- else:
- return None
- finally:
- self.session = sess
- else:
- state.trace("matched test file (was specified on cmdline): %r" %
- (fn,))
- # The requested module looks like a test file, so rewrite it. This is
- # the most magical part of the process: load the source, rewrite the
- # asserts, and load the rewritten source. We also cache the rewritten
- # module code in a special pyc. We must be aware of the possibility of
- # concurrent pytest processes rewriting and loading pycs. To avoid
- # tricky race conditions, we maintain the following invariant: The
- # cached pyc is always a complete, valid pyc. Operations on it must be
- # atomic. POSIX's atomic rename comes in handy.
- write = not sys.dont_write_bytecode
- cache_dir = os.path.join(fn_pypath.dirname, "__pycache__")
- if write:
- try:
- os.mkdir(cache_dir)
- except OSError:
- e = sys.exc_info()[1].errno
- if e == errno.EEXIST:
- # Either the __pycache__ directory already exists (the
- # common case) or it's blocked by a non-dir node. In the
- # latter case, we'll ignore it in _write_pyc.
- pass
- elif e in [errno.ENOENT, errno.ENOTDIR]:
- # One of the path components was not a directory, likely
- # because we're in a zip file.
- write = False
- elif e in [errno.EACCES, errno.EROFS, errno.EPERM]:
- state.trace("read only directory: %r" % fn_pypath.dirname)
- write = False
- else:
- raise
- cache_name = fn_pypath.basename[:-3] + PYC_TAIL
- pyc = os.path.join(cache_dir, cache_name)
- # Notice that even if we're in a read-only directory, I'm going
- # to check for a cached pyc. This may not be optimal...
- co = _read_pyc(fn_pypath, pyc, state.trace)
- if co is None:
- state.trace("rewriting %r" % (fn,))
- source_stat, co = _rewrite_test(state, fn_pypath)
- if co is None:
- # Probably a SyntaxError in the test.
- return None
- if write:
- _make_rewritten_pyc(state, source_stat, pyc, co)
- else:
- state.trace("found cached rewritten pyc for %r" % (fn,))
- self.modules[name] = co, pyc
- return self
-
- def load_module(self, name):
- # If there is an existing module object named 'fullname' in
- # sys.modules, the loader must use that existing module. (Otherwise,
- # the reload() builtin will not work correctly.)
- if name in sys.modules:
- return sys.modules[name]
-
- co, pyc = self.modules.pop(name)
- # I wish I could just call imp.load_compiled here, but __file__ has to
- # be set properly. In Python 3.2+, this all would be handled correctly
- # by load_compiled.
- mod = sys.modules[name] = imp.new_module(name)
- try:
- mod.__file__ = co.co_filename
- # Normally, this attribute is 3.2+.
- mod.__cached__ = pyc
- mod.__loader__ = self
- py.builtin.exec_(co, mod.__dict__)
- except:
- del sys.modules[name]
- raise
- return sys.modules[name]
-
-
-
- def is_package(self, name):
- try:
- fd, fn, desc = imp.find_module(name)
- except ImportError:
- return False
- if fd is not None:
- fd.close()
- tp = desc[2]
- return tp == imp.PKG_DIRECTORY
-
- @classmethod
- def _register_with_pkg_resources(cls):
- """
- Ensure package resources can be loaded from this loader. May be called
- multiple times, as the operation is idempotent.
- """
- try:
- import pkg_resources
- # access an attribute in case a deferred importer is present
- pkg_resources.__name__
- except ImportError:
- return
-
- # Since pytest tests are always located in the file system, the
- # DefaultProvider is appropriate.
- pkg_resources.register_loader_type(cls, pkg_resources.DefaultProvider)
-
- def get_data(self, pathname):
- """Optional PEP302 get_data API.
- """
- with open(pathname, 'rb') as f:
- return f.read()
-
-
-def _write_pyc(state, co, source_stat, pyc):
- # Technically, we don't have to have the same pyc format as
- # (C)Python, since these "pycs" should never be seen by builtin
- # import. However, there's little reason deviate, and I hope
- # sometime to be able to use imp.load_compiled to load them. (See
- # the comment in load_module above.)
- try:
- fp = open(pyc, "wb")
- except IOError:
- err = sys.exc_info()[1].errno
- state.trace("error writing pyc file at %s: errno=%s" %(pyc, err))
- # we ignore any failure to write the cache file
- # there are many reasons, permission-denied, __pycache__ being a
- # file etc.
- return False
- try:
- fp.write(imp.get_magic())
- mtime = int(source_stat.mtime)
- size = source_stat.size & 0xFFFFFFFF
- fp.write(struct.pack("<ll", mtime, size))
- marshal.dump(co, fp)
- finally:
- fp.close()
- return True
-
-RN = "\r\n".encode("utf-8")
-N = "\n".encode("utf-8")
-
-cookie_re = re.compile(r"^[ \t\f]*#.*coding[:=][ \t]*[-\w.]+")
-BOM_UTF8 = '\xef\xbb\xbf'
-
-def _rewrite_test(state, fn):
- """Try to read and rewrite *fn* and return the code object."""
- try:
- stat = fn.stat()
- source = fn.read("rb")
- except EnvironmentError:
- return None, None
- if ASCII_IS_DEFAULT_ENCODING:
- # ASCII is the default encoding in Python 2. Without a coding
- # declaration, Python 2 will complain about any bytes in the file
- # outside the ASCII range. Sadly, this behavior does not extend to
- # compile() or ast.parse(), which prefer to interpret the bytes as
- # latin-1. (At least they properly handle explicit coding cookies.) To
- # preserve this error behavior, we could force ast.parse() to use ASCII
- # as the encoding by inserting a coding cookie. Unfortunately, that
- # messes up line numbers. Thus, we have to check ourselves if anything
- # is outside the ASCII range in the case no encoding is explicitly
- # declared. For more context, see issue #269. Yay for Python 3 which
- # gets this right.
- end1 = source.find("\n")
- end2 = source.find("\n", end1 + 1)
- if (not source.startswith(BOM_UTF8) and
- cookie_re.match(source[0:end1]) is None and
- cookie_re.match(source[end1 + 1:end2]) is None):
- if hasattr(state, "_indecode"):
- # encodings imported us again, so don't rewrite.
- return None, None
- state._indecode = True
- try:
- try:
- source.decode("ascii")
- except UnicodeDecodeError:
- # Let it fail in real import.
- return None, None
- finally:
- del state._indecode
- # On Python versions which are not 2.7 and less than or equal to 3.1, the
- # parser expects *nix newlines.
- if REWRITE_NEWLINES:
- source = source.replace(RN, N) + N
- try:
- tree = ast.parse(source)
- except SyntaxError:
- # Let this pop up again in the real import.
- state.trace("failed to parse: %r" % (fn,))
- return None, None
- rewrite_asserts(tree)
- try:
- co = compile(tree, fn.strpath, "exec")
- except SyntaxError:
- # It's possible that this error is from some bug in the
- # assertion rewriting, but I don't know of a fast way to tell.
- state.trace("failed to compile: %r" % (fn,))
- return None, None
- return stat, co
-
-def _make_rewritten_pyc(state, source_stat, pyc, co):
- """Try to dump rewritten code to *pyc*."""
- if sys.platform.startswith("win"):
- # Windows grants exclusive access to open files and doesn't have atomic
- # rename, so just write into the final file.
- _write_pyc(state, co, source_stat, pyc)
- else:
- # When not on windows, assume rename is atomic. Dump the code object
- # into a file specific to this process and atomically replace it.
- proc_pyc = pyc + "." + str(os.getpid())
- if _write_pyc(state, co, source_stat, proc_pyc):
- os.rename(proc_pyc, pyc)
-
-def _read_pyc(source, pyc, trace=lambda x: None):
- """Possibly read a pytest pyc containing rewritten code.
-
- Return rewritten code if successful or None if not.
- """
- try:
- fp = open(pyc, "rb")
- except IOError:
- return None
- with fp:
- try:
- mtime = int(source.mtime())
- size = source.size()
- data = fp.read(12)
- except EnvironmentError as e:
- trace('_read_pyc(%s): EnvironmentError %s' % (source, e))
- return None
- # Check for invalid or out of date pyc file.
- if (len(data) != 12 or data[:4] != imp.get_magic() or
- struct.unpack("<ll", data[4:]) != (mtime, size)):
- trace('_read_pyc(%s): invalid or out of date pyc' % source)
- return None
- try:
- co = marshal.load(fp)
- except Exception as e:
- trace('_read_pyc(%s): marshal.load error %s' % (source, e))
- return None
- if not isinstance(co, types.CodeType):
- trace('_read_pyc(%s): not a code object' % source)
- return None
- return co
-
-
-def rewrite_asserts(mod):
- """Rewrite the assert statements in mod."""
- AssertionRewriter().run(mod)
-
-
-def _saferepr(obj):
- """Get a safe repr of an object for assertion error messages.
-
- The assertion formatting (util.format_explanation()) requires
- newlines to be escaped since they are a special character for it.
- Normally assertion.util.format_explanation() does this but for a
- custom repr it is possible to contain one of the special escape
- sequences, especially '\n{' and '\n}' are likely to be present in
- JSON reprs.
-
- """
- repr = py.io.saferepr(obj)
- if py.builtin._istext(repr):
- t = py.builtin.text
- else:
- t = py.builtin.bytes
- return repr.replace(t("\n"), t("\\n"))
-
-
-from _pytest.assertion.util import format_explanation as _format_explanation # noqa
-
-def _format_assertmsg(obj):
- """Format the custom assertion message given.
-
- For strings this simply replaces newlines with '\n~' so that
- util.format_explanation() will preserve them instead of escaping
- newlines. For other objects py.io.saferepr() is used first.
-
- """
- # reprlib appears to have a bug which means that if a string
- # contains a newline it gets escaped, however if an object has a
- # .__repr__() which contains newlines it does not get escaped.
- # However in either case we want to preserve the newline.
- if py.builtin._istext(obj) or py.builtin._isbytes(obj):
- s = obj
- is_repr = False
- else:
- s = py.io.saferepr(obj)
- is_repr = True
- if py.builtin._istext(s):
- t = py.builtin.text
- else:
- t = py.builtin.bytes
- s = s.replace(t("\n"), t("\n~")).replace(t("%"), t("%%"))
- if is_repr:
- s = s.replace(t("\\n"), t("\n~"))
- return s
-
-def _should_repr_global_name(obj):
- return not hasattr(obj, "__name__") and not py.builtin.callable(obj)
-
-def _format_boolop(explanations, is_or):
- explanation = "(" + (is_or and " or " or " and ").join(explanations) + ")"
- if py.builtin._istext(explanation):
- t = py.builtin.text
- else:
- t = py.builtin.bytes
- return explanation.replace(t('%'), t('%%'))
-
-def _call_reprcompare(ops, results, expls, each_obj):
- for i, res, expl in zip(range(len(ops)), results, expls):
- try:
- done = not res
- except Exception:
- done = True
- if done:
- break
- if util._reprcompare is not None:
- custom = util._reprcompare(ops[i], each_obj[i], each_obj[i + 1])
- if custom is not None:
- return custom
- return expl
-
-
-unary_map = {
- ast.Not: "not %s",
- ast.Invert: "~%s",
- ast.USub: "-%s",
- ast.UAdd: "+%s"
-}
-
-binop_map = {
- ast.BitOr: "|",
- ast.BitXor: "^",
- ast.BitAnd: "&",
- ast.LShift: "<<",
- ast.RShift: ">>",
- ast.Add: "+",
- ast.Sub: "-",
- ast.Mult: "*",
- ast.Div: "/",
- ast.FloorDiv: "//",
- ast.Mod: "%%", # escaped for string formatting
- ast.Eq: "==",
- ast.NotEq: "!=",
- ast.Lt: "<",
- ast.LtE: "<=",
- ast.Gt: ">",
- ast.GtE: ">=",
- ast.Pow: "**",
- ast.Is: "is",
- ast.IsNot: "is not",
- ast.In: "in",
- ast.NotIn: "not in"
-}
-# Python 3.5+ compatibility
-try:
- binop_map[ast.MatMult] = "@"
-except AttributeError:
- pass
-
-# Python 3.4+ compatibility
-if hasattr(ast, "NameConstant"):
- _NameConstant = ast.NameConstant
-else:
- def _NameConstant(c):
- return ast.Name(str(c), ast.Load())
-
-
-def set_location(node, lineno, col_offset):
- """Set node location information recursively."""
- def _fix(node, lineno, col_offset):
- if "lineno" in node._attributes:
- node.lineno = lineno
- if "col_offset" in node._attributes:
- node.col_offset = col_offset
- for child in ast.iter_child_nodes(node):
- _fix(child, lineno, col_offset)
- _fix(node, lineno, col_offset)
- return node
-
-
-class AssertionRewriter(ast.NodeVisitor):
- """Assertion rewriting implementation.
-
- The main entrypoint is to call .run() with an ast.Module instance,
- this will then find all the assert statements and re-write them to
- provide intermediate values and a detailed assertion error. See
- http://pybites.blogspot.be/2011/07/behind-scenes-of-pytests-new-assertion.html
- for an overview of how this works.
-
- The entry point here is .run() which will iterate over all the
- statements in an ast.Module and for each ast.Assert statement it
- finds call .visit() with it. Then .visit_Assert() takes over and
- is responsible for creating new ast statements to replace the
- original assert statement: it re-writes the test of an assertion
- to provide intermediate values and replace it with an if statement
- which raises an assertion error with a detailed explanation in
- case the expression is false.
-
- For this .visit_Assert() uses the visitor pattern to visit all the
- AST nodes of the ast.Assert.test field, each visit call returning
- an AST node and the corresponding explanation string. During this
- state is kept in several instance attributes:
-
- :statements: All the AST statements which will replace the assert
- statement.
-
- :variables: This is populated by .variable() with each variable
- used by the statements so that they can all be set to None at
- the end of the statements.
-
- :variable_counter: Counter to create new unique variables needed
- by statements. Variables are created using .variable() and
- have the form of "@py_assert0".
-
- :on_failure: The AST statements which will be executed if the
- assertion test fails. This is the code which will construct
- the failure message and raises the AssertionError.
-
- :explanation_specifiers: A dict filled by .explanation_param()
- with %-formatting placeholders and their corresponding
- expressions to use in the building of an assertion message.
- This is used by .pop_format_context() to build a message.
-
- :stack: A stack of the explanation_specifiers dicts maintained by
- .push_format_context() and .pop_format_context() which allows
- to build another %-formatted string while already building one.
-
- This state is reset on every new assert statement visited and used
- by the other visitors.
-
- """
-
- def run(self, mod):
- """Find all assert statements in *mod* and rewrite them."""
- if not mod.body:
- # Nothing to do.
- return
- # Insert some special imports at the top of the module but after any
- # docstrings and __future__ imports.
- aliases = [ast.alias(py.builtin.builtins.__name__, "@py_builtins"),
- ast.alias("_pytest.assertion.rewrite", "@pytest_ar")]
- expect_docstring = True
- pos = 0
- lineno = 0
- for item in mod.body:
- if (expect_docstring and isinstance(item, ast.Expr) and
- isinstance(item.value, ast.Str)):
- doc = item.value.s
- if "PYTEST_DONT_REWRITE" in doc:
- # The module has disabled assertion rewriting.
- return
- lineno += len(doc) - 1
- expect_docstring = False
- elif (not isinstance(item, ast.ImportFrom) or item.level > 0 or
- item.module != "__future__"):
- lineno = item.lineno
- break
- pos += 1
- imports = [ast.Import([alias], lineno=lineno, col_offset=0)
- for alias in aliases]
- mod.body[pos:pos] = imports
- # Collect asserts.
- nodes = [mod]
- while nodes:
- node = nodes.pop()
- for name, field in ast.iter_fields(node):
- if isinstance(field, list):
- new = []
- for i, child in enumerate(field):
- if isinstance(child, ast.Assert):
- # Transform assert.
- new.extend(self.visit(child))
- else:
- new.append(child)
- if isinstance(child, ast.AST):
- nodes.append(child)
- setattr(node, name, new)
- elif (isinstance(field, ast.AST) and
- # Don't recurse into expressions as they can't contain
- # asserts.
- not isinstance(field, ast.expr)):
- nodes.append(field)
-
- def variable(self):
- """Get a new variable."""
- # Use a character invalid in python identifiers to avoid clashing.
- name = "@py_assert" + str(next(self.variable_counter))
- self.variables.append(name)
- return name
-
- def assign(self, expr):
- """Give *expr* a name."""
- name = self.variable()
- self.statements.append(ast.Assign([ast.Name(name, ast.Store())], expr))
- return ast.Name(name, ast.Load())
-
- def display(self, expr):
- """Call py.io.saferepr on the expression."""
- return self.helper("saferepr", expr)
-
- def helper(self, name, *args):
- """Call a helper in this module."""
- py_name = ast.Name("@pytest_ar", ast.Load())
- attr = ast.Attribute(py_name, "_" + name, ast.Load())
- return ast_Call(attr, list(args), [])
-
- def builtin(self, name):
- """Return the builtin called *name*."""
- builtin_name = ast.Name("@py_builtins", ast.Load())
- return ast.Attribute(builtin_name, name, ast.Load())
-
- def explanation_param(self, expr):
- """Return a new named %-formatting placeholder for expr.
-
- This creates a %-formatting placeholder for expr in the
- current formatting context, e.g. ``%(py0)s``. The placeholder
- and expr are placed in the current format context so that it
- can be used on the next call to .pop_format_context().
-
- """
- specifier = "py" + str(next(self.variable_counter))
- self.explanation_specifiers[specifier] = expr
- return "%(" + specifier + ")s"
-
- def push_format_context(self):
- """Create a new formatting context.
-
- The format context is used for when an explanation wants to
- have a variable value formatted in the assertion message. In
- this case the value required can be added using
- .explanation_param(). Finally .pop_format_context() is used
- to format a string of %-formatted values as added by
- .explanation_param().
-
- """
- self.explanation_specifiers = {}
- self.stack.append(self.explanation_specifiers)
-
- def pop_format_context(self, expl_expr):
- """Format the %-formatted string with current format context.
-
- The expl_expr should be an ast.Str instance constructed from
- the %-placeholders created by .explanation_param(). This will
- add the required code to format said string to .on_failure and
- return the ast.Name instance of the formatted string.
-
- """
- current = self.stack.pop()
- if self.stack:
- self.explanation_specifiers = self.stack[-1]
- keys = [ast.Str(key) for key in current.keys()]
- format_dict = ast.Dict(keys, list(current.values()))
- form = ast.BinOp(expl_expr, ast.Mod(), format_dict)
- name = "@py_format" + str(next(self.variable_counter))
- self.on_failure.append(ast.Assign([ast.Name(name, ast.Store())], form))
- return ast.Name(name, ast.Load())
-
- def generic_visit(self, node):
- """Handle expressions we don't have custom code for."""
- assert isinstance(node, ast.expr)
- res = self.assign(node)
- return res, self.explanation_param(self.display(res))
-
- def visit_Assert(self, assert_):
- """Return the AST statements to replace the ast.Assert instance.
-
- This re-writes the test of an assertion to provide
- intermediate values and replace it with an if statement which
- raises an assertion error with a detailed explanation in case
- the expression is false.
-
- """
- self.statements = []
- self.variables = []
- self.variable_counter = itertools.count()
- self.stack = []
- self.on_failure = []
- self.push_format_context()
- # Rewrite assert into a bunch of statements.
- top_condition, explanation = self.visit(assert_.test)
- # Create failure message.
- body = self.on_failure
- negation = ast.UnaryOp(ast.Not(), top_condition)
- self.statements.append(ast.If(negation, body, []))
- if assert_.msg:
- assertmsg = self.helper('format_assertmsg', assert_.msg)
- explanation = "\n>assert " + explanation
- else:
- assertmsg = ast.Str("")
- explanation = "assert " + explanation
- template = ast.BinOp(assertmsg, ast.Add(), ast.Str(explanation))
- msg = self.pop_format_context(template)
- fmt = self.helper("format_explanation", msg)
- err_name = ast.Name("AssertionError", ast.Load())
- exc = ast_Call(err_name, [fmt], [])
- if sys.version_info[0] >= 3:
- raise_ = ast.Raise(exc, None)
- else:
- raise_ = ast.Raise(exc, None, None)
- body.append(raise_)
- # Clear temporary variables by setting them to None.
- if self.variables:
- variables = [ast.Name(name, ast.Store())
- for name in self.variables]
- clear = ast.Assign(variables, _NameConstant(None))
- self.statements.append(clear)
- # Fix line numbers.
- for stmt in self.statements:
- set_location(stmt, assert_.lineno, assert_.col_offset)
- return self.statements
-
- def visit_Name(self, name):
- # Display the repr of the name if it's a local variable or
- # _should_repr_global_name() thinks it's acceptable.
- locs = ast_Call(self.builtin("locals"), [], [])
- inlocs = ast.Compare(ast.Str(name.id), [ast.In()], [locs])
- dorepr = self.helper("should_repr_global_name", name)
- test = ast.BoolOp(ast.Or(), [inlocs, dorepr])
- expr = ast.IfExp(test, self.display(name), ast.Str(name.id))
- return name, self.explanation_param(expr)
-
- def visit_BoolOp(self, boolop):
- res_var = self.variable()
- expl_list = self.assign(ast.List([], ast.Load()))
- app = ast.Attribute(expl_list, "append", ast.Load())
- is_or = int(isinstance(boolop.op, ast.Or))
- body = save = self.statements
- fail_save = self.on_failure
- levels = len(boolop.values) - 1
- self.push_format_context()
- # Process each operand, short-circuting if needed.
- for i, v in enumerate(boolop.values):
- if i:
- fail_inner = []
- # cond is set in a prior loop iteration below
- self.on_failure.append(ast.If(cond, fail_inner, [])) # noqa
- self.on_failure = fail_inner
- self.push_format_context()
- res, expl = self.visit(v)
- body.append(ast.Assign([ast.Name(res_var, ast.Store())], res))
- expl_format = self.pop_format_context(ast.Str(expl))
- call = ast_Call(app, [expl_format], [])
- self.on_failure.append(ast.Expr(call))
- if i < levels:
- cond = res
- if is_or:
- cond = ast.UnaryOp(ast.Not(), cond)
- inner = []
- self.statements.append(ast.If(cond, inner, []))
- self.statements = body = inner
- self.statements = save
- self.on_failure = fail_save
- expl_template = self.helper("format_boolop", expl_list, ast.Num(is_or))
- expl = self.pop_format_context(expl_template)
- return ast.Name(res_var, ast.Load()), self.explanation_param(expl)
-
- def visit_UnaryOp(self, unary):
- pattern = unary_map[unary.op.__class__]
- operand_res, operand_expl = self.visit(unary.operand)
- res = self.assign(ast.UnaryOp(unary.op, operand_res))
- return res, pattern % (operand_expl,)
-
- def visit_BinOp(self, binop):
- symbol = binop_map[binop.op.__class__]
- left_expr, left_expl = self.visit(binop.left)
- right_expr, right_expl = self.visit(binop.right)
- explanation = "(%s %s %s)" % (left_expl, symbol, right_expl)
- res = self.assign(ast.BinOp(left_expr, binop.op, right_expr))
- return res, explanation
-
- def visit_Call_35(self, call):
- """
- visit `ast.Call` nodes on Python3.5 and after
- """
- new_func, func_expl = self.visit(call.func)
- arg_expls = []
- new_args = []
- new_kwargs = []
- for arg in call.args:
- res, expl = self.visit(arg)
- arg_expls.append(expl)
- new_args.append(res)
- for keyword in call.keywords:
- res, expl = self.visit(keyword.value)
- new_kwargs.append(ast.keyword(keyword.arg, res))
- if keyword.arg:
- arg_expls.append(keyword.arg + "=" + expl)
- else: ## **args have `arg` keywords with an .arg of None
- arg_expls.append("**" + expl)
-
- expl = "%s(%s)" % (func_expl, ', '.join(arg_expls))
- new_call = ast.Call(new_func, new_args, new_kwargs)
- res = self.assign(new_call)
- res_expl = self.explanation_param(self.display(res))
- outer_expl = "%s\n{%s = %s\n}" % (res_expl, res_expl, expl)
- return res, outer_expl
-
- def visit_Starred(self, starred):
- # From Python 3.5, a Starred node can appear in a function call
- res, expl = self.visit(starred.value)
- return starred, '*' + expl
-
- def visit_Call_legacy(self, call):
- """
- visit `ast.Call nodes on 3.4 and below`
- """
- new_func, func_expl = self.visit(call.func)
- arg_expls = []
- new_args = []
- new_kwargs = []
- new_star = new_kwarg = None
- for arg in call.args:
- res, expl = self.visit(arg)
- new_args.append(res)
- arg_expls.append(expl)
- for keyword in call.keywords:
- res, expl = self.visit(keyword.value)
- new_kwargs.append(ast.keyword(keyword.arg, res))
- arg_expls.append(keyword.arg + "=" + expl)
- if call.starargs:
- new_star, expl = self.visit(call.starargs)
- arg_expls.append("*" + expl)
- if call.kwargs:
- new_kwarg, expl = self.visit(call.kwargs)
- arg_expls.append("**" + expl)
- expl = "%s(%s)" % (func_expl, ', '.join(arg_expls))
- new_call = ast.Call(new_func, new_args, new_kwargs,
- new_star, new_kwarg)
- res = self.assign(new_call)
- res_expl = self.explanation_param(self.display(res))
- outer_expl = "%s\n{%s = %s\n}" % (res_expl, res_expl, expl)
- return res, outer_expl
-
- # ast.Call signature changed on 3.5,
- # conditionally change which methods is named
- # visit_Call depending on Python version
- if sys.version_info >= (3, 5):
- visit_Call = visit_Call_35
- else:
- visit_Call = visit_Call_legacy
-
-
- def visit_Attribute(self, attr):
- if not isinstance(attr.ctx, ast.Load):
- return self.generic_visit(attr)
- value, value_expl = self.visit(attr.value)
- res = self.assign(ast.Attribute(value, attr.attr, ast.Load()))
- res_expl = self.explanation_param(self.display(res))
- pat = "%s\n{%s = %s.%s\n}"
- expl = pat % (res_expl, res_expl, value_expl, attr.attr)
- return res, expl
-
- def visit_Compare(self, comp):
- self.push_format_context()
- left_res, left_expl = self.visit(comp.left)
- res_variables = [self.variable() for i in range(len(comp.ops))]
- load_names = [ast.Name(v, ast.Load()) for v in res_variables]
- store_names = [ast.Name(v, ast.Store()) for v in res_variables]
- it = zip(range(len(comp.ops)), comp.ops, comp.comparators)
- expls = []
- syms = []
- results = [left_res]
- for i, op, next_operand in it:
- next_res, next_expl = self.visit(next_operand)
- results.append(next_res)
- sym = binop_map[op.__class__]
- syms.append(ast.Str(sym))
- expl = "%s %s %s" % (left_expl, sym, next_expl)
- expls.append(ast.Str(expl))
- res_expr = ast.Compare(left_res, [op], [next_res])
- self.statements.append(ast.Assign([store_names[i]], res_expr))
- left_res, left_expl = next_res, next_expl
- # Use pytest.assertion.util._reprcompare if that's available.
- expl_call = self.helper("call_reprcompare",
- ast.Tuple(syms, ast.Load()),
- ast.Tuple(load_names, ast.Load()),
- ast.Tuple(expls, ast.Load()),
- ast.Tuple(results, ast.Load()))
- if len(comp.ops) > 1:
- res = ast.BoolOp(ast.And(), load_names)
- else:
- res = load_names[0]
- return res, self.explanation_param(self.pop_format_context(expl_call))
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/assertion/util.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/assertion/util.py
deleted file mode 100644
index f2f23ef..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/assertion/util.py
+++ /dev/null
@@ -1,332 +0,0 @@
-"""Utilities for assertion debugging"""
-import pprint
-
-import _pytest._code
-import py
-try:
- from collections import Sequence
-except ImportError:
- Sequence = list
-
-BuiltinAssertionError = py.builtin.builtins.AssertionError
-u = py.builtin._totext
-
-# The _reprcompare attribute on the util module is used by the new assertion
-# interpretation code and assertion rewriter to detect this plugin was
-# loaded and in turn call the hooks defined here as part of the
-# DebugInterpreter.
-_reprcompare = None
-
-
-# the re-encoding is needed for python2 repr
-# with non-ascii characters (see issue 877 and 1379)
-def ecu(s):
- try:
- return u(s, 'utf-8', 'replace')
- except TypeError:
- return s
-
-
-def format_explanation(explanation):
- """This formats an explanation
-
- Normally all embedded newlines are escaped, however there are
- three exceptions: \n{, \n} and \n~. The first two are intended
- cover nested explanations, see function and attribute explanations
- for examples (.visit_Call(), visit_Attribute()). The last one is
- for when one explanation needs to span multiple lines, e.g. when
- displaying diffs.
- """
- explanation = ecu(explanation)
- explanation = _collapse_false(explanation)
- lines = _split_explanation(explanation)
- result = _format_lines(lines)
- return u('\n').join(result)
-
-
-def _collapse_false(explanation):
- """Collapse expansions of False
-
- So this strips out any "assert False\n{where False = ...\n}"
- blocks.
- """
- where = 0
- while True:
- start = where = explanation.find("False\n{False = ", where)
- if where == -1:
- break
- level = 0
- prev_c = explanation[start]
- for i, c in enumerate(explanation[start:]):
- if prev_c + c == "\n{":
- level += 1
- elif prev_c + c == "\n}":
- level -= 1
- if not level:
- break
- prev_c = c
- else:
- raise AssertionError("unbalanced braces: %r" % (explanation,))
- end = start + i
- where = end
- if explanation[end - 1] == '\n':
- explanation = (explanation[:start] + explanation[start+15:end-1] +
- explanation[end+1:])
- where -= 17
- return explanation
-
-
-def _split_explanation(explanation):
- """Return a list of individual lines in the explanation
-
- This will return a list of lines split on '\n{', '\n}' and '\n~'.
- Any other newlines will be escaped and appear in the line as the
- literal '\n' characters.
- """
- raw_lines = (explanation or u('')).split('\n')
- lines = [raw_lines[0]]
- for l in raw_lines[1:]:
- if l and l[0] in ['{', '}', '~', '>']:
- lines.append(l)
- else:
- lines[-1] += '\\n' + l
- return lines
-
-
-def _format_lines(lines):
- """Format the individual lines
-
- This will replace the '{', '}' and '~' characters of our mini
- formatting language with the proper 'where ...', 'and ...' and ' +
- ...' text, taking care of indentation along the way.
-
- Return a list of formatted lines.
- """
- result = lines[:1]
- stack = [0]
- stackcnt = [0]
- for line in lines[1:]:
- if line.startswith('{'):
- if stackcnt[-1]:
- s = u('and ')
- else:
- s = u('where ')
- stack.append(len(result))
- stackcnt[-1] += 1
- stackcnt.append(0)
- result.append(u(' +') + u(' ')*(len(stack)-1) + s + line[1:])
- elif line.startswith('}'):
- stack.pop()
- stackcnt.pop()
- result[stack[-1]] += line[1:]
- else:
- assert line[0] in ['~', '>']
- stack[-1] += 1
- indent = len(stack) if line.startswith('~') else len(stack) - 1
- result.append(u(' ')*indent + line[1:])
- assert len(stack) == 1
- return result
-
-
-# Provide basestring in python3
-try:
- basestring = basestring
-except NameError:
- basestring = str
-
-
-def assertrepr_compare(config, op, left, right):
- """Return specialised explanations for some operators/operands"""
- width = 80 - 15 - len(op) - 2 # 15 chars indentation, 1 space around op
- left_repr = py.io.saferepr(left, maxsize=int(width/2))
- right_repr = py.io.saferepr(right, maxsize=width-len(left_repr))
-
- summary = u('%s %s %s') % (ecu(left_repr), op, ecu(right_repr))
-
- issequence = lambda x: (isinstance(x, (list, tuple, Sequence)) and
- not isinstance(x, basestring))
- istext = lambda x: isinstance(x, basestring)
- isdict = lambda x: isinstance(x, dict)
- isset = lambda x: isinstance(x, (set, frozenset))
-
- def isiterable(obj):
- try:
- iter(obj)
- return not istext(obj)
- except TypeError:
- return False
-
- verbose = config.getoption('verbose')
- explanation = None
- try:
- if op == '==':
- if istext(left) and istext(right):
- explanation = _diff_text(left, right, verbose)
- else:
- if issequence(left) and issequence(right):
- explanation = _compare_eq_sequence(left, right, verbose)
- elif isset(left) and isset(right):
- explanation = _compare_eq_set(left, right, verbose)
- elif isdict(left) and isdict(right):
- explanation = _compare_eq_dict(left, right, verbose)
- if isiterable(left) and isiterable(right):
- expl = _compare_eq_iterable(left, right, verbose)
- if explanation is not None:
- explanation.extend(expl)
- else:
- explanation = expl
- elif op == 'not in':
- if istext(left) and istext(right):
- explanation = _notin_text(left, right, verbose)
- except Exception:
- explanation = [
- u('(pytest_assertion plugin: representation of details failed. '
- 'Probably an object has a faulty __repr__.)'),
- u(_pytest._code.ExceptionInfo())]
-
- if not explanation:
- return None
-
- return [summary] + explanation
-
-
-def _diff_text(left, right, verbose=False):
- """Return the explanation for the diff between text or bytes
-
- Unless --verbose is used this will skip leading and trailing
- characters which are identical to keep the diff minimal.
-
- If the input are bytes they will be safely converted to text.
- """
- from difflib import ndiff
- explanation = []
- if isinstance(left, py.builtin.bytes):
- left = u(repr(left)[1:-1]).replace(r'\n', '\n')
- if isinstance(right, py.builtin.bytes):
- right = u(repr(right)[1:-1]).replace(r'\n', '\n')
- if not verbose:
- i = 0 # just in case left or right has zero length
- for i in range(min(len(left), len(right))):
- if left[i] != right[i]:
- break
- if i > 42:
- i -= 10 # Provide some context
- explanation = [u('Skipping %s identical leading '
- 'characters in diff, use -v to show') % i]
- left = left[i:]
- right = right[i:]
- if len(left) == len(right):
- for i in range(len(left)):
- if left[-i] != right[-i]:
- break
- if i > 42:
- i -= 10 # Provide some context
- explanation += [u('Skipping %s identical trailing '
- 'characters in diff, use -v to show') % i]
- left = left[:-i]
- right = right[:-i]
- explanation += [line.strip('\n')
- for line in ndiff(left.splitlines(),
- right.splitlines())]
- return explanation
-
-
-def _compare_eq_iterable(left, right, verbose=False):
- if not verbose:
- return [u('Use -v to get the full diff')]
- # dynamic import to speedup pytest
- import difflib
-
- try:
- left_formatting = pprint.pformat(left).splitlines()
- right_formatting = pprint.pformat(right).splitlines()
- explanation = [u('Full diff:')]
- except Exception:
- # hack: PrettyPrinter.pformat() in python 2 fails when formatting items that can't be sorted(), ie, calling
- # sorted() on a list would raise. See issue #718.
- # As a workaround, the full diff is generated by using the repr() string of each item of each container.
- left_formatting = sorted(repr(x) for x in left)
- right_formatting = sorted(repr(x) for x in right)
- explanation = [u('Full diff (fallback to calling repr on each item):')]
- explanation.extend(line.strip() for line in difflib.ndiff(left_formatting, right_formatting))
- return explanation
-
-
-def _compare_eq_sequence(left, right, verbose=False):
- explanation = []
- for i in range(min(len(left), len(right))):
- if left[i] != right[i]:
- explanation += [u('At index %s diff: %r != %r')
- % (i, left[i], right[i])]
- break
- if len(left) > len(right):
- explanation += [u('Left contains more items, first extra item: %s')
- % py.io.saferepr(left[len(right)],)]
- elif len(left) < len(right):
- explanation += [
- u('Right contains more items, first extra item: %s') %
- py.io.saferepr(right[len(left)],)]
- return explanation
-
-
-def _compare_eq_set(left, right, verbose=False):
- explanation = []
- diff_left = left - right
- diff_right = right - left
- if diff_left:
- explanation.append(u('Extra items in the left set:'))
- for item in diff_left:
- explanation.append(py.io.saferepr(item))
- if diff_right:
- explanation.append(u('Extra items in the right set:'))
- for item in diff_right:
- explanation.append(py.io.saferepr(item))
- return explanation
-
-
-def _compare_eq_dict(left, right, verbose=False):
- explanation = []
- common = set(left).intersection(set(right))
- same = dict((k, left[k]) for k in common if left[k] == right[k])
- if same and not verbose:
- explanation += [u('Omitting %s identical items, use -v to show') %
- len(same)]
- elif same:
- explanation += [u('Common items:')]
- explanation += pprint.pformat(same).splitlines()
- diff = set(k for k in common if left[k] != right[k])
- if diff:
- explanation += [u('Differing items:')]
- for k in diff:
- explanation += [py.io.saferepr({k: left[k]}) + ' != ' +
- py.io.saferepr({k: right[k]})]
- extra_left = set(left) - set(right)
- if extra_left:
- explanation.append(u('Left contains more items:'))
- explanation.extend(pprint.pformat(
- dict((k, left[k]) for k in extra_left)).splitlines())
- extra_right = set(right) - set(left)
- if extra_right:
- explanation.append(u('Right contains more items:'))
- explanation.extend(pprint.pformat(
- dict((k, right[k]) for k in extra_right)).splitlines())
- return explanation
-
-
-def _notin_text(term, text, verbose=False):
- index = text.find(term)
- head = text[:index]
- tail = text[index+len(term):]
- correct_text = head + tail
- diff = _diff_text(correct_text, text, verbose)
- newdiff = [u('%s is contained here:') % py.io.saferepr(term, maxsize=42)]
- for line in diff:
- if line.startswith(u('Skipping')):
- continue
- if line.startswith(u('- ')):
- continue
- if line.startswith(u('+ ')):
- newdiff.append(u(' ') + line[2:])
- else:
- newdiff.append(line)
- return newdiff
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/cacheprovider.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/cacheprovider.py
deleted file mode 100644
index 0657001..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/cacheprovider.py
+++ /dev/null
@@ -1,245 +0,0 @@
-"""
-merged implementation of the cache provider
-
-the name cache was not choosen to ensure pluggy automatically
-ignores the external pytest-cache
-"""
-
-import py
-import pytest
-import json
-from os.path import sep as _sep, altsep as _altsep
-
-
-class Cache(object):
- def __init__(self, config):
- self.config = config
- self._cachedir = config.rootdir.join(".cache")
- self.trace = config.trace.root.get("cache")
- if config.getvalue("cacheclear"):
- self.trace("clearing cachedir")
- if self._cachedir.check():
- self._cachedir.remove()
- self._cachedir.mkdir()
-
- def makedir(self, name):
- """ return a directory path object with the given name. If the
- directory does not yet exist, it will be created. You can use it
- to manage files likes e. g. store/retrieve database
- dumps across test sessions.
-
- :param name: must be a string not containing a ``/`` separator.
- Make sure the name contains your plugin or application
- identifiers to prevent clashes with other cache users.
- """
- if _sep in name or _altsep is not None and _altsep in name:
- raise ValueError("name is not allowed to contain path separators")
- return self._cachedir.ensure_dir("d", name)
-
- def _getvaluepath(self, key):
- return self._cachedir.join('v', *key.split('/'))
-
- def get(self, key, default):
- """ return cached value for the given key. If no value
- was yet cached or the value cannot be read, the specified
- default is returned.
-
- :param key: must be a ``/`` separated value. Usually the first
- name is the name of your plugin or your application.
- :param default: must be provided in case of a cache-miss or
- invalid cache values.
-
- """
- path = self._getvaluepath(key)
- if path.check():
- try:
- with path.open("r") as f:
- return json.load(f)
- except ValueError:
- self.trace("cache-invalid at %s" % (path,))
- return default
-
- def set(self, key, value):
- """ save value for the given key.
-
- :param key: must be a ``/`` separated value. Usually the first
- name is the name of your plugin or your application.
- :param value: must be of any combination of basic
- python types, including nested types
- like e. g. lists of dictionaries.
- """
- path = self._getvaluepath(key)
- try:
- path.dirpath().ensure_dir()
- except (py.error.EEXIST, py.error.EACCES):
- self.config.warn(
- code='I9', message='could not create cache path %s' % (path,)
- )
- return
- try:
- f = path.open('w')
- except py.error.ENOTDIR:
- self.config.warn(
- code='I9', message='cache could not write path %s' % (path,))
- else:
- with f:
- self.trace("cache-write %s: %r" % (key, value,))
- json.dump(value, f, indent=2, sort_keys=True)
-
-
-class LFPlugin:
- """ Plugin which implements the --lf (run last-failing) option """
- def __init__(self, config):
- self.config = config
- active_keys = 'lf', 'failedfirst'
- self.active = any(config.getvalue(key) for key in active_keys)
- if self.active:
- self.lastfailed = config.cache.get("cache/lastfailed", {})
- else:
- self.lastfailed = {}
-
- def pytest_report_header(self):
- if self.active:
- if not self.lastfailed:
- mode = "run all (no recorded failures)"
- else:
- mode = "rerun last %d failures%s" % (
- len(self.lastfailed),
- " first" if self.config.getvalue("failedfirst") else "")
- return "run-last-failure: %s" % mode
-
- def pytest_runtest_logreport(self, report):
- if report.failed and "xfail" not in report.keywords:
- self.lastfailed[report.nodeid] = True
- elif not report.failed:
- if report.when == "call":
- self.lastfailed.pop(report.nodeid, None)
-
- def pytest_collectreport(self, report):
- passed = report.outcome in ('passed', 'skipped')
- if passed:
- if report.nodeid in self.lastfailed:
- self.lastfailed.pop(report.nodeid)
- self.lastfailed.update(
- (item.nodeid, True)
- for item in report.result)
- else:
- self.lastfailed[report.nodeid] = True
-
- def pytest_collection_modifyitems(self, session, config, items):
- if self.active and self.lastfailed:
- previously_failed = []
- previously_passed = []
- for item in items:
- if item.nodeid in self.lastfailed:
- previously_failed.append(item)
- else:
- previously_passed.append(item)
- if not previously_failed and previously_passed:
- # running a subset of all tests with recorded failures outside
- # of the set of tests currently executing
- pass
- elif self.config.getvalue("failedfirst"):
- items[:] = previously_failed + previously_passed
- else:
- items[:] = previously_failed
- config.hook.pytest_deselected(items=previously_passed)
-
- def pytest_sessionfinish(self, session):
- config = self.config
- if config.getvalue("cacheshow") or hasattr(config, "slaveinput"):
- return
- prev_failed = config.cache.get("cache/lastfailed", None) is not None
- if (session.testscollected and prev_failed) or self.lastfailed:
- config.cache.set("cache/lastfailed", self.lastfailed)
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("general")
- group.addoption(
- '--lf', '--last-failed', action='store_true', dest="lf",
- help="rerun only the tests that failed "
- "at the last run (or all if none failed)")
- group.addoption(
- '--ff', '--failed-first', action='store_true', dest="failedfirst",
- help="run all tests but run the last failures first. "
- "This may re-order tests and thus lead to "
- "repeated fixture setup/teardown")
- group.addoption(
- '--cache-show', action='store_true', dest="cacheshow",
- help="show cache contents, don't perform collection or tests")
- group.addoption(
- '--cache-clear', action='store_true', dest="cacheclear",
- help="remove all cache contents at start of test run.")
-
-
-def pytest_cmdline_main(config):
- if config.option.cacheshow:
- from _pytest.main import wrap_session
- return wrap_session(config, cacheshow)
-
-
-
-@pytest.hookimpl(tryfirst=True)
-def pytest_configure(config):
- config.cache = Cache(config)
- config.pluginmanager.register(LFPlugin(config), "lfplugin")
-
-
-@pytest.fixture
-def cache(request):
- """
- Return a cache object that can persist state between testing sessions.
-
- cache.get(key, default)
- cache.set(key, value)
-
- Keys must be a ``/`` separated value, where the first part is usually the
- name of your plugin or application to avoid clashes with other cache users.
-
- Values can be any object handled by the json stdlib module.
- """
- return request.config.cache
-
-
-def pytest_report_header(config):
- if config.option.verbose:
- relpath = py.path.local().bestrelpath(config.cache._cachedir)
- return "cachedir: %s" % relpath
-
-
-def cacheshow(config, session):
- from pprint import pprint
- tw = py.io.TerminalWriter()
- tw.line("cachedir: " + str(config.cache._cachedir))
- if not config.cache._cachedir.check():
- tw.line("cache is empty")
- return 0
- dummy = object()
- basedir = config.cache._cachedir
- vdir = basedir.join("v")
- tw.sep("-", "cache values")
- for valpath in vdir.visit(lambda x: x.isfile()):
- key = valpath.relto(vdir).replace(valpath.sep, "/")
- val = config.cache.get(key, dummy)
- if val is dummy:
- tw.line("%s contains unreadable content, "
- "will be ignored" % key)
- else:
- tw.line("%s contains:" % key)
- stream = py.io.TextIO()
- pprint(val, stream=stream)
- for line in stream.getvalue().splitlines():
- tw.line(" " + line)
-
- ddir = basedir.join("d")
- if ddir.isdir() and ddir.listdir():
- tw.sep("-", "cache directories")
- for p in basedir.join("d").visit():
- #if p.check(dir=1):
- # print("%s/" % p.relto(basedir))
- if p.isfile():
- key = p.relto(basedir)
- tw.line("%s is a file of length %d" % (
- key, p.size()))
- return 0
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/capture.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/capture.py
deleted file mode 100644
index 3895a71..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/capture.py
+++ /dev/null
@@ -1,472 +0,0 @@
-"""
-per-test stdout/stderr capturing mechanism.
-
-"""
-from __future__ import with_statement
-
-import sys
-import os
-from tempfile import TemporaryFile
-
-import py
-import pytest
-
-from py.io import TextIO
-unicode = py.builtin.text
-
-patchsysdict = {0: 'stdin', 1: 'stdout', 2: 'stderr'}
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("general")
- group._addoption(
- '--capture', action="store",
- default="fd" if hasattr(os, "dup") else "sys",
- metavar="method", choices=['fd', 'sys', 'no'],
- help="per-test capturing method: one of fd|sys|no.")
- group._addoption(
- '-s', action="store_const", const="no", dest="capture",
- help="shortcut for --capture=no.")
-
-
-@pytest.hookimpl(hookwrapper=True)
-def pytest_load_initial_conftests(early_config, parser, args):
- _readline_workaround()
- ns = early_config.known_args_namespace
- pluginmanager = early_config.pluginmanager
- capman = CaptureManager(ns.capture)
- pluginmanager.register(capman, "capturemanager")
-
- # make sure that capturemanager is properly reset at final shutdown
- early_config.add_cleanup(capman.reset_capturings)
-
- # make sure logging does not raise exceptions at the end
- def silence_logging_at_shutdown():
- if "logging" in sys.modules:
- sys.modules["logging"].raiseExceptions = False
- early_config.add_cleanup(silence_logging_at_shutdown)
-
- # finally trigger conftest loading but while capturing (issue93)
- capman.init_capturings()
- outcome = yield
- out, err = capman.suspendcapture()
- if outcome.excinfo is not None:
- sys.stdout.write(out)
- sys.stderr.write(err)
-
-
-class CaptureManager:
- def __init__(self, method):
- self._method = method
-
- def _getcapture(self, method):
- if method == "fd":
- return MultiCapture(out=True, err=True, Capture=FDCapture)
- elif method == "sys":
- return MultiCapture(out=True, err=True, Capture=SysCapture)
- elif method == "no":
- return MultiCapture(out=False, err=False, in_=False)
- else:
- raise ValueError("unknown capturing method: %r" % method)
-
- def init_capturings(self):
- assert not hasattr(self, "_capturing")
- self._capturing = self._getcapture(self._method)
- self._capturing.start_capturing()
-
- def reset_capturings(self):
- cap = self.__dict__.pop("_capturing", None)
- if cap is not None:
- cap.pop_outerr_to_orig()
- cap.stop_capturing()
-
- def resumecapture(self):
- self._capturing.resume_capturing()
-
- def suspendcapture(self, in_=False):
- self.deactivate_funcargs()
- cap = getattr(self, "_capturing", None)
- if cap is not None:
- try:
- outerr = cap.readouterr()
- finally:
- cap.suspend_capturing(in_=in_)
- return outerr
-
- def activate_funcargs(self, pyfuncitem):
- capfuncarg = pyfuncitem.__dict__.pop("_capfuncarg", None)
- if capfuncarg is not None:
- capfuncarg._start()
- self._capfuncarg = capfuncarg
-
- def deactivate_funcargs(self):
- capfuncarg = self.__dict__.pop("_capfuncarg", None)
- if capfuncarg is not None:
- capfuncarg.close()
-
- @pytest.hookimpl(hookwrapper=True)
- def pytest_make_collect_report(self, collector):
- if isinstance(collector, pytest.File):
- self.resumecapture()
- outcome = yield
- out, err = self.suspendcapture()
- rep = outcome.get_result()
- if out:
- rep.sections.append(("Captured stdout", out))
- if err:
- rep.sections.append(("Captured stderr", err))
- else:
- yield
-
- @pytest.hookimpl(hookwrapper=True)
- def pytest_runtest_setup(self, item):
- self.resumecapture()
- yield
- self.suspendcapture_item(item, "setup")
-
- @pytest.hookimpl(hookwrapper=True)
- def pytest_runtest_call(self, item):
- self.resumecapture()
- self.activate_funcargs(item)
- yield
- #self.deactivate_funcargs() called from suspendcapture()
- self.suspendcapture_item(item, "call")
-
- @pytest.hookimpl(hookwrapper=True)
- def pytest_runtest_teardown(self, item):
- self.resumecapture()
- yield
- self.suspendcapture_item(item, "teardown")
-
- @pytest.hookimpl(tryfirst=True)
- def pytest_keyboard_interrupt(self, excinfo):
- self.reset_capturings()
-
- @pytest.hookimpl(tryfirst=True)
- def pytest_internalerror(self, excinfo):
- self.reset_capturings()
-
- def suspendcapture_item(self, item, when):
- out, err = self.suspendcapture()
- item.add_report_section(when, "stdout", out)
- item.add_report_section(when, "stderr", err)
-
-error_capsysfderror = "cannot use capsys and capfd at the same time"
-
-
-@pytest.fixture
-def capsys(request):
- """enables capturing of writes to sys.stdout/sys.stderr and makes
- captured output available via ``capsys.readouterr()`` method calls
- which return a ``(out, err)`` tuple.
- """
- if "capfd" in request._funcargs:
- raise request.raiseerror(error_capsysfderror)
- request.node._capfuncarg = c = CaptureFixture(SysCapture)
- return c
-
-@pytest.fixture
-def capfd(request):
- """enables capturing of writes to file descriptors 1 and 2 and makes
- captured output available via ``capfd.readouterr()`` method calls
- which return a ``(out, err)`` tuple.
- """
- if "capsys" in request._funcargs:
- request.raiseerror(error_capsysfderror)
- if not hasattr(os, 'dup'):
- pytest.skip("capfd funcarg needs os.dup")
- request.node._capfuncarg = c = CaptureFixture(FDCapture)
- return c
-
-
-class CaptureFixture:
- def __init__(self, captureclass):
- self.captureclass = captureclass
-
- def _start(self):
- self._capture = MultiCapture(out=True, err=True, in_=False,
- Capture=self.captureclass)
- self._capture.start_capturing()
-
- def close(self):
- cap = self.__dict__.pop("_capture", None)
- if cap is not None:
- self._outerr = cap.pop_outerr_to_orig()
- cap.stop_capturing()
-
- def readouterr(self):
- try:
- return self._capture.readouterr()
- except AttributeError:
- return self._outerr
-
-
-def safe_text_dupfile(f, mode, default_encoding="UTF8"):
- """ return a open text file object that's a duplicate of f on the
- FD-level if possible.
- """
- encoding = getattr(f, "encoding", None)
- try:
- fd = f.fileno()
- except Exception:
- if "b" not in getattr(f, "mode", "") and hasattr(f, "encoding"):
- # we seem to have a text stream, let's just use it
- return f
- else:
- newfd = os.dup(fd)
- if "b" not in mode:
- mode += "b"
- f = os.fdopen(newfd, mode, 0) # no buffering
- return EncodedFile(f, encoding or default_encoding)
-
-
-class EncodedFile(object):
- errors = "strict" # possibly needed by py3 code (issue555)
- def __init__(self, buffer, encoding):
- self.buffer = buffer
- self.encoding = encoding
-
- def write(self, obj):
- if isinstance(obj, unicode):
- obj = obj.encode(self.encoding, "replace")
- self.buffer.write(obj)
-
- def writelines(self, linelist):
- data = ''.join(linelist)
- self.write(data)
-
- def __getattr__(self, name):
- return getattr(object.__getattribute__(self, "buffer"), name)
-
-
-class MultiCapture(object):
- out = err = in_ = None
-
- def __init__(self, out=True, err=True, in_=True, Capture=None):
- if in_:
- self.in_ = Capture(0)
- if out:
- self.out = Capture(1)
- if err:
- self.err = Capture(2)
-
- def start_capturing(self):
- if self.in_:
- self.in_.start()
- if self.out:
- self.out.start()
- if self.err:
- self.err.start()
-
- def pop_outerr_to_orig(self):
- """ pop current snapshot out/err capture and flush to orig streams. """
- out, err = self.readouterr()
- if out:
- self.out.writeorg(out)
- if err:
- self.err.writeorg(err)
- return out, err
-
- def suspend_capturing(self, in_=False):
- if self.out:
- self.out.suspend()
- if self.err:
- self.err.suspend()
- if in_ and self.in_:
- self.in_.suspend()
- self._in_suspended = True
-
- def resume_capturing(self):
- if self.out:
- self.out.resume()
- if self.err:
- self.err.resume()
- if hasattr(self, "_in_suspended"):
- self.in_.resume()
- del self._in_suspended
-
- def stop_capturing(self):
- """ stop capturing and reset capturing streams """
- if hasattr(self, '_reset'):
- raise ValueError("was already stopped")
- self._reset = True
- if self.out:
- self.out.done()
- if self.err:
- self.err.done()
- if self.in_:
- self.in_.done()
-
- def readouterr(self):
- """ return snapshot unicode value of stdout/stderr capturings. """
- return (self.out.snap() if self.out is not None else "",
- self.err.snap() if self.err is not None else "")
-
-class NoCapture:
- __init__ = start = done = suspend = resume = lambda *args: None
-
-class FDCapture:
- """ Capture IO to/from a given os-level filedescriptor. """
-
- def __init__(self, targetfd, tmpfile=None):
- self.targetfd = targetfd
- try:
- self.targetfd_save = os.dup(self.targetfd)
- except OSError:
- self.start = lambda: None
- self.done = lambda: None
- else:
- if targetfd == 0:
- assert not tmpfile, "cannot set tmpfile with stdin"
- tmpfile = open(os.devnull, "r")
- self.syscapture = SysCapture(targetfd)
- else:
- if tmpfile is None:
- f = TemporaryFile()
- with f:
- tmpfile = safe_text_dupfile(f, mode="wb+")
- if targetfd in patchsysdict:
- self.syscapture = SysCapture(targetfd, tmpfile)
- else:
- self.syscapture = NoCapture()
- self.tmpfile = tmpfile
- self.tmpfile_fd = tmpfile.fileno()
-
- def __repr__(self):
- return "<FDCapture %s oldfd=%s>" % (self.targetfd, self.targetfd_save)
-
- def start(self):
- """ Start capturing on targetfd using memorized tmpfile. """
- try:
- os.fstat(self.targetfd_save)
- except (AttributeError, OSError):
- raise ValueError("saved filedescriptor not valid anymore")
- os.dup2(self.tmpfile_fd, self.targetfd)
- self.syscapture.start()
-
- def snap(self):
- f = self.tmpfile
- f.seek(0)
- res = f.read()
- if res:
- enc = getattr(f, "encoding", None)
- if enc and isinstance(res, bytes):
- res = py.builtin._totext(res, enc, "replace")
- f.truncate(0)
- f.seek(0)
- return res
- return ''
-
- def done(self):
- """ stop capturing, restore streams, return original capture file,
- seeked to position zero. """
- targetfd_save = self.__dict__.pop("targetfd_save")
- os.dup2(targetfd_save, self.targetfd)
- os.close(targetfd_save)
- self.syscapture.done()
- self.tmpfile.close()
-
- def suspend(self):
- self.syscapture.suspend()
- os.dup2(self.targetfd_save, self.targetfd)
-
- def resume(self):
- self.syscapture.resume()
- os.dup2(self.tmpfile_fd, self.targetfd)
-
- def writeorg(self, data):
- """ write to original file descriptor. """
- if py.builtin._istext(data):
- data = data.encode("utf8") # XXX use encoding of original stream
- os.write(self.targetfd_save, data)
-
-
-class SysCapture:
- def __init__(self, fd, tmpfile=None):
- name = patchsysdict[fd]
- self._old = getattr(sys, name)
- self.name = name
- if tmpfile is None:
- if name == "stdin":
- tmpfile = DontReadFromInput()
- else:
- tmpfile = TextIO()
- self.tmpfile = tmpfile
-
- def start(self):
- setattr(sys, self.name, self.tmpfile)
-
- def snap(self):
- f = self.tmpfile
- res = f.getvalue()
- f.truncate(0)
- f.seek(0)
- return res
-
- def done(self):
- setattr(sys, self.name, self._old)
- del self._old
- self.tmpfile.close()
-
- def suspend(self):
- setattr(sys, self.name, self._old)
-
- def resume(self):
- setattr(sys, self.name, self.tmpfile)
-
- def writeorg(self, data):
- self._old.write(data)
- self._old.flush()
-
-
-class DontReadFromInput:
- """Temporary stub class. Ideally when stdin is accessed, the
- capturing should be turned off, with possibly all data captured
- so far sent to the screen. This should be configurable, though,
- because in automated test runs it is better to crash than
- hang indefinitely.
- """
-
- encoding = None
-
- def read(self, *args):
- raise IOError("reading from stdin while output is captured")
- readline = read
- readlines = read
- __iter__ = read
-
- def fileno(self):
- raise ValueError("redirected Stdin is pseudofile, has no fileno()")
-
- def isatty(self):
- return False
-
- def close(self):
- pass
-
-
-def _readline_workaround():
- """
- Ensure readline is imported so that it attaches to the correct stdio
- handles on Windows.
-
- Pdb uses readline support where available--when not running from the Python
- prompt, the readline module is not imported until running the pdb REPL. If
- running py.test with the --pdb option this means the readline module is not
- imported until after I/O capture has been started.
-
- This is a problem for pyreadline, which is often used to implement readline
- support on Windows, as it does not attach to the correct handles for stdout
- and/or stdin if they have been redirected by the FDCapture mechanism. This
- workaround ensures that readline is imported before I/O capture is setup so
- that it can attach to the actual stdin/out for the console.
-
- See https://github.com/pytest-dev/pytest/pull/1281
- """
-
- if not sys.platform.startswith('win32'):
- return
- try:
- import readline # noqa
- except ImportError:
- pass
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/config.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/config.py
deleted file mode 100644
index fb7b177..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/config.py
+++ /dev/null
@@ -1,1192 +0,0 @@
-""" command line options, ini-file and conftest.py processing. """
-import argparse
-import shlex
-import traceback
-import types
-import warnings
-
-import py
-# DON't import pytest here because it causes import cycle troubles
-import sys, os
-import _pytest._code
-import _pytest.hookspec # the extension point definitions
-from _pytest._pluggy import PluginManager, HookimplMarker, HookspecMarker
-
-hookimpl = HookimplMarker("pytest")
-hookspec = HookspecMarker("pytest")
-
-# pytest startup
-#
-
-
-class ConftestImportFailure(Exception):
- def __init__(self, path, excinfo):
- Exception.__init__(self, path, excinfo)
- self.path = path
- self.excinfo = excinfo
-
-
-def main(args=None, plugins=None):
- """ return exit code, after performing an in-process test run.
-
- :arg args: list of command line arguments.
-
- :arg plugins: list of plugin objects to be auto-registered during
- initialization.
- """
- try:
- try:
- config = _prepareconfig(args, plugins)
- except ConftestImportFailure as e:
- tw = py.io.TerminalWriter(sys.stderr)
- for line in traceback.format_exception(*e.excinfo):
- tw.line(line.rstrip(), red=True)
- tw.line("ERROR: could not load %s\n" % (e.path), red=True)
- return 4
- else:
- try:
- config.pluginmanager.check_pending()
- return config.hook.pytest_cmdline_main(config=config)
- finally:
- config._ensure_unconfigure()
- except UsageError as e:
- for msg in e.args:
- sys.stderr.write("ERROR: %s\n" %(msg,))
- return 4
-
-class cmdline: # compatibility namespace
- main = staticmethod(main)
-
-class UsageError(Exception):
- """ error in pytest usage or invocation"""
-
-_preinit = []
-
-default_plugins = (
- "mark main terminal runner python pdb unittest capture skipping "
- "tmpdir monkeypatch recwarn pastebin helpconfig nose assertion genscript "
- "junitxml resultlog doctest cacheprovider").split()
-
-builtin_plugins = set(default_plugins)
-builtin_plugins.add("pytester")
-
-
-def _preloadplugins():
- assert not _preinit
- _preinit.append(get_config())
-
-def get_config():
- if _preinit:
- return _preinit.pop(0)
- # subsequent calls to main will create a fresh instance
- pluginmanager = PytestPluginManager()
- config = Config(pluginmanager)
- for spec in default_plugins:
- pluginmanager.import_plugin(spec)
- return config
-
-def get_plugin_manager():
- """
- Obtain a new instance of the
- :py:class:`_pytest.config.PytestPluginManager`, with default plugins
- already loaded.
-
- This function can be used by integration with other tools, like hooking
- into pytest to run tests into an IDE.
- """
- return get_config().pluginmanager
-
-def _prepareconfig(args=None, plugins=None):
- if args is None:
- args = sys.argv[1:]
- elif isinstance(args, py.path.local):
- args = [str(args)]
- elif not isinstance(args, (tuple, list)):
- if not isinstance(args, str):
- raise ValueError("not a string or argument list: %r" % (args,))
- args = shlex.split(args)
- config = get_config()
- pluginmanager = config.pluginmanager
- try:
- if plugins:
- for plugin in plugins:
- if isinstance(plugin, py.builtin._basestring):
- pluginmanager.consider_pluginarg(plugin)
- else:
- pluginmanager.register(plugin)
- return pluginmanager.hook.pytest_cmdline_parse(
- pluginmanager=pluginmanager, args=args)
- except BaseException:
- config._ensure_unconfigure()
- raise
-
-
-class PytestPluginManager(PluginManager):
- """
- Overwrites :py:class:`pluggy.PluginManager` to add pytest-specific
- functionality:
-
- * loading plugins from the command line, ``PYTEST_PLUGIN`` env variable and
- ``pytest_plugins`` global variables found in plugins being loaded;
- * ``conftest.py`` loading during start-up;
- """
- def __init__(self):
- super(PytestPluginManager, self).__init__("pytest", implprefix="pytest_")
- self._conftest_plugins = set()
-
- # state related to local conftest plugins
- self._path2confmods = {}
- self._conftestpath2mod = {}
- self._confcutdir = None
- self._noconftest = False
-
- self.add_hookspecs(_pytest.hookspec)
- self.register(self)
- if os.environ.get('PYTEST_DEBUG'):
- err = sys.stderr
- encoding = getattr(err, 'encoding', 'utf8')
- try:
- err = py.io.dupfile(err, encoding=encoding)
- except Exception:
- pass
- self.trace.root.setwriter(err.write)
- self.enable_tracing()
-
- def addhooks(self, module_or_class):
- """
- .. deprecated:: 2.8
-
- Use :py:meth:`pluggy.PluginManager.add_hookspecs` instead.
- """
- warning = dict(code="I2",
- fslocation=_pytest._code.getfslineno(sys._getframe(1)),
- nodeid=None,
- message="use pluginmanager.add_hookspecs instead of "
- "deprecated addhooks() method.")
- self._warn(warning)
- return self.add_hookspecs(module_or_class)
-
- def parse_hookimpl_opts(self, plugin, name):
- # pytest hooks are always prefixed with pytest_
- # so we avoid accessing possibly non-readable attributes
- # (see issue #1073)
- if not name.startswith("pytest_"):
- return
- # ignore some historic special names which can not be hooks anyway
- if name == "pytest_plugins" or name.startswith("pytest_funcarg__"):
- return
-
- method = getattr(plugin, name)
- opts = super(PytestPluginManager, self).parse_hookimpl_opts(plugin, name)
- if opts is not None:
- for name in ("tryfirst", "trylast", "optionalhook", "hookwrapper"):
- opts.setdefault(name, hasattr(method, name))
- return opts
-
- def parse_hookspec_opts(self, module_or_class, name):
- opts = super(PytestPluginManager, self).parse_hookspec_opts(
- module_or_class, name)
- if opts is None:
- method = getattr(module_or_class, name)
- if name.startswith("pytest_"):
- opts = {"firstresult": hasattr(method, "firstresult"),
- "historic": hasattr(method, "historic")}
- return opts
-
- def _verify_hook(self, hook, hookmethod):
- super(PytestPluginManager, self)._verify_hook(hook, hookmethod)
- if "__multicall__" in hookmethod.argnames:
- fslineno = _pytest._code.getfslineno(hookmethod.function)
- warning = dict(code="I1",
- fslocation=fslineno,
- nodeid=None,
- message="%r hook uses deprecated __multicall__ "
- "argument" % (hook.name))
- self._warn(warning)
-
- def register(self, plugin, name=None):
- ret = super(PytestPluginManager, self).register(plugin, name)
- if ret:
- self.hook.pytest_plugin_registered.call_historic(
- kwargs=dict(plugin=plugin, manager=self))
- return ret
-
- def getplugin(self, name):
- # support deprecated naming because plugins (xdist e.g.) use it
- return self.get_plugin(name)
-
- def hasplugin(self, name):
- """Return True if the plugin with the given name is registered."""
- return bool(self.get_plugin(name))
-
- def pytest_configure(self, config):
- # XXX now that the pluginmanager exposes hookimpl(tryfirst...)
- # we should remove tryfirst/trylast as markers
- config.addinivalue_line("markers",
- "tryfirst: mark a hook implementation function such that the "
- "plugin machinery will try to call it first/as early as possible.")
- config.addinivalue_line("markers",
- "trylast: mark a hook implementation function such that the "
- "plugin machinery will try to call it last/as late as possible.")
-
- def _warn(self, message):
- kwargs = message if isinstance(message, dict) else {
- 'code': 'I1',
- 'message': message,
- 'fslocation': None,
- 'nodeid': None,
- }
- self.hook.pytest_logwarning.call_historic(kwargs=kwargs)
-
- #
- # internal API for local conftest plugin handling
- #
- def _set_initial_conftests(self, namespace):
- """ load initial conftest files given a preparsed "namespace".
- As conftest files may add their own command line options
- which have arguments ('--my-opt somepath') we might get some
- false positives. All builtin and 3rd party plugins will have
- been loaded, however, so common options will not confuse our logic
- here.
- """
- current = py.path.local()
- self._confcutdir = current.join(namespace.confcutdir, abs=True) \
- if namespace.confcutdir else None
- self._noconftest = namespace.noconftest
- testpaths = namespace.file_or_dir
- foundanchor = False
- for path in testpaths:
- path = str(path)
- # remove node-id syntax
- i = path.find("::")
- if i != -1:
- path = path[:i]
- anchor = current.join(path, abs=1)
- if exists(anchor): # we found some file object
- self._try_load_conftest(anchor)
- foundanchor = True
- if not foundanchor:
- self._try_load_conftest(current)
-
- def _try_load_conftest(self, anchor):
- self._getconftestmodules(anchor)
- # let's also consider test* subdirs
- if anchor.check(dir=1):
- for x in anchor.listdir("test*"):
- if x.check(dir=1):
- self._getconftestmodules(x)
-
- def _getconftestmodules(self, path):
- if self._noconftest:
- return []
- try:
- return self._path2confmods[path]
- except KeyError:
- if path.isfile():
- clist = self._getconftestmodules(path.dirpath())
- else:
- # XXX these days we may rather want to use config.rootdir
- # and allow users to opt into looking into the rootdir parent
- # directories instead of requiring to specify confcutdir
- clist = []
- for parent in path.parts():
- if self._confcutdir and self._confcutdir.relto(parent):
- continue
- conftestpath = parent.join("conftest.py")
- if conftestpath.isfile():
- mod = self._importconftest(conftestpath)
- clist.append(mod)
-
- self._path2confmods[path] = clist
- return clist
-
- def _rget_with_confmod(self, name, path):
- modules = self._getconftestmodules(path)
- for mod in reversed(modules):
- try:
- return mod, getattr(mod, name)
- except AttributeError:
- continue
- raise KeyError(name)
-
- def _importconftest(self, conftestpath):
- try:
- return self._conftestpath2mod[conftestpath]
- except KeyError:
- pkgpath = conftestpath.pypkgpath()
- if pkgpath is None:
- _ensure_removed_sysmodule(conftestpath.purebasename)
- try:
- mod = conftestpath.pyimport()
- except Exception:
- raise ConftestImportFailure(conftestpath, sys.exc_info())
-
- self._conftest_plugins.add(mod)
- self._conftestpath2mod[conftestpath] = mod
- dirpath = conftestpath.dirpath()
- if dirpath in self._path2confmods:
- for path, mods in self._path2confmods.items():
- if path and path.relto(dirpath) or path == dirpath:
- assert mod not in mods
- mods.append(mod)
- self.trace("loaded conftestmodule %r" %(mod))
- self.consider_conftest(mod)
- return mod
-
- #
- # API for bootstrapping plugin loading
- #
- #
-
- def consider_preparse(self, args):
- for opt1,opt2 in zip(args, args[1:]):
- if opt1 == "-p":
- self.consider_pluginarg(opt2)
-
- def consider_pluginarg(self, arg):
- if arg.startswith("no:"):
- name = arg[3:]
- self.set_blocked(name)
- if not name.startswith("pytest_"):
- self.set_blocked("pytest_" + name)
- else:
- self.import_plugin(arg)
-
- def consider_conftest(self, conftestmodule):
- if self.register(conftestmodule, name=conftestmodule.__file__):
- self.consider_module(conftestmodule)
-
- def consider_env(self):
- self._import_plugin_specs(os.environ.get("PYTEST_PLUGINS"))
-
- def consider_module(self, mod):
- self._import_plugin_specs(getattr(mod, "pytest_plugins", None))
-
- def _import_plugin_specs(self, spec):
- if spec:
- if isinstance(spec, str):
- spec = spec.split(",")
- for import_spec in spec:
- self.import_plugin(import_spec)
-
- def import_plugin(self, modname):
- # most often modname refers to builtin modules, e.g. "pytester",
- # "terminal" or "capture". Those plugins are registered under their
- # basename for historic purposes but must be imported with the
- # _pytest prefix.
- assert isinstance(modname, str)
- if self.get_plugin(modname) is not None:
- return
- if modname in builtin_plugins:
- importspec = "_pytest." + modname
- else:
- importspec = modname
- try:
- __import__(importspec)
- except ImportError as e:
- new_exc = ImportError('Error importing plugin "%s": %s' % (modname, e))
- # copy over name and path attributes
- for attr in ('name', 'path'):
- if hasattr(e, attr):
- setattr(new_exc, attr, getattr(e, attr))
- raise new_exc
- except Exception as e:
- import pytest
- if not hasattr(pytest, 'skip') or not isinstance(e, pytest.skip.Exception):
- raise
- self._warn("skipped plugin %r: %s" %((modname, e.msg)))
- else:
- mod = sys.modules[importspec]
- self.register(mod, modname)
- self.consider_module(mod)
-
-
-class Parser:
- """ Parser for command line arguments and ini-file values.
-
- :ivar extra_info: dict of generic param -> value to display in case
- there's an error processing the command line arguments.
- """
-
- def __init__(self, usage=None, processopt=None):
- self._anonymous = OptionGroup("custom options", parser=self)
- self._groups = []
- self._processopt = processopt
- self._usage = usage
- self._inidict = {}
- self._ininames = []
- self.extra_info = {}
-
- def processoption(self, option):
- if self._processopt:
- if option.dest:
- self._processopt(option)
-
- def getgroup(self, name, description="", after=None):
- """ get (or create) a named option Group.
-
- :name: name of the option group.
- :description: long description for --help output.
- :after: name of other group, used for ordering --help output.
-
- The returned group object has an ``addoption`` method with the same
- signature as :py:func:`parser.addoption
- <_pytest.config.Parser.addoption>` but will be shown in the
- respective group in the output of ``pytest. --help``.
- """
- for group in self._groups:
- if group.name == name:
- return group
- group = OptionGroup(name, description, parser=self)
- i = 0
- for i, grp in enumerate(self._groups):
- if grp.name == after:
- break
- self._groups.insert(i+1, group)
- return group
-
- def addoption(self, *opts, **attrs):
- """ register a command line option.
-
- :opts: option names, can be short or long options.
- :attrs: same attributes which the ``add_option()`` function of the
- `argparse library
- <http://docs.python.org/2/library/argparse.html>`_
- accepts.
-
- After command line parsing options are available on the pytest config
- object via ``config.option.NAME`` where ``NAME`` is usually set
- by passing a ``dest`` attribute, for example
- ``addoption("--long", dest="NAME", ...)``.
- """
- self._anonymous.addoption(*opts, **attrs)
-
- def parse(self, args, namespace=None):
- from _pytest._argcomplete import try_argcomplete
- self.optparser = self._getparser()
- try_argcomplete(self.optparser)
- return self.optparser.parse_args([str(x) for x in args], namespace=namespace)
-
- def _getparser(self):
- from _pytest._argcomplete import filescompleter
- optparser = MyOptionParser(self, self.extra_info)
- groups = self._groups + [self._anonymous]
- for group in groups:
- if group.options:
- desc = group.description or group.name
- arggroup = optparser.add_argument_group(desc)
- for option in group.options:
- n = option.names()
- a = option.attrs()
- arggroup.add_argument(*n, **a)
- # bash like autocompletion for dirs (appending '/')
- optparser.add_argument(FILE_OR_DIR, nargs='*').completer=filescompleter
- return optparser
-
- def parse_setoption(self, args, option, namespace=None):
- parsedoption = self.parse(args, namespace=namespace)
- for name, value in parsedoption.__dict__.items():
- setattr(option, name, value)
- return getattr(parsedoption, FILE_OR_DIR)
-
- def parse_known_args(self, args, namespace=None):
- """parses and returns a namespace object with known arguments at this
- point.
- """
- return self.parse_known_and_unknown_args(args, namespace=namespace)[0]
-
- def parse_known_and_unknown_args(self, args, namespace=None):
- """parses and returns a namespace object with known arguments, and
- the remaining arguments unknown at this point.
- """
- optparser = self._getparser()
- args = [str(x) for x in args]
- return optparser.parse_known_args(args, namespace=namespace)
-
- def addini(self, name, help, type=None, default=None):
- """ register an ini-file option.
-
- :name: name of the ini-variable
- :type: type of the variable, can be ``pathlist``, ``args``, ``linelist``
- or ``bool``.
- :default: default value if no ini-file option exists but is queried.
-
- The value of ini-variables can be retrieved via a call to
- :py:func:`config.getini(name) <_pytest.config.Config.getini>`.
- """
- assert type in (None, "pathlist", "args", "linelist", "bool")
- self._inidict[name] = (help, type, default)
- self._ininames.append(name)
-
-
-class ArgumentError(Exception):
- """
- Raised if an Argument instance is created with invalid or
- inconsistent arguments.
- """
-
- def __init__(self, msg, option):
- self.msg = msg
- self.option_id = str(option)
-
- def __str__(self):
- if self.option_id:
- return "option %s: %s" % (self.option_id, self.msg)
- else:
- return self.msg
-
-
-class Argument:
- """class that mimics the necessary behaviour of optparse.Option """
- _typ_map = {
- 'int': int,
- 'string': str,
- }
- # enable after some grace period for plugin writers
- TYPE_WARN = False
-
- def __init__(self, *names, **attrs):
- """store parms in private vars for use in add_argument"""
- self._attrs = attrs
- self._short_opts = []
- self._long_opts = []
- self.dest = attrs.get('dest')
- if self.TYPE_WARN:
- try:
- help = attrs['help']
- if '%default' in help:
- warnings.warn(
- 'pytest now uses argparse. "%default" should be'
- ' changed to "%(default)s" ',
- FutureWarning,
- stacklevel=3)
- except KeyError:
- pass
- try:
- typ = attrs['type']
- except KeyError:
- pass
- else:
- # this might raise a keyerror as well, don't want to catch that
- if isinstance(typ, py.builtin._basestring):
- if typ == 'choice':
- if self.TYPE_WARN:
- warnings.warn(
- 'type argument to addoption() is a string %r.'
- ' For parsearg this is optional and when supplied '
- ' should be a type.'
- ' (options: %s)' % (typ, names),
- FutureWarning,
- stacklevel=3)
- # argparse expects a type here take it from
- # the type of the first element
- attrs['type'] = type(attrs['choices'][0])
- else:
- if self.TYPE_WARN:
- warnings.warn(
- 'type argument to addoption() is a string %r.'
- ' For parsearg this should be a type.'
- ' (options: %s)' % (typ, names),
- FutureWarning,
- stacklevel=3)
- attrs['type'] = Argument._typ_map[typ]
- # used in test_parseopt -> test_parse_defaultgetter
- self.type = attrs['type']
- else:
- self.type = typ
- try:
- # attribute existence is tested in Config._processopt
- self.default = attrs['default']
- except KeyError:
- pass
- self._set_opt_strings(names)
- if not self.dest:
- if self._long_opts:
- self.dest = self._long_opts[0][2:].replace('-', '_')
- else:
- try:
- self.dest = self._short_opts[0][1:]
- except IndexError:
- raise ArgumentError(
- 'need a long or short option', self)
-
- def names(self):
- return self._short_opts + self._long_opts
-
- def attrs(self):
- # update any attributes set by processopt
- attrs = 'default dest help'.split()
- if self.dest:
- attrs.append(self.dest)
- for attr in attrs:
- try:
- self._attrs[attr] = getattr(self, attr)
- except AttributeError:
- pass
- if self._attrs.get('help'):
- a = self._attrs['help']
- a = a.replace('%default', '%(default)s')
- #a = a.replace('%prog', '%(prog)s')
- self._attrs['help'] = a
- return self._attrs
-
- def _set_opt_strings(self, opts):
- """directly from optparse
-
- might not be necessary as this is passed to argparse later on"""
- for opt in opts:
- if len(opt) < 2:
- raise ArgumentError(
- "invalid option string %r: "
- "must be at least two characters long" % opt, self)
- elif len(opt) == 2:
- if not (opt[0] == "-" and opt[1] != "-"):
- raise ArgumentError(
- "invalid short option string %r: "
- "must be of the form -x, (x any non-dash char)" % opt,
- self)
- self._short_opts.append(opt)
- else:
- if not (opt[0:2] == "--" and opt[2] != "-"):
- raise ArgumentError(
- "invalid long option string %r: "
- "must start with --, followed by non-dash" % opt,
- self)
- self._long_opts.append(opt)
-
- def __repr__(self):
- retval = 'Argument('
- if self._short_opts:
- retval += '_short_opts: ' + repr(self._short_opts) + ', '
- if self._long_opts:
- retval += '_long_opts: ' + repr(self._long_opts) + ', '
- retval += 'dest: ' + repr(self.dest) + ', '
- if hasattr(self, 'type'):
- retval += 'type: ' + repr(self.type) + ', '
- if hasattr(self, 'default'):
- retval += 'default: ' + repr(self.default) + ', '
- if retval[-2:] == ', ': # always long enough to test ("Argument(" )
- retval = retval[:-2]
- retval += ')'
- return retval
-
-
-class OptionGroup:
- def __init__(self, name, description="", parser=None):
- self.name = name
- self.description = description
- self.options = []
- self.parser = parser
-
- def addoption(self, *optnames, **attrs):
- """ add an option to this group.
-
- if a shortened version of a long option is specified it will
- be suppressed in the help. addoption('--twowords', '--two-words')
- results in help showing '--two-words' only, but --twowords gets
- accepted **and** the automatic destination is in args.twowords
- """
- option = Argument(*optnames, **attrs)
- self._addoption_instance(option, shortupper=False)
-
- def _addoption(self, *optnames, **attrs):
- option = Argument(*optnames, **attrs)
- self._addoption_instance(option, shortupper=True)
-
- def _addoption_instance(self, option, shortupper=False):
- if not shortupper:
- for opt in option._short_opts:
- if opt[0] == '-' and opt[1].islower():
- raise ValueError("lowercase shortoptions reserved")
- if self.parser:
- self.parser.processoption(option)
- self.options.append(option)
-
-
-class MyOptionParser(argparse.ArgumentParser):
- def __init__(self, parser, extra_info=None):
- if not extra_info:
- extra_info = {}
- self._parser = parser
- argparse.ArgumentParser.__init__(self, usage=parser._usage,
- add_help=False, formatter_class=DropShorterLongHelpFormatter)
- # extra_info is a dict of (param -> value) to display if there's
- # an usage error to provide more contextual information to the user
- self.extra_info = extra_info
-
- def parse_args(self, args=None, namespace=None):
- """allow splitting of positional arguments"""
- args, argv = self.parse_known_args(args, namespace)
- if argv:
- for arg in argv:
- if arg and arg[0] == '-':
- lines = ['unrecognized arguments: %s' % (' '.join(argv))]
- for k, v in sorted(self.extra_info.items()):
- lines.append(' %s: %s' % (k, v))
- self.error('\n'.join(lines))
- getattr(args, FILE_OR_DIR).extend(argv)
- return args
-
-
-class DropShorterLongHelpFormatter(argparse.HelpFormatter):
- """shorten help for long options that differ only in extra hyphens
-
- - collapse **long** options that are the same except for extra hyphens
- - special action attribute map_long_option allows surpressing additional
- long options
- - shortcut if there are only two options and one of them is a short one
- - cache result on action object as this is called at least 2 times
- """
- def _format_action_invocation(self, action):
- orgstr = argparse.HelpFormatter._format_action_invocation(self, action)
- if orgstr and orgstr[0] != '-': # only optional arguments
- return orgstr
- res = getattr(action, '_formatted_action_invocation', None)
- if res:
- return res
- options = orgstr.split(', ')
- if len(options) == 2 and (len(options[0]) == 2 or len(options[1]) == 2):
- # a shortcut for '-h, --help' or '--abc', '-a'
- action._formatted_action_invocation = orgstr
- return orgstr
- return_list = []
- option_map = getattr(action, 'map_long_option', {})
- if option_map is None:
- option_map = {}
- short_long = {}
- for option in options:
- if len(option) == 2 or option[2] == ' ':
- continue
- if not option.startswith('--'):
- raise ArgumentError('long optional argument without "--": [%s]'
- % (option), self)
- xxoption = option[2:]
- if xxoption.split()[0] not in option_map:
- shortened = xxoption.replace('-', '')
- if shortened not in short_long or \
- len(short_long[shortened]) < len(xxoption):
- short_long[shortened] = xxoption
- # now short_long has been filled out to the longest with dashes
- # **and** we keep the right option ordering from add_argument
- for option in options: #
- if len(option) == 2 or option[2] == ' ':
- return_list.append(option)
- if option[2:] == short_long.get(option.replace('-', '')):
- return_list.append(option.replace(' ', '='))
- action._formatted_action_invocation = ', '.join(return_list)
- return action._formatted_action_invocation
-
-
-
-def _ensure_removed_sysmodule(modname):
- try:
- del sys.modules[modname]
- except KeyError:
- pass
-
-class CmdOptions(object):
- """ holds cmdline options as attributes."""
- def __init__(self, values=()):
- self.__dict__.update(values)
- def __repr__(self):
- return "<CmdOptions %r>" %(self.__dict__,)
- def copy(self):
- return CmdOptions(self.__dict__)
-
-class Notset:
- def __repr__(self):
- return "<NOTSET>"
-
-notset = Notset()
-FILE_OR_DIR = 'file_or_dir'
-
-class Config(object):
- """ access to configuration values, pluginmanager and plugin hooks. """
-
- def __init__(self, pluginmanager):
- #: access to command line option as attributes.
- #: (deprecated), use :py:func:`getoption() <_pytest.config.Config.getoption>` instead
- self.option = CmdOptions()
- _a = FILE_OR_DIR
- self._parser = Parser(
- usage="%%(prog)s [options] [%s] [%s] [...]" % (_a, _a),
- processopt=self._processopt,
- )
- #: a pluginmanager instance
- self.pluginmanager = pluginmanager
- self.trace = self.pluginmanager.trace.root.get("config")
- self.hook = self.pluginmanager.hook
- self._inicache = {}
- self._opt2dest = {}
- self._cleanup = []
- self._warn = self.pluginmanager._warn
- self.pluginmanager.register(self, "pytestconfig")
- self._configured = False
- def do_setns(dic):
- import pytest
- setns(pytest, dic)
- self.hook.pytest_namespace.call_historic(do_setns, {})
- self.hook.pytest_addoption.call_historic(kwargs=dict(parser=self._parser))
-
- def add_cleanup(self, func):
- """ Add a function to be called when the config object gets out of
- use (usually coninciding with pytest_unconfigure)."""
- self._cleanup.append(func)
-
- def _do_configure(self):
- assert not self._configured
- self._configured = True
- self.hook.pytest_configure.call_historic(kwargs=dict(config=self))
-
- def _ensure_unconfigure(self):
- if self._configured:
- self._configured = False
- self.hook.pytest_unconfigure(config=self)
- self.hook.pytest_configure._call_history = []
- while self._cleanup:
- fin = self._cleanup.pop()
- fin()
-
- def warn(self, code, message, fslocation=None):
- """ generate a warning for this test session. """
- self.hook.pytest_logwarning.call_historic(kwargs=dict(
- code=code, message=message,
- fslocation=fslocation, nodeid=None))
-
- def get_terminal_writer(self):
- return self.pluginmanager.get_plugin("terminalreporter")._tw
-
- def pytest_cmdline_parse(self, pluginmanager, args):
- # REF1 assert self == pluginmanager.config, (self, pluginmanager.config)
- self.parse(args)
- return self
-
- def notify_exception(self, excinfo, option=None):
- if option and option.fulltrace:
- style = "long"
- else:
- style = "native"
- excrepr = excinfo.getrepr(funcargs=True,
- showlocals=getattr(option, 'showlocals', False),
- style=style,
- )
- res = self.hook.pytest_internalerror(excrepr=excrepr,
- excinfo=excinfo)
- if not py.builtin.any(res):
- for line in str(excrepr).split("\n"):
- sys.stderr.write("INTERNALERROR> %s\n" %line)
- sys.stderr.flush()
-
- def cwd_relative_nodeid(self, nodeid):
- # nodeid's are relative to the rootpath, compute relative to cwd
- if self.invocation_dir != self.rootdir:
- fullpath = self.rootdir.join(nodeid)
- nodeid = self.invocation_dir.bestrelpath(fullpath)
- return nodeid
-
- @classmethod
- def fromdictargs(cls, option_dict, args):
- """ constructor useable for subprocesses. """
- config = get_config()
- config.option.__dict__.update(option_dict)
- config.parse(args, addopts=False)
- for x in config.option.plugins:
- config.pluginmanager.consider_pluginarg(x)
- return config
-
- def _processopt(self, opt):
- for name in opt._short_opts + opt._long_opts:
- self._opt2dest[name] = opt.dest
-
- if hasattr(opt, 'default') and opt.dest:
- if not hasattr(self.option, opt.dest):
- setattr(self.option, opt.dest, opt.default)
-
- @hookimpl(trylast=True)
- def pytest_load_initial_conftests(self, early_config):
- self.pluginmanager._set_initial_conftests(early_config.known_args_namespace)
-
- def _initini(self, args):
- ns, unknown_args = self._parser.parse_known_and_unknown_args(args, namespace=self.option.copy())
- r = determine_setup(ns.inifilename, ns.file_or_dir + unknown_args)
- self.rootdir, self.inifile, self.inicfg = r
- self._parser.extra_info['rootdir'] = self.rootdir
- self._parser.extra_info['inifile'] = self.inifile
- self.invocation_dir = py.path.local()
- self._parser.addini('addopts', 'extra command line options', 'args')
- self._parser.addini('minversion', 'minimally required pytest version')
-
- def _preparse(self, args, addopts=True):
- self._initini(args)
- if addopts:
- args[:] = shlex.split(os.environ.get('PYTEST_ADDOPTS', '')) + args
- args[:] = self.getini("addopts") + args
- self._checkversion()
- self.pluginmanager.consider_preparse(args)
- try:
- self.pluginmanager.load_setuptools_entrypoints("pytest11")
- except ImportError as e:
- self.warn("I2", "could not load setuptools entry import: %s" % (e,))
- 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 = py.path.local(self.inifile).dirname
- self.known_args_namespace.confcutdir = confcutdir
- try:
- self.hook.pytest_load_initial_conftests(early_config=self,
- args=args, parser=self._parser)
- except ConftestImportFailure:
- e = sys.exc_info()[1]
- if ns.help or ns.version:
- # we don't want to prevent --help/--version to work
- # so just let is pass and print a warning at the end
- self._warn("could not load initial conftests (%s)\n" % e.path)
- else:
- raise
-
- def _checkversion(self):
- import pytest
- minver = self.inicfg.get('minversion', None)
- if minver:
- ver = minver.split(".")
- myver = pytest.__version__.split(".")
- if myver < ver:
- raise pytest.UsageError(
- "%s:%d: requires pytest-%s, actual pytest-%s'" %(
- self.inicfg.config.path, self.inicfg.lineof('minversion'),
- minver, pytest.__version__))
-
- def parse(self, args, addopts=True):
- # parse given cmdline arguments into this config object.
- assert not hasattr(self, 'args'), (
- "can only parse cmdline args at most once per Config object")
- self._origargs = args
- self.hook.pytest_addhooks.call_historic(
- kwargs=dict(pluginmanager=self.pluginmanager))
- self._preparse(args, addopts=addopts)
- # XXX deprecated hook:
- self.hook.pytest_cmdline_preparse(config=self, args=args)
- args = self._parser.parse_setoption(args, self.option, namespace=self.option)
- if not args:
- cwd = os.getcwd()
- if cwd == self.rootdir:
- args = self.getini('testpaths')
- if not args:
- args = [cwd]
- self.args = args
-
- def addinivalue_line(self, name, line):
- """ add a line to an ini-file option. The option must have been
- declared but might not yet be set in which case the line becomes the
- the first line in its value. """
- x = self.getini(name)
- assert isinstance(x, list)
- x.append(line) # modifies the cached list inline
-
- def getini(self, name):
- """ return configuration value from an :ref:`ini file <inifiles>`. If the
- specified name hasn't been registered through a prior
- :py:func:`parser.addini <pytest.config.Parser.addini>`
- call (usually from a plugin), a ValueError is raised. """
- try:
- return self._inicache[name]
- except KeyError:
- self._inicache[name] = val = self._getini(name)
- return val
-
- def _getini(self, name):
- try:
- description, type, default = self._parser._inidict[name]
- except KeyError:
- raise ValueError("unknown configuration value: %r" %(name,))
- try:
- value = self.inicfg[name]
- except KeyError:
- if default is not None:
- return default
- if type is None:
- return ''
- return []
- if type == "pathlist":
- dp = py.path.local(self.inicfg.config.path).dirpath()
- l = []
- for relpath in shlex.split(value):
- l.append(dp.join(relpath, abs=True))
- return l
- elif type == "args":
- return shlex.split(value)
- elif type == "linelist":
- return [t for t in map(lambda x: x.strip(), value.split("\n")) if t]
- elif type == "bool":
- return bool(_strtobool(value.strip()))
- else:
- assert type is None
- return value
-
- def _getconftest_pathlist(self, name, path):
- try:
- mod, relroots = self.pluginmanager._rget_with_confmod(name, path)
- except KeyError:
- return None
- modpath = py.path.local(mod.__file__).dirpath()
- l = []
- for relroot in relroots:
- if not isinstance(relroot, py.path.local):
- relroot = relroot.replace("/", py.path.local.sep)
- relroot = modpath.join(relroot, abs=True)
- l.append(relroot)
- return l
-
- def getoption(self, name, default=notset, skip=False):
- """ return command line option value.
-
- :arg name: name of the option. You may also specify
- the literal ``--OPT`` option instead of the "dest" option name.
- :arg default: default value if no option of that name exists.
- :arg skip: if True raise pytest.skip if option does not exists
- or has a None value.
- """
- name = self._opt2dest.get(name, name)
- try:
- val = getattr(self.option, name)
- if val is None and skip:
- raise AttributeError(name)
- return val
- except AttributeError:
- if default is not notset:
- return default
- if skip:
- import pytest
- pytest.skip("no %r option found" %(name,))
- raise ValueError("no option named %r" % (name,))
-
- def getvalue(self, name, path=None):
- """ (deprecated, use getoption()) """
- return self.getoption(name)
-
- def getvalueorskip(self, name, path=None):
- """ (deprecated, use getoption(skip=True)) """
- return self.getoption(name, skip=True)
-
-def exists(path, ignore=EnvironmentError):
- try:
- return path.check()
- except ignore:
- return False
-
-def getcfg(args, inibasenames):
- args = [x for x in args if not str(x).startswith("-")]
- if not args:
- args = [py.path.local()]
- for arg in args:
- arg = py.path.local(arg)
- for base in arg.parts(reverse=True):
- for inibasename in inibasenames:
- p = base.join(inibasename)
- if exists(p):
- iniconfig = py.iniconfig.IniConfig(p)
- if 'pytest' in iniconfig.sections:
- return base, p, iniconfig['pytest']
- elif inibasename == "pytest.ini":
- # allowed to be empty
- return base, p, {}
- return None, None, None
-
-
-def get_common_ancestor(args):
- # args are what we get after early command line parsing (usually
- # strings, but can be py.path.local objects as well)
- common_ancestor = None
- for arg in args:
- if str(arg)[0] == "-":
- continue
- p = py.path.local(arg)
- if common_ancestor is None:
- common_ancestor = p
- else:
- if p.relto(common_ancestor) or p == common_ancestor:
- continue
- elif common_ancestor.relto(p):
- common_ancestor = p
- else:
- shared = p.common(common_ancestor)
- if shared is not None:
- common_ancestor = shared
- if common_ancestor is None:
- common_ancestor = py.path.local()
- elif not common_ancestor.isdir():
- common_ancestor = common_ancestor.dirpath()
- return common_ancestor
-
-
-def determine_setup(inifile, args):
- if inifile:
- iniconfig = py.iniconfig.IniConfig(inifile)
- try:
- inicfg = iniconfig["pytest"]
- except KeyError:
- inicfg = None
- rootdir = get_common_ancestor(args)
- else:
- ancestor = get_common_ancestor(args)
- rootdir, inifile, inicfg = getcfg(
- [ancestor], ["pytest.ini", "tox.ini", "setup.cfg"])
- if rootdir is None:
- for rootdir in ancestor.parts(reverse=True):
- if rootdir.join("setup.py").exists():
- break
- else:
- rootdir = ancestor
- return rootdir, inifile, inicfg or {}
-
-
-def setns(obj, dic):
- import pytest
- for name, value in dic.items():
- if isinstance(value, dict):
- mod = getattr(obj, name, None)
- if mod is None:
- modname = "pytest.%s" % name
- mod = types.ModuleType(modname)
- sys.modules[modname] = mod
- mod.__all__ = []
- setattr(obj, name, mod)
- obj.__all__.append(name)
- setns(mod, value)
- else:
- setattr(obj, name, value)
- obj.__all__.append(name)
- #if obj != pytest:
- # pytest.__all__.append(name)
- setattr(pytest, name, value)
-
-
-def create_terminal_writer(config, *args, **kwargs):
- """Create a TerminalWriter instance configured according to the options
- in the config object. Every code which requires a TerminalWriter object
- and has access to a config object should use this function.
- """
- tw = py.io.TerminalWriter(*args, **kwargs)
- if config.option.color == 'yes':
- tw.hasmarkup = True
- if config.option.color == 'no':
- tw.hasmarkup = False
- return tw
-
-
-def _strtobool(val):
- """Convert a string representation of truth to true (1) or false (0).
-
- True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
- are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
- 'val' is anything else.
-
- .. note:: copied from distutils.util
- """
- val = val.lower()
- if val in ('y', 'yes', 't', 'true', 'on', '1'):
- return 1
- elif val in ('n', 'no', 'f', 'false', 'off', '0'):
- return 0
- else:
- raise ValueError("invalid truth value %r" % (val,))
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/doctest.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/doctest.py
deleted file mode 100644
index a57f7a49..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/doctest.py
+++ /dev/null
@@ -1,290 +0,0 @@
-""" discover and run doctests in modules and test files."""
-from __future__ import absolute_import
-
-import traceback
-
-import pytest
-from _pytest._code.code import TerminalRepr, ReprFileLocation, ExceptionInfo
-from _pytest.python import FixtureRequest
-
-
-
-def pytest_addoption(parser):
- parser.addini('doctest_optionflags', 'option flags for doctests',
- type="args", default=["ELLIPSIS"])
- group = parser.getgroup("collect")
- group.addoption("--doctest-modules",
- action="store_true", default=False,
- help="run doctests in all .py modules",
- dest="doctestmodules")
- group.addoption("--doctest-glob",
- action="append", default=[], metavar="pat",
- help="doctests file matching pattern, default: test*.txt",
- dest="doctestglob")
- group.addoption("--doctest-ignore-import-errors",
- action="store_true", default=False,
- help="ignore doctest ImportErrors",
- dest="doctest_ignore_import_errors")
-
-
-def pytest_collect_file(path, parent):
- config = parent.config
- if path.ext == ".py":
- if config.option.doctestmodules:
- return DoctestModule(path, parent)
- elif _is_doctest(config, path, parent):
- return DoctestTextfile(path, parent)
-
-
-def _is_doctest(config, path, parent):
- if path.ext in ('.txt', '.rst') and parent.session.isinitpath(path):
- return True
- globs = config.getoption("doctestglob") or ['test*.txt']
- for glob in globs:
- if path.check(fnmatch=glob):
- return True
- return False
-
-
-class ReprFailDoctest(TerminalRepr):
-
- def __init__(self, reprlocation, lines):
- self.reprlocation = reprlocation
- self.lines = lines
-
- def toterminal(self, tw):
- for line in self.lines:
- tw.line(line)
- self.reprlocation.toterminal(tw)
-
-
-class DoctestItem(pytest.Item):
-
- def __init__(self, name, parent, runner=None, dtest=None):
- super(DoctestItem, self).__init__(name, parent)
- self.runner = runner
- self.dtest = dtest
- self.obj = None
- self.fixture_request = None
-
- def setup(self):
- if self.dtest is not None:
- self.fixture_request = _setup_fixtures(self)
- globs = dict(getfixture=self.fixture_request.getfuncargvalue)
- self.dtest.globs.update(globs)
-
- def runtest(self):
- _check_all_skipped(self.dtest)
- self.runner.run(self.dtest)
-
- def repr_failure(self, excinfo):
- import doctest
- if excinfo.errisinstance((doctest.DocTestFailure,
- doctest.UnexpectedException)):
- doctestfailure = excinfo.value
- example = doctestfailure.example
- test = doctestfailure.test
- filename = test.filename
- if test.lineno is None:
- lineno = None
- else:
- lineno = test.lineno + example.lineno + 1
- message = excinfo.type.__name__
- reprlocation = ReprFileLocation(filename, lineno, message)
- checker = _get_checker()
- REPORT_UDIFF = doctest.REPORT_UDIFF
- if lineno is not None:
- lines = doctestfailure.test.docstring.splitlines(False)
- # add line numbers to the left of the error message
- lines = ["%03d %s" % (i + test.lineno + 1, x)
- for (i, x) in enumerate(lines)]
- # trim docstring error lines to 10
- lines = lines[example.lineno - 9:example.lineno + 1]
- else:
- lines = ['EXAMPLE LOCATION UNKNOWN, not showing all tests of that example']
- indent = '>>>'
- for line in example.source.splitlines():
- lines.append('??? %s %s' % (indent, line))
- indent = '...'
- if excinfo.errisinstance(doctest.DocTestFailure):
- lines += checker.output_difference(example,
- doctestfailure.got, REPORT_UDIFF).split("\n")
- else:
- inner_excinfo = ExceptionInfo(excinfo.value.exc_info)
- lines += ["UNEXPECTED EXCEPTION: %s" %
- repr(inner_excinfo.value)]
- lines += traceback.format_exception(*excinfo.value.exc_info)
- return ReprFailDoctest(reprlocation, lines)
- else:
- return super(DoctestItem, self).repr_failure(excinfo)
-
- def reportinfo(self):
- return self.fspath, None, "[doctest] %s" % self.name
-
-
-def _get_flag_lookup():
- import doctest
- return dict(DONT_ACCEPT_TRUE_FOR_1=doctest.DONT_ACCEPT_TRUE_FOR_1,
- DONT_ACCEPT_BLANKLINE=doctest.DONT_ACCEPT_BLANKLINE,
- NORMALIZE_WHITESPACE=doctest.NORMALIZE_WHITESPACE,
- ELLIPSIS=doctest.ELLIPSIS,
- IGNORE_EXCEPTION_DETAIL=doctest.IGNORE_EXCEPTION_DETAIL,
- COMPARISON_FLAGS=doctest.COMPARISON_FLAGS,
- ALLOW_UNICODE=_get_allow_unicode_flag(),
- ALLOW_BYTES=_get_allow_bytes_flag(),
- )
-
-
-def get_optionflags(parent):
- optionflags_str = parent.config.getini("doctest_optionflags")
- flag_lookup_table = _get_flag_lookup()
- flag_acc = 0
- for flag in optionflags_str:
- flag_acc |= flag_lookup_table[flag]
- return flag_acc
-
-
-class DoctestTextfile(DoctestItem, pytest.Module):
-
- def runtest(self):
- import doctest
- fixture_request = _setup_fixtures(self)
-
- # inspired by doctest.testfile; ideally we would use it directly,
- # but it doesn't support passing a custom checker
- text = self.fspath.read()
- filename = str(self.fspath)
- name = self.fspath.basename
- globs = dict(getfixture=fixture_request.getfuncargvalue)
- if '__name__' not in globs:
- globs['__name__'] = '__main__'
-
- optionflags = get_optionflags(self)
- runner = doctest.DebugRunner(verbose=0, optionflags=optionflags,
- checker=_get_checker())
-
- parser = doctest.DocTestParser()
- test = parser.get_doctest(text, globs, name, filename, 0)
- _check_all_skipped(test)
- runner.run(test)
-
-
-def _check_all_skipped(test):
- """raises pytest.skip() if all examples in the given DocTest have the SKIP
- option set.
- """
- import doctest
- all_skipped = all(x.options.get(doctest.SKIP, False) for x in test.examples)
- if all_skipped:
- pytest.skip('all tests skipped by +SKIP option')
-
-
-class DoctestModule(pytest.Module):
- def collect(self):
- import doctest
- if self.fspath.basename == "conftest.py":
- module = self.config.pluginmanager._importconftest(self.fspath)
- else:
- try:
- module = self.fspath.pyimport()
- except ImportError:
- if self.config.getvalue('doctest_ignore_import_errors'):
- pytest.skip('unable to import module %r' % self.fspath)
- else:
- raise
- # uses internal doctest module parsing mechanism
- finder = doctest.DocTestFinder()
- optionflags = get_optionflags(self)
- runner = doctest.DebugRunner(verbose=0, optionflags=optionflags,
- checker=_get_checker())
- for test in finder.find(module, module.__name__):
- if test.examples: # skip empty doctests
- yield DoctestItem(test.name, self, runner, test)
-
-
-def _setup_fixtures(doctest_item):
- """
- Used by DoctestTextfile and DoctestItem to setup fixture information.
- """
- def func():
- pass
-
- doctest_item.funcargs = {}
- fm = doctest_item.session._fixturemanager
- doctest_item._fixtureinfo = fm.getfixtureinfo(node=doctest_item, func=func,
- cls=None, funcargs=False)
- fixture_request = FixtureRequest(doctest_item)
- fixture_request._fillfixtures()
- return fixture_request
-
-
-def _get_checker():
- """
- Returns a doctest.OutputChecker subclass that takes in account the
- ALLOW_UNICODE option to ignore u'' prefixes in strings and ALLOW_BYTES
- to strip b'' prefixes.
- Useful when the same doctest should run in Python 2 and Python 3.
-
- An inner class is used to avoid importing "doctest" at the module
- level.
- """
- if hasattr(_get_checker, 'LiteralsOutputChecker'):
- return _get_checker.LiteralsOutputChecker()
-
- import doctest
- import re
-
- class LiteralsOutputChecker(doctest.OutputChecker):
- """
- Copied from doctest_nose_plugin.py from the nltk project:
- https://github.com/nltk/nltk
-
- Further extended to also support byte literals.
- """
-
- _unicode_literal_re = re.compile(r"(\W|^)[uU]([rR]?[\'\"])", re.UNICODE)
- _bytes_literal_re = re.compile(r"(\W|^)[bB]([rR]?[\'\"])", re.UNICODE)
-
- def check_output(self, want, got, optionflags):
- res = doctest.OutputChecker.check_output(self, want, got,
- optionflags)
- if res:
- return True
-
- allow_unicode = optionflags & _get_allow_unicode_flag()
- allow_bytes = optionflags & _get_allow_bytes_flag()
- if not allow_unicode and not allow_bytes:
- return False
-
- else: # pragma: no cover
- def remove_prefixes(regex, txt):
- return re.sub(regex, r'\1\2', txt)
-
- if allow_unicode:
- want = remove_prefixes(self._unicode_literal_re, want)
- got = remove_prefixes(self._unicode_literal_re, got)
- if allow_bytes:
- want = remove_prefixes(self._bytes_literal_re, want)
- got = remove_prefixes(self._bytes_literal_re, got)
- res = doctest.OutputChecker.check_output(self, want, got,
- optionflags)
- return res
-
- _get_checker.LiteralsOutputChecker = LiteralsOutputChecker
- return _get_checker.LiteralsOutputChecker()
-
-
-def _get_allow_unicode_flag():
- """
- Registers and returns the ALLOW_UNICODE flag.
- """
- import doctest
- return doctest.register_optionflag('ALLOW_UNICODE')
-
-
-def _get_allow_bytes_flag():
- """
- Registers and returns the ALLOW_BYTES flag.
- """
- import doctest
- return doctest.register_optionflag('ALLOW_BYTES')
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/genscript.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/genscript.py
deleted file mode 100644
index d2962d8..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/genscript.py
+++ /dev/null
@@ -1,132 +0,0 @@
-""" (deprecated) generate a single-file self-contained version of pytest """
-import os
-import sys
-import pkgutil
-
-import py
-import _pytest
-
-
-
-def find_toplevel(name):
- for syspath in sys.path:
- base = py.path.local(syspath)
- lib = base/name
- if lib.check(dir=1):
- return lib
- mod = base.join("%s.py" % name)
- if mod.check(file=1):
- return mod
- raise LookupError(name)
-
-def pkgname(toplevel, rootpath, path):
- parts = path.parts()[len(rootpath.parts()):]
- return '.'.join([toplevel] + [x.purebasename for x in parts])
-
-def pkg_to_mapping(name):
- toplevel = find_toplevel(name)
- name2src = {}
- if toplevel.check(file=1): # module
- name2src[toplevel.purebasename] = toplevel.read()
- else: # package
- for pyfile in toplevel.visit('*.py'):
- pkg = pkgname(name, toplevel, pyfile)
- name2src[pkg] = pyfile.read()
- # with wheels py source code might be not be installed
- # and the resulting genscript is useless, just bail out.
- assert name2src, "no source code found for %r at %r" %(name, toplevel)
- return name2src
-
-def compress_mapping(mapping):
- import base64, pickle, zlib
- data = pickle.dumps(mapping, 2)
- data = zlib.compress(data, 9)
- data = base64.encodestring(data)
- data = data.decode('ascii')
- return data
-
-
-def compress_packages(names):
- mapping = {}
- for name in names:
- mapping.update(pkg_to_mapping(name))
- return compress_mapping(mapping)
-
-def generate_script(entry, packages):
- data = compress_packages(packages)
- tmpl = py.path.local(__file__).dirpath().join('standalonetemplate.py')
- exe = tmpl.read()
- exe = exe.replace('@SOURCES@', data)
- exe = exe.replace('@ENTRY@', entry)
- return exe
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("debugconfig")
- group.addoption("--genscript", action="store", default=None,
- dest="genscript", metavar="path",
- help="create standalone pytest script at given target path.")
-
-def pytest_cmdline_main(config):
- import _pytest.config
- genscript = config.getvalue("genscript")
- if genscript:
- tw = _pytest.config.create_terminal_writer(config)
- tw.line("WARNING: usage of genscript is deprecated.",
- red=True)
- deps = ['py', '_pytest', 'pytest'] # pluggy is vendored
- if sys.version_info < (2,7):
- deps.append("argparse")
- tw.line("generated script will run on python2.6-python3.3++")
- else:
- tw.line("WARNING: generated script will not run on python2.6 "
- "due to 'argparse' dependency. Use python2.6 "
- "to generate a python2.6 compatible script", red=True)
- script = generate_script(
- 'import pytest; raise SystemExit(pytest.cmdline.main())',
- deps,
- )
- genscript = py.path.local(genscript)
- genscript.write(script)
- tw.line("generated pytest standalone script: %s" % genscript,
- bold=True)
- return 0
-
-
-def pytest_namespace():
- return {'freeze_includes': freeze_includes}
-
-
-def freeze_includes():
- """
- Returns a list of module names used by py.test that should be
- included by cx_freeze.
- """
- result = list(_iter_all_modules(py))
- result += list(_iter_all_modules(_pytest))
- return result
-
-
-def _iter_all_modules(package, prefix=''):
- """
- Iterates over the names of all modules that can be found in the given
- package, recursively.
-
- Example:
- _iter_all_modules(_pytest) ->
- ['_pytest.assertion.newinterpret',
- '_pytest.capture',
- '_pytest.core',
- ...
- ]
- """
- if type(package) is not str:
- path, prefix = package.__path__[0], package.__name__ + '.'
- else:
- path = package
- for _, name, is_package in pkgutil.iter_modules([path]):
- if is_package:
- for m in _iter_all_modules(os.path.join(path, name), prefix=name + '.'):
- yield prefix + m
- else:
- yield prefix + name
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/helpconfig.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/helpconfig.py
deleted file mode 100644
index 1df0c56..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/helpconfig.py
+++ /dev/null
@@ -1,139 +0,0 @@
-""" version info, help messages, tracing configuration. """
-import py
-import pytest
-import os, sys
-
-def pytest_addoption(parser):
- group = parser.getgroup('debugconfig')
- group.addoption('--version', action="store_true",
- help="display pytest lib version and import information.")
- group._addoption("-h", "--help", action="store_true", dest="help",
- help="show help message and configuration info")
- group._addoption('-p', action="append", dest="plugins", default = [],
- metavar="name",
- help="early-load given plugin (multi-allowed). "
- "To avoid loading of plugins, use the `no:` prefix, e.g. "
- "`no:doctest`.")
- group.addoption('--traceconfig', '--trace-config',
- action="store_true", default=False,
- help="trace considerations of conftest.py files."),
- group.addoption('--debug',
- action="store_true", dest="debug", default=False,
- help="store internal tracing debug information in 'pytestdebug.log'.")
-
-
-@pytest.hookimpl(hookwrapper=True)
-def pytest_cmdline_parse():
- outcome = yield
- config = outcome.get_result()
- if config.option.debug:
- path = os.path.abspath("pytestdebug.log")
- debugfile = open(path, 'w')
- debugfile.write("versions pytest-%s, py-%s, "
- "python-%s\ncwd=%s\nargs=%s\n\n" %(
- pytest.__version__, py.__version__,
- ".".join(map(str, sys.version_info)),
- os.getcwd(), config._origargs))
- config.trace.root.setwriter(debugfile.write)
- undo_tracing = config.pluginmanager.enable_tracing()
- sys.stderr.write("writing pytestdebug information to %s\n" % path)
- def unset_tracing():
- debugfile.close()
- sys.stderr.write("wrote pytestdebug information to %s\n" %
- debugfile.name)
- config.trace.root.setwriter(None)
- undo_tracing()
- config.add_cleanup(unset_tracing)
-
-def pytest_cmdline_main(config):
- if config.option.version:
- p = py.path.local(pytest.__file__)
- sys.stderr.write("This is pytest version %s, imported from %s\n" %
- (pytest.__version__, p))
- plugininfo = getpluginversioninfo(config)
- if plugininfo:
- for line in plugininfo:
- sys.stderr.write(line + "\n")
- return 0
- elif config.option.help:
- config._do_configure()
- showhelp(config)
- config._ensure_unconfigure()
- return 0
-
-def showhelp(config):
- reporter = config.pluginmanager.get_plugin('terminalreporter')
- tw = reporter._tw
- tw.write(config._parser.optparser.format_help())
- tw.line()
- tw.line()
- #tw.sep( "=", "config file settings")
- tw.line("[pytest] ini-options in the next "
- "pytest.ini|tox.ini|setup.cfg file:")
- tw.line()
-
- for name in config._parser._ininames:
- help, type, default = config._parser._inidict[name]
- if type is None:
- type = "string"
- spec = "%s (%s)" % (name, type)
- line = " %-24s %s" %(spec, help)
- tw.line(line[:tw.fullwidth])
-
- tw.line()
- tw.line("environment variables:")
- vars = [
- ("PYTEST_ADDOPTS", "extra command line options"),
- ("PYTEST_PLUGINS", "comma-separated plugins to load during startup"),
- ("PYTEST_DEBUG", "set to enable debug tracing of pytest's internals")
- ]
- for name, help in vars:
- tw.line(" %-24s %s" % (name, help))
- tw.line()
- tw.line()
-
- tw.line("to see available markers type: py.test --markers")
- tw.line("to see available fixtures type: py.test --fixtures")
- tw.line("(shown according to specified file_or_dir or current dir "
- "if not specified)")
-
- for warningreport in reporter.stats.get('warnings', []):
- tw.line("warning : " + warningreport.message, red=True)
- return
-
-
-conftest_options = [
- ('pytest_plugins', 'list of plugin names to load'),
-]
-
-def getpluginversioninfo(config):
- lines = []
- plugininfo = config.pluginmanager.list_plugin_distinfo()
- if plugininfo:
- lines.append("setuptools registered plugins:")
- for plugin, dist in plugininfo:
- loc = getattr(plugin, '__file__', repr(plugin))
- content = "%s-%s at %s" % (dist.project_name, dist.version, loc)
- lines.append(" " + content)
- return lines
-
-def pytest_report_header(config):
- lines = []
- if config.option.debug or config.option.traceconfig:
- lines.append("using: pytest-%s pylib-%s" %
- (pytest.__version__,py.__version__))
-
- verinfo = getpluginversioninfo(config)
- if verinfo:
- lines.extend(verinfo)
-
- if config.option.traceconfig:
- lines.append("active plugins:")
- items = config.pluginmanager.list_name_plugin()
- for name, plugin in items:
- if hasattr(plugin, '__file__'):
- r = plugin.__file__
- else:
- r = repr(plugin)
- lines.append(" %-20s: %s" %(name, r))
- return lines
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/hookspec.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/hookspec.py
deleted file mode 100644
index 60e9b47..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/hookspec.py
+++ /dev/null
@@ -1,295 +0,0 @@
-""" hook specifications for pytest plugins, invoked from main.py and builtin plugins. """
-
-from _pytest._pluggy import HookspecMarker
-
-hookspec = HookspecMarker("pytest")
-
-# -------------------------------------------------------------------------
-# Initialization hooks called for every plugin
-# -------------------------------------------------------------------------
-
-@hookspec(historic=True)
-def pytest_addhooks(pluginmanager):
- """called at plugin registration time to allow adding new hooks via a call to
- pluginmanager.add_hookspecs(module_or_class, prefix)."""
-
-
-@hookspec(historic=True)
-def pytest_namespace():
- """return dict of name->object to be made globally available in
- the pytest namespace. This hook is called at plugin registration
- time.
- """
-
-@hookspec(historic=True)
-def pytest_plugin_registered(plugin, manager):
- """ a new pytest plugin got registered. """
-
-
-@hookspec(historic=True)
-def pytest_addoption(parser):
- """register argparse-style options and ini-style config values,
- called once at the beginning of a test run.
-
- .. note::
-
- This function should be implemented only in plugins or ``conftest.py``
- files situated at the tests root directory due to how py.test
- :ref:`discovers plugins during startup <pluginorder>`.
-
- :arg parser: To add command line options, call
- :py:func:`parser.addoption(...) <_pytest.config.Parser.addoption>`.
- To add ini-file values call :py:func:`parser.addini(...)
- <_pytest.config.Parser.addini>`.
-
- Options can later be accessed through the
- :py:class:`config <_pytest.config.Config>` object, respectively:
-
- - :py:func:`config.getoption(name) <_pytest.config.Config.getoption>` to
- retrieve the value of a command line option.
-
- - :py:func:`config.getini(name) <_pytest.config.Config.getini>` to retrieve
- a value read from an ini-style file.
-
- The config object is passed around on many internal objects via the ``.config``
- attribute or can be retrieved as the ``pytestconfig`` fixture or accessed
- via (deprecated) ``pytest.config``.
- """
-
-@hookspec(historic=True)
-def pytest_configure(config):
- """ called after command line options have been parsed
- and all plugins and initial conftest files been loaded.
- This hook is called for every plugin.
- """
-
-# -------------------------------------------------------------------------
-# Bootstrapping hooks called for plugins registered early enough:
-# internal and 3rd party plugins as well as directly
-# discoverable conftest.py local plugins.
-# -------------------------------------------------------------------------
-
-@hookspec(firstresult=True)
-def pytest_cmdline_parse(pluginmanager, args):
- """return initialized config object, parsing the specified args. """
-
-def pytest_cmdline_preparse(config, args):
- """(deprecated) modify command line arguments before option parsing. """
-
-@hookspec(firstresult=True)
-def pytest_cmdline_main(config):
- """ called for performing the main command line action. The default
- implementation will invoke the configure hooks and runtest_mainloop. """
-
-def pytest_load_initial_conftests(early_config, parser, args):
- """ implements the loading of initial conftest files ahead
- of command line option parsing. """
-
-
-# -------------------------------------------------------------------------
-# collection hooks
-# -------------------------------------------------------------------------
-
-@hookspec(firstresult=True)
-def pytest_collection(session):
- """ perform the collection protocol for the given session. """
-
-def pytest_collection_modifyitems(session, config, items):
- """ called after collection has been performed, may filter or re-order
- the items in-place."""
-
-def pytest_collection_finish(session):
- """ called after collection has been performed and modified. """
-
-@hookspec(firstresult=True)
-def pytest_ignore_collect(path, config):
- """ return True to prevent considering this path for collection.
- This hook is consulted for all files and directories prior to calling
- more specific hooks.
- """
-
-@hookspec(firstresult=True)
-def pytest_collect_directory(path, parent):
- """ called before traversing a directory for collection files. """
-
-def pytest_collect_file(path, parent):
- """ return collection Node or None for the given path. Any new node
- needs to have the specified ``parent`` as a parent."""
-
-# logging hooks for collection
-def pytest_collectstart(collector):
- """ collector starts collecting. """
-
-def pytest_itemcollected(item):
- """ we just collected a test item. """
-
-def pytest_collectreport(report):
- """ collector finished collecting. """
-
-def pytest_deselected(items):
- """ called for test items deselected by keyword. """
-
-@hookspec(firstresult=True)
-def pytest_make_collect_report(collector):
- """ perform ``collector.collect()`` and return a CollectReport. """
-
-# -------------------------------------------------------------------------
-# Python test function related hooks
-# -------------------------------------------------------------------------
-
-@hookspec(firstresult=True)
-def pytest_pycollect_makemodule(path, parent):
- """ return a Module collector or None for the given path.
- This hook will be called for each matching test module path.
- The pytest_collect_file hook needs to be used if you want to
- create test modules for files that do not match as a test module.
- """
-
-@hookspec(firstresult=True)
-def pytest_pycollect_makeitem(collector, name, obj):
- """ return custom item/collector for a python object in a module, or None. """
-
-@hookspec(firstresult=True)
-def pytest_pyfunc_call(pyfuncitem):
- """ call underlying test function. """
-
-def pytest_generate_tests(metafunc):
- """ generate (multiple) parametrized calls to a test function."""
-
-# -------------------------------------------------------------------------
-# generic runtest related hooks
-# -------------------------------------------------------------------------
-
-@hookspec(firstresult=True)
-def pytest_runtestloop(session):
- """ called for performing the main runtest loop
- (after collection finished). """
-
-def pytest_itemstart(item, node):
- """ (deprecated, use pytest_runtest_logstart). """
-
-@hookspec(firstresult=True)
-def pytest_runtest_protocol(item, nextitem):
- """ implements the runtest_setup/call/teardown protocol for
- the given test item, including capturing exceptions and calling
- reporting hooks.
-
- :arg item: test item for which the runtest protocol is performed.
-
- :arg nextitem: the scheduled-to-be-next test item (or None if this
- is the end my friend). This argument is passed on to
- :py:func:`pytest_runtest_teardown`.
-
- :return boolean: True if no further hook implementations should be invoked.
- """
-
-def pytest_runtest_logstart(nodeid, location):
- """ signal the start of running a single test item. """
-
-def pytest_runtest_setup(item):
- """ called before ``pytest_runtest_call(item)``. """
-
-def pytest_runtest_call(item):
- """ called to execute the test ``item``. """
-
-def pytest_runtest_teardown(item, nextitem):
- """ called after ``pytest_runtest_call``.
-
- :arg nextitem: the scheduled-to-be-next test item (None if no further
- test item is scheduled). This argument can be used to
- perform exact teardowns, i.e. calling just enough finalizers
- so that nextitem only needs to call setup-functions.
- """
-
-@hookspec(firstresult=True)
-def pytest_runtest_makereport(item, call):
- """ return a :py:class:`_pytest.runner.TestReport` object
- for the given :py:class:`pytest.Item` and
- :py:class:`_pytest.runner.CallInfo`.
- """
-
-def pytest_runtest_logreport(report):
- """ process a test setup/call/teardown report relating to
- the respective phase of executing a test. """
-
-# -------------------------------------------------------------------------
-# test session related hooks
-# -------------------------------------------------------------------------
-
-def pytest_sessionstart(session):
- """ before session.main() is called. """
-
-def pytest_sessionfinish(session, exitstatus):
- """ whole test run finishes. """
-
-def pytest_unconfigure(config):
- """ called before test process is exited. """
-
-
-# -------------------------------------------------------------------------
-# hooks for customising the assert methods
-# -------------------------------------------------------------------------
-
-def pytest_assertrepr_compare(config, op, left, right):
- """return explanation for comparisons in failing assert expressions.
-
- Return None for no custom explanation, otherwise return a list
- of strings. The strings will be joined by newlines but any newlines
- *in* a string will be escaped. Note that all but the first line will
- be indented sligthly, the intention is for the first line to be a summary.
- """
-
-# -------------------------------------------------------------------------
-# hooks for influencing reporting (invoked from _pytest_terminal)
-# -------------------------------------------------------------------------
-
-def pytest_report_header(config, startdir):
- """ return a string to be displayed as header info for terminal reporting."""
-
-@hookspec(firstresult=True)
-def pytest_report_teststatus(report):
- """ return result-category, shortletter and verbose word for reporting."""
-
-def pytest_terminal_summary(terminalreporter):
- """ add additional section in terminal summary reporting. """
-
-
-@hookspec(historic=True)
-def pytest_logwarning(message, code, nodeid, fslocation):
- """ process a warning specified by a message, a code string,
- a nodeid and fslocation (both of which may be None
- if the warning is not tied to a partilar node/location)."""
-
-# -------------------------------------------------------------------------
-# doctest hooks
-# -------------------------------------------------------------------------
-
-@hookspec(firstresult=True)
-def pytest_doctest_prepare_content(content):
- """ return processed content for a given doctest"""
-
-# -------------------------------------------------------------------------
-# error handling and internal debugging hooks
-# -------------------------------------------------------------------------
-
-def pytest_internalerror(excrepr, excinfo):
- """ called for internal errors. """
-
-def pytest_keyboard_interrupt(excinfo):
- """ called for keyboard interrupt. """
-
-def pytest_exception_interact(node, call, report):
- """called when an exception was raised which can potentially be
- interactively handled.
-
- This hook is only called if an exception was raised
- that is not an internal exception like ``skip.Exception``.
- """
-
-def pytest_enter_pdb(config):
- """ called upon pdb.set_trace(), can be used by plugins to take special
- action just before the python debugger enters in interactive mode.
-
- :arg config: pytest config object
- :type config: _pytest.config.Config
- """
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/impl b/WebDriverTests/imported/w3c/tools/pytest/_pytest/impl
deleted file mode 100644
index 889e37e..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/impl
+++ /dev/null
@@ -1,254 +0,0 @@
-Sorting per-resource
------------------------------
-
-for any given set of items:
-
-- collect items per session-scoped parametrized funcarg
-- re-order until items no parametrizations are mixed
-
- examples:
-
- test()
- test1(s1)
- test1(s2)
- test2()
- test3(s1)
- test3(s2)
-
- gets sorted to:
-
- test()
- test2()
- test1(s1)
- test3(s1)
- test1(s2)
- test3(s2)
-
-
-the new @setup functions
---------------------------------------
-
-Consider a given @setup-marked function::
-
- @pytest.mark.setup(maxscope=SCOPE)
- def mysetup(request, arg1, arg2, ...)
- ...
- request.addfinalizer(fin)
- ...
-
-then FUNCARGSET denotes the set of (arg1, arg2, ...) funcargs and
-all of its dependent funcargs. The mysetup function will execute
-for any matching test item once per scope.
-
-The scope is determined as the minimum scope of all scopes of the args
-in FUNCARGSET and the given "maxscope".
-
-If mysetup has been called and no finalizers have been called it is
-called "active".
-
-Furthermore the following rules apply:
-
-- if an arg value in FUNCARGSET is about to be torn down, the
- mysetup-registered finalizers will execute as well.
-
-- There will never be two active mysetup invocations.
-
-Example 1, session scope::
-
- @pytest.mark.funcarg(scope="session", params=[1,2])
- def db(request):
- request.addfinalizer(db_finalize)
-
- @pytest.mark.setup
- def mysetup(request, db):
- request.addfinalizer(mysetup_finalize)
- ...
-
-And a given test module:
-
- def test_something():
- ...
- def test_otherthing():
- pass
-
-Here is what happens::
-
- db(request) executes with request.param == 1
- mysetup(request, db) executes
- test_something() executes
- test_otherthing() executes
- mysetup_finalize() executes
- db_finalize() executes
- db(request) executes with request.param == 2
- mysetup(request, db) executes
- test_something() executes
- test_otherthing() executes
- mysetup_finalize() executes
- db_finalize() executes
-
-Example 2, session/function scope::
-
- @pytest.mark.funcarg(scope="session", params=[1,2])
- def db(request):
- request.addfinalizer(db_finalize)
-
- @pytest.mark.setup(scope="function")
- def mysetup(request, db):
- ...
- request.addfinalizer(mysetup_finalize)
- ...
-
-And a given test module:
-
- def test_something():
- ...
- def test_otherthing():
- pass
-
-Here is what happens::
-
- db(request) executes with request.param == 1
- mysetup(request, db) executes
- test_something() executes
- mysetup_finalize() executes
- mysetup(request, db) executes
- test_otherthing() executes
- mysetup_finalize() executes
- db_finalize() executes
- db(request) executes with request.param == 2
- mysetup(request, db) executes
- test_something() executes
- mysetup_finalize() executes
- mysetup(request, db) executes
- test_otherthing() executes
- mysetup_finalize() executes
- db_finalize() executes
-
-
-Example 3 - funcargs session-mix
-----------------------------------------
-
-Similar with funcargs, an example::
-
- @pytest.mark.funcarg(scope="session", params=[1,2])
- def db(request):
- request.addfinalizer(db_finalize)
-
- @pytest.mark.funcarg(scope="function")
- def table(request, db):
- ...
- request.addfinalizer(table_finalize)
- ...
-
-And a given test module:
-
- def test_something(table):
- ...
- def test_otherthing(table):
- pass
- def test_thirdthing():
- pass
-
-Here is what happens::
-
- db(request) executes with param == 1
- table(request, db)
- test_something(table)
- table_finalize()
- table(request, db)
- test_otherthing(table)
- table_finalize()
- db_finalize
- db(request) executes with param == 2
- table(request, db)
- test_something(table)
- table_finalize()
- table(request, db)
- test_otherthing(table)
- table_finalize()
- db_finalize
- test_thirdthing()
-
-Data structures
---------------------
-
-pytest internally maintains a dict of active funcargs with cache, param,
-finalizer, (scopeitem?) information:
-
- active_funcargs = dict()
-
-if a parametrized "db" is activated:
-
- active_funcargs["db"] = FuncargInfo(dbvalue, paramindex,
- FuncargFinalize(...), scopeitem)
-
-if a test is torn down and the next test requires a differently
-parametrized "db":
-
- for argname in item.callspec.params:
- if argname in active_funcargs:
- funcarginfo = active_funcargs[argname]
- if funcarginfo.param != item.callspec.params[argname]:
- funcarginfo.callfinalizer()
- del node2funcarg[funcarginfo.scopeitem]
- del active_funcargs[argname]
- nodes_to_be_torn_down = ...
- for node in nodes_to_be_torn_down:
- if node in node2funcarg:
- argname = node2funcarg[node]
- active_funcargs[argname].callfinalizer()
- del node2funcarg[node]
- del active_funcargs[argname]
-
-if a test is setup requiring a "db" funcarg:
-
- if "db" in active_funcargs:
- return active_funcargs["db"][0]
- funcarginfo = setup_funcarg()
- active_funcargs["db"] = funcarginfo
- node2funcarg[funcarginfo.scopeitem] = "db"
-
-Implementation plan for resources
-------------------------------------------
-
-1. Revert FuncargRequest to the old form, unmerge item/request
- (done)
-2. make funcarg factories be discovered at collection time
-3. Introduce funcarg marker
-4. Introduce funcarg scope parameter
-5. Introduce funcarg parametrize parameter
-6. make setup functions be discovered at collection time
-7. (Introduce a pytest_fixture_protocol/setup_funcargs hook)
-
-methods and data structures
---------------------------------
-
-A FuncarcManager holds all information about funcarg definitions
-including parametrization and scope definitions. It implements
-a pytest_generate_tests hook which performs parametrization as appropriate.
-
-as a simple example, let's consider a tree where a test function requires
-a "abc" funcarg and its factory defines it as parametrized and scoped
-for Modules. When collections hits the function item, it creates
-the metafunc object, and calls funcargdb.pytest_generate_tests(metafunc)
-which looks up available funcarg factories and their scope and parametrization.
-This information is equivalent to what can be provided today directly
-at the function site and it should thus be relatively straight forward
-to implement the additional way of defining parametrization/scoping.
-
-conftest loading:
- each funcarg-factory will populate the session.funcargmanager
-
-When a test item is collected, it grows a dictionary
-(funcargname2factorycalllist). A factory lookup is performed
-for each required funcarg. The resulting factory call is stored
-with the item. If a function is parametrized multiple items are
-created with respective factory calls. Else if a factory is parametrized
-multiple items and calls to the factory function are created as well.
-
-At setup time, an item populates a funcargs mapping, mapping names
-to values. If a value is funcarg factories are queried for a given item
-test functions and setup functions are put in a class
-which looks up required funcarg factories.
-
-
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/junitxml.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/junitxml.py
deleted file mode 100644
index 660d718..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/junitxml.py
+++ /dev/null
@@ -1,387 +0,0 @@
-"""
- report test results in JUnit-XML format,
- for use with Jenkins and build integration servers.
-
-
-Based on initial code from Ross Lawley.
-"""
-# Output conforms to https://github.com/jenkinsci/xunit-plugin/blob/master/
-# src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd
-
-import py
-import os
-import re
-import sys
-import time
-import pytest
-
-# Python 2.X and 3.X compatibility
-if sys.version_info[0] < 3:
- from codecs import open
-else:
- unichr = chr
- unicode = str
- long = int
-
-
-class Junit(py.xml.Namespace):
- pass
-
-# We need to get the subset of the invalid unicode ranges according to
-# XML 1.0 which are valid in this python build. Hence we calculate
-# this dynamically instead of hardcoding it. The spec range of valid
-# chars is: Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
-# | [#x10000-#x10FFFF]
-_legal_chars = (0x09, 0x0A, 0x0d)
-_legal_ranges = (
- (0x20, 0x7E), (0x80, 0xD7FF), (0xE000, 0xFFFD), (0x10000, 0x10FFFF),
-)
-_legal_xml_re = [
- unicode("%s-%s") % (unichr(low), unichr(high))
- for (low, high) in _legal_ranges if low < sys.maxunicode
-]
-_legal_xml_re = [unichr(x) for x in _legal_chars] + _legal_xml_re
-illegal_xml_re = re.compile(unicode('[^%s]') % unicode('').join(_legal_xml_re))
-del _legal_chars
-del _legal_ranges
-del _legal_xml_re
-
-_py_ext_re = re.compile(r"\.py$")
-
-
-def bin_xml_escape(arg):
- def repl(matchobj):
- i = ord(matchobj.group())
- if i <= 0xFF:
- return unicode('#x%02X') % i
- else:
- return unicode('#x%04X') % i
-
- return py.xml.raw(illegal_xml_re.sub(repl, py.xml.escape(arg)))
-
-
-class _NodeReporter(object):
- def __init__(self, nodeid, xml):
-
- self.id = nodeid
- self.xml = xml
- self.add_stats = self.xml.add_stats
- self.duration = 0
- self.properties = []
- self.nodes = []
- self.testcase = None
- self.attrs = {}
-
- def append(self, node):
- self.xml.add_stats(type(node).__name__)
- self.nodes.append(node)
-
- def add_property(self, name, value):
- self.properties.append((str(name), bin_xml_escape(value)))
-
- def make_properties_node(self):
- """Return a Junit node containing custom properties, if any.
- """
- if self.properties:
- return Junit.properties([
- Junit.property(name=name, value=value)
- for name, value in self.properties
- ])
- return ''
-
- def record_testreport(self, testreport):
- assert not self.testcase
- names = mangle_test_address(testreport.nodeid)
- classnames = names[:-1]
- if self.xml.prefix:
- classnames.insert(0, self.xml.prefix)
- attrs = {
- "classname": ".".join(classnames),
- "name": bin_xml_escape(names[-1]),
- "file": testreport.location[0],
- }
- if testreport.location[1] is not None:
- attrs["line"] = testreport.location[1]
- self.attrs = attrs
-
- def to_xml(self):
- testcase = Junit.testcase(time=self.duration, **self.attrs)
- testcase.append(self.make_properties_node())
- for node in self.nodes:
- testcase.append(node)
- return testcase
-
- def _add_simple(self, kind, message, data=None):
- data = bin_xml_escape(data)
- node = kind(data, message=message)
- self.append(node)
-
- def _write_captured_output(self, report):
- for capname in ('out', 'err'):
- allcontent = ""
- for name, content in report.get_sections("Captured std%s" %
- capname):
- allcontent += content
- if allcontent:
- tag = getattr(Junit, 'system-' + capname)
- self.append(tag(bin_xml_escape(allcontent)))
-
- def append_pass(self, report):
- self.add_stats('passed')
- self._write_captured_output(report)
-
- def append_failure(self, report):
- # msg = str(report.longrepr.reprtraceback.extraline)
- if hasattr(report, "wasxfail"):
- self._add_simple(
- Junit.skipped,
- "xfail-marked test passes unexpectedly")
- else:
- if hasattr(report.longrepr, "reprcrash"):
- message = report.longrepr.reprcrash.message
- elif isinstance(report.longrepr, (unicode, str)):
- message = report.longrepr
- else:
- message = str(report.longrepr)
- message = bin_xml_escape(message)
- fail = Junit.failure(message=message)
- fail.append(bin_xml_escape(report.longrepr))
- self.append(fail)
- self._write_captured_output(report)
-
- def append_collect_error(self, report):
- # msg = str(report.longrepr.reprtraceback.extraline)
- self.append(Junit.error(bin_xml_escape(report.longrepr),
- message="collection failure"))
-
- def append_collect_skipped(self, report):
- self._add_simple(
- Junit.skipped, "collection skipped", report.longrepr)
-
- def append_error(self, report):
- self._add_simple(
- Junit.error, "test setup failure", report.longrepr)
- self._write_captured_output(report)
-
- def append_skipped(self, report):
- if hasattr(report, "wasxfail"):
- self._add_simple(
- Junit.skipped, "expected test failure", report.wasxfail
- )
- else:
- filename, lineno, skipreason = report.longrepr
- if skipreason.startswith("Skipped: "):
- skipreason = bin_xml_escape(skipreason[9:])
- self.append(
- Junit.skipped("%s:%s: %s" % (filename, lineno, skipreason),
- type="pytest.skip",
- message=skipreason))
- self._write_captured_output(report)
-
- def finalize(self):
- data = self.to_xml().unicode(indent=0)
- self.__dict__.clear()
- self.to_xml = lambda: py.xml.raw(data)
-
-
-@pytest.fixture
-def record_xml_property(request):
- """Fixture that adds extra xml properties to the tag for the calling test.
- The fixture is callable with (name, value), with value being automatically
- xml-encoded.
- """
- request.node.warn(
- code='C3',
- message='record_xml_property is an experimental feature',
- )
- xml = getattr(request.config, "_xml", None)
- if xml is not None:
- node_reporter = xml.node_reporter(request.node.nodeid)
- return node_reporter.add_property
- else:
- def add_property_noop(name, value):
- pass
-
- return add_property_noop
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("terminal reporting")
- group.addoption(
- '--junitxml', '--junit-xml',
- action="store",
- dest="xmlpath",
- metavar="path",
- default=None,
- help="create junit-xml style report file at given path.")
- group.addoption(
- '--junitprefix', '--junit-prefix',
- action="store",
- metavar="str",
- default=None,
- help="prepend prefix to classnames in junit-xml output")
-
-
-def pytest_configure(config):
- xmlpath = config.option.xmlpath
- # prevent opening xmllog on slave nodes (xdist)
- if xmlpath and not hasattr(config, 'slaveinput'):
- config._xml = LogXML(xmlpath, config.option.junitprefix)
- config.pluginmanager.register(config._xml)
-
-
-def pytest_unconfigure(config):
- xml = getattr(config, '_xml', None)
- if xml:
- del config._xml
- config.pluginmanager.unregister(xml)
-
-
-def mangle_test_address(address):
- path, possible_open_bracket, params = address.partition('[')
- names = path.split("::")
- try:
- names.remove('()')
- except ValueError:
- pass
- # convert file path to dotted path
- names[0] = names[0].replace("/", '.')
- names[0] = _py_ext_re.sub("", names[0])
- # put any params back
- names[-1] += possible_open_bracket + params
- return names
-
-
-class LogXML(object):
- def __init__(self, logfile, prefix):
- logfile = os.path.expanduser(os.path.expandvars(logfile))
- self.logfile = os.path.normpath(os.path.abspath(logfile))
- self.prefix = prefix
- self.stats = dict.fromkeys([
- 'error',
- 'passed',
- 'failure',
- 'skipped',
- ], 0)
- self.node_reporters = {} # nodeid -> _NodeReporter
- self.node_reporters_ordered = []
-
- def finalize(self, report):
- nodeid = getattr(report, 'nodeid', report)
- # local hack to handle xdist report order
- slavenode = getattr(report, 'node', None)
- reporter = self.node_reporters.pop((nodeid, slavenode))
- if reporter is not None:
- reporter.finalize()
-
- def node_reporter(self, report):
- nodeid = getattr(report, 'nodeid', report)
- # local hack to handle xdist report order
- slavenode = getattr(report, 'node', None)
-
- key = nodeid, slavenode
-
- if key in self.node_reporters:
- # TODO: breasks for --dist=each
- return self.node_reporters[key]
- reporter = _NodeReporter(nodeid, self)
- self.node_reporters[key] = reporter
- self.node_reporters_ordered.append(reporter)
- return reporter
-
- def add_stats(self, key):
- if key in self.stats:
- self.stats[key] += 1
-
- def _opentestcase(self, report):
- reporter = self.node_reporter(report)
- reporter.record_testreport(report)
- return reporter
-
- def pytest_runtest_logreport(self, report):
- """handle a setup/call/teardown report, generating the appropriate
- xml tags as necessary.
-
- note: due to plugins like xdist, this hook may be called in interlaced
- order with reports from other nodes. for example:
-
- usual call order:
- -> setup node1
- -> call node1
- -> teardown node1
- -> setup node2
- -> call node2
- -> teardown node2
-
- possible call order in xdist:
- -> setup node1
- -> call node1
- -> setup node2
- -> call node2
- -> teardown node2
- -> teardown node1
- """
- if report.passed:
- if report.when == "call": # ignore setup/teardown
- reporter = self._opentestcase(report)
- reporter.append_pass(report)
- elif report.failed:
- reporter = self._opentestcase(report)
- if report.when == "call":
- reporter.append_failure(report)
- else:
- reporter.append_error(report)
- elif report.skipped:
- reporter = self._opentestcase(report)
- reporter.append_skipped(report)
- self.update_testcase_duration(report)
- if report.when == "teardown":
- self.finalize(report)
-
- def update_testcase_duration(self, report):
- """accumulates total duration for nodeid from given report and updates
- the Junit.testcase with the new total if already created.
- """
- reporter = self.node_reporter(report)
- reporter.duration += getattr(report, 'duration', 0.0)
-
- def pytest_collectreport(self, report):
- if not report.passed:
- reporter = self._opentestcase(report)
- if report.failed:
- reporter.append_collect_error(report)
- else:
- reporter.append_collect_skipped(report)
-
- def pytest_internalerror(self, excrepr):
- reporter = self.node_reporter('internal')
- reporter.attrs.update(classname="pytest", name='internal')
- reporter._add_simple(Junit.error, 'internal error', excrepr)
-
- def pytest_sessionstart(self):
- self.suite_start_time = time.time()
-
- def pytest_sessionfinish(self):
- dirname = os.path.dirname(os.path.abspath(self.logfile))
- if not os.path.isdir(dirname):
- os.makedirs(dirname)
- logfile = open(self.logfile, 'w', encoding='utf-8')
- suite_stop_time = time.time()
- suite_time_delta = suite_stop_time - self.suite_start_time
-
- numtests = self.stats['passed'] + self.stats['failure']
-
- logfile.write('<?xml version="1.0" encoding="utf-8"?>')
- logfile.write(Junit.testsuite(
- [x.to_xml() for x in self.node_reporters_ordered],
- name="pytest",
- errors=self.stats['error'],
- failures=self.stats['failure'],
- skips=self.stats['skipped'],
- tests=numtests,
- time="%.3f" % suite_time_delta, ).unicode(indent=0))
- logfile.close()
-
- def pytest_terminal_summary(self, terminalreporter):
- terminalreporter.write_sep("-",
- "generated xml file: %s" % (self.logfile))
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/main.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/main.py
deleted file mode 100644
index 8654d7a..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/main.py
+++ /dev/null
@@ -1,744 +0,0 @@
-""" core implementation of testing process: init, session, runtest loop. """
-import imp
-import os
-import re
-import sys
-
-import _pytest
-import _pytest._code
-import py
-import pytest
-try:
- from collections import MutableMapping as MappingMixin
-except ImportError:
- from UserDict import DictMixin as MappingMixin
-
-from _pytest.runner import collect_one_node
-
-tracebackcutdir = py.path.local(_pytest.__file__).dirpath()
-
-# exitcodes for the command line
-EXIT_OK = 0
-EXIT_TESTSFAILED = 1
-EXIT_INTERRUPTED = 2
-EXIT_INTERNALERROR = 3
-EXIT_USAGEERROR = 4
-EXIT_NOTESTSCOLLECTED = 5
-
-name_re = re.compile("^[a-zA-Z_]\w*$")
-
-def pytest_addoption(parser):
- parser.addini("norecursedirs", "directory patterns to avoid for recursion",
- type="args", default=['.*', 'CVS', '_darcs', '{arch}', '*.egg'])
- parser.addini("testpaths", "directories to search for tests when no files or directories are given in the command line.",
- type="args", default=[])
- #parser.addini("dirpatterns",
- # "patterns specifying possible locations of test files",
- # type="linelist", default=["**/test_*.txt",
- # "**/test_*.py", "**/*_test.py"]
- #)
- group = parser.getgroup("general", "running and selection options")
- group._addoption('-x', '--exitfirst', action="store_true", default=False,
- dest="exitfirst",
- help="exit instantly on first error or failed test."),
- group._addoption('--maxfail', metavar="num",
- action="store", type=int, dest="maxfail", default=0,
- help="exit after first num failures or errors.")
- group._addoption('--strict', action="store_true",
- help="run pytest in strict mode, warnings become errors.")
- group._addoption("-c", metavar="file", type=str, dest="inifilename",
- help="load configuration from `file` instead of trying to locate one of the implicit configuration files.")
-
- group = parser.getgroup("collect", "collection")
- group.addoption('--collectonly', '--collect-only', action="store_true",
- help="only collect tests, don't execute them."),
- group.addoption('--pyargs', action="store_true",
- help="try to interpret all arguments as python packages.")
- group.addoption("--ignore", action="append", metavar="path",
- help="ignore path during collection (multi-allowed).")
- # when changing this to --conf-cut-dir, config.py Conftest.setinitial
- # needs upgrading as well
- group.addoption('--confcutdir', dest="confcutdir", default=None,
- metavar="dir",
- help="only load conftest.py's relative to specified dir.")
- group.addoption('--noconftest', action="store_true",
- dest="noconftest", default=False,
- help="Don't load any conftest.py files.")
-
- group = parser.getgroup("debugconfig",
- "test session debugging and configuration")
- group.addoption('--basetemp', dest="basetemp", default=None, metavar="dir",
- help="base temporary directory for this test run.")
-
-
-def pytest_namespace():
- collect = dict(Item=Item, Collector=Collector, File=File, Session=Session)
- return dict(collect=collect)
-
-def pytest_configure(config):
- pytest.config = config # compatibiltiy
- if config.option.exitfirst:
- config.option.maxfail = 1
-
-def wrap_session(config, doit):
- """Skeleton command line program"""
- session = Session(config)
- session.exitstatus = EXIT_OK
- initstate = 0
- try:
- try:
- config._do_configure()
- initstate = 1
- config.hook.pytest_sessionstart(session=session)
- initstate = 2
- session.exitstatus = doit(config, session) or 0
- except pytest.UsageError:
- raise
- except KeyboardInterrupt:
- excinfo = _pytest._code.ExceptionInfo()
- config.hook.pytest_keyboard_interrupt(excinfo=excinfo)
- session.exitstatus = EXIT_INTERRUPTED
- except:
- excinfo = _pytest._code.ExceptionInfo()
- config.notify_exception(excinfo, config.option)
- session.exitstatus = EXIT_INTERNALERROR
- if excinfo.errisinstance(SystemExit):
- sys.stderr.write("mainloop: caught Spurious SystemExit!\n")
-
- finally:
- excinfo = None # Explicitly break reference cycle.
- session.startdir.chdir()
- if initstate >= 2:
- config.hook.pytest_sessionfinish(
- session=session,
- exitstatus=session.exitstatus)
- config._ensure_unconfigure()
- return session.exitstatus
-
-def pytest_cmdline_main(config):
- return wrap_session(config, _main)
-
-def _main(config, session):
- """ default command line protocol for initialization, session,
- running tests and reporting. """
- config.hook.pytest_collection(session=session)
- config.hook.pytest_runtestloop(session=session)
-
- if session.testsfailed:
- return EXIT_TESTSFAILED
- elif session.testscollected == 0:
- return EXIT_NOTESTSCOLLECTED
-
-def pytest_collection(session):
- return session.perform_collect()
-
-def pytest_runtestloop(session):
- if session.config.option.collectonly:
- return True
-
- def getnextitem(i):
- # this is a function to avoid python2
- # keeping sys.exc_info set when calling into a test
- # python2 keeps sys.exc_info till the frame is left
- try:
- return session.items[i+1]
- except IndexError:
- return None
-
- for i, item in enumerate(session.items):
- nextitem = getnextitem(i)
- item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
- if session.shouldstop:
- raise session.Interrupted(session.shouldstop)
- return True
-
-def pytest_ignore_collect(path, config):
- p = path.dirpath()
- ignore_paths = config._getconftest_pathlist("collect_ignore", path=p)
- ignore_paths = ignore_paths or []
- excludeopt = config.getoption("ignore")
- if excludeopt:
- ignore_paths.extend([py.path.local(x) for x in excludeopt])
- return path in ignore_paths
-
-class FSHookProxy:
- def __init__(self, fspath, pm, remove_mods):
- self.fspath = fspath
- self.pm = pm
- self.remove_mods = remove_mods
-
- def __getattr__(self, name):
- x = self.pm.subset_hook_caller(name, remove_plugins=self.remove_mods)
- self.__dict__[name] = x
- return x
-
-def compatproperty(name):
- def fget(self):
- # deprecated - use pytest.name
- return getattr(pytest, name)
-
- return property(fget)
-
-class NodeKeywords(MappingMixin):
- def __init__(self, node):
- self.node = node
- self.parent = node.parent
- self._markers = {node.name: True}
-
- def __getitem__(self, key):
- try:
- return self._markers[key]
- except KeyError:
- if self.parent is None:
- raise
- return self.parent.keywords[key]
-
- def __setitem__(self, key, value):
- self._markers[key] = value
-
- def __delitem__(self, key):
- raise ValueError("cannot delete key in keywords dict")
-
- def __iter__(self):
- seen = set(self._markers)
- if self.parent is not None:
- seen.update(self.parent.keywords)
- return iter(seen)
-
- def __len__(self):
- return len(self.__iter__())
-
- def keys(self):
- return list(self)
-
- def __repr__(self):
- return "<NodeKeywords for node %s>" % (self.node, )
-
-
-class Node(object):
- """ base class for Collector and Item the test collection tree.
- Collector subclasses have children, Items are terminal nodes."""
-
- def __init__(self, name, parent=None, config=None, session=None):
- #: a unique name within the scope of the parent node
- self.name = name
-
- #: the parent collector node.
- self.parent = parent
-
- #: the pytest config object
- self.config = config or parent.config
-
- #: the session this node is part of
- self.session = session or parent.session
-
- #: filesystem path where this node was collected from (can be None)
- self.fspath = getattr(parent, 'fspath', None)
-
- #: keywords/markers collected from all scopes
- self.keywords = NodeKeywords(self)
-
- #: allow adding of extra keywords to use for matching
- self.extra_keyword_matches = set()
-
- # used for storing artificial fixturedefs for direct parametrization
- self._name2pseudofixturedef = {}
-
- @property
- def ihook(self):
- """ fspath sensitive hook proxy used to call pytest hooks"""
- return self.session.gethookproxy(self.fspath)
-
- Module = compatproperty("Module")
- Class = compatproperty("Class")
- Instance = compatproperty("Instance")
- Function = compatproperty("Function")
- File = compatproperty("File")
- Item = compatproperty("Item")
-
- def _getcustomclass(self, name):
- cls = getattr(self, name)
- if cls != getattr(pytest, name):
- py.log._apiwarn("2.0", "use of node.%s is deprecated, "
- "use pytest_pycollect_makeitem(...) to create custom "
- "collection nodes" % name)
- return cls
-
- def __repr__(self):
- return "<%s %r>" %(self.__class__.__name__,
- getattr(self, 'name', None))
-
- def warn(self, code, message):
- """ generate a warning with the given code and message for this
- item. """
- assert isinstance(code, str)
- fslocation = getattr(self, "location", None)
- if fslocation is None:
- fslocation = getattr(self, "fspath", None)
- else:
- fslocation = "%s:%s" % fslocation[:2]
-
- self.ihook.pytest_logwarning.call_historic(kwargs=dict(
- code=code, message=message,
- nodeid=self.nodeid, fslocation=fslocation))
-
- # methods for ordering nodes
- @property
- def nodeid(self):
- """ a ::-separated string denoting its collection tree address. """
- try:
- return self._nodeid
- except AttributeError:
- self._nodeid = x = self._makeid()
- return x
-
- def _makeid(self):
- return self.parent.nodeid + "::" + self.name
-
- def __hash__(self):
- return hash(self.nodeid)
-
- def setup(self):
- pass
-
- def teardown(self):
- pass
-
- def _memoizedcall(self, attrname, function):
- exattrname = "_ex_" + attrname
- failure = getattr(self, exattrname, None)
- if failure is not None:
- py.builtin._reraise(failure[0], failure[1], failure[2])
- if hasattr(self, attrname):
- return getattr(self, attrname)
- try:
- res = function()
- except py.builtin._sysex:
- raise
- except:
- failure = sys.exc_info()
- setattr(self, exattrname, failure)
- raise
- setattr(self, attrname, res)
- return res
-
- def listchain(self):
- """ return list of all parent collectors up to self,
- starting from root of collection tree. """
- chain = []
- item = self
- while item is not None:
- chain.append(item)
- item = item.parent
- chain.reverse()
- return chain
-
- def add_marker(self, marker):
- """ dynamically add a marker object to the node.
-
- ``marker`` can be a string or pytest.mark.* instance.
- """
- from _pytest.mark import MarkDecorator
- if isinstance(marker, py.builtin._basestring):
- marker = MarkDecorator(marker)
- elif not isinstance(marker, MarkDecorator):
- raise ValueError("is not a string or pytest.mark.* Marker")
- self.keywords[marker.name] = marker
-
- def get_marker(self, name):
- """ get a marker object from this node or None if
- the node doesn't have a marker with that name. """
- val = self.keywords.get(name, None)
- if val is not None:
- from _pytest.mark import MarkInfo, MarkDecorator
- if isinstance(val, (MarkDecorator, MarkInfo)):
- return val
-
- def listextrakeywords(self):
- """ Return a set of all extra keywords in self and any parents."""
- extra_keywords = set()
- item = self
- for item in self.listchain():
- extra_keywords.update(item.extra_keyword_matches)
- return extra_keywords
-
- def listnames(self):
- return [x.name for x in self.listchain()]
-
- def addfinalizer(self, fin):
- """ register a function to be called when this node is finalized.
-
- This method can only be called when this node is active
- in a setup chain, for example during self.setup().
- """
- self.session._setupstate.addfinalizer(fin, self)
-
- def getparent(self, cls):
- """ get the next parent node (including ourself)
- which is an instance of the given class"""
- current = self
- while current and not isinstance(current, cls):
- current = current.parent
- return current
-
- def _prunetraceback(self, excinfo):
- pass
-
- def _repr_failure_py(self, excinfo, style=None):
- fm = self.session._fixturemanager
- if excinfo.errisinstance(fm.FixtureLookupError):
- return excinfo.value.formatrepr()
- tbfilter = True
- if self.config.option.fulltrace:
- style="long"
- else:
- self._prunetraceback(excinfo)
- tbfilter = False # prunetraceback already does it
- if style == "auto":
- style = "long"
- # XXX should excinfo.getrepr record all data and toterminal() process it?
- if style is None:
- if self.config.option.tbstyle == "short":
- style = "short"
- else:
- style = "long"
-
- return excinfo.getrepr(funcargs=True,
- showlocals=self.config.option.showlocals,
- style=style, tbfilter=tbfilter)
-
- repr_failure = _repr_failure_py
-
-class Collector(Node):
- """ Collector instances create children through collect()
- and thus iteratively build a tree.
- """
-
- class CollectError(Exception):
- """ an error during collection, contains a custom message. """
-
- def collect(self):
- """ returns a list of children (items and collectors)
- for this collection node.
- """
- raise NotImplementedError("abstract")
-
- def repr_failure(self, excinfo):
- """ represent a collection failure. """
- if excinfo.errisinstance(self.CollectError):
- exc = excinfo.value
- return str(exc.args[0])
- return self._repr_failure_py(excinfo, style="short")
-
- def _memocollect(self):
- """ internal helper method to cache results of calling collect(). """
- return self._memoizedcall('_collected', lambda: list(self.collect()))
-
- def _prunetraceback(self, excinfo):
- if hasattr(self, 'fspath'):
- traceback = excinfo.traceback
- ntraceback = traceback.cut(path=self.fspath)
- if ntraceback == traceback:
- ntraceback = ntraceback.cut(excludepath=tracebackcutdir)
- excinfo.traceback = ntraceback.filter()
-
-class FSCollector(Collector):
- def __init__(self, fspath, parent=None, config=None, session=None):
- fspath = py.path.local(fspath) # xxx only for test_resultlog.py?
- name = fspath.basename
- if parent is not None:
- rel = fspath.relto(parent.fspath)
- if rel:
- name = rel
- name = name.replace(os.sep, "/")
- super(FSCollector, self).__init__(name, parent, config, session)
- self.fspath = fspath
-
- def _makeid(self):
- relpath = self.fspath.relto(self.config.rootdir)
- if os.sep != "/":
- relpath = relpath.replace(os.sep, "/")
- return relpath
-
-class File(FSCollector):
- """ base class for collecting tests from a file. """
-
-class Item(Node):
- """ a basic test invocation item. Note that for a single function
- there might be multiple test invocation items.
- """
- nextitem = None
-
- def __init__(self, name, parent=None, config=None, session=None):
- super(Item, self).__init__(name, parent, config, session)
- self._report_sections = []
-
- def add_report_section(self, when, key, content):
- if content:
- self._report_sections.append((when, key, content))
-
- def reportinfo(self):
- return self.fspath, None, ""
-
- @property
- def location(self):
- try:
- return self._location
- except AttributeError:
- location = self.reportinfo()
- # bestrelpath is a quite slow function
- cache = self.config.__dict__.setdefault("_bestrelpathcache", {})
- try:
- fspath = cache[location[0]]
- except KeyError:
- fspath = self.session.fspath.bestrelpath(location[0])
- cache[location[0]] = fspath
- location = (fspath, location[1], str(location[2]))
- self._location = location
- return location
-
-class NoMatch(Exception):
- """ raised if matching cannot locate a matching names. """
-
-class Interrupted(KeyboardInterrupt):
- """ signals an interrupted test run. """
- __module__ = 'builtins' # for py3
-
-class Session(FSCollector):
- Interrupted = Interrupted
-
- def __init__(self, config):
- FSCollector.__init__(self, config.rootdir, parent=None,
- config=config, session=self)
- self._fs2hookproxy = {}
- self.testsfailed = 0
- self.testscollected = 0
- self.shouldstop = False
- self.trace = config.trace.root.get("collection")
- self._norecursepatterns = config.getini("norecursedirs")
- self.startdir = py.path.local()
- self.config.pluginmanager.register(self, name="session")
-
- def _makeid(self):
- return ""
-
- @pytest.hookimpl(tryfirst=True)
- def pytest_collectstart(self):
- if self.shouldstop:
- raise self.Interrupted(self.shouldstop)
-
- @pytest.hookimpl(tryfirst=True)
- def pytest_runtest_logreport(self, report):
- if report.failed and not hasattr(report, 'wasxfail'):
- self.testsfailed += 1
- maxfail = self.config.getvalue("maxfail")
- if maxfail and self.testsfailed >= maxfail:
- self.shouldstop = "stopping after %d failures" % (
- self.testsfailed)
- pytest_collectreport = pytest_runtest_logreport
-
- def isinitpath(self, path):
- return path in self._initialpaths
-
- def gethookproxy(self, fspath):
- try:
- return self._fs2hookproxy[fspath]
- except KeyError:
- # check if we have the common case of running
- # hooks with all conftest.py filesall conftest.py
- pm = self.config.pluginmanager
- my_conftestmodules = pm._getconftestmodules(fspath)
- remove_mods = pm._conftest_plugins.difference(my_conftestmodules)
- if remove_mods:
- # one or more conftests are not in use at this fspath
- proxy = FSHookProxy(fspath, pm, remove_mods)
- else:
- # all plugis are active for this fspath
- proxy = self.config.hook
-
- self._fs2hookproxy[fspath] = proxy
- return proxy
-
- def perform_collect(self, args=None, genitems=True):
- hook = self.config.hook
- try:
- items = self._perform_collect(args, genitems)
- hook.pytest_collection_modifyitems(session=self,
- config=self.config, items=items)
- finally:
- hook.pytest_collection_finish(session=self)
- self.testscollected = len(items)
- return items
-
- def _perform_collect(self, args, genitems):
- if args is None:
- args = self.config.args
- self.trace("perform_collect", self, args)
- self.trace.root.indent += 1
- self._notfound = []
- self._initialpaths = set()
- self._initialparts = []
- self.items = items = []
- for arg in args:
- parts = self._parsearg(arg)
- self._initialparts.append(parts)
- self._initialpaths.add(parts[0])
- rep = collect_one_node(self)
- self.ihook.pytest_collectreport(report=rep)
- self.trace.root.indent -= 1
- if self._notfound:
- errors = []
- for arg, exc in self._notfound:
- line = "(no name %r in any of %r)" % (arg, exc.args[0])
- errors.append("not found: %s\n%s" % (arg, line))
- #XXX: test this
- raise pytest.UsageError(*errors)
- if not genitems:
- return rep.result
- else:
- if rep.passed:
- for node in rep.result:
- self.items.extend(self.genitems(node))
- return items
-
- def collect(self):
- for parts in self._initialparts:
- arg = "::".join(map(str, parts))
- self.trace("processing argument", arg)
- self.trace.root.indent += 1
- try:
- for x in self._collect(arg):
- yield x
- except NoMatch:
- # we are inside a make_report hook so
- # we cannot directly pass through the exception
- self._notfound.append((arg, sys.exc_info()[1]))
-
- self.trace.root.indent -= 1
-
- def _collect(self, arg):
- names = self._parsearg(arg)
- path = names.pop(0)
- if path.check(dir=1):
- assert not names, "invalid arg %r" %(arg,)
- for path in path.visit(fil=lambda x: x.check(file=1),
- rec=self._recurse, bf=True, sort=True):
- for x in self._collectfile(path):
- yield x
- else:
- assert path.check(file=1)
- for x in self.matchnodes(self._collectfile(path), names):
- yield x
-
- def _collectfile(self, path):
- ihook = self.gethookproxy(path)
- if not self.isinitpath(path):
- if ihook.pytest_ignore_collect(path=path, config=self.config):
- return ()
- return ihook.pytest_collect_file(path=path, parent=self)
-
- def _recurse(self, path):
- ihook = self.gethookproxy(path.dirpath())
- if ihook.pytest_ignore_collect(path=path, config=self.config):
- return
- for pat in self._norecursepatterns:
- if path.check(fnmatch=pat):
- return False
- ihook = self.gethookproxy(path)
- ihook.pytest_collect_directory(path=path, parent=self)
- return True
-
- def _tryconvertpyarg(self, x):
- mod = None
- path = [os.path.abspath('.')] + sys.path
- for name in x.split('.'):
- # ignore anything that's not a proper name here
- # else something like --pyargs will mess up '.'
- # since imp.find_module will actually sometimes work for it
- # but it's supposed to be considered a filesystem path
- # not a package
- if name_re.match(name) is None:
- return x
- try:
- fd, mod, type_ = imp.find_module(name, path)
- except ImportError:
- return x
- else:
- if fd is not None:
- fd.close()
-
- if type_[2] != imp.PKG_DIRECTORY:
- path = [os.path.dirname(mod)]
- else:
- path = [mod]
- return mod
-
- def _parsearg(self, arg):
- """ return (fspath, names) tuple after checking the file exists. """
- arg = str(arg)
- if self.config.option.pyargs:
- arg = self._tryconvertpyarg(arg)
- parts = str(arg).split("::")
- relpath = parts[0].replace("/", os.sep)
- path = self.config.invocation_dir.join(relpath, abs=True)
- if not path.check():
- if self.config.option.pyargs:
- msg = "file or package not found: "
- else:
- msg = "file not found: "
- raise pytest.UsageError(msg + arg)
- parts[0] = path
- return parts
-
- def matchnodes(self, matching, names):
- self.trace("matchnodes", matching, names)
- self.trace.root.indent += 1
- nodes = self._matchnodes(matching, names)
- num = len(nodes)
- self.trace("matchnodes finished -> ", num, "nodes")
- self.trace.root.indent -= 1
- if num == 0:
- raise NoMatch(matching, names[:1])
- return nodes
-
- def _matchnodes(self, matching, names):
- if not matching or not names:
- return matching
- name = names[0]
- assert name
- nextnames = names[1:]
- resultnodes = []
- for node in matching:
- if isinstance(node, pytest.Item):
- if not names:
- resultnodes.append(node)
- continue
- assert isinstance(node, pytest.Collector)
- rep = collect_one_node(node)
- if rep.passed:
- has_matched = False
- for x in rep.result:
- # TODO: remove parametrized workaround once collection structure contains parametrization
- if x.name == name or x.name.split("[")[0] == name:
- resultnodes.extend(self.matchnodes([x], nextnames))
- has_matched = True
- # XXX accept IDs that don't have "()" for class instances
- if not has_matched and len(rep.result) == 1 and x.name == "()":
- nextnames.insert(0, name)
- resultnodes.extend(self.matchnodes([x], nextnames))
- node.ihook.pytest_collectreport(report=rep)
- return resultnodes
-
- def genitems(self, node):
- self.trace("genitems", node)
- if isinstance(node, pytest.Item):
- node.ihook.pytest_itemcollected(item=node)
- yield node
- else:
- assert isinstance(node, pytest.Collector)
- rep = collect_one_node(node)
- if rep.passed:
- for subnode in rep.result:
- for x in self.genitems(subnode):
- yield x
- node.ihook.pytest_collectreport(report=rep)
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/mark.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/mark.py
deleted file mode 100644
index 1a76354..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/mark.py
+++ /dev/null
@@ -1,311 +0,0 @@
-""" generic mechanism for marking and selecting python functions. """
-import inspect
-
-
-class MarkerError(Exception):
-
- """Error in use of a pytest marker/attribute."""
-
-
-def pytest_namespace():
- return {'mark': MarkGenerator()}
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("general")
- group._addoption(
- '-k',
- action="store", dest="keyword", default='', metavar="EXPRESSION",
- help="only run tests which match the given substring expression. "
- "An expression is a python evaluatable expression "
- "where all names are substring-matched against test names "
- "and their parent classes. Example: -k 'test_method or test "
- "other' matches all test functions and classes whose name "
- "contains 'test_method' or 'test_other'. "
- "Additionally keywords are matched to classes and functions "
- "containing extra names in their 'extra_keyword_matches' set, "
- "as well as functions which have names assigned directly to them."
- )
-
- group._addoption(
- "-m",
- action="store", dest="markexpr", default="", metavar="MARKEXPR",
- help="only run tests matching given mark expression. "
- "example: -m 'mark1 and not mark2'."
- )
-
- group.addoption(
- "--markers", action="store_true",
- help="show markers (builtin, plugin and per-project ones)."
- )
-
- parser.addini("markers", "markers for test functions", 'linelist')
-
-
-def pytest_cmdline_main(config):
- import _pytest.config
- if config.option.markers:
- config._do_configure()
- tw = _pytest.config.create_terminal_writer(config)
- for line in config.getini("markers"):
- name, rest = line.split(":", 1)
- tw.write("@pytest.mark.%s:" % name, bold=True)
- tw.line(rest)
- tw.line()
- config._ensure_unconfigure()
- return 0
-pytest_cmdline_main.tryfirst = True
-
-
-def pytest_collection_modifyitems(items, config):
- keywordexpr = config.option.keyword
- matchexpr = config.option.markexpr
- if not keywordexpr and not matchexpr:
- return
- # pytest used to allow "-" for negating
- # but today we just allow "-" at the beginning, use "not" instead
- # we probably remove "-" alltogether soon
- if keywordexpr.startswith("-"):
- keywordexpr = "not " + keywordexpr[1:]
- selectuntil = False
- if keywordexpr[-1:] == ":":
- selectuntil = True
- keywordexpr = keywordexpr[:-1]
-
- remaining = []
- deselected = []
- for colitem in items:
- if keywordexpr and not matchkeyword(colitem, keywordexpr):
- deselected.append(colitem)
- else:
- if selectuntil:
- keywordexpr = None
- if matchexpr:
- if not matchmark(colitem, matchexpr):
- deselected.append(colitem)
- continue
- remaining.append(colitem)
-
- if deselected:
- config.hook.pytest_deselected(items=deselected)
- items[:] = remaining
-
-
-class MarkMapping:
- """Provides a local mapping for markers where item access
- resolves to True if the marker is present. """
- def __init__(self, keywords):
- mymarks = set()
- for key, value in keywords.items():
- if isinstance(value, MarkInfo) or isinstance(value, MarkDecorator):
- mymarks.add(key)
- self._mymarks = mymarks
-
- def __getitem__(self, name):
- return name in self._mymarks
-
-
-class KeywordMapping:
- """Provides a local mapping for keywords.
- Given a list of names, map any substring of one of these names to True.
- """
- def __init__(self, names):
- self._names = names
-
- def __getitem__(self, subname):
- for name in self._names:
- if subname in name:
- return True
- return False
-
-
-def matchmark(colitem, markexpr):
- """Tries to match on any marker names, attached to the given colitem."""
- return eval(markexpr, {}, MarkMapping(colitem.keywords))
-
-
-def matchkeyword(colitem, keywordexpr):
- """Tries to match given keyword expression to given collector item.
-
- Will match on the name of colitem, including the names of its parents.
- Only matches names of items which are either a :class:`Class` or a
- :class:`Function`.
- Additionally, matches on names in the 'extra_keyword_matches' set of
- any item, as well as names directly assigned to test functions.
- """
- mapped_names = set()
-
- # Add the names of the current item and any parent items
- import pytest
- for item in colitem.listchain():
- if not isinstance(item, pytest.Instance):
- mapped_names.add(item.name)
-
- # Add the names added as extra keywords to current or parent items
- for name in colitem.listextrakeywords():
- mapped_names.add(name)
-
- # Add the names attached to the current function through direct assignment
- if hasattr(colitem, 'function'):
- for name in colitem.function.__dict__:
- mapped_names.add(name)
-
- mapping = KeywordMapping(mapped_names)
- if " " not in keywordexpr:
- # special case to allow for simple "-k pass" and "-k 1.3"
- return mapping[keywordexpr]
- elif keywordexpr.startswith("not ") and " " not in keywordexpr[4:]:
- return not mapping[keywordexpr[4:]]
- return eval(keywordexpr, {}, mapping)
-
-
-def pytest_configure(config):
- import pytest
- if config.option.strict:
- pytest.mark._config = config
-
-
-class MarkGenerator:
- """ Factory for :class:`MarkDecorator` objects - exposed as
- a ``pytest.mark`` singleton instance. Example::
-
- import pytest
- @pytest.mark.slowtest
- def test_function():
- pass
-
- will set a 'slowtest' :class:`MarkInfo` object
- on the ``test_function`` object. """
-
- def __getattr__(self, name):
- if name[0] == "_":
- raise AttributeError("Marker name must NOT start with underscore")
- if hasattr(self, '_config'):
- self._check(name)
- return MarkDecorator(name)
-
- def _check(self, name):
- try:
- if name in self._markers:
- return
- except AttributeError:
- pass
- self._markers = l = set()
- for line in self._config.getini("markers"):
- beginning = line.split(":", 1)
- x = beginning[0].split("(", 1)[0]
- l.add(x)
- if name not in self._markers:
- raise AttributeError("%r not a registered marker" % (name,))
-
-def istestfunc(func):
- return hasattr(func, "__call__") and \
- getattr(func, "__name__", "<lambda>") != "<lambda>"
-
-class MarkDecorator:
- """ A decorator for test functions and test classes. When applied
- it will create :class:`MarkInfo` objects which may be
- :ref:`retrieved by hooks as item keywords <excontrolskip>`.
- MarkDecorator instances are often created like this::
-
- mark1 = pytest.mark.NAME # simple MarkDecorator
- mark2 = pytest.mark.NAME(name1=value) # parametrized MarkDecorator
-
- and can then be applied as decorators to test functions::
-
- @mark2
- def test_function():
- pass
-
- When a MarkDecorator instance is called it does the following:
- 1. If called with a single class as its only positional argument and no
- additional keyword arguments, it attaches itself to the class so it
- gets applied automatically to all test cases found in that class.
- 2. If called with a single function as its only positional argument and
- no additional keyword arguments, it attaches a MarkInfo object to the
- function, containing all the arguments already stored internally in
- the MarkDecorator.
- 3. When called in any other case, it performs a 'fake construction' call,
- i.e. it returns a new MarkDecorator instance with the original
- MarkDecorator's content updated with the arguments passed to this
- call.
-
- Note: The rules above prevent MarkDecorator objects from storing only a
- single function or class reference as their positional argument with no
- additional keyword or positional arguments.
-
- """
- def __init__(self, name, args=None, kwargs=None):
- self.name = name
- self.args = args or ()
- self.kwargs = kwargs or {}
-
- @property
- def markname(self):
- return self.name # for backward-compat (2.4.1 had this attr)
-
- def __repr__(self):
- d = self.__dict__.copy()
- name = d.pop('name')
- return "<MarkDecorator %r %r>" % (name, d)
-
- def __call__(self, *args, **kwargs):
- """ if passed a single callable argument: decorate it with mark info.
- otherwise add *args/**kwargs in-place to mark information. """
- if args and not kwargs:
- func = args[0]
- is_class = inspect.isclass(func)
- if len(args) == 1 and (istestfunc(func) or is_class):
- if is_class:
- if hasattr(func, 'pytestmark'):
- mark_list = func.pytestmark
- if not isinstance(mark_list, list):
- mark_list = [mark_list]
- # always work on a copy to avoid updating pytestmark
- # from a superclass by accident
- mark_list = mark_list + [self]
- func.pytestmark = mark_list
- else:
- func.pytestmark = [self]
- else:
- holder = getattr(func, self.name, None)
- if holder is None:
- holder = MarkInfo(
- self.name, self.args, self.kwargs
- )
- setattr(func, self.name, holder)
- else:
- holder.add(self.args, self.kwargs)
- return func
- kw = self.kwargs.copy()
- kw.update(kwargs)
- args = self.args + args
- return self.__class__(self.name, args=args, kwargs=kw)
-
-
-class MarkInfo:
- """ Marking object created by :class:`MarkDecorator` instances. """
- def __init__(self, name, args, kwargs):
- #: name of attribute
- self.name = name
- #: positional argument list, empty if none specified
- self.args = args
- #: keyword argument dictionary, empty if nothing specified
- self.kwargs = kwargs.copy()
- self._arglist = [(args, kwargs.copy())]
-
- def __repr__(self):
- return "<MarkInfo %r args=%r kwargs=%r>" % (
- self.name, self.args, self.kwargs
- )
-
- def add(self, args, kwargs):
- """ add a MarkInfo with the given args and kwargs. """
- self._arglist.append((args, kwargs))
- self.args += args
- self.kwargs.update(kwargs)
-
- def __iter__(self):
- """ yield MarkInfo objects each relating to a marking-call. """
- for args, kwargs in self._arglist:
- yield MarkInfo(self.name, args, kwargs)
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/monkeypatch.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/monkeypatch.py
deleted file mode 100644
index d4c169d..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/monkeypatch.py
+++ /dev/null
@@ -1,254 +0,0 @@
-""" monkeypatching and mocking functionality. """
-
-import os, sys
-import re
-
-from py.builtin import _basestring
-
-RE_IMPORT_ERROR_NAME = re.compile("^No module named (.*)$")
-
-
-def pytest_funcarg__monkeypatch(request):
- """The returned ``monkeypatch`` funcarg provides these
- helper methods to modify objects, dictionaries or os.environ::
-
- monkeypatch.setattr(obj, name, value, raising=True)
- monkeypatch.delattr(obj, name, raising=True)
- monkeypatch.setitem(mapping, name, value)
- monkeypatch.delitem(obj, name, raising=True)
- monkeypatch.setenv(name, value, prepend=False)
- monkeypatch.delenv(name, value, raising=True)
- monkeypatch.syspath_prepend(path)
- monkeypatch.chdir(path)
-
- All modifications will be undone after the requesting
- test function has finished. The ``raising``
- parameter determines if a KeyError or AttributeError
- will be raised if the set/deletion operation has no target.
- """
- mpatch = monkeypatch()
- request.addfinalizer(mpatch.undo)
- return mpatch
-
-
-def resolve(name):
- # simplified from zope.dottedname
- parts = name.split('.')
-
- used = parts.pop(0)
- found = __import__(used)
- for part in parts:
- used += '.' + part
- try:
- found = getattr(found, part)
- except AttributeError:
- pass
- else:
- continue
- # we use explicit un-nesting of the handling block in order
- # to avoid nested exceptions on python 3
- try:
- __import__(used)
- except ImportError as ex:
- # str is used for py2 vs py3
- expected = str(ex).split()[-1]
- if expected == used:
- raise
- else:
- raise ImportError(
- 'import error in %s: %s' % (used, ex)
- )
- found = annotated_getattr(found, part, used)
- return found
-
-
-def annotated_getattr(obj, name, ann):
- try:
- obj = getattr(obj, name)
- except AttributeError:
- raise AttributeError(
- '%r object at %s has no attribute %r' % (
- type(obj).__name__, ann, name
- )
- )
- return obj
-
-
-def derive_importpath(import_path, raising):
- if not isinstance(import_path, _basestring) or "." not in import_path:
- raise TypeError("must be absolute import path string, not %r" %
- (import_path,))
- module, attr = import_path.rsplit('.', 1)
- target = resolve(module)
- if raising:
- annotated_getattr(target, attr, ann=module)
- return attr, target
-
-
-class Notset:
- def __repr__(self):
- return "<notset>"
-
-
-notset = Notset()
-
-
-class monkeypatch:
- """ Object keeping a record of setattr/item/env/syspath changes. """
-
- def __init__(self):
- self._setattr = []
- self._setitem = []
- self._cwd = None
- self._savesyspath = None
-
- def setattr(self, target, name, value=notset, raising=True):
- """ Set attribute value on target, memorizing the old value.
- By default raise AttributeError if the attribute did not exist.
-
- For convenience you can specify a string as ``target`` which
- will be interpreted as a dotted import path, with the last part
- being the attribute name. Example:
- ``monkeypatch.setattr("os.getcwd", lambda x: "/")``
- would set the ``getcwd`` function of the ``os`` module.
-
- The ``raising`` value determines if the setattr should fail
- if the attribute is not already present (defaults to True
- which means it will raise).
- """
- __tracebackhide__ = True
- import inspect
-
- if value is notset:
- if not isinstance(target, _basestring):
- raise TypeError("use setattr(target, name, value) or "
- "setattr(target, value) with target being a dotted "
- "import string")
- value = name
- name, target = derive_importpath(target, raising)
-
- oldval = getattr(target, name, notset)
- if raising and oldval is notset:
- raise AttributeError("%r has no attribute %r" % (target, name))
-
- # avoid class descriptors like staticmethod/classmethod
- if inspect.isclass(target):
- oldval = target.__dict__.get(name, notset)
- self._setattr.append((target, name, oldval))
- setattr(target, name, value)
-
- def delattr(self, target, name=notset, raising=True):
- """ Delete attribute ``name`` from ``target``, by default raise
- AttributeError it the attribute did not previously exist.
-
- If no ``name`` is specified and ``target`` is a string
- it will be interpreted as a dotted import path with the
- last part being the attribute name.
-
- If ``raising`` is set to False, no exception will be raised if the
- attribute is missing.
- """
- __tracebackhide__ = True
- if name is notset:
- if not isinstance(target, _basestring):
- raise TypeError("use delattr(target, name) or "
- "delattr(target) with target being a dotted "
- "import string")
- name, target = derive_importpath(target, raising)
-
- if not hasattr(target, name):
- if raising:
- raise AttributeError(name)
- else:
- self._setattr.append((target, name, getattr(target, name, notset)))
- delattr(target, name)
-
- def setitem(self, dic, name, value):
- """ Set dictionary entry ``name`` to value. """
- self._setitem.append((dic, name, dic.get(name, notset)))
- dic[name] = value
-
- def delitem(self, dic, name, raising=True):
- """ Delete ``name`` from dict. Raise KeyError if it doesn't exist.
-
- If ``raising`` is set to False, no exception will be raised if the
- key is missing.
- """
- if name not in dic:
- if raising:
- raise KeyError(name)
- else:
- self._setitem.append((dic, name, dic.get(name, notset)))
- del dic[name]
-
- def setenv(self, name, value, prepend=None):
- """ Set environment variable ``name`` to ``value``. If ``prepend``
- is a character, read the current environment variable value
- and prepend the ``value`` adjoined with the ``prepend`` character."""
- value = str(value)
- if prepend and name in os.environ:
- value = value + prepend + os.environ[name]
- self.setitem(os.environ, name, value)
-
- def delenv(self, name, raising=True):
- """ Delete ``name`` from the environment. Raise KeyError it does not
- exist.
-
- If ``raising`` is set to False, no exception will be raised if the
- environment variable is missing.
- """
- self.delitem(os.environ, name, raising=raising)
-
- def syspath_prepend(self, path):
- """ Prepend ``path`` to ``sys.path`` list of import locations. """
- if self._savesyspath is None:
- self._savesyspath = sys.path[:]
- sys.path.insert(0, str(path))
-
- def chdir(self, path):
- """ Change the current working directory to the specified path.
- Path can be a string or a py.path.local object.
- """
- if self._cwd is None:
- self._cwd = os.getcwd()
- if hasattr(path, "chdir"):
- path.chdir()
- else:
- os.chdir(path)
-
- def undo(self):
- """ Undo previous changes. This call consumes the
- undo stack. Calling it a second time has no effect unless
- you do more monkeypatching after the undo call.
-
- There is generally no need to call `undo()`, since it is
- called automatically during tear-down.
-
- Note that the same `monkeypatch` fixture is used across a
- single test function invocation. If `monkeypatch` is used both by
- the test function itself and one of the test fixtures,
- calling `undo()` will undo all of the changes made in
- both functions.
- """
- for obj, name, value in reversed(self._setattr):
- if value is not notset:
- setattr(obj, name, value)
- else:
- delattr(obj, name)
- self._setattr[:] = []
- for dictionary, name, value in reversed(self._setitem):
- if value is notset:
- try:
- del dictionary[name]
- except KeyError:
- pass # was already deleted, so we have the desired state
- else:
- dictionary[name] = value
- self._setitem[:] = []
- if self._savesyspath is not None:
- sys.path[:] = self._savesyspath
- self._savesyspath = None
-
- if self._cwd is not None:
- os.chdir(self._cwd)
- self._cwd = None
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/nose.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/nose.py
deleted file mode 100644
index 0387468..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/nose.py
+++ /dev/null
@@ -1,71 +0,0 @@
-""" run test suites written for nose. """
-
-import sys
-
-import py
-import pytest
-from _pytest import unittest
-
-
-def get_skip_exceptions():
- skip_classes = set()
- for module_name in ('unittest', 'unittest2', 'nose'):
- mod = sys.modules.get(module_name)
- if hasattr(mod, 'SkipTest'):
- skip_classes.add(mod.SkipTest)
- return tuple(skip_classes)
-
-
-def pytest_runtest_makereport(item, call):
- if call.excinfo and call.excinfo.errisinstance(get_skip_exceptions()):
- # let's substitute the excinfo with a pytest.skip one
- call2 = call.__class__(lambda:
- pytest.skip(str(call.excinfo.value)), call.when)
- call.excinfo = call2.excinfo
-
-
-@pytest.hookimpl(trylast=True)
-def pytest_runtest_setup(item):
- if is_potential_nosetest(item):
- if isinstance(item.parent, pytest.Generator):
- gen = item.parent
- if not hasattr(gen, '_nosegensetup'):
- call_optional(gen.obj, 'setup')
- if isinstance(gen.parent, pytest.Instance):
- call_optional(gen.parent.obj, 'setup')
- gen._nosegensetup = True
- if not call_optional(item.obj, 'setup'):
- # call module level setup if there is no object level one
- call_optional(item.parent.obj, 'setup')
- #XXX this implies we only call teardown when setup worked
- item.session._setupstate.addfinalizer((lambda: teardown_nose(item)), item)
-
-def teardown_nose(item):
- if is_potential_nosetest(item):
- if not call_optional(item.obj, 'teardown'):
- call_optional(item.parent.obj, 'teardown')
- #if hasattr(item.parent, '_nosegensetup'):
- # #call_optional(item._nosegensetup, 'teardown')
- # del item.parent._nosegensetup
-
-
-def pytest_make_collect_report(collector):
- if isinstance(collector, pytest.Generator):
- call_optional(collector.obj, 'setup')
-
-
-def is_potential_nosetest(item):
- # extra check needed since we do not do nose style setup/teardown
- # on direct unittest style classes
- return isinstance(item, pytest.Function) and \
- not isinstance(item, unittest.TestCaseFunction)
-
-
-def call_optional(obj, name):
- method = getattr(obj, name, None)
- isfixture = hasattr(method, "_pytestfixturefunction")
- if method is not None and not isfixture and py.builtin.callable(method):
- # If there's any problems allow the exception to raise rather than
- # silently ignoring them
- method()
- return True
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/pastebin.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/pastebin.py
deleted file mode 100644
index 4ec62d0..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/pastebin.py
+++ /dev/null
@@ -1,92 +0,0 @@
-""" submit failure or test session information to a pastebin service. """
-import pytest
-import sys
-import tempfile
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("terminal reporting")
- group._addoption('--pastebin', metavar="mode",
- action='store', dest="pastebin", default=None,
- choices=['failed', 'all'],
- help="send failed|all info to bpaste.net pastebin service.")
-
-@pytest.hookimpl(trylast=True)
-def pytest_configure(config):
- import py
- if config.option.pastebin == "all":
- tr = config.pluginmanager.getplugin('terminalreporter')
- # if no terminal reporter plugin is present, nothing we can do here;
- # this can happen when this function executes in a slave node
- # when using pytest-xdist, for example
- if tr is not None:
- # pastebin file will be utf-8 encoded binary file
- config._pastebinfile = tempfile.TemporaryFile('w+b')
- oldwrite = tr._tw.write
- def tee_write(s, **kwargs):
- oldwrite(s, **kwargs)
- if py.builtin._istext(s):
- s = s.encode('utf-8')
- config._pastebinfile.write(s)
- tr._tw.write = tee_write
-
-def pytest_unconfigure(config):
- if hasattr(config, '_pastebinfile'):
- # get terminal contents and delete file
- config._pastebinfile.seek(0)
- sessionlog = config._pastebinfile.read()
- config._pastebinfile.close()
- del config._pastebinfile
- # undo our patching in the terminal reporter
- tr = config.pluginmanager.getplugin('terminalreporter')
- del tr._tw.__dict__['write']
- # write summary
- tr.write_sep("=", "Sending information to Paste Service")
- pastebinurl = create_new_paste(sessionlog)
- tr.write_line("pastebin session-log: %s\n" % pastebinurl)
-
-def create_new_paste(contents):
- """
- Creates a new paste using bpaste.net service.
-
- :contents: paste contents as utf-8 encoded bytes
- :returns: url to the pasted contents
- """
- import re
- if sys.version_info < (3, 0):
- from urllib import urlopen, urlencode
- else:
- from urllib.request import urlopen
- from urllib.parse import urlencode
-
- params = {
- 'code': contents,
- 'lexer': 'python3' if sys.version_info[0] == 3 else 'python',
- 'expiry': '1week',
- }
- url = 'https://bpaste.net'
- response = urlopen(url, data=urlencode(params).encode('ascii')).read()
- m = re.search(r'href="/raw/(\w+)"', response.decode('utf-8'))
- if m:
- return '%s/show/%s' % (url, m.group(1))
- else:
- return 'bad response: ' + response
-
-def pytest_terminal_summary(terminalreporter):
- import _pytest.config
- if terminalreporter.config.option.pastebin != "failed":
- return
- tr = terminalreporter
- if 'failed' in tr.stats:
- terminalreporter.write_sep("=", "Sending information to Paste Service")
- for rep in terminalreporter.stats.get('failed'):
- try:
- msg = rep.longrepr.reprtraceback.reprentries[-1].reprfileloc
- except AttributeError:
- msg = tr._getfailureheadline(rep)
- tw = _pytest.config.create_terminal_writer(terminalreporter.config, stringio=True)
- rep.toterminal(tw)
- s = tw.stringio.getvalue()
- assert len(s)
- pastebinurl = create_new_paste(s)
- tr.write_line("%s --> %s" %(msg, pastebinurl))
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/pdb.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/pdb.py
deleted file mode 100644
index 84c920d..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/pdb.py
+++ /dev/null
@@ -1,109 +0,0 @@
-""" interactive debugging with PDB, the Python Debugger. """
-from __future__ import absolute_import
-import pdb
-import sys
-
-import pytest
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("general")
- group._addoption('--pdb',
- action="store_true", dest="usepdb", default=False,
- help="start the interactive Python debugger on errors.")
-
-def pytest_namespace():
- return {'set_trace': pytestPDB().set_trace}
-
-def pytest_configure(config):
- if config.getvalue("usepdb"):
- config.pluginmanager.register(PdbInvoke(), 'pdbinvoke')
-
- old = (pdb.set_trace, pytestPDB._pluginmanager)
- def fin():
- pdb.set_trace, pytestPDB._pluginmanager = old
- pytestPDB._config = None
- pdb.set_trace = pytest.set_trace
- pytestPDB._pluginmanager = config.pluginmanager
- pytestPDB._config = config
- config._cleanup.append(fin)
-
-class pytestPDB:
- """ Pseudo PDB that defers to the real pdb. """
- _pluginmanager = None
- _config = None
-
- def set_trace(self):
- """ invoke PDB set_trace debugging, dropping any IO capturing. """
- import _pytest.config
- frame = sys._getframe().f_back
- if self._pluginmanager is not None:
- capman = self._pluginmanager.getplugin("capturemanager")
- if capman:
- capman.suspendcapture(in_=True)
- tw = _pytest.config.create_terminal_writer(self._config)
- tw.line()
- tw.sep(">", "PDB set_trace (IO-capturing turned off)")
- self._pluginmanager.hook.pytest_enter_pdb(config=self._config)
- pdb.Pdb().set_trace(frame)
-
-
-class PdbInvoke:
- def pytest_exception_interact(self, node, call, report):
- capman = node.config.pluginmanager.getplugin("capturemanager")
- if capman:
- out, err = capman.suspendcapture(in_=True)
- sys.stdout.write(out)
- sys.stdout.write(err)
- _enter_pdb(node, call.excinfo, report)
-
- def pytest_internalerror(self, excrepr, excinfo):
- for line in str(excrepr).split("\n"):
- sys.stderr.write("INTERNALERROR> %s\n" %line)
- sys.stderr.flush()
- tb = _postmortem_traceback(excinfo)
- post_mortem(tb)
-
-
-def _enter_pdb(node, excinfo, rep):
- # XXX we re-use the TerminalReporter's terminalwriter
- # because this seems to avoid some encoding related troubles
- # for not completely clear reasons.
- tw = node.config.pluginmanager.getplugin("terminalreporter")._tw
- tw.line()
- tw.sep(">", "traceback")
- rep.toterminal(tw)
- tw.sep(">", "entering PDB")
- tb = _postmortem_traceback(excinfo)
- post_mortem(tb)
- rep._pdbshown = True
- return rep
-
-
-def _postmortem_traceback(excinfo):
- # A doctest.UnexpectedException is not useful for post_mortem.
- # Use the underlying exception instead:
- from doctest import UnexpectedException
- if isinstance(excinfo.value, UnexpectedException):
- return excinfo.value.exc_info[2]
- else:
- return excinfo._excinfo[2]
-
-
-def _find_last_non_hidden_frame(stack):
- i = max(0, len(stack) - 1)
- while i and stack[i][0].f_locals.get("__tracebackhide__", False):
- i -= 1
- return i
-
-
-def post_mortem(t):
- class Pdb(pdb.Pdb):
- def get_stack(self, f, t):
- stack, i = pdb.Pdb.get_stack(self, f, t)
- if f is None:
- i = _find_last_non_hidden_frame(stack)
- return stack, i
- p = Pdb()
- p.reset()
- p.interaction(None, t)
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/pytester.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/pytester.py
deleted file mode 100644
index faed7f581..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/pytester.py
+++ /dev/null
@@ -1,1110 +0,0 @@
-""" (disabled by default) support for testing pytest and pytest plugins. """
-import codecs
-import gc
-import os
-import platform
-import re
-import subprocess
-import sys
-import time
-import traceback
-from fnmatch import fnmatch
-
-from py.builtin import print_
-
-from _pytest._code import Source
-import py
-import pytest
-from _pytest.main import Session, EXIT_OK
-
-
-def pytest_addoption(parser):
- # group = parser.getgroup("pytester", "pytester (self-tests) options")
- parser.addoption('--lsof',
- action="store_true", dest="lsof", default=False,
- help=("run FD checks if lsof is available"))
-
- parser.addoption('--runpytest', default="inprocess", dest="runpytest",
- choices=("inprocess", "subprocess", ),
- help=("run pytest sub runs in tests using an 'inprocess' "
- "or 'subprocess' (python -m main) method"))
-
-
-def pytest_configure(config):
- # This might be called multiple times. Only take the first.
- global _pytest_fullpath
- try:
- _pytest_fullpath
- except NameError:
- _pytest_fullpath = os.path.abspath(pytest.__file__.rstrip("oc"))
- _pytest_fullpath = _pytest_fullpath.replace("$py.class", ".py")
-
- if config.getvalue("lsof"):
- checker = LsofFdLeakChecker()
- if checker.matching_platform():
- config.pluginmanager.register(checker)
-
-
-class LsofFdLeakChecker(object):
- def get_open_files(self):
- out = self._exec_lsof()
- open_files = self._parse_lsof_output(out)
- return open_files
-
- def _exec_lsof(self):
- pid = os.getpid()
- return py.process.cmdexec("lsof -Ffn0 -p %d" % pid)
-
- def _parse_lsof_output(self, out):
- def isopen(line):
- return line.startswith('f') and ("deleted" not in line and
- 'mem' not in line and "txt" not in line and 'cwd' not in line)
-
- open_files = []
-
- for line in out.split("\n"):
- if isopen(line):
- fields = line.split('\0')
- fd = fields[0][1:]
- filename = fields[1][1:]
- if filename.startswith('/'):
- open_files.append((fd, filename))
-
- return open_files
-
- def matching_platform(self):
- try:
- py.process.cmdexec("lsof -v")
- except (py.process.cmdexec.Error, UnicodeDecodeError):
- # cmdexec may raise UnicodeDecodeError on Windows systems
- # with locale other than english:
- # https://bitbucket.org/pytest-dev/py/issues/66
- return False
- else:
- return True
-
- @pytest.hookimpl(hookwrapper=True, tryfirst=True)
- def pytest_runtest_item(self, item):
- lines1 = self.get_open_files()
- yield
- if hasattr(sys, "pypy_version_info"):
- gc.collect()
- lines2 = self.get_open_files()
-
- new_fds = set([t[0] for t in lines2]) - set([t[0] for t in lines1])
- leaked_files = [t for t in lines2 if t[0] in new_fds]
- if leaked_files:
- error = []
- error.append("***** %s FD leakage detected" % len(leaked_files))
- error.extend([str(f) for f in leaked_files])
- error.append("*** Before:")
- error.extend([str(f) for f in lines1])
- error.append("*** After:")
- error.extend([str(f) for f in lines2])
- error.append(error[0])
- error.append("*** function %s:%s: %s " % item.location)
- pytest.fail("\n".join(error), pytrace=False)
-
-
-# XXX copied from execnet's conftest.py - needs to be merged
-winpymap = {
- 'python2.7': r'C:\Python27\python.exe',
- 'python2.6': r'C:\Python26\python.exe',
- 'python3.1': r'C:\Python31\python.exe',
- 'python3.2': r'C:\Python32\python.exe',
- 'python3.3': r'C:\Python33\python.exe',
- 'python3.4': r'C:\Python34\python.exe',
- 'python3.5': r'C:\Python35\python.exe',
-}
-
-def getexecutable(name, cache={}):
- try:
- return cache[name]
- except KeyError:
- executable = py.path.local.sysfind(name)
- if executable:
- if name == "jython":
- import subprocess
- popen = subprocess.Popen([str(executable), "--version"],
- universal_newlines=True, stderr=subprocess.PIPE)
- out, err = popen.communicate()
- if not err or "2.5" not in err:
- executable = None
- if "2.5.2" in err:
- executable = None # http://bugs.jython.org/issue1790
- cache[name] = executable
- return executable
-
-@pytest.fixture(params=['python2.6', 'python2.7', 'python3.3', "python3.4",
- 'pypy', 'pypy3'])
-def anypython(request):
- name = request.param
- executable = getexecutable(name)
- if executable is None:
- if sys.platform == "win32":
- executable = winpymap.get(name, None)
- if executable:
- executable = py.path.local(executable)
- if executable.check():
- return executable
- pytest.skip("no suitable %s found" % (name,))
- return executable
-
-# used at least by pytest-xdist plugin
-@pytest.fixture
-def _pytest(request):
- """ Return a helper which offers a gethookrecorder(hook)
- method which returns a HookRecorder instance which helps
- to make assertions about called hooks.
- """
- return PytestArg(request)
-
-class PytestArg:
- def __init__(self, request):
- self.request = request
-
- def gethookrecorder(self, hook):
- hookrecorder = HookRecorder(hook._pm)
- self.request.addfinalizer(hookrecorder.finish_recording)
- return hookrecorder
-
-
-def get_public_names(l):
- """Only return names from iterator l without a leading underscore."""
- return [x for x in l if x[0] != "_"]
-
-
-class ParsedCall:
- def __init__(self, name, kwargs):
- self.__dict__.update(kwargs)
- self._name = name
-
- def __repr__(self):
- d = self.__dict__.copy()
- del d['_name']
- return "<ParsedCall %r(**%r)>" %(self._name, d)
-
-
-class HookRecorder:
- """Record all hooks called in a plugin manager.
-
- This wraps all the hook calls in the plugin manager, recording
- each call before propagating the normal calls.
-
- """
-
- def __init__(self, pluginmanager):
- self._pluginmanager = pluginmanager
- self.calls = []
-
- def before(hook_name, hook_impls, kwargs):
- self.calls.append(ParsedCall(hook_name, kwargs))
-
- def after(outcome, hook_name, hook_impls, kwargs):
- pass
-
- self._undo_wrapping = pluginmanager.add_hookcall_monitoring(before, after)
-
- def finish_recording(self):
- self._undo_wrapping()
-
- def getcalls(self, names):
- if isinstance(names, str):
- names = names.split()
- return [call for call in self.calls if call._name in names]
-
- def assert_contains(self, entries):
- __tracebackhide__ = True
- i = 0
- entries = list(entries)
- backlocals = sys._getframe(1).f_locals
- while entries:
- name, check = entries.pop(0)
- for ind, call in enumerate(self.calls[i:]):
- if call._name == name:
- print_("NAMEMATCH", name, call)
- if eval(check, backlocals, call.__dict__):
- print_("CHECKERMATCH", repr(check), "->", call)
- else:
- print_("NOCHECKERMATCH", repr(check), "-", call)
- continue
- i += ind + 1
- break
- print_("NONAMEMATCH", name, "with", call)
- else:
- pytest.fail("could not find %r check %r" % (name, check))
-
- def popcall(self, name):
- __tracebackhide__ = True
- for i, call in enumerate(self.calls):
- if call._name == name:
- del self.calls[i]
- return call
- lines = ["could not find call %r, in:" % (name,)]
- lines.extend([" %s" % str(x) for x in self.calls])
- pytest.fail("\n".join(lines))
-
- def getcall(self, name):
- l = self.getcalls(name)
- assert len(l) == 1, (name, l)
- return l[0]
-
- # functionality for test reports
-
- def getreports(self,
- names="pytest_runtest_logreport pytest_collectreport"):
- return [x.report for x in self.getcalls(names)]
-
- def matchreport(self, inamepart="",
- names="pytest_runtest_logreport pytest_collectreport", when=None):
- """ return a testreport whose dotted import path matches """
- l = []
- for rep in self.getreports(names=names):
- try:
- if not when and rep.when != "call" and rep.passed:
- # setup/teardown passing reports - let's ignore those
- continue
- except AttributeError:
- pass
- if when and getattr(rep, 'when', None) != when:
- continue
- if not inamepart or inamepart in rep.nodeid.split("::"):
- l.append(rep)
- if not l:
- raise ValueError("could not find test report matching %r: "
- "no test reports at all!" % (inamepart,))
- if len(l) > 1:
- raise ValueError(
- "found 2 or more testreports matching %r: %s" %(inamepart, l))
- return l[0]
-
- def getfailures(self,
- names='pytest_runtest_logreport pytest_collectreport'):
- return [rep for rep in self.getreports(names) if rep.failed]
-
- def getfailedcollections(self):
- return self.getfailures('pytest_collectreport')
-
- def listoutcomes(self):
- passed = []
- skipped = []
- failed = []
- for rep in self.getreports(
- "pytest_collectreport pytest_runtest_logreport"):
- if rep.passed:
- if getattr(rep, "when", None) == "call":
- passed.append(rep)
- elif rep.skipped:
- skipped.append(rep)
- elif rep.failed:
- failed.append(rep)
- return passed, skipped, failed
-
- def countoutcomes(self):
- return [len(x) for x in self.listoutcomes()]
-
- def assertoutcome(self, passed=0, skipped=0, failed=0):
- realpassed, realskipped, realfailed = self.listoutcomes()
- assert passed == len(realpassed)
- assert skipped == len(realskipped)
- assert failed == len(realfailed)
-
- def clear(self):
- self.calls[:] = []
-
-
-@pytest.fixture
-def linecomp(request):
- return LineComp()
-
-
-def pytest_funcarg__LineMatcher(request):
- return LineMatcher
-
-
-@pytest.fixture
-def testdir(request, tmpdir_factory):
- return Testdir(request, tmpdir_factory)
-
-
-rex_outcome = re.compile("(\d+) ([\w-]+)")
-class RunResult:
- """The result of running a command.
-
- Attributes:
-
- :ret: The return value.
- :outlines: List of lines captured from stdout.
- :errlines: List of lines captures from stderr.
- :stdout: :py:class:`LineMatcher` of stdout, use ``stdout.str()`` to
- reconstruct stdout or the commonly used
- ``stdout.fnmatch_lines()`` method.
- :stderrr: :py:class:`LineMatcher` of stderr.
- :duration: Duration in seconds.
-
- """
- def __init__(self, ret, outlines, errlines, duration):
- self.ret = ret
- self.outlines = outlines
- self.errlines = errlines
- self.stdout = LineMatcher(outlines)
- self.stderr = LineMatcher(errlines)
- self.duration = duration
-
- def parseoutcomes(self):
- """ Return a dictionary of outcomestring->num from parsing
- the terminal output that the test process produced."""
- for line in reversed(self.outlines):
- if 'seconds' in line:
- outcomes = rex_outcome.findall(line)
- if outcomes:
- d = {}
- for num, cat in outcomes:
- d[cat] = int(num)
- return d
-
- def assert_outcomes(self, passed=0, skipped=0, failed=0):
- """ assert that the specified outcomes appear with the respective
- numbers (0 means it didn't occur) in the text output from a test run."""
- d = self.parseoutcomes()
- assert passed == d.get("passed", 0)
- assert skipped == d.get("skipped", 0)
- assert failed == d.get("failed", 0)
-
-
-
-class Testdir:
- """Temporary test directory with tools to test/run py.test itself.
-
- This is based on the ``tmpdir`` fixture but provides a number of
- methods which aid with testing py.test itself. Unless
- :py:meth:`chdir` is used all methods will use :py:attr:`tmpdir` as
- current working directory.
-
- Attributes:
-
- :tmpdir: The :py:class:`py.path.local` instance of the temporary
- directory.
-
- :plugins: A list of plugins to use with :py:meth:`parseconfig` and
- :py:meth:`runpytest`. Initially this is an empty list but
- plugins can be added to the list. The type of items to add to
- the list depend on the method which uses them so refer to them
- for details.
-
- """
-
- def __init__(self, request, tmpdir_factory):
- self.request = request
- # XXX remove duplication with tmpdir plugin
- basetmp = tmpdir_factory.ensuretemp("testdir")
- name = request.function.__name__
- for i in range(100):
- try:
- tmpdir = basetmp.mkdir(name + str(i))
- except py.error.EEXIST:
- continue
- break
- self.tmpdir = tmpdir
- self.plugins = []
- self._savesyspath = (list(sys.path), list(sys.meta_path))
- self._savemodulekeys = set(sys.modules)
- self.chdir() # always chdir
- self.request.addfinalizer(self.finalize)
- method = self.request.config.getoption("--runpytest")
- if method == "inprocess":
- self._runpytest_method = self.runpytest_inprocess
- elif method == "subprocess":
- self._runpytest_method = self.runpytest_subprocess
-
- def __repr__(self):
- return "<Testdir %r>" % (self.tmpdir,)
-
- def finalize(self):
- """Clean up global state artifacts.
-
- Some methods modify the global interpreter state and this
- tries to clean this up. It does not remove the temporary
- directory however so it can be looked at after the test run
- has finished.
-
- """
- sys.path[:], sys.meta_path[:] = self._savesyspath
- if hasattr(self, '_olddir'):
- self._olddir.chdir()
- self.delete_loaded_modules()
-
- def delete_loaded_modules(self):
- """Delete modules that have been loaded during a test.
-
- This allows the interpreter to catch module changes in case
- the module is re-imported.
- """
- for name in set(sys.modules).difference(self._savemodulekeys):
- # it seems zope.interfaces is keeping some state
- # (used by twisted related tests)
- if name != "zope.interface":
- del sys.modules[name]
-
- def make_hook_recorder(self, pluginmanager):
- """Create a new :py:class:`HookRecorder` for a PluginManager."""
- assert not hasattr(pluginmanager, "reprec")
- pluginmanager.reprec = reprec = HookRecorder(pluginmanager)
- self.request.addfinalizer(reprec.finish_recording)
- return reprec
-
- def chdir(self):
- """Cd into the temporary directory.
-
- This is done automatically upon instantiation.
-
- """
- old = self.tmpdir.chdir()
- if not hasattr(self, '_olddir'):
- self._olddir = old
-
- def _makefile(self, ext, args, kwargs):
- items = list(kwargs.items())
- if args:
- source = py.builtin._totext("\n").join(
- map(py.builtin._totext, args)) + py.builtin._totext("\n")
- basename = self.request.function.__name__
- items.insert(0, (basename, source))
- ret = None
- for name, value in items:
- p = self.tmpdir.join(name).new(ext=ext)
- source = Source(value)
- def my_totext(s, encoding="utf-8"):
- if py.builtin._isbytes(s):
- s = py.builtin._totext(s, encoding=encoding)
- return s
- source_unicode = "\n".join([my_totext(line) for line in source.lines])
- source = py.builtin._totext(source_unicode)
- content = source.strip().encode("utf-8") # + "\n"
- #content = content.rstrip() + "\n"
- p.write(content, "wb")
- if ret is None:
- ret = p
- return ret
-
- def makefile(self, ext, *args, **kwargs):
- """Create a new file in the testdir.
-
- ext: The extension the file should use, including the dot.
- E.g. ".py".
-
- args: All args will be treated as strings and joined using
- newlines. The result will be written as contents to the
- file. The name of the file will be based on the test
- function requesting this fixture.
- E.g. "testdir.makefile('.txt', 'line1', 'line2')"
-
- kwargs: Each keyword is the name of a file, while the value of
- it will be written as contents of the file.
- E.g. "testdir.makefile('.ini', pytest='[pytest]\naddopts=-rs\n')"
-
- """
- return self._makefile(ext, args, kwargs)
-
- def makeconftest(self, source):
- """Write a contest.py file with 'source' as contents."""
- return self.makepyfile(conftest=source)
-
- def makeini(self, source):
- """Write a tox.ini file with 'source' as contents."""
- return self.makefile('.ini', tox=source)
-
- def getinicfg(self, source):
- """Return the pytest section from the tox.ini config file."""
- p = self.makeini(source)
- return py.iniconfig.IniConfig(p)['pytest']
-
- def makepyfile(self, *args, **kwargs):
- """Shortcut for .makefile() with a .py extension."""
- return self._makefile('.py', args, kwargs)
-
- def maketxtfile(self, *args, **kwargs):
- """Shortcut for .makefile() with a .txt extension."""
- return self._makefile('.txt', args, kwargs)
-
- def syspathinsert(self, path=None):
- """Prepend a directory to sys.path, defaults to :py:attr:`tmpdir`.
-
- This is undone automatically after the test.
- """
- if path is None:
- path = self.tmpdir
- sys.path.insert(0, str(path))
- # a call to syspathinsert() usually means that the caller
- # wants to import some dynamically created files.
- # with python3 we thus invalidate import caches.
- self._possibly_invalidate_import_caches()
-
- def _possibly_invalidate_import_caches(self):
- # invalidate caches if we can (py33 and above)
- try:
- import importlib
- except ImportError:
- pass
- else:
- if hasattr(importlib, "invalidate_caches"):
- importlib.invalidate_caches()
-
- def mkdir(self, name):
- """Create a new (sub)directory."""
- return self.tmpdir.mkdir(name)
-
- def mkpydir(self, name):
- """Create a new python package.
-
- This creates a (sub)direcotry with an empty ``__init__.py``
- file so that is recognised as a python package.
-
- """
- p = self.mkdir(name)
- p.ensure("__init__.py")
- return p
-
- Session = Session
- def getnode(self, config, arg):
- """Return the collection node of a file.
-
- :param config: :py:class:`_pytest.config.Config` instance, see
- :py:meth:`parseconfig` and :py:meth:`parseconfigure` to
- create the configuration.
-
- :param arg: A :py:class:`py.path.local` instance of the file.
-
- """
- session = Session(config)
- assert '::' not in str(arg)
- p = py.path.local(arg)
- config.hook.pytest_sessionstart(session=session)
- res = session.perform_collect([str(p)], genitems=False)[0]
- config.hook.pytest_sessionfinish(session=session, exitstatus=EXIT_OK)
- return res
-
- def getpathnode(self, path):
- """Return the collection node of a file.
-
- This is like :py:meth:`getnode` but uses
- :py:meth:`parseconfigure` to create the (configured) py.test
- Config instance.
-
- :param path: A :py:class:`py.path.local` instance of the file.
-
- """
- config = self.parseconfigure(path)
- session = Session(config)
- x = session.fspath.bestrelpath(path)
- config.hook.pytest_sessionstart(session=session)
- res = session.perform_collect([x], genitems=False)[0]
- config.hook.pytest_sessionfinish(session=session, exitstatus=EXIT_OK)
- return res
-
- def genitems(self, colitems):
- """Generate all test items from a collection node.
-
- This recurses into the collection node and returns a list of
- all the test items contained within.
-
- """
- session = colitems[0].session
- result = []
- for colitem in colitems:
- result.extend(session.genitems(colitem))
- return result
-
- def runitem(self, source):
- """Run the "test_func" Item.
-
- The calling test instance (the class which contains the test
- method) must provide a ``.getrunner()`` method which should
- return a runner which can run the test protocol for a single
- item, like e.g. :py:func:`_pytest.runner.runtestprotocol`.
-
- """
- # used from runner functional tests
- item = self.getitem(source)
- # the test class where we are called from wants to provide the runner
- testclassinstance = self.request.instance
- runner = testclassinstance.getrunner()
- return runner(item)
-
- def inline_runsource(self, source, *cmdlineargs):
- """Run a test module in process using ``pytest.main()``.
-
- This run writes "source" into a temporary file and runs
- ``pytest.main()`` on it, returning a :py:class:`HookRecorder`
- instance for the result.
-
- :param source: The source code of the test module.
-
- :param cmdlineargs: Any extra command line arguments to use.
-
- :return: :py:class:`HookRecorder` instance of the result.
-
- """
- p = self.makepyfile(source)
- l = list(cmdlineargs) + [p]
- return self.inline_run(*l)
-
- def inline_genitems(self, *args):
- """Run ``pytest.main(['--collectonly'])`` in-process.
-
- Retuns a tuple of the collected items and a
- :py:class:`HookRecorder` instance.
-
- This runs the :py:func:`pytest.main` function to run all of
- py.test inside the test process itself like
- :py:meth:`inline_run`. However the return value is a tuple of
- the collection items and a :py:class:`HookRecorder` instance.
-
- """
- rec = self.inline_run("--collect-only", *args)
- items = [x.item for x in rec.getcalls("pytest_itemcollected")]
- return items, rec
-
- def inline_run(self, *args, **kwargs):
- """Run ``pytest.main()`` in-process, returning a HookRecorder.
-
- This runs the :py:func:`pytest.main` function to run all of
- py.test inside the test process itself. This means it can
- return a :py:class:`HookRecorder` instance which gives more
- detailed results from then run then can be done by matching
- stdout/stderr from :py:meth:`runpytest`.
-
- :param args: Any command line arguments to pass to
- :py:func:`pytest.main`.
-
- :param plugin: (keyword-only) Extra plugin instances the
- ``pytest.main()`` instance should use.
-
- :return: A :py:class:`HookRecorder` instance.
-
- """
- rec = []
- class Collect:
- def pytest_configure(x, config):
- rec.append(self.make_hook_recorder(config.pluginmanager))
-
- plugins = kwargs.get("plugins") or []
- plugins.append(Collect())
- ret = pytest.main(list(args), plugins=plugins)
- self.delete_loaded_modules()
- if len(rec) == 1:
- reprec = rec.pop()
- else:
- class reprec:
- pass
- reprec.ret = ret
-
- # typically we reraise keyboard interrupts from the child run
- # because it's our user requesting interruption of the testing
- if ret == 2 and not kwargs.get("no_reraise_ctrlc"):
- calls = reprec.getcalls("pytest_keyboard_interrupt")
- if calls and calls[-1].excinfo.type == KeyboardInterrupt:
- raise KeyboardInterrupt()
- return reprec
-
- def runpytest_inprocess(self, *args, **kwargs):
- """ Return result of running pytest in-process, providing a similar
- interface to what self.runpytest() provides. """
- if kwargs.get("syspathinsert"):
- self.syspathinsert()
- now = time.time()
- capture = py.io.StdCapture()
- try:
- try:
- reprec = self.inline_run(*args, **kwargs)
- except SystemExit as e:
- class reprec:
- ret = e.args[0]
- except Exception:
- traceback.print_exc()
- class reprec:
- ret = 3
- finally:
- out, err = capture.reset()
- sys.stdout.write(out)
- sys.stderr.write(err)
-
- res = RunResult(reprec.ret,
- out.split("\n"), err.split("\n"),
- time.time()-now)
- res.reprec = reprec
- return res
-
- def runpytest(self, *args, **kwargs):
- """ Run pytest inline or in a subprocess, depending on the command line
- option "--runpytest" and return a :py:class:`RunResult`.
-
- """
- args = self._ensure_basetemp(args)
- return self._runpytest_method(*args, **kwargs)
-
- def _ensure_basetemp(self, args):
- args = [str(x) for x in args]
- for x in args:
- if str(x).startswith('--basetemp'):
- #print ("basedtemp exists: %s" %(args,))
- break
- else:
- args.append("--basetemp=%s" % self.tmpdir.dirpath('basetemp'))
- #print ("added basetemp: %s" %(args,))
- return args
-
- def parseconfig(self, *args):
- """Return a new py.test Config instance from given commandline args.
-
- This invokes the py.test bootstrapping code in _pytest.config
- to create a new :py:class:`_pytest.core.PluginManager` and
- call the pytest_cmdline_parse hook to create new
- :py:class:`_pytest.config.Config` instance.
-
- If :py:attr:`plugins` has been populated they should be plugin
- modules which will be registered with the PluginManager.
-
- """
- args = self._ensure_basetemp(args)
-
- import _pytest.config
- config = _pytest.config._prepareconfig(args, self.plugins)
- # we don't know what the test will do with this half-setup config
- # object and thus we make sure it gets unconfigured properly in any
- # case (otherwise capturing could still be active, for example)
- self.request.addfinalizer(config._ensure_unconfigure)
- return config
-
- def parseconfigure(self, *args):
- """Return a new py.test configured Config instance.
-
- This returns a new :py:class:`_pytest.config.Config` instance
- like :py:meth:`parseconfig`, but also calls the
- pytest_configure hook.
-
- """
- config = self.parseconfig(*args)
- config._do_configure()
- self.request.addfinalizer(config._ensure_unconfigure)
- return config
-
- def getitem(self, source, funcname="test_func"):
- """Return the test item for a test function.
-
- This writes the source to a python file and runs py.test's
- collection on the resulting module, returning the test item
- for the requested function name.
-
- :param source: The module source.
-
- :param funcname: The name of the test function for which the
- Item must be returned.
-
- """
- items = self.getitems(source)
- for item in items:
- if item.name == funcname:
- return item
- assert 0, "%r item not found in module:\n%s\nitems: %s" %(
- funcname, source, items)
-
- def getitems(self, source):
- """Return all test items collected from the module.
-
- This writes the source to a python file and runs py.test's
- collection on the resulting module, returning all test items
- contained within.
-
- """
- modcol = self.getmodulecol(source)
- return self.genitems([modcol])
-
- def getmodulecol(self, source, configargs=(), withinit=False):
- """Return the module collection node for ``source``.
-
- This writes ``source`` to a file using :py:meth:`makepyfile`
- and then runs the py.test collection on it, returning the
- collection node for the test module.
-
- :param source: The source code of the module to collect.
-
- :param configargs: Any extra arguments to pass to
- :py:meth:`parseconfigure`.
-
- :param withinit: Whether to also write a ``__init__.py`` file
- to the temporarly directory to ensure it is a package.
-
- """
- kw = {self.request.function.__name__: Source(source).strip()}
- path = self.makepyfile(**kw)
- if withinit:
- self.makepyfile(__init__ = "#")
- self.config = config = self.parseconfigure(path, *configargs)
- node = self.getnode(config, path)
- return node
-
- def collect_by_name(self, modcol, name):
- """Return the collection node for name from the module collection.
-
- This will search a module collection node for a collection
- node matching the given name.
-
- :param modcol: A module collection node, see
- :py:meth:`getmodulecol`.
-
- :param name: The name of the node to return.
-
- """
- for colitem in modcol._memocollect():
- if colitem.name == name:
- return colitem
-
- def popen(self, cmdargs, stdout, stderr, **kw):
- """Invoke subprocess.Popen.
-
- This calls subprocess.Popen making sure the current working
- directory is the PYTHONPATH.
-
- You probably want to use :py:meth:`run` instead.
-
- """
- env = os.environ.copy()
- env['PYTHONPATH'] = os.pathsep.join(filter(None, [
- str(os.getcwd()), env.get('PYTHONPATH', '')]))
- kw['env'] = env
- return subprocess.Popen(cmdargs,
- stdout=stdout, stderr=stderr, **kw)
-
- def run(self, *cmdargs):
- """Run a command with arguments.
-
- Run a process using subprocess.Popen saving the stdout and
- stderr.
-
- Returns a :py:class:`RunResult`.
-
- """
- return self._run(*cmdargs)
-
- def _run(self, *cmdargs):
- cmdargs = [str(x) for x in cmdargs]
- p1 = self.tmpdir.join("stdout")
- p2 = self.tmpdir.join("stderr")
- print_("running:", ' '.join(cmdargs))
- print_(" in:", str(py.path.local()))
- f1 = codecs.open(str(p1), "w", encoding="utf8")
- f2 = codecs.open(str(p2), "w", encoding="utf8")
- try:
- now = time.time()
- popen = self.popen(cmdargs, stdout=f1, stderr=f2,
- close_fds=(sys.platform != "win32"))
- ret = popen.wait()
- finally:
- f1.close()
- f2.close()
- f1 = codecs.open(str(p1), "r", encoding="utf8")
- f2 = codecs.open(str(p2), "r", encoding="utf8")
- try:
- out = f1.read().splitlines()
- err = f2.read().splitlines()
- finally:
- f1.close()
- f2.close()
- self._dump_lines(out, sys.stdout)
- self._dump_lines(err, sys.stderr)
- return RunResult(ret, out, err, time.time()-now)
-
- def _dump_lines(self, lines, fp):
- try:
- for line in lines:
- py.builtin.print_(line, file=fp)
- except UnicodeEncodeError:
- print("couldn't print to %s because of encoding" % (fp,))
-
- def _getpytestargs(self):
- # we cannot use "(sys.executable,script)"
- # because on windows the script is e.g. a py.test.exe
- return (sys.executable, _pytest_fullpath,) # noqa
-
- def runpython(self, script):
- """Run a python script using sys.executable as interpreter.
-
- Returns a :py:class:`RunResult`.
- """
- return self.run(sys.executable, script)
-
- def runpython_c(self, command):
- """Run python -c "command", return a :py:class:`RunResult`."""
- return self.run(sys.executable, "-c", command)
-
- def runpytest_subprocess(self, *args, **kwargs):
- """Run py.test as a subprocess with given arguments.
-
- Any plugins added to the :py:attr:`plugins` list will added
- using the ``-p`` command line option. Addtionally
- ``--basetemp`` is used put any temporary files and directories
- in a numbered directory prefixed with "runpytest-" so they do
- not conflict with the normal numberd pytest location for
- temporary files and directories.
-
- Returns a :py:class:`RunResult`.
-
- """
- p = py.path.local.make_numbered_dir(prefix="runpytest-",
- keep=None, rootdir=self.tmpdir)
- args = ('--basetemp=%s' % p, ) + args
- #for x in args:
- # if '--confcutdir' in str(x):
- # break
- #else:
- # pass
- # args = ('--confcutdir=.',) + args
- plugins = [x for x in self.plugins if isinstance(x, str)]
- if plugins:
- args = ('-p', plugins[0]) + args
- args = self._getpytestargs() + args
- return self.run(*args)
-
- def spawn_pytest(self, string, expect_timeout=10.0):
- """Run py.test using pexpect.
-
- This makes sure to use the right py.test and sets up the
- temporary directory locations.
-
- The pexpect child is returned.
-
- """
- basetemp = self.tmpdir.mkdir("pexpect")
- invoke = " ".join(map(str, self._getpytestargs()))
- cmd = "%s --basetemp=%s %s" % (invoke, basetemp, string)
- return self.spawn(cmd, expect_timeout=expect_timeout)
-
- def spawn(self, cmd, expect_timeout=10.0):
- """Run a command using pexpect.
-
- The pexpect child is returned.
- """
- pexpect = pytest.importorskip("pexpect", "3.0")
- if hasattr(sys, 'pypy_version_info') and '64' in platform.machine():
- pytest.skip("pypy-64 bit not supported")
- if sys.platform == "darwin":
- pytest.xfail("pexpect does not work reliably on darwin?!")
- if sys.platform.startswith("freebsd"):
- pytest.xfail("pexpect does not work reliably on freebsd")
- logfile = self.tmpdir.join("spawn.out").open("wb")
- child = pexpect.spawn(cmd, logfile=logfile)
- self.request.addfinalizer(logfile.close)
- child.timeout = expect_timeout
- return child
-
-def getdecoded(out):
- try:
- return out.decode("utf-8")
- except UnicodeDecodeError:
- return "INTERNAL not-utf8-decodeable, truncated string:\n%s" % (
- py.io.saferepr(out),)
-
-
-class LineComp:
- def __init__(self):
- self.stringio = py.io.TextIO()
-
- def assert_contains_lines(self, lines2):
- """ assert that lines2 are contained (linearly) in lines1.
- return a list of extralines found.
- """
- __tracebackhide__ = True
- val = self.stringio.getvalue()
- self.stringio.truncate(0)
- self.stringio.seek(0)
- lines1 = val.split("\n")
- return LineMatcher(lines1).fnmatch_lines(lines2)
-
-
-class LineMatcher:
- """Flexible matching of text.
-
- This is a convenience class to test large texts like the output of
- commands.
-
- The constructor takes a list of lines without their trailing
- newlines, i.e. ``text.splitlines()``.
-
- """
-
- def __init__(self, lines):
- self.lines = lines
-
- def str(self):
- """Return the entire original text."""
- return "\n".join(self.lines)
-
- def _getlines(self, lines2):
- if isinstance(lines2, str):
- lines2 = Source(lines2)
- if isinstance(lines2, Source):
- lines2 = lines2.strip().lines
- return lines2
-
- def fnmatch_lines_random(self, lines2):
- """Check lines exist in the output.
-
- The argument is a list of lines which have to occur in the
- output, in any order. Each line can contain glob whildcards.
-
- """
- lines2 = self._getlines(lines2)
- for line in lines2:
- for x in self.lines:
- if line == x or fnmatch(x, line):
- print_("matched: ", repr(line))
- break
- else:
- raise ValueError("line %r not found in output" % line)
-
- def get_lines_after(self, fnline):
- """Return all lines following the given line in the text.
-
- The given line can contain glob wildcards.
- """
- for i, line in enumerate(self.lines):
- if fnline == line or fnmatch(line, fnline):
- return self.lines[i+1:]
- raise ValueError("line %r not found in output" % fnline)
-
- def fnmatch_lines(self, lines2):
- """Search the text for matching lines.
-
- The argument is a list of lines which have to match and can
- use glob wildcards. If they do not match an pytest.fail() is
- called. The matches and non-matches are also printed on
- stdout.
-
- """
- def show(arg1, arg2):
- py.builtin.print_(arg1, arg2, file=sys.stderr)
- lines2 = self._getlines(lines2)
- lines1 = self.lines[:]
- nextline = None
- extralines = []
- __tracebackhide__ = True
- for line in lines2:
- nomatchprinted = False
- while lines1:
- nextline = lines1.pop(0)
- if line == nextline:
- show("exact match:", repr(line))
- break
- elif fnmatch(nextline, line):
- show("fnmatch:", repr(line))
- show(" with:", repr(nextline))
- break
- else:
- if not nomatchprinted:
- show("nomatch:", repr(line))
- nomatchprinted = True
- show(" and:", repr(nextline))
- extralines.append(nextline)
- else:
- pytest.fail("remains unmatched: %r, see stderr" % (line,))
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/python.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/python.py
deleted file mode 100644
index 3580eae..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/python.py
+++ /dev/null
@@ -1,2302 +0,0 @@
-""" Python test discovery, setup and run of test functions. """
-import fnmatch
-import functools
-import inspect
-import re
-import types
-import sys
-
-import py
-import pytest
-from _pytest._code.code import TerminalRepr
-from _pytest.mark import MarkDecorator, MarkerError
-
-try:
- import enum
-except ImportError: # pragma: no cover
- # Only available in Python 3.4+ or as a backport
- enum = None
-
-import _pytest
-import _pytest._pluggy as pluggy
-
-cutdir2 = py.path.local(_pytest.__file__).dirpath()
-cutdir1 = py.path.local(pluggy.__file__.rstrip("oc"))
-
-
-NoneType = type(None)
-NOTSET = object()
-isfunction = inspect.isfunction
-isclass = inspect.isclass
-callable = py.builtin.callable
-# used to work around a python2 exception info leak
-exc_clear = getattr(sys, 'exc_clear', lambda: None)
-# The type of re.compile objects is not exposed in Python.
-REGEX_TYPE = type(re.compile(''))
-
-_PY3 = sys.version_info > (3, 0)
-_PY2 = not _PY3
-
-
-if hasattr(inspect, 'signature'):
- def _format_args(func):
- return str(inspect.signature(func))
-else:
- def _format_args(func):
- return inspect.formatargspec(*inspect.getargspec(func))
-
-if sys.version_info[:2] == (2, 6):
- def isclass(object):
- """ Return true if the object is a class. Overrides inspect.isclass for
- python 2.6 because it will return True for objects which always return
- something on __getattr__ calls (see #1035).
- Backport of https://hg.python.org/cpython/rev/35bf8f7a8edc
- """
- return isinstance(object, (type, types.ClassType))
-
-def _has_positional_arg(func):
- return func.__code__.co_argcount
-
-
-def filter_traceback(entry):
- # entry.path might sometimes return a str object when the entry
- # points to dynamically generated code
- # see https://bitbucket.org/pytest-dev/py/issues/71
- raw_filename = entry.frame.code.raw.co_filename
- is_generated = '<' in raw_filename and '>' in raw_filename
- if is_generated:
- return False
- # entry.path might point to an inexisting file, in which case it will
- # alsso return a str object. see #1133
- p = py.path.local(entry.path)
- return p != cutdir1 and not p.relto(cutdir2)
-
-
-def get_real_func(obj):
- """ gets the real function object of the (possibly) wrapped object by
- functools.wraps or functools.partial.
- """
- while hasattr(obj, "__wrapped__"):
- obj = obj.__wrapped__
- if isinstance(obj, functools.partial):
- obj = obj.func
- return obj
-
-def getfslineno(obj):
- # xxx let decorators etc specify a sane ordering
- obj = get_real_func(obj)
- if hasattr(obj, 'place_as'):
- obj = obj.place_as
- fslineno = _pytest._code.getfslineno(obj)
- assert isinstance(fslineno[1], int), obj
- return fslineno
-
-def getimfunc(func):
- try:
- return func.__func__
- except AttributeError:
- try:
- return func.im_func
- except AttributeError:
- return func
-
-def safe_getattr(object, name, default):
- """ Like getattr but return default upon any Exception.
-
- Attribute access can potentially fail for 'evil' Python objects.
- See issue214
- """
- try:
- return getattr(object, name, default)
- except Exception:
- return default
-
-
-class FixtureFunctionMarker:
- def __init__(self, scope, params,
- autouse=False, yieldctx=False, ids=None):
- self.scope = scope
- self.params = params
- self.autouse = autouse
- self.yieldctx = yieldctx
- self.ids = ids
-
- def __call__(self, function):
- if isclass(function):
- raise ValueError(
- "class fixtures not supported (may be in the future)")
- function._pytestfixturefunction = self
- return function
-
-
-def fixture(scope="function", params=None, autouse=False, ids=None):
- """ (return a) decorator to mark a fixture factory function.
-
- This decorator can be used (with or or without parameters) to define
- a fixture function. The name of the fixture function can later be
- referenced to cause its invocation ahead of running tests: test
- modules or classes can use the pytest.mark.usefixtures(fixturename)
- marker. Test functions can directly use fixture names as input
- arguments in which case the fixture instance returned from the fixture
- function will be injected.
-
- :arg scope: the scope for which this fixture is shared, one of
- "function" (default), "class", "module", "session".
-
- :arg params: an optional list of parameters which will cause multiple
- invocations of the fixture function and all of the tests
- using it.
-
- :arg autouse: if True, the fixture func is activated for all tests that
- can see it. If False (the default) then an explicit
- reference is needed to activate the fixture.
-
- :arg ids: list of string ids each corresponding to the params
- so that they are part of the test id. If no ids are provided
- they will be generated automatically from the params.
-
- """
- if callable(scope) and params is None and autouse == False:
- # direct decoration
- return FixtureFunctionMarker(
- "function", params, autouse)(scope)
- if params is not None and not isinstance(params, (list, tuple)):
- params = list(params)
- return FixtureFunctionMarker(scope, params, autouse, ids=ids)
-
-def yield_fixture(scope="function", params=None, autouse=False, ids=None):
- """ (return a) decorator to mark a yield-fixture factory function
- (EXPERIMENTAL).
-
- This takes the same arguments as :py:func:`pytest.fixture` but
- expects a fixture function to use a ``yield`` instead of a ``return``
- statement to provide a fixture. See
- http://pytest.org/en/latest/yieldfixture.html for more info.
- """
- if callable(scope) and params is None and autouse == False:
- # direct decoration
- return FixtureFunctionMarker(
- "function", params, autouse, yieldctx=True)(scope)
- else:
- return FixtureFunctionMarker(scope, params, autouse,
- yieldctx=True, ids=ids)
-
-defaultfuncargprefixmarker = fixture()
-
-def pyobj_property(name):
- def get(self):
- node = self.getparent(getattr(pytest, name))
- if node is not None:
- return node.obj
- doc = "python %s object this node was collected from (can be None)." % (
- name.lower(),)
- return property(get, None, None, doc)
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("general")
- group.addoption('--fixtures', '--funcargs',
- action="store_true", dest="showfixtures", default=False,
- help="show available fixtures, sorted by plugin appearance")
- parser.addini("usefixtures", type="args", default=[],
- help="list of default fixtures to be used with this project")
- parser.addini("python_files", type="args",
- default=['test_*.py', '*_test.py'],
- help="glob-style file patterns for Python test module discovery")
- parser.addini("python_classes", type="args", default=["Test",],
- help="prefixes or glob names for Python test class discovery")
- parser.addini("python_functions", type="args", default=["test",],
- help="prefixes or glob names for Python test function and "
- "method discovery")
-
- group.addoption("--import-mode", default="prepend",
- choices=["prepend", "append"], dest="importmode",
- help="prepend/append to sys.path when importing test modules, "
- "default is to prepend.")
-
-
-def pytest_cmdline_main(config):
- if config.option.showfixtures:
- showfixtures(config)
- return 0
-
-
-def pytest_generate_tests(metafunc):
- # those alternative spellings are common - raise a specific error to alert
- # the user
- alt_spellings = ['parameterize', 'parametrise', 'parameterise']
- for attr in alt_spellings:
- if hasattr(metafunc.function, attr):
- msg = "{0} has '{1}', spelling should be 'parametrize'"
- raise MarkerError(msg.format(metafunc.function.__name__, attr))
- try:
- markers = metafunc.function.parametrize
- except AttributeError:
- return
- for marker in markers:
- metafunc.parametrize(*marker.args, **marker.kwargs)
-
-def pytest_configure(config):
- config.addinivalue_line("markers",
- "parametrize(argnames, argvalues): call a test function multiple "
- "times passing in different arguments in turn. argvalues generally "
- "needs to be a list of values if argnames specifies only one name "
- "or a list of tuples of values if argnames specifies multiple names. "
- "Example: @parametrize('arg1', [1,2]) would lead to two calls of the "
- "decorated test function, one with arg1=1 and another with arg1=2."
- "see http://pytest.org/latest/parametrize.html for more info and "
- "examples."
- )
- config.addinivalue_line("markers",
- "usefixtures(fixturename1, fixturename2, ...): mark tests as needing "
- "all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures "
- )
-
-def pytest_sessionstart(session):
- session._fixturemanager = FixtureManager(session)
-
-@pytest.hookimpl(trylast=True)
-def pytest_namespace():
- raises.Exception = pytest.fail.Exception
- return {
- 'fixture': fixture,
- 'yield_fixture': yield_fixture,
- 'raises' : raises,
- 'collect': {
- 'Module': Module, 'Class': Class, 'Instance': Instance,
- 'Function': Function, 'Generator': Generator,
- '_fillfuncargs': fillfixtures}
- }
-
-@fixture(scope="session")
-def pytestconfig(request):
- """ the pytest config object with access to command line opts."""
- return request.config
-
-
-@pytest.hookimpl(trylast=True)
-def pytest_pyfunc_call(pyfuncitem):
- testfunction = pyfuncitem.obj
- if pyfuncitem._isyieldedfunction():
- testfunction(*pyfuncitem._args)
- else:
- funcargs = pyfuncitem.funcargs
- testargs = {}
- for arg in pyfuncitem._fixtureinfo.argnames:
- testargs[arg] = funcargs[arg]
- testfunction(**testargs)
- return True
-
-def pytest_collect_file(path, parent):
- ext = path.ext
- if ext == ".py":
- if not parent.session.isinitpath(path):
- for pat in parent.config.getini('python_files'):
- if path.fnmatch(pat):
- break
- else:
- return
- ihook = parent.session.gethookproxy(path)
- return ihook.pytest_pycollect_makemodule(path=path, parent=parent)
-
-def pytest_pycollect_makemodule(path, parent):
- return Module(path, parent)
-
-@pytest.hookimpl(hookwrapper=True)
-def pytest_pycollect_makeitem(collector, name, obj):
- outcome = yield
- res = outcome.get_result()
- if res is not None:
- raise StopIteration
- # nothing was collected elsewhere, let's do it here
- if isclass(obj):
- if collector.istestclass(obj, name):
- Class = collector._getcustomclass("Class")
- outcome.force_result(Class(name, parent=collector))
- elif collector.istestfunction(obj, name):
- # mock seems to store unbound methods (issue473), normalize it
- obj = getattr(obj, "__func__", obj)
- # We need to try and unwrap the function if it's a functools.partial
- # or a funtools.wrapped.
- # We musn't if it's been wrapped with mock.patch (python 2 only)
- if not (isfunction(obj) or isfunction(get_real_func(obj))):
- collector.warn(code="C2", message=
- "cannot collect %r because it is not a function."
- % name, )
- elif getattr(obj, "__test__", True):
- if is_generator(obj):
- res = Generator(name, parent=collector)
- else:
- res = list(collector._genfunctions(name, obj))
- outcome.force_result(res)
-
-def is_generator(func):
- try:
- return _pytest._code.getrawcode(func).co_flags & 32 # generator function
- except AttributeError: # builtin functions have no bytecode
- # assume them to not be generators
- return False
-
-class PyobjContext(object):
- module = pyobj_property("Module")
- cls = pyobj_property("Class")
- instance = pyobj_property("Instance")
-
-class PyobjMixin(PyobjContext):
- def obj():
- def fget(self):
- try:
- return self._obj
- except AttributeError:
- self._obj = obj = self._getobj()
- return obj
- def fset(self, value):
- self._obj = value
- return property(fget, fset, None, "underlying python object")
- obj = obj()
-
- def _getobj(self):
- return getattr(self.parent.obj, self.name)
-
- def getmodpath(self, stopatmodule=True, includemodule=False):
- """ return python path relative to the containing module. """
- chain = self.listchain()
- chain.reverse()
- parts = []
- for node in chain:
- if isinstance(node, Instance):
- continue
- name = node.name
- if isinstance(node, Module):
- assert name.endswith(".py")
- name = name[:-3]
- if stopatmodule:
- if includemodule:
- parts.append(name)
- break
- parts.append(name)
- parts.reverse()
- s = ".".join(parts)
- return s.replace(".[", "[")
-
- def _getfslineno(self):
- return getfslineno(self.obj)
-
- def reportinfo(self):
- # XXX caching?
- obj = self.obj
- compat_co_firstlineno = getattr(obj, 'compat_co_firstlineno', None)
- if isinstance(compat_co_firstlineno, int):
- # nose compatibility
- fspath = sys.modules[obj.__module__].__file__
- if fspath.endswith(".pyc"):
- fspath = fspath[:-1]
- lineno = compat_co_firstlineno
- else:
- fspath, lineno = getfslineno(obj)
- modpath = self.getmodpath()
- assert isinstance(lineno, int)
- return fspath, lineno, modpath
-
-class PyCollector(PyobjMixin, pytest.Collector):
-
- def funcnamefilter(self, name):
- return self._matches_prefix_or_glob_option('python_functions', name)
-
- def isnosetest(self, obj):
- """ Look for the __test__ attribute, which is applied by the
- @nose.tools.istest decorator
- """
- # We explicitly check for "is True" here to not mistakenly treat
- # classes with a custom __getattr__ returning something truthy (like a
- # function) as test classes.
- return safe_getattr(obj, '__test__', False) is True
-
- def classnamefilter(self, name):
- return self._matches_prefix_or_glob_option('python_classes', name)
-
- def istestfunction(self, obj, name):
- return (
- (self.funcnamefilter(name) or self.isnosetest(obj)) and
- safe_getattr(obj, "__call__", False) and getfixturemarker(obj) is None
- )
-
- def istestclass(self, obj, name):
- return self.classnamefilter(name) or self.isnosetest(obj)
-
- def _matches_prefix_or_glob_option(self, option_name, name):
- """
- checks if the given name matches the prefix or glob-pattern defined
- in ini configuration.
- """
- for option in self.config.getini(option_name):
- if name.startswith(option):
- return True
- # check that name looks like a glob-string before calling fnmatch
- # because this is called for every name in each collected module,
- # and fnmatch is somewhat expensive to call
- elif ('*' in option or '?' in option or '[' in option) and \
- fnmatch.fnmatch(name, option):
- return True
- return False
-
- def collect(self):
- if not getattr(self.obj, "__test__", True):
- return []
-
- # NB. we avoid random getattrs and peek in the __dict__ instead
- # (XXX originally introduced from a PyPy need, still true?)
- dicts = [getattr(self.obj, '__dict__', {})]
- for basecls in inspect.getmro(self.obj.__class__):
- dicts.append(basecls.__dict__)
- seen = {}
- l = []
- for dic in dicts:
- for name, obj in list(dic.items()):
- if name in seen:
- continue
- seen[name] = True
- res = self.makeitem(name, obj)
- if res is None:
- continue
- if not isinstance(res, list):
- res = [res]
- l.extend(res)
- l.sort(key=lambda item: item.reportinfo()[:2])
- return l
-
- def makeitem(self, name, obj):
- #assert self.ihook.fspath == self.fspath, self
- return self.ihook.pytest_pycollect_makeitem(
- collector=self, name=name, obj=obj)
-
- def _genfunctions(self, name, funcobj):
- module = self.getparent(Module).obj
- clscol = self.getparent(Class)
- cls = clscol and clscol.obj or None
- transfer_markers(funcobj, cls, module)
- fm = self.session._fixturemanager
- fixtureinfo = fm.getfixtureinfo(self, funcobj, cls)
- metafunc = Metafunc(funcobj, fixtureinfo, self.config,
- cls=cls, module=module)
- methods = []
- if hasattr(module, "pytest_generate_tests"):
- methods.append(module.pytest_generate_tests)
- if hasattr(cls, "pytest_generate_tests"):
- methods.append(cls().pytest_generate_tests)
- if methods:
- self.ihook.pytest_generate_tests.call_extra(methods,
- dict(metafunc=metafunc))
- else:
- self.ihook.pytest_generate_tests(metafunc=metafunc)
-
- Function = self._getcustomclass("Function")
- if not metafunc._calls:
- yield Function(name, parent=self, fixtureinfo=fixtureinfo)
- else:
- # add funcargs() as fixturedefs to fixtureinfo.arg2fixturedefs
- add_funcarg_pseudo_fixture_def(self, metafunc, fm)
-
- for callspec in metafunc._calls:
- subname = "%s[%s]" %(name, callspec.id)
- yield Function(name=subname, parent=self,
- callspec=callspec, callobj=funcobj,
- fixtureinfo=fixtureinfo,
- keywords={callspec.id:True})
-
-def add_funcarg_pseudo_fixture_def(collector, metafunc, fixturemanager):
- # this function will transform all collected calls to a functions
- # if they use direct funcargs (i.e. direct parametrization)
- # because we want later test execution to be able to rely on
- # an existing FixtureDef structure for all arguments.
- # XXX we can probably avoid this algorithm if we modify CallSpec2
- # to directly care for creating the fixturedefs within its methods.
- if not metafunc._calls[0].funcargs:
- return # this function call does not have direct parametrization
- # collect funcargs of all callspecs into a list of values
- arg2params = {}
- arg2scope = {}
- for callspec in metafunc._calls:
- for argname, argvalue in callspec.funcargs.items():
- assert argname not in callspec.params
- callspec.params[argname] = argvalue
- arg2params_list = arg2params.setdefault(argname, [])
- callspec.indices[argname] = len(arg2params_list)
- arg2params_list.append(argvalue)
- if argname not in arg2scope:
- scopenum = callspec._arg2scopenum.get(argname,
- scopenum_function)
- arg2scope[argname] = scopes[scopenum]
- callspec.funcargs.clear()
-
- # register artificial FixtureDef's so that later at test execution
- # time we can rely on a proper FixtureDef to exist for fixture setup.
- arg2fixturedefs = metafunc._arg2fixturedefs
- for argname, valuelist in arg2params.items():
- # if we have a scope that is higher than function we need
- # to make sure we only ever create an according fixturedef on
- # a per-scope basis. We thus store and cache the fixturedef on the
- # node related to the scope.
- scope = arg2scope[argname]
- node = None
- if scope != "function":
- node = get_scope_node(collector, scope)
- if node is None:
- assert scope == "class" and isinstance(collector, Module)
- # use module-level collector for class-scope (for now)
- node = collector
- if node and argname in node._name2pseudofixturedef:
- arg2fixturedefs[argname] = [node._name2pseudofixturedef[argname]]
- else:
- fixturedef = FixtureDef(fixturemanager, '', argname,
- get_direct_param_fixture_func,
- arg2scope[argname],
- valuelist, False, False)
- arg2fixturedefs[argname] = [fixturedef]
- if node is not None:
- node._name2pseudofixturedef[argname] = fixturedef
-
-
-def get_direct_param_fixture_func(request):
- return request.param
-
-class FuncFixtureInfo:
- def __init__(self, argnames, names_closure, name2fixturedefs):
- self.argnames = argnames
- self.names_closure = names_closure
- self.name2fixturedefs = name2fixturedefs
-
-
-def _marked(func, mark):
- """ Returns True if :func: is already marked with :mark:, False otherwise.
- This can happen if marker is applied to class and the test file is
- invoked more than once.
- """
- try:
- func_mark = getattr(func, mark.name)
- except AttributeError:
- return False
- return mark.args == func_mark.args and mark.kwargs == func_mark.kwargs
-
-
-def transfer_markers(funcobj, cls, mod):
- # XXX this should rather be code in the mark plugin or the mark
- # plugin should merge with the python plugin.
- for holder in (cls, mod):
- try:
- pytestmark = holder.pytestmark
- except AttributeError:
- continue
- if isinstance(pytestmark, list):
- for mark in pytestmark:
- if not _marked(funcobj, mark):
- mark(funcobj)
- else:
- if not _marked(funcobj, pytestmark):
- pytestmark(funcobj)
-
-class Module(pytest.File, PyCollector):
- """ Collector for test classes and functions. """
- def _getobj(self):
- return self._memoizedcall('_obj', self._importtestmodule)
-
- def collect(self):
- self.session._fixturemanager.parsefactories(self)
- return super(Module, self).collect()
-
- def _importtestmodule(self):
- # we assume we are only called once per module
- importmode = self.config.getoption("--import-mode")
- try:
- mod = self.fspath.pyimport(ensuresyspath=importmode)
- except SyntaxError:
- raise self.CollectError(
- _pytest._code.ExceptionInfo().getrepr(style="short"))
- except self.fspath.ImportMismatchError:
- e = sys.exc_info()[1]
- raise self.CollectError(
- "import file mismatch:\n"
- "imported module %r has this __file__ attribute:\n"
- " %s\n"
- "which is not the same as the test file we want to collect:\n"
- " %s\n"
- "HINT: remove __pycache__ / .pyc files and/or use a "
- "unique basename for your test file modules"
- % e.args
- )
- #print "imported test module", mod
- self.config.pluginmanager.consider_module(mod)
- return mod
-
- def setup(self):
- setup_module = xunitsetup(self.obj, "setUpModule")
- if setup_module is None:
- setup_module = xunitsetup(self.obj, "setup_module")
- if setup_module is not None:
- #XXX: nose compat hack, move to nose plugin
- # if it takes a positional arg, its probably a pytest style one
- # so we pass the current module object
- if _has_positional_arg(setup_module):
- setup_module(self.obj)
- else:
- setup_module()
- fin = getattr(self.obj, 'tearDownModule', None)
- if fin is None:
- fin = getattr(self.obj, 'teardown_module', None)
- if fin is not None:
- #XXX: nose compat hack, move to nose plugin
- # if it takes a positional arg, it's probably a pytest style one
- # so we pass the current module object
- if _has_positional_arg(fin):
- finalizer = lambda: fin(self.obj)
- else:
- finalizer = fin
- self.addfinalizer(finalizer)
-
-
-class Class(PyCollector):
- """ Collector for test methods. """
- def collect(self):
- if hasinit(self.obj):
- self.warn("C1", "cannot collect test class %r because it has a "
- "__init__ constructor" % self.obj.__name__)
- return []
- return [self._getcustomclass("Instance")(name="()", parent=self)]
-
- def setup(self):
- setup_class = xunitsetup(self.obj, 'setup_class')
- if setup_class is not None:
- setup_class = getattr(setup_class, 'im_func', setup_class)
- setup_class = getattr(setup_class, '__func__', setup_class)
- setup_class(self.obj)
-
- fin_class = getattr(self.obj, 'teardown_class', None)
- if fin_class is not None:
- fin_class = getattr(fin_class, 'im_func', fin_class)
- fin_class = getattr(fin_class, '__func__', fin_class)
- self.addfinalizer(lambda: fin_class(self.obj))
-
-class Instance(PyCollector):
- def _getobj(self):
- obj = self.parent.obj()
- return obj
-
- def collect(self):
- self.session._fixturemanager.parsefactories(self)
- return super(Instance, self).collect()
-
- def newinstance(self):
- self.obj = self._getobj()
- return self.obj
-
-class FunctionMixin(PyobjMixin):
- """ mixin for the code common to Function and Generator.
- """
-
- def setup(self):
- """ perform setup for this test function. """
- if hasattr(self, '_preservedparent'):
- obj = self._preservedparent
- elif isinstance(self.parent, Instance):
- obj = self.parent.newinstance()
- self.obj = self._getobj()
- else:
- obj = self.parent.obj
- if inspect.ismethod(self.obj):
- setup_name = 'setup_method'
- teardown_name = 'teardown_method'
- else:
- setup_name = 'setup_function'
- teardown_name = 'teardown_function'
- setup_func_or_method = xunitsetup(obj, setup_name)
- if setup_func_or_method is not None:
- setup_func_or_method(self.obj)
- fin = getattr(obj, teardown_name, None)
- if fin is not None:
- self.addfinalizer(lambda: fin(self.obj))
-
- def _prunetraceback(self, excinfo):
- if hasattr(self, '_obj') and not self.config.option.fulltrace:
- code = _pytest._code.Code(get_real_func(self.obj))
- path, firstlineno = code.path, code.firstlineno
- traceback = excinfo.traceback
- ntraceback = traceback.cut(path=path, firstlineno=firstlineno)
- if ntraceback == traceback:
- ntraceback = ntraceback.cut(path=path)
- if ntraceback == traceback:
- #ntraceback = ntraceback.cut(excludepath=cutdir2)
- ntraceback = ntraceback.filter(filter_traceback)
- if not ntraceback:
- ntraceback = traceback
-
- excinfo.traceback = ntraceback.filter()
- # issue364: mark all but first and last frames to
- # only show a single-line message for each frame
- if self.config.option.tbstyle == "auto":
- if len(excinfo.traceback) > 2:
- for entry in excinfo.traceback[1:-1]:
- entry.set_repr_style('short')
-
- def _repr_failure_py(self, excinfo, style="long"):
- if excinfo.errisinstance(pytest.fail.Exception):
- if not excinfo.value.pytrace:
- return py._builtin._totext(excinfo.value)
- return super(FunctionMixin, self)._repr_failure_py(excinfo,
- style=style)
-
- def repr_failure(self, excinfo, outerr=None):
- assert outerr is None, "XXX outerr usage is deprecated"
- style = self.config.option.tbstyle
- if style == "auto":
- style = "long"
- return self._repr_failure_py(excinfo, style=style)
-
-
-class Generator(FunctionMixin, PyCollector):
- def collect(self):
- # test generators are seen as collectors but they also
- # invoke setup/teardown on popular request
- # (induced by the common "test_*" naming shared with normal tests)
- self.session._setupstate.prepare(self)
- # see FunctionMixin.setup and test_setupstate_is_preserved_134
- self._preservedparent = self.parent.obj
- l = []
- seen = {}
- for i, x in enumerate(self.obj()):
- name, call, args = self.getcallargs(x)
- if not callable(call):
- raise TypeError("%r yielded non callable test %r" %(self.obj, call,))
- if name is None:
- name = "[%d]" % i
- else:
- name = "['%s']" % name
- if name in seen:
- raise ValueError("%r generated tests with non-unique name %r" %(self, name))
- seen[name] = True
- l.append(self.Function(name, self, args=args, callobj=call))
- return l
-
- def getcallargs(self, obj):
- if not isinstance(obj, (tuple, list)):
- obj = (obj,)
- # explict naming
- if isinstance(obj[0], py.builtin._basestring):
- name = obj[0]
- obj = obj[1:]
- else:
- name = None
- call, args = obj[0], obj[1:]
- return name, call, args
-
-
-def hasinit(obj):
- init = getattr(obj, '__init__', None)
- if init:
- if init != object.__init__:
- return True
-
-
-
-def fillfixtures(function):
- """ fill missing funcargs for a test function. """
- try:
- request = function._request
- except AttributeError:
- # XXX this special code path is only expected to execute
- # with the oejskit plugin. It uses classes with funcargs
- # and we thus have to work a bit to allow this.
- fm = function.session._fixturemanager
- fi = fm.getfixtureinfo(function.parent, function.obj, None)
- function._fixtureinfo = fi
- request = function._request = FixtureRequest(function)
- request._fillfixtures()
- # prune out funcargs for jstests
- newfuncargs = {}
- for name in fi.argnames:
- newfuncargs[name] = function.funcargs[name]
- function.funcargs = newfuncargs
- else:
- request._fillfixtures()
-
-
-_notexists = object()
-
-class CallSpec2(object):
- def __init__(self, metafunc):
- self.metafunc = metafunc
- self.funcargs = {}
- self._idlist = []
- self.params = {}
- self._globalid = _notexists
- self._globalid_args = set()
- self._globalparam = _notexists
- self._arg2scopenum = {} # used for sorting parametrized resources
- self.keywords = {}
- self.indices = {}
-
- def copy(self, metafunc):
- cs = CallSpec2(self.metafunc)
- cs.funcargs.update(self.funcargs)
- cs.params.update(self.params)
- cs.keywords.update(self.keywords)
- cs.indices.update(self.indices)
- cs._arg2scopenum.update(self._arg2scopenum)
- cs._idlist = list(self._idlist)
- cs._globalid = self._globalid
- cs._globalid_args = self._globalid_args
- cs._globalparam = self._globalparam
- return cs
-
- def _checkargnotcontained(self, arg):
- if arg in self.params or arg in self.funcargs:
- raise ValueError("duplicate %r" %(arg,))
-
- def getparam(self, name):
- try:
- return self.params[name]
- except KeyError:
- if self._globalparam is _notexists:
- raise ValueError(name)
- return self._globalparam
-
- @property
- def id(self):
- return "-".join(map(str, filter(None, self._idlist)))
-
- def setmulti(self, valtypes, argnames, valset, id, keywords, scopenum,
- param_index):
- for arg,val in zip(argnames, valset):
- self._checkargnotcontained(arg)
- valtype_for_arg = valtypes[arg]
- getattr(self, valtype_for_arg)[arg] = val
- self.indices[arg] = param_index
- self._arg2scopenum[arg] = scopenum
- if val is _notexists:
- self._emptyparamspecified = True
- self._idlist.append(id)
- self.keywords.update(keywords)
-
- def setall(self, funcargs, id, param):
- for x in funcargs:
- self._checkargnotcontained(x)
- self.funcargs.update(funcargs)
- if id is not _notexists:
- self._idlist.append(id)
- if param is not _notexists:
- assert self._globalparam is _notexists
- self._globalparam = param
- for arg in funcargs:
- self._arg2scopenum[arg] = scopenum_function
-
-
-class FuncargnamesCompatAttr:
- """ helper class so that Metafunc, Function and FixtureRequest
- don't need to each define the "funcargnames" compatibility attribute.
- """
- @property
- def funcargnames(self):
- """ alias attribute for ``fixturenames`` for pre-2.3 compatibility"""
- return self.fixturenames
-
-class Metafunc(FuncargnamesCompatAttr):
- """
- Metafunc objects are passed to the ``pytest_generate_tests`` hook.
- They help to inspect a test function and to generate tests according to
- test configuration or values specified in the class or module where a
- test function is defined.
-
- :ivar fixturenames: set of fixture names required by the test function
-
- :ivar function: underlying python test function
-
- :ivar cls: class object where the test function is defined in or ``None``.
-
- :ivar module: the module object where the test function is defined in.
-
- :ivar config: access to the :class:`_pytest.config.Config` object for the
- test session.
-
- :ivar funcargnames:
- .. deprecated:: 2.3
- Use ``fixturenames`` instead.
- """
- def __init__(self, function, fixtureinfo, config, cls=None, module=None):
- self.config = config
- self.module = module
- self.function = function
- self.fixturenames = fixtureinfo.names_closure
- self._arg2fixturedefs = fixtureinfo.name2fixturedefs
- self.cls = cls
- self._calls = []
- self._ids = py.builtin.set()
-
- def parametrize(self, argnames, argvalues, indirect=False, ids=None,
- scope=None):
- """ Add new invocations to the underlying test function using the list
- of argvalues for the given argnames. Parametrization is performed
- during the collection phase. If you need to setup expensive resources
- see about setting indirect to do it rather at test setup time.
-
- :arg argnames: a comma-separated string denoting one or more argument
- names, or a list/tuple of argument strings.
-
- :arg argvalues: The list of argvalues determines how often a
- test is invoked with different argument values. If only one
- argname was specified argvalues is a list of values. If N
- argnames were specified, argvalues must be a list of N-tuples,
- where each tuple-element specifies a value for its respective
- argname.
-
- :arg indirect: The list of argnames or boolean. A list of arguments'
- names (subset of argnames). If True the list contains all names from
- the argnames. Each argvalue corresponding to an argname in this list will
- be passed as request.param to its respective argname fixture
- function so that it can perform more expensive setups during the
- setup phase of a test rather than at collection time.
-
- :arg ids: list of string ids, or a callable.
- If strings, each is corresponding to the argvalues so that they are
- part of the test id.
- If callable, it should take one argument (a single argvalue) and return
- a string or return None. If None, the automatically generated id for that
- argument will be used.
- If no ids are provided they will be generated automatically from
- the argvalues.
-
- :arg scope: if specified it denotes the scope of the parameters.
- The scope is used for grouping tests by parameter instances.
- It will also override any fixture-function defined scope, allowing
- to set a dynamic scope using test context or configuration.
- """
-
- # individual parametrized argument sets can be wrapped in a series
- # of markers in which case we unwrap the values and apply the mark
- # at Function init
- newkeywords = {}
- unwrapped_argvalues = []
- for i, argval in enumerate(argvalues):
- while isinstance(argval, MarkDecorator):
- newmark = MarkDecorator(argval.markname,
- argval.args[:-1], argval.kwargs)
- newmarks = newkeywords.setdefault(i, {})
- newmarks[newmark.markname] = newmark
- argval = argval.args[-1]
- unwrapped_argvalues.append(argval)
- argvalues = unwrapped_argvalues
-
- if not isinstance(argnames, (tuple, list)):
- argnames = [x.strip() for x in argnames.split(",") if x.strip()]
- if len(argnames) == 1:
- argvalues = [(val,) for val in argvalues]
- if not argvalues:
- argvalues = [(_notexists,) * len(argnames)]
-
- if scope is None:
- scope = "function"
- scopenum = scopes.index(scope)
- valtypes = {}
- for arg in argnames:
- if arg not in self.fixturenames:
- raise ValueError("%r uses no fixture %r" %(self.function, arg))
-
- if indirect is True:
- valtypes = dict.fromkeys(argnames, "params")
- elif indirect is False:
- valtypes = dict.fromkeys(argnames, "funcargs")
- elif isinstance(indirect, (tuple, list)):
- valtypes = dict.fromkeys(argnames, "funcargs")
- for arg in indirect:
- if arg not in argnames:
- raise ValueError("indirect given to %r: fixture %r doesn't exist" %(
- self.function, arg))
- valtypes[arg] = "params"
- idfn = None
- if callable(ids):
- idfn = ids
- ids = None
- if ids and len(ids) != len(argvalues):
- raise ValueError('%d tests specified with %d ids' %(
- len(argvalues), len(ids)))
- if not ids:
- ids = idmaker(argnames, argvalues, idfn)
- newcalls = []
- for callspec in self._calls or [CallSpec2(self)]:
- for param_index, valset in enumerate(argvalues):
- assert len(valset) == len(argnames)
- newcallspec = callspec.copy(self)
- newcallspec.setmulti(valtypes, argnames, valset, ids[param_index],
- newkeywords.get(param_index, {}), scopenum,
- param_index)
- newcalls.append(newcallspec)
- self._calls = newcalls
-
- def addcall(self, funcargs=None, id=_notexists, param=_notexists):
- """ (deprecated, use parametrize) Add a new call to the underlying
- test function during the collection phase of a test run. Note that
- request.addcall() is called during the test collection phase prior and
- independently to actual test execution. You should only use addcall()
- if you need to specify multiple arguments of a test function.
-
- :arg funcargs: argument keyword dictionary used when invoking
- the test function.
-
- :arg id: used for reporting and identification purposes. If you
- don't supply an `id` an automatic unique id will be generated.
-
- :arg param: a parameter which will be exposed to a later fixture function
- invocation through the ``request.param`` attribute.
- """
- assert funcargs is None or isinstance(funcargs, dict)
- if funcargs is not None:
- for name in funcargs:
- if name not in self.fixturenames:
- pytest.fail("funcarg %r not used in this function." % name)
- else:
- funcargs = {}
- if id is None:
- raise ValueError("id=None not allowed")
- if id is _notexists:
- id = len(self._calls)
- id = str(id)
- if id in self._ids:
- raise ValueError("duplicate id %r" % id)
- self._ids.add(id)
-
- cs = CallSpec2(self)
- cs.setall(funcargs, id, param)
- self._calls.append(cs)
-
-
-if _PY3:
- import codecs
-
- def _escape_bytes(val):
- """
- If val is pure ascii, returns it as a str(), otherwise escapes
- into a sequence of escaped bytes:
- b'\xc3\xb4\xc5\xd6' -> u'\\xc3\\xb4\\xc5\\xd6'
-
- note:
- the obvious "v.decode('unicode-escape')" will return
- valid utf-8 unicode if it finds them in the string, but we
- want to return escaped bytes for any byte, even if they match
- a utf-8 string.
- """
- if val:
- # source: http://goo.gl/bGsnwC
- encoded_bytes, _ = codecs.escape_encode(val)
- return encoded_bytes.decode('ascii')
- else:
- # empty bytes crashes codecs.escape_encode (#1087)
- return ''
-else:
- def _escape_bytes(val):
- """
- In py2 bytes and str are the same type, so return it unchanged if it
- is a full ascii string, otherwise escape it into its binary form.
- """
- try:
- return val.decode('ascii')
- except UnicodeDecodeError:
- return val.encode('string-escape')
-
-
-def _idval(val, argname, idx, idfn):
- if idfn:
- try:
- s = idfn(val)
- if s:
- return s
- except Exception:
- pass
-
- if isinstance(val, bytes):
- return _escape_bytes(val)
- elif isinstance(val, (float, int, str, bool, NoneType)):
- return str(val)
- elif isinstance(val, REGEX_TYPE):
- return _escape_bytes(val.pattern) if isinstance(val.pattern, bytes) else val.pattern
- elif enum is not None and isinstance(val, enum.Enum):
- return str(val)
- elif isclass(val) and hasattr(val, '__name__'):
- return val.__name__
- elif _PY2 and isinstance(val, unicode):
- # special case for python 2: if a unicode string is
- # convertible to ascii, return it as an str() object instead
- try:
- return str(val)
- except UnicodeError:
- # fallthrough
- pass
- return str(argname)+str(idx)
-
-def _idvalset(idx, valset, argnames, idfn):
- this_id = [_idval(val, argname, idx, idfn)
- for val, argname in zip(valset, argnames)]
- return "-".join(this_id)
-
-def idmaker(argnames, argvalues, idfn=None):
- ids = [_idvalset(valindex, valset, argnames, idfn)
- for valindex, valset in enumerate(argvalues)]
- if len(set(ids)) < len(ids):
- # user may have provided a bad idfn which means the ids are not unique
- ids = [str(i) + testid for i, testid in enumerate(ids)]
- return ids
-
-def showfixtures(config):
- from _pytest.main import wrap_session
- return wrap_session(config, _showfixtures_main)
-
-def _showfixtures_main(config, session):
- import _pytest.config
- session.perform_collect()
- curdir = py.path.local()
- tw = _pytest.config.create_terminal_writer(config)
- verbose = config.getvalue("verbose")
-
- fm = session._fixturemanager
-
- available = []
- for argname, fixturedefs in fm._arg2fixturedefs.items():
- assert fixturedefs is not None
- if not fixturedefs:
- continue
- fixturedef = fixturedefs[-1]
- loc = getlocation(fixturedef.func, curdir)
- available.append((len(fixturedef.baseid),
- fixturedef.func.__module__,
- curdir.bestrelpath(loc),
- fixturedef.argname, fixturedef))
-
- available.sort()
- currentmodule = None
- for baseid, module, bestrel, argname, fixturedef in available:
- if currentmodule != module:
- if not module.startswith("_pytest."):
- tw.line()
- tw.sep("-", "fixtures defined from %s" %(module,))
- currentmodule = module
- if verbose <= 0 and argname[0] == "_":
- continue
- if verbose > 0:
- funcargspec = "%s -- %s" %(argname, bestrel,)
- else:
- funcargspec = argname
- tw.line(funcargspec, green=True)
- loc = getlocation(fixturedef.func, curdir)
- doc = fixturedef.func.__doc__ or ""
- if doc:
- for line in doc.strip().split("\n"):
- tw.line(" " + line.strip())
- else:
- tw.line(" %s: no docstring available" %(loc,),
- red=True)
-
-def getlocation(function, curdir):
- import inspect
- fn = py.path.local(inspect.getfile(function))
- lineno = py.builtin._getcode(function).co_firstlineno
- if fn.relto(curdir):
- fn = fn.relto(curdir)
- return "%s:%d" %(fn, lineno+1)
-
-# builtin pytest.raises helper
-
-def raises(expected_exception, *args, **kwargs):
- """ assert that a code block/function call raises ``expected_exception``
- and raise a failure exception otherwise.
-
- This helper produces a ``ExceptionInfo()`` object (see below).
-
- If using Python 2.5 or above, you may use this function as a
- context manager::
-
- >>> with raises(ZeroDivisionError):
- ... 1/0
-
- .. note::
-
- When using ``pytest.raises`` as a context manager, it's worthwhile to
- note that normal context manager rules apply and that the exception
- raised *must* be the final line in the scope of the context manager.
- Lines of code after that, within the scope of the context manager will
- not be executed. For example::
-
- >>> with raises(OSError) as exc_info:
- assert 1 == 1 # this will execute as expected
- raise OSError(errno.EEXISTS, 'directory exists')
- assert exc_info.value.errno == errno.EEXISTS # this will not execute
-
- Instead, the following approach must be taken (note the difference in
- scope)::
-
- >>> with raises(OSError) as exc_info:
- assert 1 == 1 # this will execute as expected
- raise OSError(errno.EEXISTS, 'directory exists')
-
- assert exc_info.value.errno == errno.EEXISTS # this will now execute
-
- Or you can specify a callable by passing a to-be-called lambda::
-
- >>> raises(ZeroDivisionError, lambda: 1/0)
- <ExceptionInfo ...>
-
- or you can specify an arbitrary callable with arguments::
-
- >>> def f(x): return 1/x
- ...
- >>> raises(ZeroDivisionError, f, 0)
- <ExceptionInfo ...>
- >>> raises(ZeroDivisionError, f, x=0)
- <ExceptionInfo ...>
-
- A third possibility is to use a string to be executed::
-
- >>> raises(ZeroDivisionError, "f(0)")
- <ExceptionInfo ...>
-
- .. autoclass:: _pytest._code.ExceptionInfo
- :members:
-
- .. note::
- Similar to caught exception objects in Python, explicitly clearing
- local references to returned ``ExceptionInfo`` objects can
- help the Python interpreter speed up its garbage collection.
-
- Clearing those references breaks a reference cycle
- (``ExceptionInfo`` --> caught exception --> frame stack raising
- the exception --> current frame stack --> local variables -->
- ``ExceptionInfo``) which makes Python keep all objects referenced
- from that cycle (including all local variables in the current
- frame) alive until the next cyclic garbage collection run. See the
- official Python ``try`` statement documentation for more detailed
- information.
-
- """
- __tracebackhide__ = True
- if expected_exception is AssertionError:
- # we want to catch a AssertionError
- # replace our subclass with the builtin one
- # see https://github.com/pytest-dev/pytest/issues/176
- from _pytest.assertion.util import BuiltinAssertionError \
- as expected_exception
- msg = ("exceptions must be old-style classes or"
- " derived from BaseException, not %s")
- if isinstance(expected_exception, tuple):
- for exc in expected_exception:
- if not isclass(exc):
- raise TypeError(msg % type(exc))
- elif not isclass(expected_exception):
- raise TypeError(msg % type(expected_exception))
-
- if not args:
- return RaisesContext(expected_exception)
- elif isinstance(args[0], str):
- code, = args
- assert isinstance(code, str)
- frame = sys._getframe(1)
- loc = frame.f_locals.copy()
- loc.update(kwargs)
- #print "raises frame scope: %r" % frame.f_locals
- try:
- code = _pytest._code.Source(code).compile()
- py.builtin.exec_(code, frame.f_globals, loc)
- # XXX didn'T mean f_globals == f_locals something special?
- # this is destroyed here ...
- except expected_exception:
- return _pytest._code.ExceptionInfo()
- else:
- func = args[0]
- try:
- func(*args[1:], **kwargs)
- except expected_exception:
- return _pytest._code.ExceptionInfo()
- pytest.fail("DID NOT RAISE {0}".format(expected_exception))
-
-class RaisesContext(object):
- def __init__(self, expected_exception):
- self.expected_exception = expected_exception
- self.excinfo = None
-
- def __enter__(self):
- self.excinfo = object.__new__(_pytest._code.ExceptionInfo)
- return self.excinfo
-
- def __exit__(self, *tp):
- __tracebackhide__ = True
- if tp[0] is None:
- pytest.fail("DID NOT RAISE")
- if sys.version_info < (2, 7):
- # py26: on __exit__() exc_value often does not contain the
- # exception value.
- # http://bugs.python.org/issue7853
- if not isinstance(tp[1], BaseException):
- exc_type, value, traceback = tp
- tp = exc_type, exc_type(value), traceback
- self.excinfo.__init__(tp)
- return issubclass(self.excinfo.type, self.expected_exception)
-
-#
-# the basic pytest Function item
-#
-
-class Function(FunctionMixin, pytest.Item, FuncargnamesCompatAttr):
- """ a Function Item is responsible for setting up and executing a
- Python test function.
- """
- _genid = None
- def __init__(self, name, parent, args=None, config=None,
- callspec=None, callobj=NOTSET, keywords=None, session=None,
- fixtureinfo=None):
- super(Function, self).__init__(name, parent, config=config,
- session=session)
- self._args = args
- if callobj is not NOTSET:
- self.obj = callobj
-
- self.keywords.update(self.obj.__dict__)
- if callspec:
- self.callspec = callspec
- self.keywords.update(callspec.keywords)
- if keywords:
- self.keywords.update(keywords)
-
- if fixtureinfo is None:
- fixtureinfo = self.session._fixturemanager.getfixtureinfo(
- self.parent, self.obj, self.cls,
- funcargs=not self._isyieldedfunction())
- self._fixtureinfo = fixtureinfo
- self.fixturenames = fixtureinfo.names_closure
- self._initrequest()
-
- def _initrequest(self):
- self.funcargs = {}
- if self._isyieldedfunction():
- assert not hasattr(self, "callspec"), (
- "yielded functions (deprecated) cannot have funcargs")
- else:
- if hasattr(self, "callspec"):
- callspec = self.callspec
- assert not callspec.funcargs
- self._genid = callspec.id
- if hasattr(callspec, "param"):
- self.param = callspec.param
- self._request = FixtureRequest(self)
-
- @property
- def function(self):
- "underlying python 'function' object"
- return getattr(self.obj, 'im_func', self.obj)
-
- def _getobj(self):
- name = self.name
- i = name.find("[") # parametrization
- if i != -1:
- name = name[:i]
- return getattr(self.parent.obj, name)
-
- @property
- def _pyfuncitem(self):
- "(compatonly) for code expecting pytest-2.2 style request objects"
- return self
-
- def _isyieldedfunction(self):
- return getattr(self, "_args", None) is not None
-
- def runtest(self):
- """ execute the underlying test function. """
- self.ihook.pytest_pyfunc_call(pyfuncitem=self)
-
- def setup(self):
- # check if parametrization happend with an empty list
- try:
- self.callspec._emptyparamspecified
- except AttributeError:
- pass
- else:
- fs, lineno = self._getfslineno()
- pytest.skip("got empty parameter set, function %s at %s:%d" %(
- self.function.__name__, fs, lineno))
- super(Function, self).setup()
- fillfixtures(self)
-
-
-scope2props = dict(session=())
-scope2props["module"] = ("fspath", "module")
-scope2props["class"] = scope2props["module"] + ("cls",)
-scope2props["instance"] = scope2props["class"] + ("instance", )
-scope2props["function"] = scope2props["instance"] + ("function", "keywords")
-
-def scopeproperty(name=None, doc=None):
- def decoratescope(func):
- scopename = name or func.__name__
- def provide(self):
- if func.__name__ in scope2props[self.scope]:
- return func(self)
- raise AttributeError("%s not available in %s-scoped context" % (
- scopename, self.scope))
- return property(provide, None, None, func.__doc__)
- return decoratescope
-
-
-class FixtureRequest(FuncargnamesCompatAttr):
- """ A request for a fixture from a test or fixture function.
-
- A request object gives access to the requesting test context
- and has an optional ``param`` attribute in case
- the fixture is parametrized indirectly.
- """
-
- def __init__(self, pyfuncitem):
- self._pyfuncitem = pyfuncitem
- #: fixture for which this request is being performed
- self.fixturename = None
- #: Scope string, one of "function", "cls", "module", "session"
- self.scope = "function"
- self._funcargs = {}
- self._fixturedefs = {}
- fixtureinfo = pyfuncitem._fixtureinfo
- self._arg2fixturedefs = fixtureinfo.name2fixturedefs.copy()
- self._arg2index = {}
- self.fixturenames = fixtureinfo.names_closure
- self._fixturemanager = pyfuncitem.session._fixturemanager
-
- @property
- def node(self):
- """ underlying collection node (depends on current request scope)"""
- return self._getscopeitem(self.scope)
-
-
- def _getnextfixturedef(self, argname):
- fixturedefs = self._arg2fixturedefs.get(argname, None)
- if fixturedefs is None:
- # we arrive here because of a a dynamic call to
- # getfuncargvalue(argname) usage which was naturally
- # not known at parsing/collection time
- fixturedefs = self._fixturemanager.getfixturedefs(
- argname, self._pyfuncitem.parent.nodeid)
- self._arg2fixturedefs[argname] = fixturedefs
- # fixturedefs list is immutable so we maintain a decreasing index
- index = self._arg2index.get(argname, 0) - 1
- if fixturedefs is None or (-index > len(fixturedefs)):
- raise FixtureLookupError(argname, self)
- self._arg2index[argname] = index
- return fixturedefs[index]
-
- @property
- def config(self):
- """ the pytest config object associated with this request. """
- return self._pyfuncitem.config
-
-
- @scopeproperty()
- def function(self):
- """ test function object if the request has a per-function scope. """
- return self._pyfuncitem.obj
-
- @scopeproperty("class")
- def cls(self):
- """ class (can be None) where the test function was collected. """
- clscol = self._pyfuncitem.getparent(pytest.Class)
- if clscol:
- return clscol.obj
-
- @property
- def instance(self):
- """ instance (can be None) on which test function was collected. """
- # unittest support hack, see _pytest.unittest.TestCaseFunction
- try:
- return self._pyfuncitem._testcase
- except AttributeError:
- function = getattr(self, "function", None)
- if function is not None:
- return py.builtin._getimself(function)
-
- @scopeproperty()
- def module(self):
- """ python module object where the test function was collected. """
- return self._pyfuncitem.getparent(pytest.Module).obj
-
- @scopeproperty()
- def fspath(self):
- """ the file system path of the test module which collected this test. """
- return self._pyfuncitem.fspath
-
- @property
- def keywords(self):
- """ keywords/markers dictionary for the underlying node. """
- return self.node.keywords
-
- @property
- def session(self):
- """ pytest session object. """
- return self._pyfuncitem.session
-
- def addfinalizer(self, finalizer):
- """ add finalizer/teardown function to be called after the
- last test within the requesting test context finished
- execution. """
- # XXX usually this method is shadowed by fixturedef specific ones
- self._addfinalizer(finalizer, scope=self.scope)
-
- def _addfinalizer(self, finalizer, scope):
- colitem = self._getscopeitem(scope)
- self._pyfuncitem.session._setupstate.addfinalizer(
- finalizer=finalizer, colitem=colitem)
-
- def applymarker(self, marker):
- """ Apply a marker to a single test function invocation.
- This method is useful if you don't want to have a keyword/marker
- on all function invocations.
-
- :arg marker: a :py:class:`_pytest.mark.MarkDecorator` object
- created by a call to ``pytest.mark.NAME(...)``.
- """
- try:
- self.node.keywords[marker.markname] = marker
- except AttributeError:
- raise ValueError(marker)
-
- def raiseerror(self, msg):
- """ raise a FixtureLookupError with the given message. """
- raise self._fixturemanager.FixtureLookupError(None, self, msg)
-
- def _fillfixtures(self):
- item = self._pyfuncitem
- fixturenames = getattr(item, "fixturenames", self.fixturenames)
- for argname in fixturenames:
- if argname not in item.funcargs:
- item.funcargs[argname] = self.getfuncargvalue(argname)
-
- def cached_setup(self, setup, teardown=None, scope="module", extrakey=None):
- """ (deprecated) Return a testing resource managed by ``setup`` &
- ``teardown`` calls. ``scope`` and ``extrakey`` determine when the
- ``teardown`` function will be called so that subsequent calls to
- ``setup`` would recreate the resource. With pytest-2.3 you often
- do not need ``cached_setup()`` as you can directly declare a scope
- on a fixture function and register a finalizer through
- ``request.addfinalizer()``.
-
- :arg teardown: function receiving a previously setup resource.
- :arg setup: a no-argument function creating a resource.
- :arg scope: a string value out of ``function``, ``class``, ``module``
- or ``session`` indicating the caching lifecycle of the resource.
- :arg extrakey: added to internal caching key of (funcargname, scope).
- """
- if not hasattr(self.config, '_setupcache'):
- self.config._setupcache = {} # XXX weakref?
- cachekey = (self.fixturename, self._getscopeitem(scope), extrakey)
- cache = self.config._setupcache
- try:
- val = cache[cachekey]
- except KeyError:
- self._check_scope(self.fixturename, self.scope, scope)
- val = setup()
- cache[cachekey] = val
- if teardown is not None:
- def finalizer():
- del cache[cachekey]
- teardown(val)
- self._addfinalizer(finalizer, scope=scope)
- return val
-
- def getfuncargvalue(self, argname):
- """ Dynamically retrieve a named fixture function argument.
-
- As of pytest-2.3, it is easier and usually better to access other
- fixture values by stating it as an input argument in the fixture
- function. If you only can decide about using another fixture at test
- setup time, you may use this function to retrieve it inside a fixture
- function body.
- """
- return self._get_active_fixturedef(argname).cached_result[0]
-
- def _get_active_fixturedef(self, argname):
- try:
- return self._fixturedefs[argname]
- except KeyError:
- try:
- fixturedef = self._getnextfixturedef(argname)
- except FixtureLookupError:
- if argname == "request":
- class PseudoFixtureDef:
- cached_result = (self, [0], None)
- scope = "function"
- return PseudoFixtureDef
- raise
- # remove indent to prevent the python3 exception
- # from leaking into the call
- result = self._getfuncargvalue(fixturedef)
- self._funcargs[argname] = result
- self._fixturedefs[argname] = fixturedef
- return fixturedef
-
- def _get_fixturestack(self):
- current = self
- l = []
- while 1:
- fixturedef = getattr(current, "_fixturedef", None)
- if fixturedef is None:
- l.reverse()
- return l
- l.append(fixturedef)
- current = current._parent_request
-
- def _getfuncargvalue(self, fixturedef):
- # prepare a subrequest object before calling fixture function
- # (latter managed by fixturedef)
- argname = fixturedef.argname
- funcitem = self._pyfuncitem
- scope = fixturedef.scope
- try:
- param = funcitem.callspec.getparam(argname)
- except (AttributeError, ValueError):
- param = NOTSET
- param_index = 0
- else:
- # indices might not be set if old-style metafunc.addcall() was used
- param_index = funcitem.callspec.indices.get(argname, 0)
- # if a parametrize invocation set a scope it will override
- # the static scope defined with the fixture function
- paramscopenum = funcitem.callspec._arg2scopenum.get(argname)
- if paramscopenum is not None:
- scope = scopes[paramscopenum]
-
- subrequest = SubRequest(self, scope, param, param_index, fixturedef)
-
- # check if a higher-level scoped fixture accesses a lower level one
- subrequest._check_scope(argname, self.scope, scope)
-
- # clear sys.exc_info before invoking the fixture (python bug?)
- # if its not explicitly cleared it will leak into the call
- exc_clear()
- try:
- # call the fixture function
- val = fixturedef.execute(request=subrequest)
- finally:
- # if fixture function failed it might have registered finalizers
- self.session._setupstate.addfinalizer(fixturedef.finish,
- subrequest.node)
- return val
-
- def _check_scope(self, argname, invoking_scope, requested_scope):
- if argname == "request":
- return
- if scopemismatch(invoking_scope, requested_scope):
- # try to report something helpful
- lines = self._factorytraceback()
- pytest.fail("ScopeMismatch: You tried to access the %r scoped "
- "fixture %r with a %r scoped request object, "
- "involved factories\n%s" %(
- (requested_scope, argname, invoking_scope, "\n".join(lines))),
- pytrace=False)
-
- def _factorytraceback(self):
- lines = []
- for fixturedef in self._get_fixturestack():
- factory = fixturedef.func
- fs, lineno = getfslineno(factory)
- p = self._pyfuncitem.session.fspath.bestrelpath(fs)
- args = _format_args(factory)
- lines.append("%s:%d: def %s%s" %(
- p, lineno, factory.__name__, args))
- return lines
-
- def _getscopeitem(self, scope):
- if scope == "function":
- # this might also be a non-function Item despite its attribute name
- return self._pyfuncitem
- node = get_scope_node(self._pyfuncitem, scope)
- if node is None and scope == "class":
- # fallback to function item itself
- node = self._pyfuncitem
- assert node
- return node
-
- def __repr__(self):
- return "<FixtureRequest for %r>" %(self.node)
-
-
-class SubRequest(FixtureRequest):
- """ a sub request for handling getting a fixture from a
- test function/fixture. """
- def __init__(self, request, scope, param, param_index, fixturedef):
- self._parent_request = request
- self.fixturename = fixturedef.argname
- if param is not NOTSET:
- self.param = param
- self.param_index = param_index
- self.scope = scope
- self._fixturedef = fixturedef
- self.addfinalizer = fixturedef.addfinalizer
- self._pyfuncitem = request._pyfuncitem
- self._funcargs = request._funcargs
- self._fixturedefs = request._fixturedefs
- self._arg2fixturedefs = request._arg2fixturedefs
- self._arg2index = request._arg2index
- self.fixturenames = request.fixturenames
- self._fixturemanager = request._fixturemanager
-
- def __repr__(self):
- return "<SubRequest %r for %r>" % (self.fixturename, self._pyfuncitem)
-
-
-class ScopeMismatchError(Exception):
- """ A fixture function tries to use a different fixture function which
- which has a lower scope (e.g. a Session one calls a function one)
- """
-
-scopes = "session module class function".split()
-scopenum_function = scopes.index("function")
-def scopemismatch(currentscope, newscope):
- return scopes.index(newscope) > scopes.index(currentscope)
-
-
-class FixtureLookupError(LookupError):
- """ could not return a requested Fixture (missing or invalid). """
- def __init__(self, argname, request, msg=None):
- self.argname = argname
- self.request = request
- self.fixturestack = request._get_fixturestack()
- self.msg = msg
-
- def formatrepr(self):
- tblines = []
- addline = tblines.append
- stack = [self.request._pyfuncitem.obj]
- stack.extend(map(lambda x: x.func, self.fixturestack))
- msg = self.msg
- if msg is not None:
- # the last fixture raise an error, let's present
- # it at the requesting side
- stack = stack[:-1]
- for function in stack:
- fspath, lineno = getfslineno(function)
- try:
- lines, _ = inspect.getsourcelines(get_real_func(function))
- except (IOError, IndexError):
- error_msg = "file %s, line %s: source code not available"
- addline(error_msg % (fspath, lineno+1))
- else:
- addline("file %s, line %s" % (fspath, lineno+1))
- for i, line in enumerate(lines):
- line = line.rstrip()
- addline(" " + line)
- if line.lstrip().startswith('def'):
- break
-
- if msg is None:
- fm = self.request._fixturemanager
- available = []
- for name, fixturedef in fm._arg2fixturedefs.items():
- parentid = self.request._pyfuncitem.parent.nodeid
- faclist = list(fm._matchfactories(fixturedef, parentid))
- if faclist:
- available.append(name)
- msg = "fixture %r not found" % (self.argname,)
- msg += "\n available fixtures: %s" %(", ".join(available),)
- msg += "\n use 'py.test --fixtures [testpath]' for help on them."
-
- return FixtureLookupErrorRepr(fspath, lineno, tblines, msg, self.argname)
-
-class FixtureLookupErrorRepr(TerminalRepr):
- def __init__(self, filename, firstlineno, tblines, errorstring, argname):
- self.tblines = tblines
- self.errorstring = errorstring
- self.filename = filename
- self.firstlineno = firstlineno
- self.argname = argname
-
- def toterminal(self, tw):
- #tw.line("FixtureLookupError: %s" %(self.argname), red=True)
- for tbline in self.tblines:
- tw.line(tbline.rstrip())
- for line in self.errorstring.split("\n"):
- tw.line(" " + line.strip(), red=True)
- tw.line()
- tw.line("%s:%d" % (self.filename, self.firstlineno+1))
-
-class FixtureManager:
- """
- pytest fixtures definitions and information is stored and managed
- from this class.
-
- During collection fm.parsefactories() is called multiple times to parse
- fixture function definitions into FixtureDef objects and internal
- data structures.
-
- During collection of test functions, metafunc-mechanics instantiate
- a FuncFixtureInfo object which is cached per node/func-name.
- This FuncFixtureInfo object is later retrieved by Function nodes
- which themselves offer a fixturenames attribute.
-
- The FuncFixtureInfo object holds information about fixtures and FixtureDefs
- relevant for a particular function. An initial list of fixtures is
- assembled like this:
-
- - ini-defined usefixtures
- - autouse-marked fixtures along the collection chain up from the function
- - usefixtures markers at module/class/function level
- - test function funcargs
-
- Subsequently the funcfixtureinfo.fixturenames attribute is computed
- as the closure of the fixtures needed to setup the initial fixtures,
- i. e. fixtures needed by fixture functions themselves are appended
- to the fixturenames list.
-
- Upon the test-setup phases all fixturenames are instantiated, retrieved
- by a lookup of their FuncFixtureInfo.
- """
-
- _argprefix = "pytest_funcarg__"
- FixtureLookupError = FixtureLookupError
- FixtureLookupErrorRepr = FixtureLookupErrorRepr
-
- def __init__(self, session):
- self.session = session
- self.config = session.config
- self._arg2fixturedefs = {}
- self._holderobjseen = set()
- self._arg2finish = {}
- self._nodeid_and_autousenames = [("", self.config.getini("usefixtures"))]
- session.config.pluginmanager.register(self, "funcmanage")
-
-
- def getfixtureinfo(self, node, func, cls, funcargs=True):
- if funcargs and not hasattr(node, "nofuncargs"):
- if cls is not None:
- startindex = 1
- else:
- startindex = None
- argnames = getfuncargnames(func, startindex)
- else:
- argnames = ()
- usefixtures = getattr(func, "usefixtures", None)
- initialnames = argnames
- if usefixtures is not None:
- initialnames = usefixtures.args + initialnames
- fm = node.session._fixturemanager
- names_closure, arg2fixturedefs = fm.getfixtureclosure(initialnames,
- node)
- return FuncFixtureInfo(argnames, names_closure, arg2fixturedefs)
-
- def pytest_plugin_registered(self, plugin):
- nodeid = None
- try:
- p = py.path.local(plugin.__file__)
- except AttributeError:
- pass
- else:
- # construct the base nodeid which is later used to check
- # what fixtures are visible for particular tests (as denoted
- # by their test id)
- if p.basename.startswith("conftest.py"):
- nodeid = p.dirpath().relto(self.config.rootdir)
- if p.sep != "/":
- nodeid = nodeid.replace(p.sep, "/")
- self.parsefactories(plugin, nodeid)
-
- def _getautousenames(self, nodeid):
- """ return a tuple of fixture names to be used. """
- autousenames = []
- for baseid, basenames in self._nodeid_and_autousenames:
- if nodeid.startswith(baseid):
- if baseid:
- i = len(baseid)
- nextchar = nodeid[i:i+1]
- if nextchar and nextchar not in ":/":
- continue
- autousenames.extend(basenames)
- # make sure autousenames are sorted by scope, scopenum 0 is session
- autousenames.sort(
- key=lambda x: self._arg2fixturedefs[x][-1].scopenum)
- return autousenames
-
- def getfixtureclosure(self, fixturenames, parentnode):
- # collect the closure of all fixtures , starting with the given
- # fixturenames as the initial set. As we have to visit all
- # factory definitions anyway, we also return a arg2fixturedefs
- # mapping so that the caller can reuse it and does not have
- # to re-discover fixturedefs again for each fixturename
- # (discovering matching fixtures for a given name/node is expensive)
-
- parentid = parentnode.nodeid
- fixturenames_closure = self._getautousenames(parentid)
- def merge(otherlist):
- for arg in otherlist:
- if arg not in fixturenames_closure:
- fixturenames_closure.append(arg)
- merge(fixturenames)
- arg2fixturedefs = {}
- lastlen = -1
- while lastlen != len(fixturenames_closure):
- lastlen = len(fixturenames_closure)
- for argname in fixturenames_closure:
- if argname in arg2fixturedefs:
- continue
- fixturedefs = self.getfixturedefs(argname, parentid)
- if fixturedefs:
- arg2fixturedefs[argname] = fixturedefs
- merge(fixturedefs[-1].argnames)
- return fixturenames_closure, arg2fixturedefs
-
- def pytest_generate_tests(self, metafunc):
- for argname in metafunc.fixturenames:
- faclist = metafunc._arg2fixturedefs.get(argname)
- if faclist:
- fixturedef = faclist[-1]
- if fixturedef.params is not None:
- func_params = getattr(getattr(metafunc.function, 'parametrize', None), 'args', [[None]])
- # skip directly parametrized arguments
- argnames = func_params[0]
- if not isinstance(argnames, (tuple, list)):
- argnames = [x.strip() for x in argnames.split(",") if x.strip()]
- if argname not in func_params and argname not in argnames:
- metafunc.parametrize(argname, fixturedef.params,
- indirect=True, scope=fixturedef.scope,
- ids=fixturedef.ids)
- else:
- continue # will raise FixtureLookupError at setup time
-
- def pytest_collection_modifyitems(self, items):
- # separate parametrized setups
- items[:] = reorder_items(items)
-
- def parsefactories(self, node_or_obj, nodeid=NOTSET, unittest=False):
- if nodeid is not NOTSET:
- holderobj = node_or_obj
- else:
- holderobj = node_or_obj.obj
- nodeid = node_or_obj.nodeid
- if holderobj in self._holderobjseen:
- return
- self._holderobjseen.add(holderobj)
- autousenames = []
- for name in dir(holderobj):
- obj = getattr(holderobj, name, None)
- # fixture functions have a pytest_funcarg__ prefix (pre-2.3 style)
- # or are "@pytest.fixture" marked
- marker = getfixturemarker(obj)
- if marker is None:
- if not name.startswith(self._argprefix):
- continue
- if not callable(obj):
- continue
- marker = defaultfuncargprefixmarker
- name = name[len(self._argprefix):]
- elif not isinstance(marker, FixtureFunctionMarker):
- # magic globals with __getattr__ might have got us a wrong
- # fixture attribute
- continue
- else:
- assert not name.startswith(self._argprefix)
- fixturedef = FixtureDef(self, nodeid, name, obj,
- marker.scope, marker.params,
- yieldctx=marker.yieldctx,
- unittest=unittest, ids=marker.ids)
- faclist = self._arg2fixturedefs.setdefault(name, [])
- if fixturedef.has_location:
- faclist.append(fixturedef)
- else:
- # fixturedefs with no location are at the front
- # so this inserts the current fixturedef after the
- # existing fixturedefs from external plugins but
- # before the fixturedefs provided in conftests.
- i = len([f for f in faclist if not f.has_location])
- faclist.insert(i, fixturedef)
- if marker.autouse:
- autousenames.append(name)
- if autousenames:
- self._nodeid_and_autousenames.append((nodeid or '', autousenames))
-
- def getfixturedefs(self, argname, nodeid):
- try:
- fixturedefs = self._arg2fixturedefs[argname]
- except KeyError:
- return None
- else:
- return tuple(self._matchfactories(fixturedefs, nodeid))
-
- def _matchfactories(self, fixturedefs, nodeid):
- for fixturedef in fixturedefs:
- if nodeid.startswith(fixturedef.baseid):
- yield fixturedef
-
-
-def fail_fixturefunc(fixturefunc, msg):
- fs, lineno = getfslineno(fixturefunc)
- location = "%s:%s" % (fs, lineno+1)
- source = _pytest._code.Source(fixturefunc)
- pytest.fail(msg + ":\n\n" + str(source.indent()) + "\n" + location,
- pytrace=False)
-
-def call_fixture_func(fixturefunc, request, kwargs, yieldctx):
- if yieldctx:
- if not is_generator(fixturefunc):
- fail_fixturefunc(fixturefunc,
- msg="yield_fixture requires yield statement in function")
- iter = fixturefunc(**kwargs)
- next = getattr(iter, "__next__", None)
- if next is None:
- next = getattr(iter, "next")
- res = next()
- def teardown():
- try:
- next()
- except StopIteration:
- pass
- else:
- fail_fixturefunc(fixturefunc,
- "yield_fixture function has more than one 'yield'")
- request.addfinalizer(teardown)
- else:
- if is_generator(fixturefunc):
- fail_fixturefunc(fixturefunc,
- msg="pytest.fixture functions cannot use ``yield``. "
- "Instead write and return an inner function/generator "
- "and let the consumer call and iterate over it.")
- res = fixturefunc(**kwargs)
- return res
-
-class FixtureDef:
- """ A container for a factory definition. """
- def __init__(self, fixturemanager, baseid, argname, func, scope, params,
- yieldctx, unittest=False, ids=None):
- self._fixturemanager = fixturemanager
- self.baseid = baseid or ''
- self.has_location = baseid is not None
- self.func = func
- self.argname = argname
- self.scope = scope
- self.scopenum = scopes.index(scope or "function")
- self.params = params
- startindex = unittest and 1 or None
- self.argnames = getfuncargnames(func, startindex=startindex)
- self.yieldctx = yieldctx
- self.unittest = unittest
- self.ids = ids
- self._finalizer = []
-
- def addfinalizer(self, finalizer):
- self._finalizer.append(finalizer)
-
- def finish(self):
- try:
- while self._finalizer:
- func = self._finalizer.pop()
- func()
- finally:
- # even if finalization fails, we invalidate
- # the cached fixture value
- if hasattr(self, "cached_result"):
- del self.cached_result
-
- def execute(self, request):
- # get required arguments and register our own finish()
- # with their finalization
- kwargs = {}
- for argname in self.argnames:
- fixturedef = request._get_active_fixturedef(argname)
- result, arg_cache_key, exc = fixturedef.cached_result
- request._check_scope(argname, request.scope, fixturedef.scope)
- kwargs[argname] = result
- if argname != "request":
- fixturedef.addfinalizer(self.finish)
-
- my_cache_key = request.param_index
- cached_result = getattr(self, "cached_result", None)
- if cached_result is not None:
- result, cache_key, err = cached_result
- if my_cache_key == cache_key:
- if err is not None:
- py.builtin._reraise(*err)
- else:
- return result
- # we have a previous but differently parametrized fixture instance
- # so we need to tear it down before creating a new one
- self.finish()
- assert not hasattr(self, "cached_result")
-
- fixturefunc = self.func
-
- if self.unittest:
- if request.instance is not None:
- # bind the unbound method to the TestCase instance
- fixturefunc = self.func.__get__(request.instance)
- else:
- # the fixture function needs to be bound to the actual
- # request.instance so that code working with "self" behaves
- # as expected.
- if request.instance is not None:
- fixturefunc = getimfunc(self.func)
- if fixturefunc != self.func:
- fixturefunc = fixturefunc.__get__(request.instance)
-
- try:
- result = call_fixture_func(fixturefunc, request, kwargs,
- self.yieldctx)
- except Exception:
- self.cached_result = (None, my_cache_key, sys.exc_info())
- raise
- self.cached_result = (result, my_cache_key, None)
- return result
-
- def __repr__(self):
- return ("<FixtureDef name=%r scope=%r baseid=%r >" %
- (self.argname, self.scope, self.baseid))
-
-def num_mock_patch_args(function):
- """ return number of arguments used up by mock arguments (if any) """
- patchings = getattr(function, "patchings", None)
- if not patchings:
- return 0
- mock = sys.modules.get("mock", sys.modules.get("unittest.mock", None))
- if mock is not None:
- return len([p for p in patchings
- if not p.attribute_name and p.new is mock.DEFAULT])
- return len(patchings)
-
-
-def getfuncargnames(function, startindex=None):
- # XXX merge with main.py's varnames
- #assert not isclass(function)
- realfunction = function
- while hasattr(realfunction, "__wrapped__"):
- realfunction = realfunction.__wrapped__
- if startindex is None:
- startindex = inspect.ismethod(function) and 1 or 0
- if realfunction != function:
- startindex += num_mock_patch_args(function)
- function = realfunction
- if isinstance(function, functools.partial):
- argnames = inspect.getargs(_pytest._code.getrawcode(function.func))[0]
- partial = function
- argnames = argnames[len(partial.args):]
- if partial.keywords:
- for kw in partial.keywords:
- argnames.remove(kw)
- else:
- argnames = inspect.getargs(_pytest._code.getrawcode(function))[0]
- defaults = getattr(function, 'func_defaults',
- getattr(function, '__defaults__', None)) or ()
- numdefaults = len(defaults)
- if numdefaults:
- return tuple(argnames[startindex:-numdefaults])
- return tuple(argnames[startindex:])
-
-# algorithm for sorting on a per-parametrized resource setup basis
-# it is called for scopenum==0 (session) first and performs sorting
-# down to the lower scopes such as to minimize number of "high scope"
-# setups and teardowns
-
-def reorder_items(items):
- argkeys_cache = {}
- for scopenum in range(0, scopenum_function):
- argkeys_cache[scopenum] = d = {}
- for item in items:
- keys = set(get_parametrized_fixture_keys(item, scopenum))
- if keys:
- d[item] = keys
- return reorder_items_atscope(items, set(), argkeys_cache, 0)
-
-def reorder_items_atscope(items, ignore, argkeys_cache, scopenum):
- if scopenum >= scopenum_function or len(items) < 3:
- return items
- items_done = []
- while 1:
- items_before, items_same, items_other, newignore = \
- slice_items(items, ignore, argkeys_cache[scopenum])
- items_before = reorder_items_atscope(
- items_before, ignore, argkeys_cache,scopenum+1)
- if items_same is None:
- # nothing to reorder in this scope
- assert items_other is None
- return items_done + items_before
- items_done.extend(items_before)
- items = items_same + items_other
- ignore = newignore
-
-
-def slice_items(items, ignore, scoped_argkeys_cache):
- # we pick the first item which uses a fixture instance in the
- # requested scope and which we haven't seen yet. We slice the input
- # items list into a list of items_nomatch, items_same and
- # items_other
- if scoped_argkeys_cache: # do we need to do work at all?
- it = iter(items)
- # first find a slicing key
- for i, item in enumerate(it):
- argkeys = scoped_argkeys_cache.get(item)
- if argkeys is not None:
- argkeys = argkeys.difference(ignore)
- if argkeys: # found a slicing key
- slicing_argkey = argkeys.pop()
- items_before = items[:i]
- items_same = [item]
- items_other = []
- # now slice the remainder of the list
- for item in it:
- argkeys = scoped_argkeys_cache.get(item)
- if argkeys and slicing_argkey in argkeys and \
- slicing_argkey not in ignore:
- items_same.append(item)
- else:
- items_other.append(item)
- newignore = ignore.copy()
- newignore.add(slicing_argkey)
- return (items_before, items_same, items_other, newignore)
- return items, None, None, None
-
-def get_parametrized_fixture_keys(item, scopenum):
- """ return list of keys for all parametrized arguments which match
- the specified scope. """
- assert scopenum < scopenum_function # function
- try:
- cs = item.callspec
- except AttributeError:
- pass
- else:
- # cs.indictes.items() is random order of argnames but
- # then again different functions (items) can change order of
- # arguments so it doesn't matter much probably
- for argname, param_index in cs.indices.items():
- if cs._arg2scopenum[argname] != scopenum:
- continue
- if scopenum == 0: # session
- key = (argname, param_index)
- elif scopenum == 1: # module
- key = (argname, param_index, item.fspath)
- elif scopenum == 2: # class
- key = (argname, param_index, item.fspath, item.cls)
- yield key
-
-
-def xunitsetup(obj, name):
- meth = getattr(obj, name, None)
- if getfixturemarker(meth) is None:
- return meth
-
-def getfixturemarker(obj):
- """ return fixturemarker or None if it doesn't exist or raised
- exceptions."""
- try:
- return getattr(obj, "_pytestfixturefunction", None)
- except KeyboardInterrupt:
- raise
- except Exception:
- # some objects raise errors like request (from flask import request)
- # we don't expect them to be fixture functions
- return None
-
-scopename2class = {
- 'class': Class,
- 'module': Module,
- 'function': pytest.Item,
-}
-def get_scope_node(node, scope):
- cls = scopename2class.get(scope)
- if cls is None:
- if scope == "session":
- return node.session
- raise ValueError("unknown scope")
- return node.getparent(cls)
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/recwarn.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/recwarn.py
deleted file mode 100644
index a89474c..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/recwarn.py
+++ /dev/null
@@ -1,221 +0,0 @@
-""" recording warnings during test function execution. """
-
-import inspect
-
-import _pytest._code
-import py
-import sys
-import warnings
-import pytest
-
-
-@pytest.yield_fixture
-def recwarn(request):
- """Return a WarningsRecorder instance that provides these methods:
-
- * ``pop(category=None)``: return last warning matching the category.
- * ``clear()``: clear list of warnings
-
- See http://docs.python.org/library/warnings.html for information
- on warning categories.
- """
- wrec = WarningsRecorder()
- with wrec:
- warnings.simplefilter('default')
- yield wrec
-
-
-def pytest_namespace():
- return {'deprecated_call': deprecated_call,
- 'warns': warns}
-
-
-def deprecated_call(func=None, *args, **kwargs):
- """ assert that calling ``func(*args, **kwargs)`` triggers a
- ``DeprecationWarning`` or ``PendingDeprecationWarning``.
-
- This function can be used as a context manager::
-
- >>> with deprecated_call():
- ... myobject.deprecated_method()
-
- Note: we cannot use WarningsRecorder here because it is still subject
- to the mechanism that prevents warnings of the same type from being
- triggered twice for the same module. See #1190.
- """
- if not func:
- return WarningsChecker(expected_warning=DeprecationWarning)
-
- categories = []
-
- def warn_explicit(message, category, *args, **kwargs):
- categories.append(category)
- old_warn_explicit(message, category, *args, **kwargs)
-
- def warn(message, category=None, *args, **kwargs):
- if isinstance(message, Warning):
- categories.append(message.__class__)
- else:
- categories.append(category)
- old_warn(message, category, *args, **kwargs)
-
- old_warn = warnings.warn
- old_warn_explicit = warnings.warn_explicit
- warnings.warn_explicit = warn_explicit
- warnings.warn = warn
- try:
- ret = func(*args, **kwargs)
- finally:
- warnings.warn_explicit = old_warn_explicit
- warnings.warn = old_warn
- deprecation_categories = (DeprecationWarning, PendingDeprecationWarning)
- if not any(issubclass(c, deprecation_categories) for c in categories):
- __tracebackhide__ = True
- raise AssertionError("%r did not produce DeprecationWarning" % (func,))
- return ret
-
-
-def warns(expected_warning, *args, **kwargs):
- """Assert that code raises a particular class of warning.
-
- Specifically, the input @expected_warning can be a warning class or
- tuple of warning classes, and the code must return that warning
- (if a single class) or one of those warnings (if a tuple).
-
- This helper produces a list of ``warnings.WarningMessage`` objects,
- one for each warning raised.
-
- This function can be used as a context manager, or any of the other ways
- ``pytest.raises`` can be used::
-
- >>> with warns(RuntimeWarning):
- ... warnings.warn("my warning", RuntimeWarning)
- """
- wcheck = WarningsChecker(expected_warning)
- if not args:
- return wcheck
- elif isinstance(args[0], str):
- code, = args
- assert isinstance(code, str)
- frame = sys._getframe(1)
- loc = frame.f_locals.copy()
- loc.update(kwargs)
-
- with wcheck:
- code = _pytest._code.Source(code).compile()
- py.builtin.exec_(code, frame.f_globals, loc)
- else:
- func = args[0]
- with wcheck:
- return func(*args[1:], **kwargs)
-
-
-class RecordedWarning(object):
- def __init__(self, message, category, filename, lineno, file, line):
- self.message = message
- self.category = category
- self.filename = filename
- self.lineno = lineno
- self.file = file
- self.line = line
-
-
-class WarningsRecorder(object):
- """A context manager to record raised warnings.
-
- Adapted from `warnings.catch_warnings`.
- """
-
- def __init__(self, module=None):
- self._module = sys.modules['warnings'] if module is None else module
- self._entered = False
- self._list = []
-
- @property
- def list(self):
- """The list of recorded warnings."""
- return self._list
-
- def __getitem__(self, i):
- """Get a recorded warning by index."""
- return self._list[i]
-
- def __iter__(self):
- """Iterate through the recorded warnings."""
- return iter(self._list)
-
- def __len__(self):
- """The number of recorded warnings."""
- return len(self._list)
-
- def pop(self, cls=Warning):
- """Pop the first recorded warning, raise exception if not exists."""
- for i, w in enumerate(self._list):
- if issubclass(w.category, cls):
- return self._list.pop(i)
- __tracebackhide__ = True
- raise AssertionError("%r not found in warning list" % cls)
-
- def clear(self):
- """Clear the list of recorded warnings."""
- self._list[:] = []
-
- def __enter__(self):
- if self._entered:
- __tracebackhide__ = True
- raise RuntimeError("Cannot enter %r twice" % self)
- self._entered = True
- self._filters = self._module.filters
- self._module.filters = self._filters[:]
- self._showwarning = self._module.showwarning
-
- def showwarning(message, category, filename, lineno,
- file=None, line=None):
- self._list.append(RecordedWarning(
- message, category, filename, lineno, file, line))
-
- # still perform old showwarning functionality
- self._showwarning(
- message, category, filename, lineno, file=file, line=line)
-
- self._module.showwarning = showwarning
-
- # allow the same warning to be raised more than once
-
- self._module.simplefilter('always')
- return self
-
- def __exit__(self, *exc_info):
- if not self._entered:
- __tracebackhide__ = True
- raise RuntimeError("Cannot exit %r without entering first" % self)
- self._module.filters = self._filters
- self._module.showwarning = self._showwarning
-
-
-class WarningsChecker(WarningsRecorder):
- def __init__(self, expected_warning=None, module=None):
- super(WarningsChecker, self).__init__(module=module)
-
- msg = ("exceptions must be old-style classes or "
- "derived from Warning, not %s")
- if isinstance(expected_warning, tuple):
- for exc in expected_warning:
- if not inspect.isclass(exc):
- raise TypeError(msg % type(exc))
- elif inspect.isclass(expected_warning):
- expected_warning = (expected_warning,)
- elif expected_warning is not None:
- raise TypeError(msg % type(expected_warning))
-
- self.expected_warning = expected_warning
-
- def __exit__(self, *exc_info):
- super(WarningsChecker, self).__exit__(*exc_info)
-
- # only check if we're not currently handling an exception
- if all(a is None for a in exc_info):
- if self.expected_warning is not None:
- if not any(r.category in self.expected_warning for r in self):
- __tracebackhide__ = True
- pytest.fail("DID NOT WARN")
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/resultlog.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/resultlog.py
deleted file mode 100644
index 3670f02..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/resultlog.py
+++ /dev/null
@@ -1,104 +0,0 @@
-""" log machine-parseable test session result information in a plain
-text file.
-"""
-
-import py
-import os
-
-def pytest_addoption(parser):
- group = parser.getgroup("terminal reporting", "resultlog plugin options")
- group.addoption('--resultlog', '--result-log', action="store",
- metavar="path", default=None,
- help="path for machine-readable result log.")
-
-def pytest_configure(config):
- resultlog = config.option.resultlog
- # prevent opening resultlog on slave nodes (xdist)
- if resultlog and not hasattr(config, 'slaveinput'):
- dirname = os.path.dirname(os.path.abspath(resultlog))
- if not os.path.isdir(dirname):
- os.makedirs(dirname)
- logfile = open(resultlog, 'w', 1) # line buffered
- config._resultlog = ResultLog(config, logfile)
- config.pluginmanager.register(config._resultlog)
-
-def pytest_unconfigure(config):
- resultlog = getattr(config, '_resultlog', None)
- if resultlog:
- resultlog.logfile.close()
- del config._resultlog
- config.pluginmanager.unregister(resultlog)
-
-def generic_path(item):
- chain = item.listchain()
- gpath = [chain[0].name]
- fspath = chain[0].fspath
- fspart = False
- for node in chain[1:]:
- newfspath = node.fspath
- if newfspath == fspath:
- if fspart:
- gpath.append(':')
- fspart = False
- else:
- gpath.append('.')
- else:
- gpath.append('/')
- fspart = True
- name = node.name
- if name[0] in '([':
- gpath.pop()
- gpath.append(name)
- fspath = newfspath
- return ''.join(gpath)
-
-class ResultLog(object):
- def __init__(self, config, logfile):
- self.config = config
- self.logfile = logfile # preferably line buffered
-
- def write_log_entry(self, testpath, lettercode, longrepr):
- py.builtin.print_("%s %s" % (lettercode, testpath), file=self.logfile)
- for line in longrepr.splitlines():
- py.builtin.print_(" %s" % line, file=self.logfile)
-
- def log_outcome(self, report, lettercode, longrepr):
- testpath = getattr(report, 'nodeid', None)
- if testpath is None:
- testpath = report.fspath
- self.write_log_entry(testpath, lettercode, longrepr)
-
- def pytest_runtest_logreport(self, report):
- if report.when != "call" and report.passed:
- return
- res = self.config.hook.pytest_report_teststatus(report=report)
- code = res[1]
- if code == 'x':
- longrepr = str(report.longrepr)
- elif code == 'X':
- longrepr = ''
- elif report.passed:
- longrepr = ""
- elif report.failed:
- longrepr = str(report.longrepr)
- elif report.skipped:
- longrepr = str(report.longrepr[2])
- self.log_outcome(report, code, longrepr)
-
- def pytest_collectreport(self, report):
- if not report.passed:
- if report.failed:
- code = "F"
- longrepr = str(report.longrepr)
- else:
- assert report.skipped
- code = "S"
- longrepr = "%s:%d: %s" % report.longrepr
- self.log_outcome(report, code, longrepr)
-
- def pytest_internalerror(self, excrepr):
- reprcrash = getattr(excrepr, 'reprcrash', None)
- path = getattr(reprcrash, "path", None)
- if path is None:
- path = "cwd:%s" % py.path.local()
- self.write_log_entry(path, '!', str(excrepr))
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/runner.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/runner.py
deleted file mode 100644
index cde94c8..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/runner.py
+++ /dev/null
@@ -1,515 +0,0 @@
-""" basic collect and runtest protocol implementations """
-import bdb
-import sys
-from time import time
-
-import py
-import pytest
-from _pytest._code.code import TerminalRepr, ExceptionInfo
-
-
-def pytest_namespace():
- return {
- 'fail' : fail,
- 'skip' : skip,
- 'importorskip' : importorskip,
- 'exit' : exit,
- }
-
-#
-# pytest plugin hooks
-
-def pytest_addoption(parser):
- group = parser.getgroup("terminal reporting", "reporting", after="general")
- group.addoption('--durations',
- action="store", type=int, default=None, metavar="N",
- help="show N slowest setup/test durations (N=0 for all)."),
-
-def pytest_terminal_summary(terminalreporter):
- durations = terminalreporter.config.option.durations
- if durations is None:
- return
- tr = terminalreporter
- dlist = []
- for replist in tr.stats.values():
- for rep in replist:
- if hasattr(rep, 'duration'):
- dlist.append(rep)
- if not dlist:
- return
- dlist.sort(key=lambda x: x.duration)
- dlist.reverse()
- if not durations:
- tr.write_sep("=", "slowest test durations")
- else:
- tr.write_sep("=", "slowest %s test durations" % durations)
- dlist = dlist[:durations]
-
- for rep in dlist:
- nodeid = rep.nodeid.replace("::()::", "::")
- tr.write_line("%02.2fs %-8s %s" %
- (rep.duration, rep.when, nodeid))
-
-def pytest_sessionstart(session):
- session._setupstate = SetupState()
-def pytest_sessionfinish(session):
- session._setupstate.teardown_all()
-
-class NodeInfo:
- def __init__(self, location):
- self.location = location
-
-def pytest_runtest_protocol(item, nextitem):
- item.ihook.pytest_runtest_logstart(
- nodeid=item.nodeid, location=item.location,
- )
- runtestprotocol(item, nextitem=nextitem)
- return True
-
-def runtestprotocol(item, log=True, nextitem=None):
- hasrequest = hasattr(item, "_request")
- if hasrequest and not item._request:
- item._initrequest()
- rep = call_and_report(item, "setup", log)
- reports = [rep]
- if rep.passed:
- reports.append(call_and_report(item, "call", log))
- reports.append(call_and_report(item, "teardown", log,
- nextitem=nextitem))
- # after all teardown hooks have been called
- # want funcargs and request info to go away
- if hasrequest:
- item._request = False
- item.funcargs = None
- return reports
-
-def pytest_runtest_setup(item):
- item.session._setupstate.prepare(item)
-
-def pytest_runtest_call(item):
- try:
- item.runtest()
- except Exception:
- # Store trace info to allow postmortem debugging
- type, value, tb = sys.exc_info()
- tb = tb.tb_next # Skip *this* frame
- sys.last_type = type
- sys.last_value = value
- sys.last_traceback = tb
- del tb # Get rid of it in this namespace
- raise
-
-def pytest_runtest_teardown(item, nextitem):
- item.session._setupstate.teardown_exact(item, nextitem)
-
-def pytest_report_teststatus(report):
- if report.when in ("setup", "teardown"):
- if report.failed:
- # category, shortletter, verbose-word
- return "error", "E", "ERROR"
- elif report.skipped:
- return "skipped", "s", "SKIPPED"
- else:
- return "", "", ""
-
-
-#
-# Implementation
-
-def call_and_report(item, when, log=True, **kwds):
- call = call_runtest_hook(item, when, **kwds)
- hook = item.ihook
- report = hook.pytest_runtest_makereport(item=item, call=call)
- if log:
- hook.pytest_runtest_logreport(report=report)
- if check_interactive_exception(call, report):
- hook.pytest_exception_interact(node=item, call=call, report=report)
- return report
-
-def check_interactive_exception(call, report):
- return call.excinfo and not (
- hasattr(report, "wasxfail") or
- call.excinfo.errisinstance(skip.Exception) or
- call.excinfo.errisinstance(bdb.BdbQuit))
-
-def call_runtest_hook(item, when, **kwds):
- hookname = "pytest_runtest_" + when
- ihook = getattr(item.ihook, hookname)
- return CallInfo(lambda: ihook(item=item, **kwds), when=when)
-
-class CallInfo:
- """ Result/Exception info a function invocation. """
- #: None or ExceptionInfo object.
- excinfo = None
- def __init__(self, func, when):
- #: context of invocation: one of "setup", "call",
- #: "teardown", "memocollect"
- self.when = when
- self.start = time()
- try:
- self.result = func()
- except KeyboardInterrupt:
- self.stop = time()
- raise
- except:
- self.excinfo = ExceptionInfo()
- self.stop = time()
-
- def __repr__(self):
- if self.excinfo:
- status = "exception: %s" % str(self.excinfo.value)
- else:
- status = "result: %r" % (self.result,)
- return "<CallInfo when=%r %s>" % (self.when, status)
-
-def getslaveinfoline(node):
- try:
- return node._slaveinfocache
- except AttributeError:
- d = node.slaveinfo
- ver = "%s.%s.%s" % d['version_info'][:3]
- node._slaveinfocache = s = "[%s] %s -- Python %s %s" % (
- d['id'], d['sysplatform'], ver, d['executable'])
- return s
-
-class BaseReport(object):
-
- def __init__(self, **kw):
- self.__dict__.update(kw)
-
- def toterminal(self, out):
- if hasattr(self, 'node'):
- out.line(getslaveinfoline(self.node))
-
- longrepr = self.longrepr
- if longrepr is None:
- return
-
- if hasattr(longrepr, 'toterminal'):
- longrepr.toterminal(out)
- else:
- try:
- out.line(longrepr)
- except UnicodeEncodeError:
- out.line("<unprintable longrepr>")
-
- def get_sections(self, prefix):
- for name, content in self.sections:
- if name.startswith(prefix):
- yield prefix, content
-
- passed = property(lambda x: x.outcome == "passed")
- failed = property(lambda x: x.outcome == "failed")
- skipped = property(lambda x: x.outcome == "skipped")
-
- @property
- def fspath(self):
- return self.nodeid.split("::")[0]
-
-def pytest_runtest_makereport(item, call):
- when = call.when
- duration = call.stop-call.start
- keywords = dict([(x,1) for x in item.keywords])
- excinfo = call.excinfo
- sections = []
- if not call.excinfo:
- outcome = "passed"
- longrepr = None
- else:
- if not isinstance(excinfo, ExceptionInfo):
- outcome = "failed"
- longrepr = excinfo
- elif excinfo.errisinstance(pytest.skip.Exception):
- outcome = "skipped"
- r = excinfo._getreprcrash()
- longrepr = (str(r.path), r.lineno, r.message)
- else:
- outcome = "failed"
- if call.when == "call":
- longrepr = item.repr_failure(excinfo)
- else: # exception in setup or teardown
- longrepr = item._repr_failure_py(excinfo,
- style=item.config.option.tbstyle)
- for rwhen, key, content in item._report_sections:
- sections.append(("Captured %s %s" %(key, rwhen), content))
- return TestReport(item.nodeid, item.location,
- keywords, outcome, longrepr, when,
- sections, duration)
-
-class TestReport(BaseReport):
- """ Basic test report object (also used for setup and teardown calls if
- they fail).
- """
- def __init__(self, nodeid, location, keywords, outcome,
- longrepr, when, sections=(), duration=0, **extra):
- #: normalized collection node id
- self.nodeid = nodeid
-
- #: a (filesystempath, lineno, domaininfo) tuple indicating the
- #: actual location of a test item - it might be different from the
- #: collected one e.g. if a method is inherited from a different module.
- self.location = location
-
- #: a name -> value dictionary containing all keywords and
- #: markers associated with a test invocation.
- self.keywords = keywords
-
- #: test outcome, always one of "passed", "failed", "skipped".
- self.outcome = outcome
-
- #: None or a failure representation.
- self.longrepr = longrepr
-
- #: one of 'setup', 'call', 'teardown' to indicate runtest phase.
- self.when = when
-
- #: list of (secname, data) extra information which needs to
- #: marshallable
- self.sections = list(sections)
-
- #: time it took to run just the test
- self.duration = duration
-
- self.__dict__.update(extra)
-
- def __repr__(self):
- return "<TestReport %r when=%r outcome=%r>" % (
- self.nodeid, self.when, self.outcome)
-
-class TeardownErrorReport(BaseReport):
- outcome = "failed"
- when = "teardown"
- def __init__(self, longrepr, **extra):
- self.longrepr = longrepr
- self.sections = []
- self.__dict__.update(extra)
-
-def pytest_make_collect_report(collector):
- call = CallInfo(collector._memocollect, "memocollect")
- longrepr = None
- if not call.excinfo:
- outcome = "passed"
- else:
- from _pytest import nose
- skip_exceptions = (Skipped,) + nose.get_skip_exceptions()
- if call.excinfo.errisinstance(skip_exceptions):
- outcome = "skipped"
- r = collector._repr_failure_py(call.excinfo, "line").reprcrash
- longrepr = (str(r.path), r.lineno, r.message)
- else:
- outcome = "failed"
- errorinfo = collector.repr_failure(call.excinfo)
- if not hasattr(errorinfo, "toterminal"):
- errorinfo = CollectErrorRepr(errorinfo)
- longrepr = errorinfo
- rep = CollectReport(collector.nodeid, outcome, longrepr,
- getattr(call, 'result', None))
- rep.call = call # see collect_one_node
- return rep
-
-
-class CollectReport(BaseReport):
- def __init__(self, nodeid, outcome, longrepr, result,
- sections=(), **extra):
- self.nodeid = nodeid
- self.outcome = outcome
- self.longrepr = longrepr
- self.result = result or []
- self.sections = list(sections)
- self.__dict__.update(extra)
-
- @property
- def location(self):
- return (self.fspath, None, self.fspath)
-
- def __repr__(self):
- return "<CollectReport %r lenresult=%s outcome=%r>" % (
- self.nodeid, len(self.result), self.outcome)
-
-class CollectErrorRepr(TerminalRepr):
- def __init__(self, msg):
- self.longrepr = msg
- def toterminal(self, out):
- out.line(self.longrepr, red=True)
-
-class SetupState(object):
- """ shared state for setting up/tearing down test items or collectors. """
- def __init__(self):
- self.stack = []
- self._finalizers = {}
-
- def addfinalizer(self, finalizer, colitem):
- """ attach a finalizer to the given colitem.
- if colitem is None, this will add a finalizer that
- is called at the end of teardown_all().
- """
- assert colitem and not isinstance(colitem, tuple)
- assert py.builtin.callable(finalizer)
- #assert colitem in self.stack # some unit tests don't setup stack :/
- self._finalizers.setdefault(colitem, []).append(finalizer)
-
- def _pop_and_teardown(self):
- colitem = self.stack.pop()
- self._teardown_with_finalization(colitem)
-
- def _callfinalizers(self, colitem):
- finalizers = self._finalizers.pop(colitem, None)
- exc = None
- while finalizers:
- fin = finalizers.pop()
- try:
- fin()
- except Exception:
- # XXX Only first exception will be seen by user,
- # ideally all should be reported.
- if exc is None:
- exc = sys.exc_info()
- if exc:
- py.builtin._reraise(*exc)
-
- def _teardown_with_finalization(self, colitem):
- self._callfinalizers(colitem)
- if hasattr(colitem, "teardown"):
- colitem.teardown()
- for colitem in self._finalizers:
- assert colitem is None or colitem in self.stack \
- or isinstance(colitem, tuple)
-
- def teardown_all(self):
- while self.stack:
- self._pop_and_teardown()
- for key in list(self._finalizers):
- self._teardown_with_finalization(key)
- assert not self._finalizers
-
- def teardown_exact(self, item, nextitem):
- needed_collectors = nextitem and nextitem.listchain() or []
- self._teardown_towards(needed_collectors)
-
- def _teardown_towards(self, needed_collectors):
- while self.stack:
- if self.stack == needed_collectors[:len(self.stack)]:
- break
- self._pop_and_teardown()
-
- def prepare(self, colitem):
- """ setup objects along the collector chain to the test-method
- and teardown previously setup objects."""
- needed_collectors = colitem.listchain()
- self._teardown_towards(needed_collectors)
-
- # check if the last collection node has raised an error
- for col in self.stack:
- if hasattr(col, '_prepare_exc'):
- py.builtin._reraise(*col._prepare_exc)
- for col in needed_collectors[len(self.stack):]:
- self.stack.append(col)
- try:
- col.setup()
- except Exception:
- col._prepare_exc = sys.exc_info()
- raise
-
-def collect_one_node(collector):
- ihook = collector.ihook
- ihook.pytest_collectstart(collector=collector)
- rep = ihook.pytest_make_collect_report(collector=collector)
- call = rep.__dict__.pop("call", None)
- if call and check_interactive_exception(call, rep):
- ihook.pytest_exception_interact(node=collector, call=call, report=rep)
- return rep
-
-
-# =============================================================
-# Test OutcomeExceptions and helpers for creating them.
-
-
-class OutcomeException(Exception):
- """ OutcomeException and its subclass instances indicate and
- contain info about test and collection outcomes.
- """
- def __init__(self, msg=None, pytrace=True):
- Exception.__init__(self, msg)
- self.msg = msg
- self.pytrace = pytrace
-
- def __repr__(self):
- if self.msg:
- val = self.msg
- if isinstance(val, bytes):
- val = py._builtin._totext(val, errors='replace')
- return val
- return "<%s instance>" %(self.__class__.__name__,)
- __str__ = __repr__
-
-class Skipped(OutcomeException):
- # XXX hackish: on 3k we fake to live in the builtins
- # in order to have Skipped exception printing shorter/nicer
- __module__ = 'builtins'
-
-class Failed(OutcomeException):
- """ raised from an explicit call to pytest.fail() """
- __module__ = 'builtins'
-
-class Exit(KeyboardInterrupt):
- """ raised for immediate program exits (no tracebacks/summaries)"""
- def __init__(self, msg="unknown reason"):
- self.msg = msg
- KeyboardInterrupt.__init__(self, msg)
-
-# exposed helper methods
-
-def exit(msg):
- """ exit testing process as if KeyboardInterrupt was triggered. """
- __tracebackhide__ = True
- raise Exit(msg)
-
-exit.Exception = Exit
-
-def skip(msg=""):
- """ skip an executing test with the given message. Note: it's usually
- better to use the pytest.mark.skipif marker to declare a test to be
- skipped under certain conditions like mismatching platforms or
- dependencies. See the pytest_skipping plugin for details.
- """
- __tracebackhide__ = True
- raise Skipped(msg=msg)
-skip.Exception = Skipped
-
-def fail(msg="", pytrace=True):
- """ explicitly fail an currently-executing test with the given Message.
-
- :arg pytrace: if false the msg represents the full failure information
- and no python traceback will be reported.
- """
- __tracebackhide__ = True
- raise Failed(msg=msg, pytrace=pytrace)
-fail.Exception = Failed
-
-
-def importorskip(modname, minversion=None):
- """ return imported module if it has at least "minversion" as its
- __version__ attribute. If no minversion is specified the a skip
- is only triggered if the module can not be imported.
- """
- __tracebackhide__ = True
- compile(modname, '', 'eval') # to catch syntaxerrors
- try:
- __import__(modname)
- except ImportError:
- skip("could not import %r" %(modname,))
- mod = sys.modules[modname]
- if minversion is None:
- return mod
- verattr = getattr(mod, '__version__', None)
- if minversion is not None:
- try:
- from pkg_resources import parse_version as pv
- except ImportError:
- skip("we have a required version for %r but can not import "
- "no pkg_resources to parse version strings." %(modname,))
- if verattr is None or pv(verattr) < pv(minversion):
- skip("module %r has __version__ %r, required is: %r" %(
- modname, verattr, minversion))
- return mod
-
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/skipping.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/skipping.py
deleted file mode 100644
index 69157f4..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/skipping.py
+++ /dev/null
@@ -1,354 +0,0 @@
-""" support for skip/xfail functions and markers. """
-import os
-import sys
-import traceback
-
-import py
-import pytest
-from _pytest.mark import MarkInfo, MarkDecorator
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("general")
- group.addoption('--runxfail',
- action="store_true", dest="runxfail", default=False,
- help="run tests even if they are marked xfail")
-
- parser.addini("xfail_strict", "default for the strict parameter of xfail "
- "markers when not given explicitly (default: "
- "False)",
- default=False,
- type="bool")
-
-
-def pytest_configure(config):
- if config.option.runxfail:
- old = pytest.xfail
- config._cleanup.append(lambda: setattr(pytest, "xfail", old))
- def nop(*args, **kwargs):
- pass
- nop.Exception = XFailed
- setattr(pytest, "xfail", nop)
-
- config.addinivalue_line("markers",
- "skipif(condition): skip the given test function if eval(condition) "
- "results in a True value. Evaluation happens within the "
- "module global context. Example: skipif('sys.platform == \"win32\"') "
- "skips the test if we are on the win32 platform. see "
- "http://pytest.org/latest/skipping.html"
- )
- config.addinivalue_line("markers",
- "xfail(condition, reason=None, run=True, raises=None): mark the the test function "
- "as an expected failure if eval(condition) has a True value. "
- "Optionally specify a reason for better reporting and run=False if "
- "you don't even want to execute the test function. If only specific "
- "exception(s) are expected, you can list them in raises, and if the test fails "
- "in other ways, it will be reported as a true failure. "
- "See http://pytest.org/latest/skipping.html"
- )
-
-
-def pytest_namespace():
- return dict(xfail=xfail)
-
-
-class XFailed(pytest.fail.Exception):
- """ raised from an explicit call to pytest.xfail() """
-
-
-def xfail(reason=""):
- """ xfail an executing test or setup functions with the given reason."""
- __tracebackhide__ = True
- raise XFailed(reason)
-xfail.Exception = XFailed
-
-
-class MarkEvaluator:
- def __init__(self, item, name):
- self.item = item
- self.name = name
-
- @property
- def holder(self):
- return self.item.keywords.get(self.name)
-
- def __bool__(self):
- return bool(self.holder)
- __nonzero__ = __bool__
-
- def wasvalid(self):
- return not hasattr(self, 'exc')
-
- def invalidraise(self, exc):
- raises = self.get('raises')
- if not raises:
- return
- return not isinstance(exc, raises)
-
- def istrue(self):
- try:
- return self._istrue()
- except Exception:
- self.exc = sys.exc_info()
- if isinstance(self.exc[1], SyntaxError):
- msg = [" " * (self.exc[1].offset + 4) + "^",]
- msg.append("SyntaxError: invalid syntax")
- else:
- msg = traceback.format_exception_only(*self.exc[:2])
- pytest.fail("Error evaluating %r expression\n"
- " %s\n"
- "%s"
- %(self.name, self.expr, "\n".join(msg)),
- pytrace=False)
-
- def _getglobals(self):
- d = {'os': os, 'sys': sys, 'config': self.item.config}
- func = self.item.obj
- try:
- d.update(func.__globals__)
- except AttributeError:
- d.update(func.func_globals)
- return d
-
- def _istrue(self):
- if hasattr(self, 'result'):
- return self.result
- if self.holder:
- d = self._getglobals()
- if self.holder.args:
- self.result = False
- # "holder" might be a MarkInfo or a MarkDecorator; only
- # MarkInfo keeps track of all parameters it received in an
- # _arglist attribute
- if hasattr(self.holder, '_arglist'):
- arglist = self.holder._arglist
- else:
- arglist = [(self.holder.args, self.holder.kwargs)]
- for args, kwargs in arglist:
- for expr in args:
- self.expr = expr
- if isinstance(expr, py.builtin._basestring):
- result = cached_eval(self.item.config, expr, d)
- else:
- if "reason" not in kwargs:
- # XXX better be checked at collection time
- msg = "you need to specify reason=STRING " \
- "when using booleans as conditions."
- pytest.fail(msg)
- result = bool(expr)
- if result:
- self.result = True
- self.reason = kwargs.get('reason', None)
- self.expr = expr
- return self.result
- else:
- self.result = True
- return getattr(self, 'result', False)
-
- def get(self, attr, default=None):
- return self.holder.kwargs.get(attr, default)
-
- def getexplanation(self):
- expl = getattr(self, 'reason', None) or self.get('reason', None)
- if not expl:
- if not hasattr(self, 'expr'):
- return ""
- else:
- return "condition: " + str(self.expr)
- return expl
-
-
-@pytest.hookimpl(tryfirst=True)
-def pytest_runtest_setup(item):
- # Check if skip or skipif are specified as pytest marks
-
- skipif_info = item.keywords.get('skipif')
- if isinstance(skipif_info, (MarkInfo, MarkDecorator)):
- eval_skipif = MarkEvaluator(item, 'skipif')
- if eval_skipif.istrue():
- item._evalskip = eval_skipif
- pytest.skip(eval_skipif.getexplanation())
-
- skip_info = item.keywords.get('skip')
- if isinstance(skip_info, (MarkInfo, MarkDecorator)):
- item._evalskip = True
- if 'reason' in skip_info.kwargs:
- pytest.skip(skip_info.kwargs['reason'])
- elif skip_info.args:
- pytest.skip(skip_info.args[0])
- else:
- pytest.skip("unconditional skip")
-
- item._evalxfail = MarkEvaluator(item, 'xfail')
- check_xfail_no_run(item)
-
-
-@pytest.mark.hookwrapper
-def pytest_pyfunc_call(pyfuncitem):
- check_xfail_no_run(pyfuncitem)
- outcome = yield
- passed = outcome.excinfo is None
- if passed:
- check_strict_xfail(pyfuncitem)
-
-
-def check_xfail_no_run(item):
- """check xfail(run=False)"""
- if not item.config.option.runxfail:
- evalxfail = item._evalxfail
- if evalxfail.istrue():
- if not evalxfail.get('run', True):
- pytest.xfail("[NOTRUN] " + evalxfail.getexplanation())
-
-
-def check_strict_xfail(pyfuncitem):
- """check xfail(strict=True) for the given PASSING test"""
- evalxfail = pyfuncitem._evalxfail
- if evalxfail.istrue():
- strict_default = pyfuncitem.config.getini('xfail_strict')
- is_strict_xfail = evalxfail.get('strict', strict_default)
- if is_strict_xfail:
- del pyfuncitem._evalxfail
- explanation = evalxfail.getexplanation()
- pytest.fail('[XPASS(strict)] ' + explanation, pytrace=False)
-
-
-@pytest.hookimpl(hookwrapper=True)
-def pytest_runtest_makereport(item, call):
- outcome = yield
- rep = outcome.get_result()
- evalxfail = getattr(item, '_evalxfail', None)
- evalskip = getattr(item, '_evalskip', None)
- # unitttest special case, see setting of _unexpectedsuccess
- if hasattr(item, '_unexpectedsuccess') and rep.when == "call":
- # we need to translate into how pytest encodes xpass
- rep.wasxfail = "reason: " + repr(item._unexpectedsuccess)
- rep.outcome = "failed"
- elif item.config.option.runxfail:
- pass # don't interefere
- elif call.excinfo and call.excinfo.errisinstance(pytest.xfail.Exception):
- rep.wasxfail = "reason: " + call.excinfo.value.msg
- rep.outcome = "skipped"
- elif evalxfail and not rep.skipped and evalxfail.wasvalid() and \
- evalxfail.istrue():
- if call.excinfo:
- if evalxfail.invalidraise(call.excinfo.value):
- rep.outcome = "failed"
- else:
- rep.outcome = "skipped"
- rep.wasxfail = evalxfail.getexplanation()
- elif call.when == "call":
- rep.outcome = "failed" # xpass outcome
- rep.wasxfail = evalxfail.getexplanation()
- elif evalskip is not None and rep.skipped and type(rep.longrepr) is tuple:
- # skipped by mark.skipif; change the location of the failure
- # to point to the item definition, otherwise it will display
- # the location of where the skip exception was raised within pytest
- filename, line, reason = rep.longrepr
- filename, line = item.location[:2]
- rep.longrepr = filename, line, reason
-
-# called by terminalreporter progress reporting
-def pytest_report_teststatus(report):
- if hasattr(report, "wasxfail"):
- if report.skipped:
- return "xfailed", "x", "xfail"
- elif report.failed:
- return "xpassed", "X", ("XPASS", {'yellow': True})
-
-# called by the terminalreporter instance/plugin
-def pytest_terminal_summary(terminalreporter):
- tr = terminalreporter
- if not tr.reportchars:
- #for name in "xfailed skipped failed xpassed":
- # if not tr.stats.get(name, 0):
- # tr.write_line("HINT: use '-r' option to see extra "
- # "summary info about tests")
- # break
- return
-
- lines = []
- for char in tr.reportchars:
- if char == "x":
- show_xfailed(terminalreporter, lines)
- elif char == "X":
- show_xpassed(terminalreporter, lines)
- elif char in "fF":
- show_simple(terminalreporter, lines, 'failed', "FAIL %s")
- elif char in "sS":
- show_skipped(terminalreporter, lines)
- elif char == "E":
- show_simple(terminalreporter, lines, 'error', "ERROR %s")
- elif char == 'p':
- show_simple(terminalreporter, lines, 'passed', "PASSED %s")
-
- if lines:
- tr._tw.sep("=", "short test summary info")
- for line in lines:
- tr._tw.line(line)
-
-def show_simple(terminalreporter, lines, stat, format):
- failed = terminalreporter.stats.get(stat)
- if failed:
- for rep in failed:
- pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
- lines.append(format %(pos,))
-
-def show_xfailed(terminalreporter, lines):
- xfailed = terminalreporter.stats.get("xfailed")
- if xfailed:
- for rep in xfailed:
- pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
- reason = rep.wasxfail
- lines.append("XFAIL %s" % (pos,))
- if reason:
- lines.append(" " + str(reason))
-
-def show_xpassed(terminalreporter, lines):
- xpassed = terminalreporter.stats.get("xpassed")
- if xpassed:
- for rep in xpassed:
- pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
- reason = rep.wasxfail
- lines.append("XPASS %s %s" %(pos, reason))
-
-def cached_eval(config, expr, d):
- if not hasattr(config, '_evalcache'):
- config._evalcache = {}
- try:
- return config._evalcache[expr]
- except KeyError:
- import _pytest._code
- exprcode = _pytest._code.compile(expr, mode="eval")
- config._evalcache[expr] = x = eval(exprcode, d)
- return x
-
-
-def folded_skips(skipped):
- d = {}
- for event in skipped:
- key = event.longrepr
- assert len(key) == 3, (event, key)
- d.setdefault(key, []).append(event)
- l = []
- for key, events in d.items():
- l.append((len(events),) + key)
- return l
-
-def show_skipped(terminalreporter, lines):
- tr = terminalreporter
- skipped = tr.stats.get('skipped', [])
- if skipped:
- #if not tr.hasopt('skipped'):
- # tr.write_line(
- # "%d skipped tests, specify -rs for more info" %
- # len(skipped))
- # return
- fskips = folded_skips(skipped)
- if fskips:
- #tr.write_sep("_", "skipped test summary")
- for num, fspath, lineno, reason in fskips:
- if reason.startswith("Skipped: "):
- reason = reason[9:]
- lines.append("SKIP [%d] %s:%d: %s" %
- (num, fspath, lineno, reason))
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/standalonetemplate.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/standalonetemplate.py
deleted file mode 100644
index 484d5d1..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/standalonetemplate.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#! /usr/bin/env python
-
-# Hi There!
-# You may be wondering what this giant blob of binary data here is, you might
-# even be worried that we're up to something nefarious (good for you for being
-# paranoid!). This is a base64 encoding of a zip file, this zip file contains
-# a fully functional basic pytest script.
-#
-# Pytest is a thing that tests packages, pytest itself is a package that some-
-# one might want to install, especially if they're looking to run tests inside
-# some package they want to install. Pytest has a lot of code to collect and
-# execute tests, and other such sort of "tribal knowledge" that has been en-
-# coded in its code base. Because of this we basically include a basic copy
-# of pytest inside this blob. We do this because it let's you as a maintainer
-# or application developer who wants people who don't deal with python much to
-# easily run tests without installing the complete pytest package.
-#
-# If you're wondering how this is created: you can create it yourself if you
-# have a complete pytest installation by using this command on the command-
-# line: ``py.test --genscript=runtests.py``.
-
-sources = """
-@SOURCES@"""
-
-import sys
-import base64
-import zlib
-
-class DictImporter(object):
- def __init__(self, sources):
- self.sources = sources
-
- def find_module(self, fullname, path=None):
- if fullname == "argparse" and sys.version_info >= (2,7):
- # we were generated with <python2.7 (which pulls in argparse)
- # but we are running now on a stdlib which has it, so use that.
- return None
- if fullname in self.sources:
- return self
- if fullname + '.__init__' in self.sources:
- return self
- return None
-
- def load_module(self, fullname):
- # print "load_module:", fullname
- from types import ModuleType
- try:
- s = self.sources[fullname]
- is_pkg = False
- except KeyError:
- s = self.sources[fullname + '.__init__']
- is_pkg = True
-
- co = compile(s, fullname, 'exec')
- module = sys.modules.setdefault(fullname, ModuleType(fullname))
- module.__file__ = "%s/%s" % (__file__, fullname)
- module.__loader__ = self
- if is_pkg:
- module.__path__ = [fullname]
-
- do_exec(co, module.__dict__) # noqa
- return sys.modules[fullname]
-
- def get_source(self, name):
- res = self.sources.get(name)
- if res is None:
- res = self.sources.get(name + '.__init__')
- return res
-
-if __name__ == "__main__":
- try:
- import pkg_resources # noqa
- except ImportError:
- sys.stderr.write("ERROR: setuptools not installed\n")
- sys.exit(2)
- if sys.version_info >= (3, 0):
- exec("def do_exec(co, loc): exec(co, loc)\n")
- import pickle
- sources = sources.encode("ascii") # ensure bytes
- sources = pickle.loads(zlib.decompress(base64.decodebytes(sources)))
- else:
- import cPickle as pickle
- exec("def do_exec(co, loc): exec co in loc\n")
- sources = pickle.loads(zlib.decompress(base64.decodestring(sources)))
-
- importer = DictImporter(sources)
- sys.meta_path.insert(0, importer)
- entry = "@ENTRY@"
- do_exec(entry, locals()) # noqa
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/terminal.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/terminal.py
deleted file mode 100644
index 825f553..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/terminal.py
+++ /dev/null
@@ -1,593 +0,0 @@
-""" terminal reporting of the full testing process.
-
-This is a good source for looking at the various reporting hooks.
-"""
-from _pytest.main import EXIT_OK, EXIT_TESTSFAILED, EXIT_INTERRUPTED, \
- EXIT_USAGEERROR, EXIT_NOTESTSCOLLECTED
-import pytest
-import py
-import sys
-import time
-import platform
-
-import _pytest._pluggy as pluggy
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("terminal reporting", "reporting", after="general")
- group._addoption('-v', '--verbose', action="count",
- dest="verbose", default=0, help="increase verbosity."),
- group._addoption('-q', '--quiet', action="count",
- dest="quiet", default=0, help="decrease verbosity."),
- group._addoption('-r',
- action="store", dest="reportchars", default=None, metavar="chars",
- help="show extra test summary info as specified by chars (f)ailed, "
- "(E)error, (s)skipped, (x)failed, (X)passed (w)pytest-warnings "
- "(p)passed, (P)passed with output, (a)all except pP.")
- group._addoption('-l', '--showlocals',
- action="store_true", dest="showlocals", default=False,
- help="show locals in tracebacks (disabled by default).")
- group._addoption('--report',
- action="store", dest="report", default=None, metavar="opts",
- help="(deprecated, use -r)")
- group._addoption('--tb', metavar="style",
- action="store", dest="tbstyle", default='auto',
- choices=['auto', 'long', 'short', 'no', 'line', 'native'],
- help="traceback print mode (auto/long/short/line/native/no).")
- group._addoption('--fulltrace', '--full-trace',
- action="store_true", default=False,
- help="don't cut any tracebacks (default is to cut).")
- group._addoption('--color', metavar="color",
- action="store", dest="color", default='auto',
- choices=['yes', 'no', 'auto'],
- help="color terminal output (yes/no/auto).")
-
-def pytest_configure(config):
- config.option.verbose -= config.option.quiet
- reporter = TerminalReporter(config, sys.stdout)
- config.pluginmanager.register(reporter, 'terminalreporter')
- if config.option.debug or config.option.traceconfig:
- def mywriter(tags, args):
- msg = " ".join(map(str, args))
- reporter.write_line("[traceconfig] " + msg)
- config.trace.root.setprocessor("pytest:config", mywriter)
-
-def getreportopt(config):
- reportopts = ""
- optvalue = config.option.report
- if optvalue:
- py.builtin.print_("DEPRECATED: use -r instead of --report option.",
- file=sys.stderr)
- if optvalue:
- for setting in optvalue.split(","):
- setting = setting.strip()
- if setting == "skipped":
- reportopts += "s"
- elif setting == "xfailed":
- reportopts += "x"
- reportchars = config.option.reportchars
- if reportchars:
- for char in reportchars:
- if char not in reportopts and char != 'a':
- reportopts += char
- elif char == 'a':
- reportopts = 'fEsxXw'
- return reportopts
-
-def pytest_report_teststatus(report):
- if report.passed:
- letter = "."
- elif report.skipped:
- letter = "s"
- elif report.failed:
- letter = "F"
- if report.when != "call":
- letter = "f"
- return report.outcome, letter, report.outcome.upper()
-
-class WarningReport:
- def __init__(self, code, message, nodeid=None, fslocation=None):
- self.code = code
- self.message = message
- self.nodeid = nodeid
- self.fslocation = fslocation
-
-
-class TerminalReporter:
- def __init__(self, config, file=None):
- import _pytest.config
- self.config = config
- self.verbosity = self.config.option.verbose
- self.showheader = self.verbosity >= 0
- self.showfspath = self.verbosity >= 0
- self.showlongtestinfo = self.verbosity > 0
- self._numcollected = 0
-
- self.stats = {}
- self.startdir = py.path.local()
- if file is None:
- file = sys.stdout
- self._tw = self.writer = _pytest.config.create_terminal_writer(config,
- file)
- self.currentfspath = None
- self.reportchars = getreportopt(config)
- self.hasmarkup = self._tw.hasmarkup
- self.isatty = file.isatty()
-
- def hasopt(self, char):
- char = {'xfailed': 'x', 'skipped': 's'}.get(char, char)
- return char in self.reportchars
-
- def write_fspath_result(self, nodeid, res):
- fspath = self.config.rootdir.join(nodeid.split("::")[0])
- if fspath != self.currentfspath:
- self.currentfspath = fspath
- fspath = self.startdir.bestrelpath(fspath)
- self._tw.line()
- self._tw.write(fspath + " ")
- self._tw.write(res)
-
- def write_ensure_prefix(self, prefix, extra="", **kwargs):
- if self.currentfspath != prefix:
- self._tw.line()
- self.currentfspath = prefix
- self._tw.write(prefix)
- if extra:
- self._tw.write(extra, **kwargs)
- self.currentfspath = -2
-
- def ensure_newline(self):
- if self.currentfspath:
- self._tw.line()
- self.currentfspath = None
-
- def write(self, content, **markup):
- self._tw.write(content, **markup)
-
- def write_line(self, line, **markup):
- if not py.builtin._istext(line):
- line = py.builtin.text(line, errors="replace")
- self.ensure_newline()
- self._tw.line(line, **markup)
-
- def rewrite(self, line, **markup):
- line = str(line)
- self._tw.write("\r" + line, **markup)
-
- def write_sep(self, sep, title=None, **markup):
- self.ensure_newline()
- self._tw.sep(sep, title, **markup)
-
- def section(self, title, sep="=", **kw):
- self._tw.sep(sep, title, **kw)
-
- def line(self, msg, **kw):
- self._tw.line(msg, **kw)
-
- def pytest_internalerror(self, excrepr):
- for line in py.builtin.text(excrepr).split("\n"):
- self.write_line("INTERNALERROR> " + line)
- return 1
-
- def pytest_logwarning(self, code, fslocation, message, nodeid):
- warnings = self.stats.setdefault("warnings", [])
- if isinstance(fslocation, tuple):
- fslocation = "%s:%d" % fslocation
- warning = WarningReport(code=code, fslocation=fslocation,
- message=message, nodeid=nodeid)
- warnings.append(warning)
-
- def pytest_plugin_registered(self, plugin):
- if self.config.option.traceconfig:
- msg = "PLUGIN registered: %s" % (plugin,)
- # XXX this event may happen during setup/teardown time
- # which unfortunately captures our output here
- # which garbles our output if we use self.write_line
- self.write_line(msg)
-
- def pytest_deselected(self, items):
- self.stats.setdefault('deselected', []).extend(items)
-
- def pytest_runtest_logstart(self, nodeid, location):
- # ensure that the path is printed before the
- # 1st test of a module starts running
- if self.showlongtestinfo:
- line = self._locationline(nodeid, *location)
- self.write_ensure_prefix(line, "")
- elif self.showfspath:
- fsid = nodeid.split("::")[0]
- self.write_fspath_result(fsid, "")
-
- def pytest_runtest_logreport(self, report):
- rep = report
- res = self.config.hook.pytest_report_teststatus(report=rep)
- cat, letter, word = res
- self.stats.setdefault(cat, []).append(rep)
- self._tests_ran = True
- if not letter and not word:
- # probably passed setup/teardown
- return
- if self.verbosity <= 0:
- if not hasattr(rep, 'node') and self.showfspath:
- self.write_fspath_result(rep.nodeid, letter)
- else:
- self._tw.write(letter)
- else:
- if isinstance(word, tuple):
- word, markup = word
- else:
- if rep.passed:
- markup = {'green':True}
- elif rep.failed:
- markup = {'red':True}
- elif rep.skipped:
- markup = {'yellow':True}
- line = self._locationline(rep.nodeid, *rep.location)
- if not hasattr(rep, 'node'):
- self.write_ensure_prefix(line, word, **markup)
- #self._tw.write(word, **markup)
- else:
- self.ensure_newline()
- if hasattr(rep, 'node'):
- self._tw.write("[%s] " % rep.node.gateway.id)
- self._tw.write(word, **markup)
- self._tw.write(" " + line)
- self.currentfspath = -2
-
- def pytest_collection(self):
- if not self.isatty and self.config.option.verbose >= 1:
- self.write("collecting ... ", bold=True)
-
- def pytest_collectreport(self, report):
- if report.failed:
- self.stats.setdefault("error", []).append(report)
- elif report.skipped:
- self.stats.setdefault("skipped", []).append(report)
- items = [x for x in report.result if isinstance(x, pytest.Item)]
- self._numcollected += len(items)
- if self.isatty:
- #self.write_fspath_result(report.nodeid, 'E')
- self.report_collect()
-
- def report_collect(self, final=False):
- if self.config.option.verbose < 0:
- return
-
- errors = len(self.stats.get('error', []))
- skipped = len(self.stats.get('skipped', []))
- if final:
- line = "collected "
- else:
- line = "collecting "
- line += str(self._numcollected) + " items"
- if errors:
- line += " / %d errors" % errors
- if skipped:
- line += " / %d skipped" % skipped
- if self.isatty:
- if final:
- line += " \n"
- self.rewrite(line, bold=True)
- else:
- self.write_line(line)
-
- def pytest_collection_modifyitems(self):
- self.report_collect(True)
-
- @pytest.hookimpl(trylast=True)
- def pytest_sessionstart(self, session):
- self._sessionstarttime = time.time()
- if not self.showheader:
- return
- self.write_sep("=", "test session starts", bold=True)
- verinfo = platform.python_version()
- msg = "platform %s -- Python %s" % (sys.platform, verinfo)
- if hasattr(sys, 'pypy_version_info'):
- verinfo = ".".join(map(str, sys.pypy_version_info[:3]))
- msg += "[pypy-%s-%s]" % (verinfo, sys.pypy_version_info[3])
- msg += ", pytest-%s, py-%s, pluggy-%s" % (
- pytest.__version__, py.__version__, pluggy.__version__)
- if self.verbosity > 0 or self.config.option.debug or \
- getattr(self.config.option, 'pastebin', None):
- msg += " -- " + str(sys.executable)
- self.write_line(msg)
- lines = self.config.hook.pytest_report_header(
- config=self.config, startdir=self.startdir)
- lines.reverse()
- for line in flatten(lines):
- self.write_line(line)
-
- def pytest_report_header(self, config):
- inifile = ""
- if config.inifile:
- inifile = config.rootdir.bestrelpath(config.inifile)
- lines = ["rootdir: %s, inifile: %s" %(config.rootdir, inifile)]
-
- plugininfo = config.pluginmanager.list_plugin_distinfo()
- if plugininfo:
-
- lines.append(
- "plugins: %s" % ", ".join(_plugin_nameversions(plugininfo)))
- return lines
-
- def pytest_collection_finish(self, session):
- if self.config.option.collectonly:
- self._printcollecteditems(session.items)
- if self.stats.get('failed'):
- self._tw.sep("!", "collection failures")
- for rep in self.stats.get('failed'):
- rep.toterminal(self._tw)
- return 1
- return 0
- if not self.showheader:
- return
- #for i, testarg in enumerate(self.config.args):
- # self.write_line("test path %d: %s" %(i+1, testarg))
-
- def _printcollecteditems(self, items):
- # to print out items and their parent collectors
- # we take care to leave out Instances aka ()
- # because later versions are going to get rid of them anyway
- if self.config.option.verbose < 0:
- if self.config.option.verbose < -1:
- counts = {}
- for item in items:
- name = item.nodeid.split('::', 1)[0]
- counts[name] = counts.get(name, 0) + 1
- for name, count in sorted(counts.items()):
- self._tw.line("%s: %d" % (name, count))
- else:
- for item in items:
- nodeid = item.nodeid
- nodeid = nodeid.replace("::()::", "::")
- self._tw.line(nodeid)
- return
- stack = []
- indent = ""
- for item in items:
- needed_collectors = item.listchain()[1:] # strip root node
- while stack:
- if stack == needed_collectors[:len(stack)]:
- break
- stack.pop()
- for col in needed_collectors[len(stack):]:
- stack.append(col)
- #if col.name == "()":
- # continue
- indent = (len(stack) - 1) * " "
- self._tw.line("%s%s" % (indent, col))
-
- @pytest.hookimpl(hookwrapper=True)
- def pytest_sessionfinish(self, exitstatus):
- outcome = yield
- outcome.get_result()
- self._tw.line("")
- summary_exit_codes = (
- EXIT_OK, EXIT_TESTSFAILED, EXIT_INTERRUPTED, EXIT_USAGEERROR,
- EXIT_NOTESTSCOLLECTED)
- if exitstatus in summary_exit_codes:
- self.config.hook.pytest_terminal_summary(terminalreporter=self)
- self.summary_errors()
- self.summary_failures()
- self.summary_warnings()
- self.summary_passes()
- if exitstatus == EXIT_INTERRUPTED:
- self._report_keyboardinterrupt()
- del self._keyboardinterrupt_memo
- self.summary_deselected()
- self.summary_stats()
-
- def pytest_keyboard_interrupt(self, excinfo):
- self._keyboardinterrupt_memo = excinfo.getrepr(funcargs=True)
-
- def pytest_unconfigure(self):
- if hasattr(self, '_keyboardinterrupt_memo'):
- self._report_keyboardinterrupt()
-
- def _report_keyboardinterrupt(self):
- excrepr = self._keyboardinterrupt_memo
- msg = excrepr.reprcrash.message
- self.write_sep("!", msg)
- if "KeyboardInterrupt" in msg:
- if self.config.option.fulltrace:
- excrepr.toterminal(self._tw)
- else:
- self._tw.line("to show a full traceback on KeyboardInterrupt use --fulltrace", yellow=True)
- excrepr.reprcrash.toterminal(self._tw)
-
- def _locationline(self, nodeid, fspath, lineno, domain):
- def mkrel(nodeid):
- line = self.config.cwd_relative_nodeid(nodeid)
- if domain and line.endswith(domain):
- line = line[:-len(domain)]
- l = domain.split("[")
- l[0] = l[0].replace('.', '::') # don't replace '.' in params
- line += "[".join(l)
- return line
- # collect_fspath comes from testid which has a "/"-normalized path
-
- if fspath:
- res = mkrel(nodeid).replace("::()", "") # parens-normalization
- if nodeid.split("::")[0] != fspath.replace("\\", "/"):
- res += " <- " + self.startdir.bestrelpath(fspath)
- else:
- res = "[location]"
- return res + " "
-
- def _getfailureheadline(self, rep):
- if hasattr(rep, 'location'):
- fspath, lineno, domain = rep.location
- return domain
- else:
- return "test session" # XXX?
-
- def _getcrashline(self, rep):
- try:
- return str(rep.longrepr.reprcrash)
- except AttributeError:
- try:
- return str(rep.longrepr)[:50]
- except AttributeError:
- return ""
-
- #
- # summaries for sessionfinish
- #
- def getreports(self, name):
- l = []
- for x in self.stats.get(name, []):
- if not hasattr(x, '_pdbshown'):
- l.append(x)
- return l
-
- def summary_warnings(self):
- if self.hasopt("w"):
- warnings = self.stats.get("warnings")
- if not warnings:
- return
- self.write_sep("=", "pytest-warning summary")
- for w in warnings:
- self._tw.line("W%s %s %s" % (w.code,
- w.fslocation, w.message))
-
- def summary_passes(self):
- if self.config.option.tbstyle != "no":
- if self.hasopt("P"):
- reports = self.getreports('passed')
- if not reports:
- return
- self.write_sep("=", "PASSES")
- for rep in reports:
- msg = self._getfailureheadline(rep)
- self.write_sep("_", msg)
- self._outrep_summary(rep)
-
- def summary_failures(self):
- if self.config.option.tbstyle != "no":
- reports = self.getreports('failed')
- if not reports:
- return
- self.write_sep("=", "FAILURES")
- for rep in reports:
- if self.config.option.tbstyle == "line":
- line = self._getcrashline(rep)
- self.write_line(line)
- else:
- msg = self._getfailureheadline(rep)
- markup = {'red': True, 'bold': True}
- self.write_sep("_", msg, **markup)
- self._outrep_summary(rep)
-
- def summary_errors(self):
- if self.config.option.tbstyle != "no":
- reports = self.getreports('error')
- if not reports:
- return
- self.write_sep("=", "ERRORS")
- for rep in self.stats['error']:
- msg = self._getfailureheadline(rep)
- if not hasattr(rep, 'when'):
- # collect
- msg = "ERROR collecting " + msg
- elif rep.when == "setup":
- msg = "ERROR at setup of " + msg
- elif rep.when == "teardown":
- msg = "ERROR at teardown of " + msg
- self.write_sep("_", msg)
- self._outrep_summary(rep)
-
- def _outrep_summary(self, rep):
- rep.toterminal(self._tw)
- for secname, content in rep.sections:
- self._tw.sep("-", secname)
- if content[-1:] == "\n":
- content = content[:-1]
- self._tw.line(content)
-
- def summary_stats(self):
- session_duration = time.time() - self._sessionstarttime
- (line, color) = build_summary_stats_line(self.stats)
- msg = "%s in %.2f seconds" % (line, session_duration)
- markup = {color: True, 'bold': True}
-
- if self.verbosity >= 0:
- self.write_sep("=", msg, **markup)
- if self.verbosity == -1:
- self.write_line(msg, **markup)
-
- def summary_deselected(self):
- if 'deselected' in self.stats:
- l = []
- k = self.config.option.keyword
- if k:
- l.append("-k%s" % k)
- m = self.config.option.markexpr
- if m:
- l.append("-m %r" % m)
- if l:
- self.write_sep("=", "%d tests deselected by %r" % (
- len(self.stats['deselected']), " ".join(l)), bold=True)
-
-def repr_pythonversion(v=None):
- if v is None:
- v = sys.version_info
- try:
- return "%s.%s.%s-%s-%s" % v
- except (TypeError, ValueError):
- return str(v)
-
-def flatten(l):
- for x in l:
- if isinstance(x, (list, tuple)):
- for y in flatten(x):
- yield y
- else:
- yield x
-
-def build_summary_stats_line(stats):
- keys = ("failed passed skipped deselected "
- "xfailed xpassed warnings error").split()
- key_translation = {'warnings': 'pytest-warnings'}
- unknown_key_seen = False
- for key in stats.keys():
- if key not in keys:
- if key: # setup/teardown reports have an empty key, ignore them
- keys.append(key)
- unknown_key_seen = True
- parts = []
- for key in keys:
- val = stats.get(key, None)
- if val:
- key_name = key_translation.get(key, key)
- parts.append("%d %s" % (len(val), key_name))
-
- if parts:
- line = ", ".join(parts)
- else:
- line = "no tests ran"
-
- if 'failed' in stats or 'error' in stats:
- color = 'red'
- elif 'warnings' in stats or unknown_key_seen:
- color = 'yellow'
- elif 'passed' in stats:
- color = 'green'
- else:
- color = 'yellow'
-
- return (line, color)
-
-
-def _plugin_nameversions(plugininfo):
- l = []
- for plugin, dist in plugininfo:
- # gets us name and version!
- name = '{dist.project_name}-{dist.version}'.format(dist=dist)
- # questionable convenience, but it keeps things short
- if name.startswith("pytest-"):
- name = name[7:]
- # we decided to print python package names
- # they can have more than one plugin
- if name not in l:
- l.append(name)
- return l
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/tmpdir.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/tmpdir.py
deleted file mode 100644
index ebc48db..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/tmpdir.py
+++ /dev/null
@@ -1,123 +0,0 @@
-""" support for providing temporary directories to test functions. """
-import re
-
-import pytest
-import py
-from _pytest.monkeypatch import monkeypatch
-
-
-class TempdirFactory:
- """Factory for temporary directories under the common base temp directory.
-
- The base directory can be configured using the ``--basetemp`` option.
- """
-
- def __init__(self, config):
- self.config = config
- self.trace = config.trace.get("tmpdir")
-
- def ensuretemp(self, string, dir=1):
- """ (deprecated) return temporary directory path with
- the given string as the trailing part. It is usually
- better to use the 'tmpdir' function argument which
- provides an empty unique-per-test-invocation directory
- and is guaranteed to be empty.
- """
- #py.log._apiwarn(">1.1", "use tmpdir function argument")
- return self.getbasetemp().ensure(string, dir=dir)
-
- def mktemp(self, basename, numbered=True):
- """Create a subdirectory of the base temporary directory and return it.
- If ``numbered``, ensure the directory is unique by adding a number
- prefix greater than any existing one.
- """
- basetemp = self.getbasetemp()
- if not numbered:
- p = basetemp.mkdir(basename)
- else:
- p = py.path.local.make_numbered_dir(prefix=basename,
- keep=0, rootdir=basetemp, lock_timeout=None)
- self.trace("mktemp", p)
- return p
-
- def getbasetemp(self):
- """ return base temporary directory. """
- try:
- return self._basetemp
- except AttributeError:
- basetemp = self.config.option.basetemp
- if basetemp:
- basetemp = py.path.local(basetemp)
- if basetemp.check():
- basetemp.remove()
- basetemp.mkdir()
- else:
- temproot = py.path.local.get_temproot()
- user = get_user()
- if user:
- # use a sub-directory in the temproot to speed-up
- # make_numbered_dir() call
- rootdir = temproot.join('pytest-of-%s' % user)
- else:
- rootdir = temproot
- rootdir.ensure(dir=1)
- basetemp = py.path.local.make_numbered_dir(prefix='pytest-',
- rootdir=rootdir)
- self._basetemp = t = basetemp.realpath()
- self.trace("new basetemp", t)
- return t
-
- def finish(self):
- self.trace("finish")
-
-
-def get_user():
- """Return the current user name, or None if getuser() does not work
- in the current environment (see #1010).
- """
- import getpass
- try:
- return getpass.getuser()
- except (ImportError, KeyError):
- return None
-
-# backward compatibility
-TempdirHandler = TempdirFactory
-
-
-def pytest_configure(config):
- """Create a TempdirFactory and attach it to the config object.
-
- This is to comply with existing plugins which expect the handler to be
- available at pytest_configure time, but ideally should be moved entirely
- to the tmpdir_factory session fixture.
- """
- mp = monkeypatch()
- t = TempdirFactory(config)
- config._cleanup.extend([mp.undo, t.finish])
- mp.setattr(config, '_tmpdirhandler', t, raising=False)
- mp.setattr(pytest, 'ensuretemp', t.ensuretemp, raising=False)
-
-
-@pytest.fixture(scope='session')
-def tmpdir_factory(request):
- """Return a TempdirFactory instance for the test session.
- """
- return request.config._tmpdirhandler
-
-
-@pytest.fixture
-def tmpdir(request, tmpdir_factory):
- """return a temporary directory path object
- which is unique to each test function invocation,
- created as a sub directory of the base temporary
- directory. The returned object is a `py.path.local`_
- path object.
- """
- name = request.node.name
- name = re.sub("[\W]", "_", name)
- MAXVAL = 30
- if len(name) > MAXVAL:
- name = name[:MAXVAL]
- x = tmpdir_factory.mktemp(name, numbered=True)
- return x
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/unittest.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/unittest.py
deleted file mode 100644
index 8120e94..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/unittest.py
+++ /dev/null
@@ -1,205 +0,0 @@
-""" discovery and running of std-library "unittest" style tests. """
-from __future__ import absolute_import
-
-import sys
-import traceback
-
-import pytest
-# for transfering markers
-import _pytest._code
-from _pytest.python import transfer_markers
-from _pytest.skipping import MarkEvaluator
-
-
-def pytest_pycollect_makeitem(collector, name, obj):
- # has unittest been imported and is obj a subclass of its TestCase?
- try:
- if not issubclass(obj, sys.modules["unittest"].TestCase):
- return
- except Exception:
- return
- # yes, so let's collect it
- return UnitTestCase(name, parent=collector)
-
-
-class UnitTestCase(pytest.Class):
- # marker for fixturemanger.getfixtureinfo()
- # to declare that our children do not support funcargs
- nofuncargs = True
-
- def setup(self):
- cls = self.obj
- if getattr(cls, '__unittest_skip__', False):
- return # skipped
- setup = getattr(cls, 'setUpClass', None)
- if setup is not None:
- setup()
- teardown = getattr(cls, 'tearDownClass', None)
- if teardown is not None:
- self.addfinalizer(teardown)
- super(UnitTestCase, self).setup()
-
- def collect(self):
- from unittest import TestLoader
- cls = self.obj
- if not getattr(cls, "__test__", True):
- return
- self.session._fixturemanager.parsefactories(self, unittest=True)
- loader = TestLoader()
- module = self.getparent(pytest.Module).obj
- foundsomething = False
- for name in loader.getTestCaseNames(self.obj):
- x = getattr(self.obj, name)
- funcobj = getattr(x, 'im_func', x)
- transfer_markers(funcobj, cls, module)
- yield TestCaseFunction(name, parent=self)
- foundsomething = True
-
- if not foundsomething:
- runtest = getattr(self.obj, 'runTest', None)
- if runtest is not None:
- ut = sys.modules.get("twisted.trial.unittest", None)
- if ut is None or runtest != ut.TestCase.runTest:
- yield TestCaseFunction('runTest', parent=self)
-
-
-
-class TestCaseFunction(pytest.Function):
- _excinfo = None
-
- def setup(self):
- self._testcase = self.parent.obj(self.name)
- self._fix_unittest_skip_decorator()
- self._obj = getattr(self._testcase, self.name)
- if hasattr(self._testcase, 'setup_method'):
- self._testcase.setup_method(self._obj)
- if hasattr(self, "_request"):
- self._request._fillfixtures()
-
- def _fix_unittest_skip_decorator(self):
- """
- The @unittest.skip decorator calls functools.wraps(self._testcase)
- The call to functools.wraps() fails unless self._testcase
- has a __name__ attribute. This is usually automatically supplied
- if the test is a function or method, but we need to add manually
- here.
-
- See issue #1169
- """
- if sys.version_info[0] == 2:
- setattr(self._testcase, "__name__", self.name)
-
- def teardown(self):
- if hasattr(self._testcase, 'teardown_method'):
- self._testcase.teardown_method(self._obj)
-
- def startTest(self, testcase):
- pass
-
- def _addexcinfo(self, rawexcinfo):
- # unwrap potential exception info (see twisted trial support below)
- rawexcinfo = getattr(rawexcinfo, '_rawexcinfo', rawexcinfo)
- try:
- excinfo = _pytest._code.ExceptionInfo(rawexcinfo)
- except TypeError:
- try:
- try:
- l = traceback.format_exception(*rawexcinfo)
- l.insert(0, "NOTE: Incompatible Exception Representation, "
- "displaying natively:\n\n")
- pytest.fail("".join(l), pytrace=False)
- except (pytest.fail.Exception, KeyboardInterrupt):
- raise
- except:
- pytest.fail("ERROR: Unknown Incompatible Exception "
- "representation:\n%r" %(rawexcinfo,), pytrace=False)
- except KeyboardInterrupt:
- raise
- except pytest.fail.Exception:
- excinfo = _pytest._code.ExceptionInfo()
- self.__dict__.setdefault('_excinfo', []).append(excinfo)
-
- def addError(self, testcase, rawexcinfo):
- self._addexcinfo(rawexcinfo)
- def addFailure(self, testcase, rawexcinfo):
- self._addexcinfo(rawexcinfo)
-
- def addSkip(self, testcase, reason):
- try:
- pytest.skip(reason)
- except pytest.skip.Exception:
- self._evalskip = MarkEvaluator(self, 'SkipTest')
- self._evalskip.result = True
- self._addexcinfo(sys.exc_info())
-
- def addExpectedFailure(self, testcase, rawexcinfo, reason=""):
- try:
- pytest.xfail(str(reason))
- except pytest.xfail.Exception:
- self._addexcinfo(sys.exc_info())
-
- def addUnexpectedSuccess(self, testcase, reason=""):
- self._unexpectedsuccess = reason
-
- def addSuccess(self, testcase):
- pass
-
- def stopTest(self, testcase):
- pass
-
- def runtest(self):
- self._testcase(result=self)
-
- def _prunetraceback(self, excinfo):
- pytest.Function._prunetraceback(self, excinfo)
- traceback = excinfo.traceback.filter(
- lambda x:not x.frame.f_globals.get('__unittest'))
- if traceback:
- excinfo.traceback = traceback
-
-@pytest.hookimpl(tryfirst=True)
-def pytest_runtest_makereport(item, call):
- if isinstance(item, TestCaseFunction):
- if item._excinfo:
- call.excinfo = item._excinfo.pop(0)
- try:
- del call.result
- except AttributeError:
- pass
-
-# twisted trial support
-
-@pytest.hookimpl(hookwrapper=True)
-def pytest_runtest_protocol(item):
- if isinstance(item, TestCaseFunction) and \
- 'twisted.trial.unittest' in sys.modules:
- ut = sys.modules['twisted.python.failure']
- Failure__init__ = ut.Failure.__init__
- check_testcase_implements_trial_reporter()
- def excstore(self, exc_value=None, exc_type=None, exc_tb=None,
- captureVars=None):
- if exc_value is None:
- self._rawexcinfo = sys.exc_info()
- else:
- if exc_type is None:
- exc_type = type(exc_value)
- self._rawexcinfo = (exc_type, exc_value, exc_tb)
- try:
- Failure__init__(self, exc_value, exc_type, exc_tb,
- captureVars=captureVars)
- except TypeError:
- Failure__init__(self, exc_value, exc_type, exc_tb)
- ut.Failure.__init__ = excstore
- yield
- ut.Failure.__init__ = Failure__init__
- else:
- yield
-
-
-def check_testcase_implements_trial_reporter(done=[]):
- if done:
- return
- from zope.interface import classImplements
- from twisted.trial.itrial import IReporter
- classImplements(TestCaseFunction, IReporter)
- done.append(1)
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/README.md b/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/README.md
deleted file mode 100644
index eab7c71..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-This directory vendors the `pluggy` module.
-
-For a more detailed discussion for the reasons to vendoring this
-package, please see [this issue](https://github.com/pytest-dev/pytest/issues/944).
-
-To update the current version, execute:
-
-```
-$ pip install -U pluggy==<version> --no-compile --target=_pytest/vendored_packages
-```
-
-And commit the modified files. The `pluggy-<version>.dist-info` directory
-created by `pip` should be ignored.
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/__init__.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/__init__.py
+++ /dev/null
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/DESCRIPTION.rst b/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/DESCRIPTION.rst
deleted file mode 100644
index aa3bbf8..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/DESCRIPTION.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-Plugin registration and hook calling for Python
-===============================================
-
-This is the plugin manager as used by pytest but stripped
-of pytest specific details.
-
-During the 0.x series this plugin does not have much documentation
-except extensive docstrings in the pluggy.py module.
-
-
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/METADATA b/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/METADATA
deleted file mode 100644
index ec81f0a..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/METADATA
+++ /dev/null
@@ -1,39 +0,0 @@
-Metadata-Version: 2.0
-Name: pluggy
-Version: 0.3.1
-Summary: plugin and hook calling mechanisms for python
-Home-page: UNKNOWN
-Author: Holger Krekel
-Author-email: holger at merlinux.eu
-License: MIT license
-Platform: unix
-Platform: linux
-Platform: osx
-Platform: win32
-Classifier: Development Status :: 4 - Beta
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Operating System :: POSIX
-Classifier: Operating System :: Microsoft :: Windows
-Classifier: Operating System :: MacOS :: MacOS X
-Classifier: Topic :: Software Development :: Testing
-Classifier: Topic :: Software Development :: Libraries
-Classifier: Topic :: Utilities
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Programming Language :: Python :: 3.5
-
-Plugin registration and hook calling for Python
-===============================================
-
-This is the plugin manager as used by pytest but stripped
-of pytest specific details.
-
-During the 0.x series this plugin does not have much documentation
-except extensive docstrings in the pluggy.py module.
-
-
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/RECORD b/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/RECORD
deleted file mode 100644
index 9626673..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/RECORD
+++ /dev/null
@@ -1,8 +0,0 @@
-pluggy.py,sha256=v_RfWzyW6DPU1cJu_EFoL_OHq3t13qloVdR6UaMCXQA,29862
-pluggy-0.3.1.dist-info/top_level.txt,sha256=xKSCRhai-v9MckvMuWqNz16c1tbsmOggoMSwTgcpYHE,7
-pluggy-0.3.1.dist-info/pbr.json,sha256=xX3s6__wOcAyF-AZJX1sdZyW6PUXT-FkfBlM69EEUCg,47
-pluggy-0.3.1.dist-info/RECORD,,
-pluggy-0.3.1.dist-info/metadata.json,sha256=nLKltOT78dMV-00uXD6Aeemp4xNsz2q59j6ORSDeLjw,1027
-pluggy-0.3.1.dist-info/METADATA,sha256=1b85Ho2u4iK30M099k7axMzcDDhLcIMb-A82JUJZnSo,1334
-pluggy-0.3.1.dist-info/WHEEL,sha256=AvR0WeTpDaxT645bl5FQxUK6NPsTls2ttpcGJg3j1Xg,110
-pluggy-0.3.1.dist-info/DESCRIPTION.rst,sha256=P5Akh1EdIBR6CeqtV2P8ZwpGSpZiTKPw0NyS7jEiD-g,306
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/WHEEL b/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/WHEEL
deleted file mode 100644
index 9dff69d..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/WHEEL
+++ /dev/null
@@ -1,6 +0,0 @@
-Wheel-Version: 1.0
-Generator: bdist_wheel (0.24.0)
-Root-Is-Purelib: true
-Tag: py2-none-any
-Tag: py3-none-any
-
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/metadata.json b/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/metadata.json
deleted file mode 100644
index 426a3a7..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/metadata.json
+++ /dev/null
@@ -1 +0,0 @@
-{"license": "MIT license", "name": "pluggy", "metadata_version": "2.0", "generator": "bdist_wheel (0.24.0)", "summary": "plugin and hook calling mechanisms for python", "platform": "unix", "version": "0.3.1", "extensions": {"python.details": {"document_names": {"description": "DESCRIPTION.rst"}, "contacts": [{"role": "author", "email": "holger at merlinux.eu", "name": "Holger Krekel"}]}}, "classifiers": ["Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: POSIX", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS :: MacOS X", "Topic :: Software Development :: Testing", "Topic :: Software Development :: Libraries", "Topic :: Utilities", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5"]}
\ No newline at end of file
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/pbr.json b/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/pbr.json
deleted file mode 100644
index d6b7986..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/pbr.json
+++ /dev/null
@@ -1 +0,0 @@
-{"is_release": false, "git_version": "7d4c9cd"}
\ No newline at end of file
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/top_level.txt b/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/top_level.txt
deleted file mode 100644
index 11bdb5c..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/top_level.txt
+++ /dev/null
@@ -1 +0,0 @@
-pluggy
diff --git a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy.py b/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy.py
deleted file mode 100644
index 2f848b2..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/_pytest/vendored_packages/pluggy.py
+++ /dev/null
@@ -1,777 +0,0 @@
-"""
-PluginManager, basic initialization and tracing.
-
-pluggy is the cristallized core of plugin management as used
-by some 150 plugins for pytest.
-
-Pluggy uses semantic versioning. Breaking changes are only foreseen for
-Major releases (incremented X in "X.Y.Z"). If you want to use pluggy in
-your project you should thus use a dependency restriction like
-"pluggy>=0.1.0,<1.0" to avoid surprises.
-
-pluggy is concerned with hook specification, hook implementations and hook
-calling. For any given hook specification a hook call invokes up to N implementations.
-A hook implementation can influence its position and type of execution:
-if attributed "tryfirst" or "trylast" it will be tried to execute
-first or last. However, if attributed "hookwrapper" an implementation
-can wrap all calls to non-hookwrapper implementations. A hookwrapper
-can thus execute some code ahead and after the execution of other hooks.
-
-Hook specification is done by way of a regular python function where
-both the function name and the names of all its arguments are significant.
-Each hook implementation function is verified against the original specification
-function, including the names of all its arguments. To allow for hook specifications
-to evolve over the livetime of a project, hook implementations can
-accept less arguments. One can thus add new arguments and semantics to
-a hook specification by adding another argument typically without breaking
-existing hook implementations.
-
-The chosen approach is meant to let a hook designer think carefuly about
-which objects are needed by an extension writer. By contrast, subclass-based
-extension mechanisms often expose a lot more state and behaviour than needed,
-thus restricting future developments.
-
-Pluggy currently consists of functionality for:
-
-- a way to register new hook specifications. Without a hook
- specification no hook calling can be performed.
-
-- a registry of plugins which contain hook implementation functions. It
- is possible to register plugins for which a hook specification is not yet
- known and validate all hooks when the system is in a more referentially
- consistent state. Setting an "optionalhook" attribution to a hook
- implementation will avoid PluginValidationError's if a specification
- is missing. This allows to have optional integration between plugins.
-
-- a "hook" relay object from which you can launch 1:N calls to
- registered hook implementation functions
-
-- a mechanism for ordering hook implementation functions
-
-- mechanisms for two different type of 1:N calls: "firstresult" for when
- the call should stop when the first implementation returns a non-None result.
- And the other (default) way of guaranteeing that all hook implementations
- will be called and their non-None result collected.
-
-- mechanisms for "historic" extension points such that all newly
- registered functions will receive all hook calls that happened
- before their registration.
-
-- a mechanism for discovering plugin objects which are based on
- setuptools based entry points.
-
-- a simple tracing mechanism, including tracing of plugin calls and
- their arguments.
-
-"""
-import sys
-import inspect
-
-__version__ = '0.3.1'
-__all__ = ["PluginManager", "PluginValidationError",
- "HookspecMarker", "HookimplMarker"]
-
-_py3 = sys.version_info > (3, 0)
-
-
-class HookspecMarker:
- """ Decorator helper class for marking functions as hook specifications.
-
- You can instantiate it with a project_name to get a decorator.
- Calling PluginManager.add_hookspecs later will discover all marked functions
- if the PluginManager uses the same project_name.
- """
-
- def __init__(self, project_name):
- self.project_name = project_name
-
- def __call__(self, function=None, firstresult=False, historic=False):
- """ if passed a function, directly sets attributes on the function
- which will make it discoverable to add_hookspecs(). If passed no
- function, returns a decorator which can be applied to a function
- later using the attributes supplied.
-
- If firstresult is True the 1:N hook call (N being the number of registered
- hook implementation functions) will stop at I<=N when the I'th function
- returns a non-None result.
-
- If historic is True calls to a hook will be memorized and replayed
- on later registered plugins.
-
- """
- def setattr_hookspec_opts(func):
- if historic and firstresult:
- raise ValueError("cannot have a historic firstresult hook")
- setattr(func, self.project_name + "_spec",
- dict(firstresult=firstresult, historic=historic))
- return func
-
- if function is not None:
- return setattr_hookspec_opts(function)
- else:
- return setattr_hookspec_opts
-
-
-class HookimplMarker:
- """ Decorator helper class for marking functions as hook implementations.
-
- You can instantiate with a project_name to get a decorator.
- Calling PluginManager.register later will discover all marked functions
- if the PluginManager uses the same project_name.
- """
- def __init__(self, project_name):
- self.project_name = project_name
-
- def __call__(self, function=None, hookwrapper=False, optionalhook=False,
- tryfirst=False, trylast=False):
-
- """ if passed a function, directly sets attributes on the function
- which will make it discoverable to register(). If passed no function,
- returns a decorator which can be applied to a function later using
- the attributes supplied.
-
- If optionalhook is True a missing matching hook specification will not result
- in an error (by default it is an error if no matching spec is found).
-
- If tryfirst is True this hook implementation will run as early as possible
- in the chain of N hook implementations for a specfication.
-
- If trylast is True this hook implementation will run as late as possible
- in the chain of N hook implementations.
-
- If hookwrapper is True the hook implementations needs to execute exactly
- one "yield". The code before the yield is run early before any non-hookwrapper
- function is run. The code after the yield is run after all non-hookwrapper
- function have run. The yield receives an ``_CallOutcome`` object representing
- the exception or result outcome of the inner calls (including other hookwrapper
- calls).
-
- """
- def setattr_hookimpl_opts(func):
- setattr(func, self.project_name + "_impl",
- dict(hookwrapper=hookwrapper, optionalhook=optionalhook,
- tryfirst=tryfirst, trylast=trylast))
- return func
-
- if function is None:
- return setattr_hookimpl_opts
- else:
- return setattr_hookimpl_opts(function)
-
-
-def normalize_hookimpl_opts(opts):
- opts.setdefault("tryfirst", False)
- opts.setdefault("trylast", False)
- opts.setdefault("hookwrapper", False)
- opts.setdefault("optionalhook", False)
-
-
-class _TagTracer:
- def __init__(self):
- self._tag2proc = {}
- self.writer = None
- self.indent = 0
-
- def get(self, name):
- return _TagTracerSub(self, (name,))
-
- def format_message(self, tags, args):
- if isinstance(args[-1], dict):
- extra = args[-1]
- args = args[:-1]
- else:
- extra = {}
-
- content = " ".join(map(str, args))
- indent = " " * self.indent
-
- lines = [
- "%s%s [%s]\n" % (indent, content, ":".join(tags))
- ]
-
- for name, value in extra.items():
- lines.append("%s %s: %s\n" % (indent, name, value))
- return lines
-
- def processmessage(self, tags, args):
- if self.writer is not None and args:
- lines = self.format_message(tags, args)
- self.writer(''.join(lines))
- try:
- self._tag2proc[tags](tags, args)
- except KeyError:
- pass
-
- def setwriter(self, writer):
- self.writer = writer
-
- def setprocessor(self, tags, processor):
- if isinstance(tags, str):
- tags = tuple(tags.split(":"))
- else:
- assert isinstance(tags, tuple)
- self._tag2proc[tags] = processor
-
-
-class _TagTracerSub:
- def __init__(self, root, tags):
- self.root = root
- self.tags = tags
-
- def __call__(self, *args):
- self.root.processmessage(self.tags, args)
-
- def setmyprocessor(self, processor):
- self.root.setprocessor(self.tags, processor)
-
- def get(self, name):
- return self.__class__(self.root, self.tags + (name,))
-
-
-def _raise_wrapfail(wrap_controller, msg):
- co = wrap_controller.gi_code
- raise RuntimeError("wrap_controller at %r %s:%d %s" %
- (co.co_name, co.co_filename, co.co_firstlineno, msg))
-
-
-def _wrapped_call(wrap_controller, func):
- """ Wrap calling to a function with a generator which needs to yield
- exactly once. The yield point will trigger calling the wrapped function
- and return its _CallOutcome to the yield point. The generator then needs
- to finish (raise StopIteration) in order for the wrapped call to complete.
- """
- try:
- next(wrap_controller) # first yield
- except StopIteration:
- _raise_wrapfail(wrap_controller, "did not yield")
- call_outcome = _CallOutcome(func)
- try:
- wrap_controller.send(call_outcome)
- _raise_wrapfail(wrap_controller, "has second yield")
- except StopIteration:
- pass
- return call_outcome.get_result()
-
-
-class _CallOutcome:
- """ Outcome of a function call, either an exception or a proper result.
- Calling the ``get_result`` method will return the result or reraise
- the exception raised when the function was called. """
- excinfo = None
-
- def __init__(self, func):
- try:
- self.result = func()
- except BaseException:
- self.excinfo = sys.exc_info()
-
- def force_result(self, result):
- self.result = result
- self.excinfo = None
-
- def get_result(self):
- if self.excinfo is None:
- return self.result
- else:
- ex = self.excinfo
- if _py3:
- raise ex[1].with_traceback(ex[2])
- _reraise(*ex) # noqa
-
-if not _py3:
- exec("""
-def _reraise(cls, val, tb):
- raise cls, val, tb
-""")
-
-
-class _TracedHookExecution:
- def __init__(self, pluginmanager, before, after):
- self.pluginmanager = pluginmanager
- self.before = before
- self.after = after
- self.oldcall = pluginmanager._inner_hookexec
- assert not isinstance(self.oldcall, _TracedHookExecution)
- self.pluginmanager._inner_hookexec = self
-
- def __call__(self, hook, hook_impls, kwargs):
- self.before(hook.name, hook_impls, kwargs)
- outcome = _CallOutcome(lambda: self.oldcall(hook, hook_impls, kwargs))
- self.after(outcome, hook.name, hook_impls, kwargs)
- return outcome.get_result()
-
- def undo(self):
- self.pluginmanager._inner_hookexec = self.oldcall
-
-
-class PluginManager(object):
- """ Core Pluginmanager class which manages registration
- of plugin objects and 1:N hook calling.
-
- You can register new hooks by calling ``addhooks(module_or_class)``.
- You can register plugin objects (which contain hooks) by calling
- ``register(plugin)``. The Pluginmanager is initialized with a
- prefix that is searched for in the names of the dict of registered
- plugin objects. An optional excludefunc allows to blacklist names which
- are not considered as hooks despite a matching prefix.
-
- For debugging purposes you can call ``enable_tracing()``
- which will subsequently send debug information to the trace helper.
- """
-
- def __init__(self, project_name, implprefix=None):
- """ if implprefix is given implementation functions
- will be recognized if their name matches the implprefix. """
- self.project_name = project_name
- self._name2plugin = {}
- self._plugin2hookcallers = {}
- self._plugin_distinfo = []
- self.trace = _TagTracer().get("pluginmanage")
- self.hook = _HookRelay(self.trace.root.get("hook"))
- self._implprefix = implprefix
- self._inner_hookexec = lambda hook, methods, kwargs: \
- _MultiCall(methods, kwargs, hook.spec_opts).execute()
-
- 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)
-
- def register(self, plugin, name=None):
- """ Register a plugin and return its canonical name or None if the name
- is blocked from registering. Raise a ValueError if the plugin is already
- registered. """
- plugin_name = name or self.get_canonical_name(plugin)
-
- if plugin_name in self._name2plugin or plugin in self._plugin2hookcallers:
- if self._name2plugin.get(plugin_name, -1) is None:
- return # blocked plugin, return None to indicate no registration
- raise ValueError("Plugin already registered: %s=%s\n%s" %
- (plugin_name, plugin, self._name2plugin))
-
- # XXX if an error happens we should make sure no state has been
- # changed at point of return
- self._name2plugin[plugin_name] = plugin
-
- # register matching hook implementations of the plugin
- self._plugin2hookcallers[plugin] = hookcallers = []
- for name in dir(plugin):
- hookimpl_opts = self.parse_hookimpl_opts(plugin, name)
- if hookimpl_opts is not None:
- normalize_hookimpl_opts(hookimpl_opts)
- method = getattr(plugin, name)
- hookimpl = HookImpl(plugin, plugin_name, method, hookimpl_opts)
- hook = getattr(self.hook, name, None)
- if hook is None:
- hook = _HookCaller(name, self._hookexec)
- setattr(self.hook, name, hook)
- elif hook.has_spec():
- self._verify_hook(hook, hookimpl)
- hook._maybe_apply_history(hookimpl)
- hook._add_hookimpl(hookimpl)
- hookcallers.append(hook)
- return plugin_name
-
- def parse_hookimpl_opts(self, plugin, name):
- method = getattr(plugin, name)
- res = getattr(method, self.project_name + "_impl", None)
- if res is not None and not isinstance(res, dict):
- # false positive
- res = None
- elif res is None and self._implprefix and name.startswith(self._implprefix):
- res = {}
- return res
-
- def unregister(self, plugin=None, name=None):
- """ unregister a plugin object and all its contained hook implementations
- from internal data structures. """
- if name is None:
- assert plugin is not None, "one of name or plugin needs to be specified"
- name = self.get_name(plugin)
-
- if plugin is None:
- plugin = self.get_plugin(name)
-
- # if self._name2plugin[name] == None registration was blocked: ignore
- if self._name2plugin.get(name):
- del self._name2plugin[name]
-
- for hookcaller in self._plugin2hookcallers.pop(plugin, []):
- hookcaller._remove_plugin(plugin)
-
- return plugin
-
- def set_blocked(self, name):
- """ block registrations of the given name, unregister if already registered. """
- self.unregister(name=name)
- self._name2plugin[name] = None
-
- def is_blocked(self, name):
- """ return True if the name blogs registering plugins of that name. """
- return name in self._name2plugin and self._name2plugin[name] is None
-
- def add_hookspecs(self, module_or_class):
- """ add new hook specifications defined in the given module_or_class.
- Functions are recognized if they have been decorated accordingly. """
- names = []
- for name in dir(module_or_class):
- spec_opts = self.parse_hookspec_opts(module_or_class, name)
- if spec_opts is not None:
- hc = getattr(self.hook, name, None)
- if hc is None:
- hc = _HookCaller(name, self._hookexec, module_or_class, spec_opts)
- setattr(self.hook, name, hc)
- else:
- # plugins registered this hook without knowing the spec
- hc.set_specification(module_or_class, spec_opts)
- for hookfunction in (hc._wrappers + hc._nonwrappers):
- self._verify_hook(hc, hookfunction)
- names.append(name)
-
- if not names:
- raise ValueError("did not find any %r hooks in %r" %
- (self.project_name, module_or_class))
-
- def parse_hookspec_opts(self, module_or_class, name):
- method = getattr(module_or_class, name)
- return getattr(method, self.project_name + "_spec", None)
-
- def get_plugins(self):
- """ return the set of registered plugins. """
- return set(self._plugin2hookcallers)
-
- def is_registered(self, plugin):
- """ Return True if the plugin is already registered. """
- return plugin in self._plugin2hookcallers
-
- def get_canonical_name(self, plugin):
- """ Return canonical name for a plugin object. Note that a plugin
- may be registered under a different name which was specified
- by the caller of register(plugin, name). To obtain the name
- of an registered plugin use ``get_name(plugin)`` instead."""
- return getattr(plugin, "__name__", None) or str(id(plugin))
-
- def get_plugin(self, name):
- """ Return a plugin or None for the given name. """
- return self._name2plugin.get(name)
-
- def get_name(self, plugin):
- """ Return name for registered plugin or None if not registered. """
- for name, val in self._name2plugin.items():
- if plugin == val:
- return name
-
- def _verify_hook(self, hook, hookimpl):
- if hook.is_historic() and hookimpl.hookwrapper:
- raise PluginValidationError(
- "Plugin %r\nhook %r\nhistoric incompatible to hookwrapper" %
- (hookimpl.plugin_name, hook.name))
-
- for arg in hookimpl.argnames:
- if arg not in hook.argnames:
- raise PluginValidationError(
- "Plugin %r\nhook %r\nargument %r not available\n"
- "plugin definition: %s\n"
- "available hookargs: %s" %
- (hookimpl.plugin_name, hook.name, arg,
- _formatdef(hookimpl.function), ", ".join(hook.argnames)))
-
- def check_pending(self):
- """ Verify that all hooks which have not been verified against
- a hook specification are optional, otherwise raise PluginValidationError"""
- for name in self.hook.__dict__:
- if name[0] != "_":
- hook = getattr(self.hook, name)
- if not hook.has_spec():
- for hookimpl in (hook._wrappers + hook._nonwrappers):
- if not hookimpl.optionalhook:
- raise PluginValidationError(
- "unknown hook %r in plugin %r" %
- (name, hookimpl.plugin))
-
- def load_setuptools_entrypoints(self, entrypoint_name):
- """ Load modules from querying the specified setuptools entrypoint name.
- Return the number of loaded plugins. """
- from pkg_resources import iter_entry_points, DistributionNotFound
- for ep in iter_entry_points(entrypoint_name):
- # is the plugin registered or blocked?
- if self.get_plugin(ep.name) or self.is_blocked(ep.name):
- continue
- try:
- plugin = ep.load()
- except DistributionNotFound:
- continue
- self.register(plugin, name=ep.name)
- self._plugin_distinfo.append((plugin, ep.dist))
- return len(self._plugin_distinfo)
-
- def list_plugin_distinfo(self):
- """ return list of distinfo/plugin tuples for all setuptools registered
- plugins. """
- return list(self._plugin_distinfo)
-
- def list_name_plugin(self):
- """ return list of name/plugin pairs. """
- return list(self._name2plugin.items())
-
- def get_hookcallers(self, plugin):
- """ get all hook callers for the specified plugin. """
- return self._plugin2hookcallers.get(plugin)
-
- def add_hookcall_monitoring(self, before, after):
- """ add before/after tracing functions for all hooks
- and return an undo function which, when called,
- will remove the added tracers.
-
- ``before(hook_name, hook_impls, kwargs)`` will be called ahead
- of all hook calls and receive a hookcaller instance, a list
- of HookImpl instances and the keyword arguments for the hook call.
-
- ``after(outcome, hook_name, hook_impls, kwargs)`` receives the
- same arguments as ``before`` but also a :py:class:`_CallOutcome`` object
- which represents the result of the overall hook call.
- """
- return _TracedHookExecution(self, before, after).undo
-
- def enable_tracing(self):
- """ enable tracing of hook calls and return an undo function. """
- hooktrace = self.hook._trace
-
- def before(hook_name, methods, kwargs):
- hooktrace.root.indent += 1
- hooktrace(hook_name, kwargs)
-
- def after(outcome, hook_name, methods, kwargs):
- if outcome.excinfo is None:
- hooktrace("finish", hook_name, "-->", outcome.result)
- hooktrace.root.indent -= 1
-
- return self.add_hookcall_monitoring(before, after)
-
- def subset_hook_caller(self, name, remove_plugins):
- """ Return a new _HookCaller instance for the named method
- which manages calls to all registered plugins except the
- ones from remove_plugins. """
- orig = getattr(self.hook, name)
- plugins_to_remove = [plug for plug in remove_plugins if hasattr(plug, name)]
- if plugins_to_remove:
- hc = _HookCaller(orig.name, orig._hookexec, orig._specmodule_or_class,
- orig.spec_opts)
- for hookimpl in (orig._wrappers + orig._nonwrappers):
- plugin = hookimpl.plugin
- if plugin not in plugins_to_remove:
- hc._add_hookimpl(hookimpl)
- # we also keep track of this hook caller so it
- # gets properly removed on plugin unregistration
- self._plugin2hookcallers.setdefault(plugin, []).append(hc)
- return hc
- return orig
-
-
-class _MultiCall:
- """ execute a call into multiple python functions/methods. """
-
- # XXX note that the __multicall__ argument is supported only
- # for pytest compatibility reasons. It was never officially
- # supported there and is explicitly deprecated since 2.8
- # so we can remove it soon, allowing to avoid the below recursion
- # in execute() and simplify/speed up the execute loop.
-
- def __init__(self, hook_impls, kwargs, specopts={}):
- self.hook_impls = hook_impls
- self.kwargs = kwargs
- self.kwargs["__multicall__"] = self
- self.specopts = specopts
-
- def execute(self):
- all_kwargs = self.kwargs
- self.results = results = []
- firstresult = self.specopts.get("firstresult")
-
- while self.hook_impls:
- hook_impl = self.hook_impls.pop()
- args = [all_kwargs[argname] for argname in hook_impl.argnames]
- if hook_impl.hookwrapper:
- return _wrapped_call(hook_impl.function(*args), self.execute)
- res = hook_impl.function(*args)
- if res is not None:
- if firstresult:
- return res
- results.append(res)
-
- if not firstresult:
- return results
-
- def __repr__(self):
- status = "%d meths" % (len(self.hook_impls),)
- if hasattr(self, "results"):
- status = ("%d results, " % len(self.results)) + status
- return "<_MultiCall %s, kwargs=%r>" % (status, self.kwargs)
-
-
-def varnames(func, startindex=None):
- """ return argument name tuple for a function, method, class or callable.
-
- In case of a class, its "__init__" method is considered.
- For methods the "self" parameter is not included unless you are passing
- an unbound method with Python3 (which has no supports for unbound methods)
- """
- cache = getattr(func, "__dict__", {})
- try:
- return cache["_varnames"]
- except KeyError:
- pass
- if inspect.isclass(func):
- try:
- func = func.__init__
- except AttributeError:
- return ()
- startindex = 1
- else:
- if not inspect.isfunction(func) and not inspect.ismethod(func):
- func = getattr(func, '__call__', func)
- if startindex is None:
- startindex = int(inspect.ismethod(func))
-
- try:
- rawcode = func.__code__
- except AttributeError:
- return ()
- try:
- x = rawcode.co_varnames[startindex:rawcode.co_argcount]
- except AttributeError:
- x = ()
- else:
- defaults = func.__defaults__
- if defaults:
- x = x[:-len(defaults)]
- try:
- cache["_varnames"] = x
- except TypeError:
- pass
- return x
-
-
-class _HookRelay:
- """ hook holder object for performing 1:N hook calls where N is the number
- of registered plugins.
-
- """
-
- def __init__(self, trace):
- self._trace = trace
-
-
-class _HookCaller(object):
- def __init__(self, name, hook_execute, specmodule_or_class=None, spec_opts=None):
- self.name = name
- self._wrappers = []
- self._nonwrappers = []
- self._hookexec = hook_execute
- if specmodule_or_class is not None:
- assert spec_opts is not None
- self.set_specification(specmodule_or_class, spec_opts)
-
- def has_spec(self):
- return hasattr(self, "_specmodule_or_class")
-
- def set_specification(self, specmodule_or_class, spec_opts):
- assert not self.has_spec()
- self._specmodule_or_class = specmodule_or_class
- specfunc = getattr(specmodule_or_class, self.name)
- argnames = varnames(specfunc, startindex=inspect.isclass(specmodule_or_class))
- assert "self" not in argnames # sanity check
- self.argnames = ["__multicall__"] + list(argnames)
- self.spec_opts = spec_opts
- if spec_opts.get("historic"):
- self._call_history = []
-
- def is_historic(self):
- return hasattr(self, "_call_history")
-
- def _remove_plugin(self, plugin):
- def remove(wrappers):
- for i, method in enumerate(wrappers):
- if method.plugin == plugin:
- del wrappers[i]
- return True
- if remove(self._wrappers) is None:
- if remove(self._nonwrappers) is None:
- raise ValueError("plugin %r not found" % (plugin,))
-
- def _add_hookimpl(self, hookimpl):
- if hookimpl.hookwrapper:
- methods = self._wrappers
- else:
- methods = self._nonwrappers
-
- if hookimpl.trylast:
- methods.insert(0, hookimpl)
- elif hookimpl.tryfirst:
- methods.append(hookimpl)
- else:
- # find last non-tryfirst method
- i = len(methods) - 1
- while i >= 0 and methods[i].tryfirst:
- i -= 1
- methods.insert(i + 1, hookimpl)
-
- def __repr__(self):
- return "<_HookCaller %r>" % (self.name,)
-
- def __call__(self, **kwargs):
- assert not self.is_historic()
- return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
-
- def call_historic(self, proc=None, kwargs=None):
- self._call_history.append((kwargs or {}, proc))
- # historizing hooks don't return results
- self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
-
- def call_extra(self, methods, kwargs):
- """ Call the hook with some additional temporarily participating
- methods using the specified kwargs as call parameters. """
- old = list(self._nonwrappers), list(self._wrappers)
- for method in methods:
- opts = dict(hookwrapper=False, trylast=False, tryfirst=False)
- hookimpl = HookImpl(None, "<temp>", method, opts)
- self._add_hookimpl(hookimpl)
- try:
- return self(**kwargs)
- finally:
- self._nonwrappers, self._wrappers = old
-
- def _maybe_apply_history(self, method):
- if self.is_historic():
- for kwargs, proc in self._call_history:
- res = self._hookexec(self, [method], kwargs)
- if res and proc is not None:
- proc(res[0])
-
-
-class HookImpl:
- def __init__(self, plugin, plugin_name, function, hook_impl_opts):
- self.function = function
- self.argnames = varnames(self.function)
- self.plugin = plugin
- self.opts = hook_impl_opts
- self.plugin_name = plugin_name
- self.__dict__.update(hook_impl_opts)
-
-
-class PluginValidationError(Exception):
- """ plugin failed validation. """
-
-
-if hasattr(inspect, 'signature'):
- def _formatdef(func):
- return "%s%s" % (
- func.__name__,
- str(inspect.signature(func))
- )
-else:
- def _formatdef(func):
- return "%s%s" % (
- func.__name__,
- inspect.formatargspec(*inspect.getargspec(func))
- )
diff --git a/WebDriverTests/imported/w3c/tools/pytest/appveyor.yml b/WebDriverTests/imported/w3c/tools/pytest/appveyor.yml
deleted file mode 100644
index 4b73645..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/appveyor.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-environment:
- COVERALLS_REPO_TOKEN:
- secure: 2NJ5Ct55cHJ9WEg3xbSqCuv0rdgzzb6pnzOIG5OkMbTndw3wOBrXntWFoQrXiMFi
- # this is pytest's token in coveralls.io, encrypted
- # using pytestbot account as detailed here:
- # https://www.appveyor.com/docs/build-configuration#secure-variables
-
-install:
- - echo Installed Pythons
- - dir c:\Python*
-
- # install pypy using choco (redirect to a file and write to console in case
- # choco install returns non-zero, because choco install python.pypy is too
- # noisy)
- - choco install python.pypy > pypy-inst.log 2>&1 || (type pypy-inst.log & exit /b 1)
- - set PATH=C:\tools\pypy\pypy;%PATH% # so tox can find pypy
- - echo PyPy installed
- - pypy --version
-
- - 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
diff --git a/WebDriverTests/imported/w3c/tools/pytest/bench/bench.py b/WebDriverTests/imported/w3c/tools/pytest/bench/bench.py
deleted file mode 100644
index ce94964..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/bench/bench.py
+++ /dev/null
@@ -1,12 +0,0 @@
-import sys
-
-if __name__ == '__main__':
- import cProfile
- import pytest
- import pstats
- script = sys.argv[1:] if len(sys.argv) > 1 else "empty.py"
- stats = cProfile.run('pytest.cmdline.main(%r)' % script, 'prof')
- p = pstats.Stats("prof")
- p.strip_dirs()
- p.sort_stats('cumulative')
- print(p.print_stats(500))
diff --git a/WebDriverTests/imported/w3c/tools/pytest/bench/bench_argcomplete.py b/WebDriverTests/imported/w3c/tools/pytest/bench/bench_argcomplete.py
deleted file mode 100644
index d66c664..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/bench/bench_argcomplete.py
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-# 10000 iterations, just for relative comparison
-# 2.7.5 3.3.2
-# FilesCompleter 75.1109 69.2116
-# FastFilesCompleter 0.7383 1.0760
-
-
-if __name__ == '__main__':
- import sys
- import timeit
- from argcomplete.completers import FilesCompleter
- from _pytest._argcomplete import FastFilesCompleter
- count = 1000 # only a few seconds
- setup = 'from __main__ import FastFilesCompleter\nfc = FastFilesCompleter()'
- run = 'fc("/d")'
- sys.stdout.write('%s\n' % (timeit.timeit(run,
- setup=setup.replace('Fast', ''), number=count)))
- sys.stdout.write('%s\n' % (timeit.timeit(run, setup=setup, number=count)))
diff --git a/WebDriverTests/imported/w3c/tools/pytest/bench/empty.py b/WebDriverTests/imported/w3c/tools/pytest/bench/empty.py
deleted file mode 100644
index ac5e257..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/bench/empty.py
+++ /dev/null
@@ -1,3 +0,0 @@
-import py
-for i in range(1000):
- py.builtin.exec_("def test_func_%d(): pass" % i)
diff --git a/WebDriverTests/imported/w3c/tools/pytest/bench/manyparam.py b/WebDriverTests/imported/w3c/tools/pytest/bench/manyparam.py
deleted file mode 100644
index d2bca0e..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/bench/manyparam.py
+++ /dev/null
@@ -1,12 +0,0 @@
-
-import pytest
-
-@pytest.fixture(scope='module', params=range(966))
-def foo(request):
- return request.param
-
-def test_it(foo):
- pass
-def test_it2(foo):
- pass
-
diff --git a/WebDriverTests/imported/w3c/tools/pytest/bench/skip.py b/WebDriverTests/imported/w3c/tools/pytest/bench/skip.py
deleted file mode 100644
index 960b308..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/bench/skip.py
+++ /dev/null
@@ -1,10 +0,0 @@
-
-import pytest
-
-
-SKIP = True
-
-@pytest.mark.parametrize("x", xrange(5000))
-def test_foo(x):
- if SKIP:
- pytest.skip("heh")
diff --git a/WebDriverTests/imported/w3c/tools/pytest/extra/get_issues.py b/WebDriverTests/imported/w3c/tools/pytest/extra/get_issues.py
deleted file mode 100644
index 6437ba4..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/extra/get_issues.py
+++ /dev/null
@@ -1,74 +0,0 @@
-import json
-import py
-import textwrap
-
-issues_url = "http://bitbucket.org/api/1.0/repositories/pytest-dev/pytest/issues"
-
-import requests
-
-def get_issues():
- chunksize = 50
- start = 0
- issues = []
- while 1:
- post_data = {"accountname": "pytest-dev",
- "repo_slug": "pytest",
- "start": start,
- "limit": chunksize}
- print ("getting from", start)
- r = requests.get(issues_url, params=post_data)
- data = r.json()
- issues.extend(data["issues"])
- if start + chunksize >= data["count"]:
- return issues
- start += chunksize
-
-kind2num = "bug enhancement task proposal".split()
-
-status2num = "new open resolved duplicate invalid wontfix".split()
-
-def main(args):
- cachefile = py.path.local(args.cache)
- if not cachefile.exists() or args.refresh:
- issues = get_issues()
- cachefile.write(json.dumps(issues))
- else:
- issues = json.loads(cachefile.read())
-
- open_issues = [x for x in issues
- if x["status"] in ("new", "open")]
-
- def kind_and_id(x):
- kind = x["metadata"]["kind"]
- return kind2num.index(kind), len(issues)-int(x["local_id"])
- open_issues.sort(key=kind_and_id)
- report(open_issues)
-
-def report(issues):
- for issue in issues:
- metadata = issue["metadata"]
- priority = issue["priority"]
- title = issue["title"]
- content = issue["content"]
- kind = metadata["kind"]
- status = issue["status"]
- id = issue["local_id"]
- link = "https://bitbucket.org/pytest-dev/pytest/issue/%s/" % id
- print("----")
- print(status, kind, link)
- print(title)
- #print()
- #lines = content.split("\n")
- #print ("\n".join(lines[:3]))
- #if len(lines) > 3 or len(content) > 240:
- # print ("...")
-
-if __name__ == "__main__":
- import argparse
- parser = argparse.ArgumentParser("process bitbucket issues")
- parser.add_argument("--refresh", action="store_true",
- help="invalidate cache, refresh issues")
- parser.add_argument("--cache", action="store", default="issues.json",
- help="cache file")
- args = parser.parse_args()
- main(args)
diff --git a/WebDriverTests/imported/w3c/tools/pytest/extra/setup-py.test/setup.py b/WebDriverTests/imported/w3c/tools/pytest/extra/setup-py.test/setup.py
deleted file mode 100644
index d0560ce..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/extra/setup-py.test/setup.py
+++ /dev/null
@@ -1,11 +0,0 @@
-import sys
-from distutils.core import setup
-
-if __name__ == "__main__":
- if "sdist" not in sys.argv[1:]:
- raise ValueError("please use 'pytest' pypi package instead of 'py.test'")
- setup(
- name="py.test",
- version="0.0",
- description="please use 'pytest' for installation",
- )
diff --git a/WebDriverTests/imported/w3c/tools/pytest/plugin-test.sh b/WebDriverTests/imported/w3c/tools/pytest/plugin-test.sh
deleted file mode 100644
index 9c61b50..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/plugin-test.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-
-# this assumes plugins are installed as sister directories
-
-set -e
-cd ../pytest-pep8
-py.test
-cd ../pytest-instafail
-py.test
-cd ../pytest-cache
-py.test
-cd ../pytest-xprocess
-py.test
-#cd ../pytest-cov
-#py.test
-cd ../pytest-capturelog
-py.test
-cd ../pytest-xdist
-py.test
-
diff --git a/WebDriverTests/imported/w3c/tools/pytest/pytest.py b/WebDriverTests/imported/w3c/tools/pytest/pytest.py
deleted file mode 100644
index e376e41..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/pytest.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# PYTHON_ARGCOMPLETE_OK
-"""
-pytest: unit and functional testing with Python.
-"""
-__all__ = [
- 'main',
- 'UsageError',
- 'cmdline',
- 'hookspec',
- 'hookimpl',
- '__version__',
-]
-
-if __name__ == '__main__': # if run as a script or by 'python -m pytest'
- # we trigger the below "else" condition by the following import
- import pytest
- raise SystemExit(pytest.main())
-
-# else we are imported
-
-from _pytest.config import (
- main, UsageError, _preloadplugins, cmdline,
- hookspec, hookimpl
-)
-from _pytest import __version__
-
-_preloadplugins() # to populate pytest.* namespace so help(pytest) works
-
diff --git a/WebDriverTests/imported/w3c/tools/pytest/requirements-docs.txt b/WebDriverTests/imported/w3c/tools/pytest/requirements-docs.txt
deleted file mode 100644
index be3a232..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/requirements-docs.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-sphinx==1.2.3
-regendoc
-pyyaml
diff --git a/WebDriverTests/imported/w3c/tools/pytest/runtox.py b/WebDriverTests/imported/w3c/tools/pytest/runtox.py
deleted file mode 100644
index 8c13c53..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/runtox.py
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env python
-
-if __name__ == "__main__":
- import subprocess
- import sys
- subprocess.call([sys.executable, "-m", "tox",
- "-i", "ALL=https://devpi.net/hpk/dev/",
- "--develop"] + sys.argv[1:])
diff --git a/WebDriverTests/imported/w3c/tools/pytest/setup.cfg b/WebDriverTests/imported/w3c/tools/pytest/setup.cfg
deleted file mode 100644
index 1ab4fd0..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/setup.cfg
+++ /dev/null
@@ -1,13 +0,0 @@
-[build_sphinx]
-source-dir = doc/en/
-build-dir = doc/build
-all_files = 1
-
-[upload_sphinx]
-upload-dir = doc/en/build/html
-
-[bdist_wheel]
-universal = 1
-
-[devpi:upload]
-formats = sdist.tgz,bdist_wheel
diff --git a/WebDriverTests/imported/w3c/tools/pytest/setup.py b/WebDriverTests/imported/w3c/tools/pytest/setup.py
deleted file mode 100644
index 6660f21..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/setup.py
+++ /dev/null
@@ -1,122 +0,0 @@
-import os, sys
-import setuptools
-import pkg_resources
-from setuptools import setup, Command
-
-classifiers = ['Development Status :: 6 - Mature',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: MIT License',
- 'Operating System :: POSIX',
- 'Operating System :: Microsoft :: Windows',
- 'Operating System :: MacOS :: MacOS X',
- 'Topic :: Software Development :: Testing',
- 'Topic :: Software Development :: Libraries',
- 'Topic :: Utilities'] + [
- ('Programming Language :: Python :: %s' % x) for x in
- '2 2.6 2.7 3 3.2 3.3 3.4 3.5'.split()]
-
-with open('README.rst') as fd:
- long_description = fd.read()
-
-def get_version():
- p = os.path.join(os.path.dirname(
- os.path.abspath(__file__)), "_pytest", "__init__.py")
- with open(p) as f:
- for line in f.readlines():
- if "__version__" in line:
- return line.strip().split("=")[-1].strip(" '")
- raise ValueError("could not read version")
-
-
-def has_environment_marker_support():
- """
- Tests that setuptools has support for PEP-426 environment marker support.
-
- The first known release to support it is 0.7 (and the earliest on PyPI seems to be 0.7.2
- so we're using that), see: http://pythonhosted.org/setuptools/history.html#id142
-
- References:
-
- * https://wheel.readthedocs.org/en/latest/index.html#defining-conditional-dependencies
- * https://www.python.org/dev/peps/pep-0426/#environment-markers
- """
- try:
- return pkg_resources.parse_version(setuptools.__version__) >= pkg_resources.parse_version('0.7.2')
- except Exception as exc:
- sys.stderr.write("Could not test setuptool's version: %s\n" % exc)
- return False
-
-
-def main():
- install_requires = ['py>=1.4.29'] # pluggy is vendored in _pytest.vendored_packages
- extras_require = {}
- if has_environment_marker_support():
- extras_require[':python_version=="2.6" or python_version=="3.0" or python_version=="3.1"'] = ['argparse']
- extras_require[':sys_platform=="win32"'] = ['colorama']
- else:
- if sys.version_info < (2, 7) or (3,) <= sys.version_info < (3, 2):
- install_requires.append('argparse')
- if sys.platform == 'win32':
- install_requires.append('colorama')
-
- setup(
- name='pytest',
- description='pytest: simple powerful testing with Python',
- long_description=long_description,
- version=get_version(),
- url='http://pytest.org',
- license='MIT license',
- platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
- author='Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, Brianna Laugher, Florian Bruhin and others',
- author_email='holger at merlinux.eu',
- entry_points=make_entry_points(),
- classifiers=classifiers,
- cmdclass={'test': PyTest},
- # the following should be enabled for release
- install_requires=install_requires,
- extras_require=extras_require,
- packages=['_pytest', '_pytest.assertion', '_pytest._code', '_pytest.vendored_packages'],
- py_modules=['pytest'],
- zip_safe=False,
- )
-
-
-def cmdline_entrypoints(versioninfo, platform, basename):
- target = 'pytest:main'
- if platform.startswith('java'):
- points = {'py.test-jython': target}
- else:
- if basename.startswith('pypy'):
- points = {'py.test-%s' % basename: target}
- else: # cpython
- points = {'py.test-%s.%s' % versioninfo[:2] : target}
- points['py.test'] = target
- return points
-
-
-def make_entry_points():
- basename = os.path.basename(sys.executable)
- points = cmdline_entrypoints(sys.version_info, sys.platform, basename)
- keys = list(points.keys())
- keys.sort()
- l = ['%s = %s' % (x, points[x]) for x in keys]
- return {'console_scripts': l}
-
-
-class PyTest(Command):
- user_options = []
- def initialize_options(self):
- pass
- def finalize_options(self):
- pass
- def run(self):
- import subprocess
- PPATH = [x for x in os.environ.get('PYTHONPATH', '').split(':') if x]
- PPATH.insert(0, os.getcwd())
- os.environ['PYTHONPATH'] = ':'.join(PPATH)
- errno = subprocess.call([sys.executable, 'pytest.py', '--ignore=doc'])
- raise SystemExit(errno)
-
-
-if __name__ == '__main__':
- main()
diff --git a/WebDriverTests/imported/w3c/tools/pytest/tox.ini b/WebDriverTests/imported/w3c/tools/pytest/tox.ini
deleted file mode 100644
index 5f65446..0000000
--- a/WebDriverTests/imported/w3c/tools/pytest/tox.ini
+++ /dev/null
@@ -1,160 +0,0 @@
-[tox]
-minversion=2.0
-distshare={homedir}/.tox/distshare
-envlist=
- linting,py26,py27,py33,py34,py35,pypy,
- {py27,py35}-{pexpect,xdist,trial},
- py27-nobyte,doctesting,py27-cxfreeze
-
-[testenv]
-commands= py.test --lsof -rfsxX {posargs:testing}
-passenv = USER USERNAME
-deps=
- nose
- mock
- requests
-
-[testenv:py26]
-commands= py.test --lsof -rfsxX {posargs:testing}
-deps=
- nose
- mock<1.1 # last supported version for py26
-
-[testenv:py27-subprocess]
-changedir=.
-basepython=python2.7
-deps=pytest-xdist>=1.13
- mock
- nose
-commands=
- py.test -n3 -rfsxX --runpytest=subprocess {posargs:testing}
-
-[testenv:genscript]
-commands= py.test --genscript=pytest1
-
-[testenv:linting]
-basepython = python2.7
-deps = flake8
- restructuredtext_lint
-commands = flake8 pytest.py _pytest testing
- rst-lint CHANGELOG.rst
-
-[testenv:py27-xdist]
-deps=pytest-xdist>=1.13
- mock
- nose
-commands=
- py.test -n1 -rfsxX {posargs:testing}
-
-[testenv:py35-xdist]
-deps={[testenv:py27-xdist]deps}
-commands=
- py.test -n3 -rfsxX {posargs:testing}
-
-[testenv:py27-pexpect]
-changedir=testing
-platform=linux|darwin
-deps=pexpect
-commands=
- py.test -rfsxX test_pdb.py test_terminal.py test_unittest.py
-
-[testenv:py35-pexpect]
-changedir=testing
-platform=linux|darwin
-deps={[testenv:py27-pexpect]deps}
-commands=
- py.test -rfsxX test_pdb.py test_terminal.py test_unittest.py
-
-[testenv:py27-nobyte]
-deps=pytest-xdist>=1.13
-distribute=true
-setenv=
- PYTHONDONTWRITEBYTECODE=1
-commands=
- py.test -n3 -rfsxX {posargs:testing}
-
-[testenv:py27-trial]
-deps=twisted
-commands=
- py.test -rsxf {posargs:testing/test_unittest.py}
-
-[testenv:py35-trial]
-platform=linux|darwin
-deps={[testenv:py27-trial]deps}
-commands=
- py.test -rsxf {posargs:testing/test_unittest.py}
-
-[testenv:doctest]
-commands=py.test --doctest-modules _pytest
-deps=
-
-[testenv:doc]
-basepython=python
-changedir=doc/en
-deps=sphinx
- PyYAML
-
-commands=
- make clean
- make html
-
-[testenv:doctesting]
-basepython = python3.4
-changedir=doc/en
-deps=PyYAML
-commands= py.test -rfsxX {posargs}
-
-[testenv:regen]
-changedir=doc/en
-basepython = python3.4
-deps=sphinx
- PyYAML
- regendoc>=0.6.1
-whitelist_externals=
- rm
- make
-commands=
- rm -rf /tmp/doc-exec*
- make regen
-
-[testenv:jython]
-changedir=testing
-commands=
- {envpython} {envbindir}/py.test-jython -rfsxX {posargs}
-
-[testenv:py27-cxfreeze]
-changedir=testing/cx_freeze
-platform=linux|darwin
-commands=
- {envpython} install_cx_freeze.py
- {envpython} runtests_setup.py build --build-exe build
- {envpython} tox_run.py
-
-
-[testenv:coveralls]
-passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH COVERALLS_REPO_TOKEN
-usedevelop=True
-basepython=python3.4
-changedir=.
-deps =
- {[testenv]deps}
- coveralls
-commands=
- coverage run --source=_pytest -m pytest testing
- coverage report -m
- coveralls
-
-[pytest]
-minversion=2.0
-plugins=pytester
-#--pyargs --doctest-modules --ignore=.tox
-addopts= -rxsX -p pytester --ignore=testing/cx_freeze
-rsyncdirs=tox.ini pytest.py _pytest testing
-python_files=test_*.py *_test.py testing/*/*.py
-python_classes=Test Acceptance
-python_functions=test
-norecursedirs = .tox ja .hg cx_freeze_source
-
-
-[flake8]
-ignore =E401,E225,E261,E128,E124,E301,E302,E121,E303,W391,E501,E231,E126,E701,E265,E241,E251,E226,E101,W191,E131,E203,E122,E123,E271,E712,E222,E127,E125,E221,W292,E111,E113,E293,E262,W293,E129,E702,E201,E272,E202,E704,E731,E402