Merge branch 'main' into improve-high-scope-fixtures-teardown-issue-3806

This commit is contained in:
Sadra Barikbin 2023-06-01 16:08:48 +03:30 committed by GitHub
commit 14ff2abb06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 562 additions and 161 deletions

View File

@ -72,6 +72,7 @@ Charles Cloud
Charles Machalow
Charnjit SiNGH (CCSJ)
Cheuk Ting Ho
Chris Mahoney
Chris Lamb
Chris NeJame
Chris Rose
@ -130,6 +131,7 @@ Eric Siegerman
Erik Aronesty
Erik M. Bray
Evan Kepner
Evgeny Seliverstov
Fabien Zarifian
Fabio Zadrozny
Felix Hofstätter
@ -196,6 +198,7 @@ Justice Ndou
Justyna Janczyszyn
Kale Kundert
Kamran Ahmad
Kenny Y
Karl O. Pinc
Karthikeyan Singaravelan
Katarzyna Jachim

View File

@ -0,0 +1 @@
Added handling of ``%f`` directive to print microseconds in log format options, such as ``log-date-format``.

View File

@ -0,0 +1 @@
Added warning when :confval:`testpaths` is set, but paths are not found by glob. In this case, pytest will fall back to searching from the current directory.

View File

@ -0,0 +1 @@
Fixed bug in assertion rewriting where a variable assigned with the walrus operator could not be used later in a function call.

View File

@ -0,0 +1 @@
Enhanced the CLI flag for ``-c`` to now include ``--config-file`` to make it clear that this flag applies to the usage of a custom config file.

View File

@ -0,0 +1,3 @@
When `--confcutdir` is not specified, and there is no config file present, the conftest cutoff directory (`--confcutdir`) is now set to the :ref:`rootdir`.
Previously in such cases, `conftest.py` files would be probed all the way to the root directory of the filesystem.
If you are badly affected by this change, consider adding an empty config file to your desired cutoff directory, or explicitly set `--confcutdir`.

View File

@ -0,0 +1 @@
Fixed ``--last-failed``'s "(skipped N files)" functionality for files inside of packages (directories with `__init__.py` files).

View File

@ -0,0 +1 @@
Fixed traceback entries hidden with ``__tracebackhide__ = True`` still being shown for chained exceptions (parts after "... the above exception ..." message).

View File

@ -11,7 +11,7 @@ automatically. Packages classified as inactive are excluded.
creating a PDF, because otherwise the table gets far too wide for the
page.
This list contains 1256 plugins.
This list contains 1259 plugins.
.. only:: not latex
@ -38,7 +38,7 @@ This list contains 1256 plugins.
:pypi:`pytest-aioworkers` A plugin to test aioworkers project with pytest May 01, 2023 5 - Production/Stable pytest>=6.1.0
:pypi:`pytest-airflow` pytest support for airflow. Apr 03, 2019 3 - Alpha pytest (>=4.4.0)
:pypi:`pytest-airflow-utils` Nov 15, 2021 N/A N/A
:pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Apr 18, 2023 N/A pytest (>=6.0)
:pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. May 23, 2023 N/A pytest (>=6.0)
:pypi:`pytest-allclose` Pytest fixture extending Numpy's allclose function Jul 30, 2019 5 - Production/Stable pytest
:pypi:`pytest-allure-adaptor` Plugin for py.test to generate allure xml reports Jan 10, 2018 N/A pytest (>=2.7.3)
:pypi:`pytest-allure-adaptor2` Plugin for py.test to generate allure xml reports Oct 14, 2020 N/A pytest (>=2.7.3)
@ -213,7 +213,7 @@ This list contains 1256 plugins.
:pypi:`pytest-concurrent` Concurrently execute test cases with multithread, multiprocess and gevent Jan 12, 2019 4 - Beta pytest (>=3.1.1)
:pypi:`pytest-config` Base configurations and utilities for developing your Python project test suite with pytest. Nov 07, 2014 5 - Production/Stable N/A
:pypi:`pytest-confluence-report` Package stands for pytest plugin to upload results into Confluence page. Apr 17, 2022 N/A N/A
:pypi:`pytest-console-scripts` Pytest plugin for testing console scripts Mar 18, 2022 4 - Beta N/A
:pypi:`pytest-console-scripts` Pytest plugin for testing console scripts May 22, 2023 4 - Beta N/A
:pypi:`pytest-consul` pytest plugin with fixtures for testing consul aware apps Nov 24, 2018 3 - Alpha pytest
:pypi:`pytest-container` Pytest fixtures for writing container based tests Mar 21, 2023 4 - Beta pytest (>=3.10)
:pypi:`pytest-contextfixture` Define pytest fixtures as context managers. Mar 12, 2013 4 - Beta N/A
@ -221,14 +221,14 @@ This list contains 1256 plugins.
:pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0)
:pypi:`pytest-couchdbkit` py.test extension for per-test couchdb databases using couchdbkit Apr 17, 2012 N/A N/A
:pypi:`pytest-count` count erros and send email Jan 12, 2018 4 - Beta N/A
:pypi:`pytest-cov` Pytest plugin for measuring coverage. Sep 28, 2022 5 - Production/Stable pytest (>=4.6)
:pypi:`pytest-cov` Pytest plugin for measuring coverage. May 24, 2023 5 - Production/Stable pytest (>=4.6)
:pypi:`pytest-cover` Pytest plugin for measuring coverage. Forked from \`pytest-cov\`. Aug 01, 2015 5 - Production/Stable N/A
:pypi:`pytest-coverage` Jun 17, 2015 N/A N/A
:pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jan 04, 2021 4 - Beta pytest (>=6.1.0)
:pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0)
:pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev'
:pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Jan 30, 2023 5 - Production/Stable pytest (>=7.0)
:pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Apr 20, 2023 N/A N/A
:pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types May 25, 2023 N/A N/A
:pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0)
:pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A
:pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0)
@ -304,7 +304,7 @@ This list contains 1256 plugins.
:pypi:`pytest-django-filefield` Replaces FileField.storage with something you can patch globally. May 09, 2022 5 - Production/Stable pytest >= 5.2
:pypi:`pytest-django-gcir` A Django plugin for pytest. Mar 06, 2018 5 - Production/Stable N/A
:pypi:`pytest-django-haystack` Cleanup your Haystack indexes between tests Sep 03, 2017 5 - Production/Stable pytest (>=2.3.4)
:pypi:`pytest-django-ifactory` A model instance factory for pytest-django Feb 09, 2022 3 - Alpha N/A
:pypi:`pytest-django-ifactory` A model instance factory for pytest-django May 21, 2023 5 - Production/Stable N/A
:pypi:`pytest-django-lite` The bare minimum to integrate py.test with Django. Jan 30, 2014 N/A N/A
:pypi:`pytest-django-liveserver-ssl` Jan 20, 2022 3 - Alpha N/A
:pypi:`pytest-django-model` A Simple Way to Test your Django Models Feb 14, 2019 4 - Beta N/A
@ -486,7 +486,7 @@ This list contains 1256 plugins.
:pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0)
:pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest
:pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A
:pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. May 20, 2023 N/A N/A
:pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. May 22, 2023 N/A N/A
:pypi:`pytest-git` Git repository fixture for py.test May 28, 2019 5 - Production/Stable pytest
:pypi:`pytest-gitcov` Pytest plugin for reporting on coverage of the last git commit. Jan 11, 2020 2 - Pre-Alpha N/A
:pypi:`pytest-git-fixtures` Pytest fixtures for testing with git. Mar 11, 2021 4 - Beta pytest
@ -499,7 +499,7 @@ This list contains 1256 plugins.
:pypi:`pytest-glamor-allure` Extends allure-pytest functionality Jul 22, 2022 4 - Beta pytest
:pypi:`pytest-gnupg-fixtures` Pytest fixtures for testing with gnupg. Mar 04, 2021 4 - Beta pytest
:pypi:`pytest-golden` Plugin for pytest that offloads expected outputs to data files Jul 18, 2022 N/A pytest (>=6.1.2)
:pypi:`pytest-goldie` A plugin to support golden tests with pytest. Apr 12, 2023 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-goldie` A plugin to support golden tests with pytest. May 23, 2023 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-google-chat` Notify google chat channel for test results Mar 27, 2022 4 - Beta pytest
:pypi:`pytest-graphql-schema` Get graphql schema as fixture for pytest Oct 18, 2019 N/A N/A
:pypi:`pytest-greendots` Green progress dots Feb 08, 2014 3 - Alpha N/A
@ -518,7 +518,7 @@ This list contains 1256 plugins.
:pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest
:pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest
:pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A
:pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components May 15, 2023 3 - Alpha pytest (==7.3.1)
:pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components May 24, 2023 3 - Alpha pytest (==7.3.1)
:pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A
:pypi:`pytest-hot-reloading` May 18, 2023 N/A N/A
@ -539,7 +539,7 @@ This list contains 1256 plugins.
:pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace May 09, 2023 3 - Alpha pytest (>=7.0.0)
:pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A
:pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A
:pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 16, 2023 3 - Alpha N/A
:pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A
:pypi:`pytest-httptesting` http_testing framework on top of pytest Apr 19, 2023 N/A pytest (>=7.2.0,<8.0.0)
:pypi:`pytest-httpx` Send responses to httpx. Apr 12, 2023 5 - Production/Stable pytest (<8.0,>=6.0)
:pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1)
@ -569,7 +569,7 @@ This list contains 1256 plugins.
:pypi:`pytest-instafail` pytest plugin to show failures instantly Mar 31, 2023 4 - Beta pytest (>=5)
:pypi:`pytest-instrument` pytest plugin to instrument tests Apr 05, 2020 5 - Production/Stable pytest (>=5.1.0)
:pypi:`pytest-integration` Organizing pytests by integration or not Nov 17, 2022 N/A N/A
:pypi:`pytest-integration-mark` Automatic integration test marking and excluding plugin for pytest Jul 19, 2021 N/A pytest (>=5.2,<7.0)
:pypi:`pytest-integration-mark` Automatic integration test marking and excluding plugin for pytest May 22, 2023 N/A pytest (>=5.2)
:pypi:`pytest-interactive` A pytest plugin for console based interactive test selection just after the collection phase Nov 30, 2017 3 - Alpha N/A
:pypi:`pytest-intercept-remote` Pytest plugin for intercepting outgoing connection requests during pytest run. May 24, 2021 4 - Beta pytest (>=4.6)
:pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. May 09, 2023 4 - Beta pytest
@ -649,7 +649,7 @@ This list contains 1256 plugins.
:pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Jul 25, 2019 4 - Beta pytest (>=3.2)
:pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A
:pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0)
:pypi:`pytest-logikal` Common testing environment May 15, 2023 5 - Production/Stable pytest (==7.3.1)
:pypi:`pytest-logikal` Common testing environment May 27, 2023 5 - Production/Stable pytest (==7.3.1)
:pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A
:pypi:`pytest-loguru` Pytest Loguru Apr 12, 2022 5 - Production/Stable N/A
:pypi:`pytest-loop` pytest plugin for looping tests Jul 22, 2022 5 - Production/Stable pytest (>=6)
@ -680,9 +680,9 @@ This list contains 1256 plugins.
:pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2)
:pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5)
:pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A
:pypi:`pytest-metadata` pytest plugin for test session metadata Oct 30, 2022 5 - Production/Stable pytest (>=3.0.0,<8.0.0)
:pypi:`pytest-metadata` pytest plugin for test session metadata May 27, 2023 5 - Production/Stable pytest>=7.0.0
:pypi:`pytest-metrics` Custom metrics report for pytest Apr 04, 2020 N/A pytest
:pypi:`pytest-mh` Pytest multihost plugin May 04, 2023 N/A pytest
:pypi:`pytest-mh` Pytest multihost plugin May 25, 2023 N/A pytest
:pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2)
:pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1)
:pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0)
@ -695,7 +695,7 @@ This list contains 1256 plugins.
:pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest
:pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A
:pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A
:pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. May 03, 2023 N/A pytest (>=1.0)
:pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. May 23, 2023 N/A pytest (>=1.0)
:pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0)
:pypi:`pytest-mocktcp` A pytest plugin for testing TCP clients Oct 11, 2022 N/A pytest
@ -825,6 +825,7 @@ This list contains 1256 plugins.
:pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Dec 24, 2022 5 - Production/Stable pytest (>=6.0.1)
:pypi:`pytest-pmisc` Mar 21, 2019 5 - Production/Stable N/A
:pypi:`pytest-pointers` Pytest plugin to define functions you test with special marks for better navigation and reports Dec 26, 2022 N/A N/A
:pypi:`pytest-pokie` Pokie plugin for pytest May 22, 2023 5 - Production/Stable N/A
:pypi:`pytest-polarion-cfme` pytest plugin for collecting test cases and recording test results Nov 13, 2017 3 - Alpha N/A
:pypi:`pytest-polarion-collect` pytest plugin for collecting polarion test cases data Jun 18, 2020 3 - Alpha pytest
:pypi:`pytest-polecat` Provides Polecat pytest fixtures Aug 12, 2019 4 - Beta N/A
@ -910,11 +911,12 @@ This list contains 1256 plugins.
:pypi:`pytest-redmine` Pytest plugin for redmine Mar 19, 2018 1 - Planning N/A
:pypi:`pytest-ref` A plugin to store reference files to ease regression testing Nov 23, 2019 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-reference-formatter` Conveniently run pytest with a dot-formatted test reference. Oct 01, 2019 4 - Beta N/A
:pypi:`pytest-regex` Select pytest tests with regular expressions May 23, 2023 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest
:pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Jan 13, 2023 5 - Production/Stable pytest (>=6.2.0)
:pypi:`pytest-regtest` pytest plugin for regression tests Jul 08, 2022 N/A N/A
:pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A
:pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest Dec 31, 2022 5 - Production/Stable pytest (>=7)
:pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest May 23, 2023 5 - Production/Stable pytest (>=7)
:pypi:`pytest-remfiles` Pytest plugin to create a temporary directory with remote files Jul 01, 2019 5 - Production/Stable N/A
:pypi:`pytest-remotedata` Pytest plugin for controlling remote data access. Dec 12, 2022 3 - Alpha pytest (>=4.6)
:pypi:`pytest-remote-response` Pytest plugin for capturing and mocking connection requests. Apr 26, 2023 5 - Production/Stable pytest (>=4.6)
@ -929,10 +931,10 @@ This list contains 1256 plugins.
:pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A
:pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A
:pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility Apr 26, 2023 3 - Alpha pytest
:pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest
:pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest
:pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2)
:pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Apr 21, 2023 N/A pytest (>=3.8.0)
:pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal May 24, 2023 N/A pytest (>=3.8.0)
:pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2)
:pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0)
:pypi:`pytest-requestselapsed` collect and show http requests elapsed time Aug 14, 2022 N/A N/A
@ -989,18 +991,19 @@ This list contains 1256 plugins.
:pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2)
:pypi:`pytest-sanity` Dec 07, 2020 N/A N/A
:pypi:`pytest-sa-pg` May 14, 2019 N/A N/A
:pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 12, 2023 5 - Production/Stable N/A
:pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 25, 2023 5 - Production/Stable N/A
:pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A
:pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A
:pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0)
:pypi:`pytest-securestore` An encrypted password store for use within pytest cases Nov 08, 2021 4 - Beta N/A
:pypi:`pytest-select` A pytest plugin which allows to (de-)select tests from a file. Jan 18, 2019 3 - Alpha pytest (>=3.0)
:pypi:`pytest-selenium` pytest plugin for Selenium Sep 21, 2022 5 - Production/Stable pytest (>=6.0.0,<7.0.0)
:pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. May 12, 2023 5 - Production/Stable N/A
:pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. May 25, 2023 5 - Production/Stable N/A
:pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A
:pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A
:pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A
:pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Jan 05, 2023 N/A N/A
:pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A
:pypi:`pytest-server-fixtures` Extensible server fixures for py.test May 28, 2019 5 - Production/Stable pytest
:pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A
:pypi:`pytest-servers` pytest servers Apr 15, 2023 3 - Alpha pytest (>=6.2)
@ -1102,7 +1105,7 @@ This list contains 1256 plugins.
:pypi:`pytest-tagging` a pytest plugin to tag tests Apr 01, 2023 N/A pytest (>=7.1.3,<8.0.0)
:pypi:`pytest-takeltest` Fixtures for ansible, testinfra and molecule Feb 15, 2023 N/A N/A
:pypi:`pytest-talisker` Nov 28, 2021 N/A N/A
:pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 20, 2023 4 - Beta pytest (>=6.2.5)
:pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 22, 2023 4 - Beta pytest (>=6.2.5)
:pypi:`pytest-tap` Test Anything Protocol (TAP) reporting plugin for pytest Oct 27, 2021 5 - Production/Stable pytest (>=3.0)
:pypi:`pytest-tape` easy assertion with expected results saved to yaml files Mar 17, 2021 4 - Beta N/A
:pypi:`pytest-target` Pytest plugin for remote target orchestration. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0)
@ -1121,7 +1124,7 @@ This list contains 1256 plugins.
:pypi:`pytest-testdox` A testdox format reporter for pytest Apr 19, 2022 5 - Production/Stable pytest (>=4.6.0)
:pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5)
:pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A
:pypi:`pytest-testinfra` Test infrastructures May 19, 2023 5 - Production/Stable pytest (!=3.0.2)
:pypi:`pytest-testinfra` Test infrastructures May 21, 2023 5 - Production/Stable pytest (!=3.0.2)
:pypi:`pytest-testlink-adaptor` pytest reporting plugin for testlink Dec 20, 2018 4 - Beta pytest (>=2.6)
:pypi:`pytest-testmon` selects tests affected by changed files and methods May 18, 2023 4 - Beta pytest (<8,>=5)
:pypi:`pytest-testmon-dev` selects tests affected by changed files and methods Mar 30, 2023 4 - Beta pytest (<8,>=5)
@ -1208,7 +1211,7 @@ This list contains 1256 plugins.
:pypi:`pytest-utils` Some helpers for pytest. Feb 02, 2023 4 - Beta pytest (>=7.0.0,<8.0.0)
:pypi:`pytest-vagrant` A py.test plugin providing access to vagrant. Sep 07, 2021 5 - Production/Stable pytest
:pypi:`pytest-valgrind` May 19, 2021 N/A N/A
:pypi:`pytest-variables` pytest plugin for providing variables to tests/fixtures Mar 27, 2022 5 - Production/Stable pytest (>=3.0.0,<8.0.0)
:pypi:`pytest-variables` pytest plugin for providing variables to tests/fixtures May 27, 2023 5 - Production/Stable pytest>=7.0.0
:pypi:`pytest-variant` Variant support for Pytest Jun 06, 2022 N/A N/A
:pypi:`pytest-vcr` Plugin for managing VCR.py cassettes Apr 26, 2019 5 - Production/Stable pytest (>=3.6.0)
:pypi:`pytest-vcr-delete-on-fail` A pytest plugin that automates vcrpy cassettes deletion on test failure. Jun 20, 2022 5 - Production/Stable pytest (>=6.2.2)
@ -1235,7 +1238,7 @@ This list contains 1256 plugins.
:pypi:`pytest-web3-data` Sep 15, 2022 4 - Beta pytest
:pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest
:pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A
:pypi:`pytest-when` Utility which makes mocking more readable and controllable May 19, 2023 N/A N/A
:pypi:`pytest-when` Utility which makes mocking more readable and controllable May 22, 2023 N/A pytest>=7.3.1
:pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A
:pypi:`pytest-wholenodeid` pytest addon for displaying the whole node id for failures Aug 26, 2015 4 - Beta pytest (>=2.0)
:pypi:`pytest-win32consoletitle` Pytest progress in console title (Win32 only) Aug 08, 2021 N/A N/A
@ -1262,7 +1265,7 @@ This list contains 1256 plugins.
:pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml Mar 17, 2023 N/A pytest>=7.2.0
:pypi:`pytest-yamltree` Create or check file/directory trees described by YAML Mar 02, 2020 4 - Beta pytest (>=3.1.1)
:pypi:`pytest-yamlwsgi` Run tests against wsgi apps defined in yaml May 11, 2010 N/A N/A
:pypi:`pytest-yaml-yoyo` http/https API run by yaml May 20, 2023 N/A pytest (>=7.2.0)
:pypi:`pytest-yaml-yoyo` http/https API run by yaml May 22, 2023 N/A pytest (>=7.2.0)
:pypi:`pytest-yapf` Run yapf Jul 06, 2017 4 - Beta pytest (>=3.1.1)
:pypi:`pytest-yapf3` Validate your Python file format with yapf Mar 29, 2023 5 - Production/Stable pytest (>=7)
:pypi:`pytest-yield` PyTest plugin to run tests concurrently, each \`yield\` switch context to other one Jan 23, 2019 N/A N/A
@ -1420,7 +1423,7 @@ This list contains 1256 plugins.
:pypi:`pytest-alembic`
*last release*: Apr 18, 2023,
*last release*: May 23, 2023,
*status*: N/A,
*requires*: pytest (>=6.0)
@ -2645,7 +2648,7 @@ This list contains 1256 plugins.
Package stands for pytest plugin to upload results into Confluence page.
:pypi:`pytest-console-scripts`
*last release*: Mar 18, 2022,
*last release*: May 22, 2023,
*status*: 4 - Beta,
*requires*: N/A
@ -2701,7 +2704,7 @@ This list contains 1256 plugins.
count erros and send email
:pypi:`pytest-cov`
*last release*: Sep 28, 2022,
*last release*: May 24, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest (>=4.6)
@ -2750,7 +2753,7 @@ This list contains 1256 plugins.
Use pytest's runner to discover and execute C++ tests
:pypi:`pytest-cppython`
*last release*: Apr 20, 2023,
*last release*: May 25, 2023,
*status*: N/A,
*requires*: N/A
@ -3282,8 +3285,8 @@ This list contains 1256 plugins.
Cleanup your Haystack indexes between tests
:pypi:`pytest-django-ifactory`
*last release*: Feb 09, 2022,
*status*: 3 - Alpha,
*last release*: May 21, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
A model instance factory for pytest-django
@ -4556,7 +4559,7 @@ This list contains 1256 plugins.
For finding/executing Ghost Inspector tests
:pypi:`pytest-girder`
*last release*: May 20, 2023,
*last release*: May 22, 2023,
*status*: N/A,
*requires*: N/A
@ -4647,7 +4650,7 @@ This list contains 1256 plugins.
Plugin for pytest that offloads expected outputs to data files
:pypi:`pytest-goldie`
*last release*: Apr 12, 2023,
*last release*: May 23, 2023,
*status*: 4 - Beta,
*requires*: pytest (>=3.5.0)
@ -4780,7 +4783,7 @@ This list contains 1256 plugins.
A pytest plugin for use with homeassistant custom components.
:pypi:`pytest-homeassistant-custom-component`
*last release*: May 15, 2023,
*last release*: May 24, 2023,
*status*: 3 - Alpha,
*requires*: pytest (==7.3.1)
@ -4927,7 +4930,7 @@ This list contains 1256 plugins.
A thin wrapper of HTTPretty for pytest
:pypi:`pytest-httpserver`
*last release*: May 16, 2023,
*last release*: May 22, 2023,
*status*: 3 - Alpha,
*requires*: N/A
@ -5137,9 +5140,9 @@ This list contains 1256 plugins.
Organizing pytests by integration or not
:pypi:`pytest-integration-mark`
*last release*: Jul 19, 2021,
*last release*: May 22, 2023,
*status*: N/A,
*requires*: pytest (>=5.2,<7.0)
*requires*: pytest (>=5.2)
Automatic integration test marking and excluding plugin for pytest
@ -5697,7 +5700,7 @@ This list contains 1256 plugins.
:pypi:`pytest-logikal`
*last release*: May 15, 2023,
*last release*: May 27, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest (==7.3.1)
@ -5914,9 +5917,9 @@ This list contains 1256 plugins.
Pytest to Slack reporting plugin
:pypi:`pytest-metadata`
*last release*: Oct 30, 2022,
*last release*: May 27, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest (>=3.0.0,<8.0.0)
*requires*: pytest>=7.0.0
pytest plugin for test session metadata
@ -5928,7 +5931,7 @@ This list contains 1256 plugins.
Custom metrics report for pytest
:pypi:`pytest-mh`
*last release*: May 04, 2023,
*last release*: May 25, 2023,
*status*: N/A,
*requires*: pytest
@ -6019,7 +6022,7 @@ This list contains 1256 plugins.
An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database.
:pypi:`pytest-mock-resources`
*last release*: May 03, 2023,
*last release*: May 23, 2023,
*status*: N/A,
*requires*: pytest (>=1.0)
@ -6928,6 +6931,13 @@ This list contains 1256 plugins.
Pytest plugin to define functions you test with special marks for better navigation and reports
:pypi:`pytest-pokie`
*last release*: May 22, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
Pokie plugin for pytest
:pypi:`pytest-polarion-cfme`
*last release*: Nov 13, 2017,
*status*: 3 - Alpha,
@ -7523,6 +7533,13 @@ This list contains 1256 plugins.
Conveniently run pytest with a dot-formatted test reference.
:pypi:`pytest-regex`
*last release*: May 23, 2023,
*status*: 4 - Beta,
*requires*: pytest (>=3.5.0)
Select pytest tests with regular expressions
:pypi:`pytest-regex-dependency`
*last release*: Jun 12, 2022,
*status*: N/A,
@ -7552,7 +7569,7 @@ This list contains 1256 plugins.
a pytest plugin that sorts tests using "before" and "after" markers
:pypi:`pytest-relaxed`
*last release*: Dec 31, 2022,
*last release*: May 23, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest (>=7)
@ -7657,7 +7674,7 @@ This list contains 1256 plugins.
A plugin to report summarized results in a table format
:pypi:`pytest-reportlog`
*last release*: Apr 26, 2023,
*last release*: May 22, 2023,
*status*: 3 - Alpha,
*requires*: pytest
@ -7678,7 +7695,7 @@ This list contains 1256 plugins.
pytest plugin for adding tests' parameters to junit report
:pypi:`pytest-reportportal`
*last release*: Apr 21, 2023,
*last release*: May 24, 2023,
*status*: N/A,
*requires*: pytest (>=3.8.0)
@ -8077,7 +8094,7 @@ This list contains 1256 plugins.
:pypi:`pytest-sbase`
*last release*: May 12, 2023,
*last release*: May 25, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
@ -8126,7 +8143,7 @@ This list contains 1256 plugins.
pytest plugin for Selenium
:pypi:`pytest-seleniumbase`
*last release*: May 12, 2023,
*last release*: May 25, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
@ -8160,6 +8177,13 @@ This list contains 1256 plugins.
A pytest plugin to send testrun information to Sentry.io
:pypi:`pytest-sequence-markers`
*last release*: May 23, 2023,
*status*: 5 - Production/Stable,
*requires*: N/A
Pytest plugin for sequencing markers for execution of tests
:pypi:`pytest-server-fixtures`
*last release*: May 28, 2019,
*status*: 5 - Production/Stable,
@ -8868,7 +8892,7 @@ This list contains 1256 plugins.
:pypi:`pytest-tally`
*last release*: May 20, 2023,
*last release*: May 22, 2023,
*status*: 4 - Beta,
*requires*: pytest (>=6.2.5)
@ -9001,7 +9025,7 @@ This list contains 1256 plugins.
A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups.
:pypi:`pytest-testinfra`
*last release*: May 19, 2023,
*last release*: May 21, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest (!=3.0.2)
@ -9610,9 +9634,9 @@ This list contains 1256 plugins.
:pypi:`pytest-variables`
*last release*: Mar 27, 2022,
*last release*: May 27, 2023,
*status*: 5 - Production/Stable,
*requires*: pytest (>=3.0.0,<8.0.0)
*requires*: pytest>=7.0.0
pytest plugin for providing variables to tests/fixtures
@ -9799,9 +9823,9 @@ This list contains 1256 plugins.
Welian API Automation test framework pytest plugin
:pypi:`pytest-when`
*last release*: May 19, 2023,
*last release*: May 22, 2023,
*status*: N/A,
*requires*: N/A
*requires*: pytest>=7.3.1
Utility which makes mocking more readable and controllable
@ -9988,7 +10012,7 @@ This list contains 1256 plugins.
Run tests against wsgi apps defined in yaml
:pypi:`pytest-yaml-yoyo`
*last release*: May 20, 2023,
*last release*: May 22, 2023,
*status*: N/A,
*requires*: pytest (>=7.2.0)

View File

@ -1918,7 +1918,8 @@ All the command-line flags can be obtained by running ``pytest --help``::
--strict-markers Markers not registered in the `markers` section of
the configuration file raise errors
--strict (Deprecated) alias to --strict-markers
-c file Load configuration from `file` instead of trying to
-c, --config-file FILE
Load configuration from `FILE` instead of trying to
locate one of the implicit configuration files
--continue-on-collection-errors
Force test execution even if collection errors occur

View File

@ -31,7 +31,6 @@ from typing import Type
from typing import TYPE_CHECKING
from typing import TypeVar
from typing import Union
from weakref import ref
import pluggy
@ -50,9 +49,9 @@ from _pytest.pathlib import absolutepath
from _pytest.pathlib import bestrelpath
if TYPE_CHECKING:
from typing_extensions import Final
from typing_extensions import Literal
from typing_extensions import SupportsIndex
from weakref import ReferenceType
_TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"]
@ -194,25 +193,25 @@ class Frame:
class TracebackEntry:
"""A single entry in a Traceback."""
__slots__ = ("_rawentry", "_excinfo", "_repr_style")
__slots__ = ("_rawentry", "_repr_style")
def __init__(
self,
rawentry: TracebackType,
excinfo: Optional["ReferenceType[ExceptionInfo[BaseException]]"] = None,
repr_style: Optional['Literal["short", "long"]'] = None,
) -> None:
self._rawentry = rawentry
self._excinfo = excinfo
self._repr_style: Optional['Literal["short", "long"]'] = None
self._rawentry: "Final" = rawentry
self._repr_style: "Final" = repr_style
def with_repr_style(
self, repr_style: Optional['Literal["short", "long"]']
) -> "TracebackEntry":
return TracebackEntry(self._rawentry, repr_style)
@property
def lineno(self) -> int:
return self._rawentry.tb_lineno - 1
def set_repr_style(self, mode: "Literal['short', 'long']") -> None:
assert mode in ("short", "long")
self._repr_style = mode
@property
def frame(self) -> Frame:
return Frame(self._rawentry.tb_frame)
@ -272,7 +271,7 @@ class TracebackEntry:
source = property(getsource)
def ishidden(self) -> bool:
def ishidden(self, excinfo: Optional["ExceptionInfo[BaseException]"]) -> bool:
"""Return True if the current frame has a var __tracebackhide__
resolving to True.
@ -296,7 +295,7 @@ class TracebackEntry:
else:
break
if tbh and callable(tbh):
return tbh(None if self._excinfo is None else self._excinfo())
return tbh(excinfo)
return tbh
def __str__(self) -> str:
@ -329,16 +328,14 @@ class Traceback(List[TracebackEntry]):
def __init__(
self,
tb: Union[TracebackType, Iterable[TracebackEntry]],
excinfo: Optional["ReferenceType[ExceptionInfo[BaseException]]"] = None,
) -> None:
"""Initialize from given python traceback object and ExceptionInfo."""
self._excinfo = excinfo
if isinstance(tb, TracebackType):
def f(cur: TracebackType) -> Iterable[TracebackEntry]:
cur_: Optional[TracebackType] = cur
while cur_ is not None:
yield TracebackEntry(cur_, excinfo=excinfo)
yield TracebackEntry(cur_)
cur_ = cur_.tb_next
super().__init__(f(tb))
@ -378,7 +375,7 @@ class Traceback(List[TracebackEntry]):
continue
if firstlineno is not None and x.frame.code.firstlineno != firstlineno:
continue
return Traceback(x._rawentry, self._excinfo)
return Traceback(x._rawentry)
return self
@overload
@ -398,27 +395,27 @@ class Traceback(List[TracebackEntry]):
return super().__getitem__(key)
def filter(
self, fn: Callable[[TracebackEntry], bool] = lambda x: not x.ishidden()
self,
# TODO(py38): change to positional only.
_excinfo_or_fn: Union[
"ExceptionInfo[BaseException]",
Callable[[TracebackEntry], bool],
],
) -> "Traceback":
"""Return a Traceback instance with certain items removed
"""Return a Traceback instance with certain items removed.
fn is a function that gets a single argument, a TracebackEntry
instance, and should return True when the item should be added
to the Traceback, False when not.
If the filter is an `ExceptionInfo`, removes all the ``TracebackEntry``s
which are hidden (see ishidden() above).
By default this removes all the TracebackEntries which are hidden
(see ishidden() above).
Otherwise, the filter is a function that gets a single argument, a
``TracebackEntry`` instance, and should return True when the item should
be added to the ``Traceback``, False when not.
"""
return Traceback(filter(fn, self), self._excinfo)
def getcrashentry(self) -> Optional[TracebackEntry]:
"""Return last non-hidden traceback entry that lead to the exception of
a traceback, or None if all hidden."""
for i in range(-1, -len(self) - 1, -1):
entry = self[i]
if not entry.ishidden():
return entry
return None
if isinstance(_excinfo_or_fn, ExceptionInfo):
fn = lambda x: not x.ishidden(_excinfo_or_fn) # noqa: E731
else:
fn = _excinfo_or_fn
return Traceback(filter(fn, self))
def recursionindex(self) -> Optional[int]:
"""Return the index of the frame/TracebackEntry where recursion originates if
@ -583,7 +580,7 @@ class ExceptionInfo(Generic[E]):
def traceback(self) -> Traceback:
"""The traceback."""
if self._traceback is None:
self._traceback = Traceback(self.tb, excinfo=ref(self))
self._traceback = Traceback(self.tb)
return self._traceback
@traceback.setter
@ -623,19 +620,24 @@ class ExceptionInfo(Generic[E]):
return isinstance(self.value, exc)
def _getreprcrash(self) -> Optional["ReprFileLocation"]:
exconly = self.exconly(tryshort=True)
entry = self.traceback.getcrashentry()
if entry is None:
return None
# Find last non-hidden traceback entry that led to the exception of the
# traceback, or None if all hidden.
for i in range(-1, -len(self.traceback) - 1, -1):
entry = self.traceback[i]
if not entry.ishidden(self):
path, lineno = entry.frame.code.raw.co_filename, entry.lineno
exconly = self.exconly(tryshort=True)
return ReprFileLocation(path, lineno + 1, exconly)
return None
def getrepr(
self,
showlocals: bool = False,
style: "_TracebackStyle" = "long",
abspath: bool = False,
tbfilter: bool = True,
tbfilter: Union[
bool, Callable[["ExceptionInfo[BaseException]"], Traceback]
] = True,
funcargs: bool = False,
truncate_locals: bool = True,
chain: bool = True,
@ -652,9 +654,15 @@ class ExceptionInfo(Generic[E]):
:param bool abspath:
If paths should be changed to absolute or left unchanged.
:param bool tbfilter:
Hide entries that contain a local variable ``__tracebackhide__==True``.
Ignored if ``style=="native"``.
:param tbfilter:
A filter for traceback entries.
* If false, don't hide any entries.
* If true, hide internal entries and entries that contain a local
variable ``__tracebackhide__ = True``.
* If a callable, delegates the filtering to the callable.
Ignored if ``style`` is ``"native"``.
:param bool funcargs:
Show fixtures ("funcargs" for legacy purposes) per traceback entry.
@ -719,7 +727,7 @@ class FormattedExcinfo:
showlocals: bool = False
style: "_TracebackStyle" = "long"
abspath: bool = True
tbfilter: bool = True
tbfilter: Union[bool, Callable[[ExceptionInfo[BaseException]], Traceback]] = True
funcargs: bool = False
truncate_locals: bool = True
chain: bool = True
@ -881,8 +889,10 @@ class FormattedExcinfo:
def repr_traceback(self, excinfo: ExceptionInfo[BaseException]) -> "ReprTraceback":
traceback = excinfo.traceback
if self.tbfilter:
traceback = traceback.filter()
if callable(self.tbfilter):
traceback = self.tbfilter(excinfo)
elif self.tbfilter:
traceback = traceback.filter(excinfo)
if isinstance(excinfo.value, RecursionError):
traceback, extraline = self._truncate_recursive_traceback(traceback)

View File

@ -996,7 +996,9 @@ class AssertionRewriter(ast.NodeVisitor):
]
):
pytest_temp = self.variable()
self.variables_overwrite[v.left.target.id] = pytest_temp
self.variables_overwrite[
v.left.target.id
] = v.left # type:ignore[assignment]
v.left.target.id = pytest_temp
self.push_format_context()
res, expl = self.visit(v)
@ -1037,10 +1039,19 @@ class AssertionRewriter(ast.NodeVisitor):
new_args = []
new_kwargs = []
for arg in call.args:
if isinstance(arg, ast.Name) and arg.id in self.variables_overwrite:
arg = self.variables_overwrite[arg.id] # type:ignore[assignment]
res, expl = self.visit(arg)
arg_expls.append(expl)
new_args.append(res)
for keyword in call.keywords:
if (
isinstance(keyword.value, ast.Name)
and keyword.value.id in self.variables_overwrite
):
keyword.value = self.variables_overwrite[
keyword.value.id
] # type:ignore[assignment]
res, expl = self.visit(keyword.value)
new_kwargs.append(ast.keyword(keyword.arg, res))
if keyword.arg:
@ -1075,7 +1086,13 @@ class AssertionRewriter(ast.NodeVisitor):
self.push_format_context()
# We first check if we have overwritten a variable in the previous assert
if isinstance(comp.left, ast.Name) and comp.left.id in self.variables_overwrite:
comp.left.id = self.variables_overwrite[comp.left.id]
comp.left = self.variables_overwrite[
comp.left.id
] # type:ignore[assignment]
if isinstance(comp.left, namedExpr):
self.variables_overwrite[
comp.left.target.id
] = comp.left # type:ignore[assignment]
left_res, left_expl = self.visit(comp.left)
if isinstance(comp.left, (ast.Compare, ast.BoolOp)):
left_expl = f"({left_expl})"
@ -1093,7 +1110,9 @@ class AssertionRewriter(ast.NodeVisitor):
and next_operand.target.id == left_res.id
):
next_operand.target.id = self.variable()
self.variables_overwrite[left_res.id] = next_operand.target.id
self.variables_overwrite[
left_res.id
] = next_operand # type:ignore[assignment]
next_res, next_expl = self.visit(next_operand)
if isinstance(next_operand, (ast.Compare, ast.BoolOp)):
next_expl = f"({next_expl})"

View File

@ -219,7 +219,7 @@ class LFPluginCollWrapper:
@hookimpl(hookwrapper=True)
def pytest_make_collect_report(self, collector: nodes.Collector):
if isinstance(collector, Session):
if isinstance(collector, (Session, Package)):
out = yield
res: CollectReport = out.get_result()

View File

@ -1261,8 +1261,11 @@ class Config:
_pytest.deprecated.STRICT_OPTION, stacklevel=2
)
if self.known_args_namespace.confcutdir is None and self.inipath is not None:
if self.known_args_namespace.confcutdir is None:
if self.inipath is not None:
confcutdir = str(self.inipath.parent)
else:
confcutdir = str(self.rootpath)
self.known_args_namespace.confcutdir = confcutdir
try:
self.hook.pytest_load_initial_conftests(
@ -1382,6 +1385,15 @@ class Config:
args = []
for path in testpaths:
args.extend(sorted(glob.iglob(path, recursive=True)))
if testpaths and not args:
warning_text = (
"No files were found in testpaths; "
"consider removing or adjusting your testpaths configuration. "
"Searching recursively from the current directory instead."
)
self.issue_config_time_warning(
PytestConfigWarning(warning_text), stacklevel=3
)
if not args:
source = Config.ArgsSource.INCOVATION_DIR
args = [str(self.invocation_params.dir)]

View File

@ -5,7 +5,11 @@ import os
import re
from contextlib import contextmanager
from contextlib import nullcontext
from datetime import datetime
from datetime import timedelta
from datetime import timezone
from io import StringIO
from logging import LogRecord
from pathlib import Path
from typing import AbstractSet
from typing import Dict
@ -53,7 +57,25 @@ def _remove_ansi_escape_sequences(text: str) -> str:
return _ANSI_ESCAPE_SEQ.sub("", text)
class ColoredLevelFormatter(logging.Formatter):
class DatetimeFormatter(logging.Formatter):
"""A logging formatter which formats record with
:func:`datetime.datetime.strftime` formatter instead of
:func:`time.strftime` in case of microseconds in format string.
"""
def formatTime(self, record: LogRecord, datefmt=None) -> str:
if datefmt and "%f" in datefmt:
ct = self.converter(record.created)
tz = timezone(timedelta(seconds=ct.tm_gmtoff), ct.tm_zone)
# Construct `datetime.datetime` object from `struct_time`
# and msecs information from `record`
dt = datetime(*ct[0:6], microsecond=round(record.msecs * 1000), tzinfo=tz)
return dt.strftime(datefmt)
# Use `logging.Formatter` for non-microsecond formats
return super().formatTime(record, datefmt)
class ColoredLevelFormatter(DatetimeFormatter):
"""A logging formatter which colorizes the %(levelname)..s part of the
log format passed to __init__."""
@ -625,7 +647,7 @@ class LoggingPlugin:
config, "log_file_date_format", "log_date_format"
)
log_file_formatter = logging.Formatter(
log_file_formatter = DatetimeFormatter(
log_file_format, datefmt=log_file_date_format
)
self.log_file_handler.setFormatter(log_file_formatter)
@ -669,7 +691,7 @@ class LoggingPlugin:
create_terminal_writer(self._config), log_format, log_date_format
)
else:
formatter = logging.Formatter(log_format, log_date_format)
formatter = DatetimeFormatter(log_format, log_date_format)
formatter._style = PercentStyleMultiline(
formatter._style._fmt, auto_indent=auto_indent

View File

@ -122,11 +122,12 @@ def pytest_addoption(parser: Parser) -> None:
)
group._addoption(
"-c",
metavar="file",
"--config-file",
metavar="FILE",
type=str,
dest="inifilename",
help="Load configuration from `file` instead of trying to locate one of the "
"implicit configuration files",
help="Load configuration from `FILE` instead of trying to locate one of the "
"implicit configuration files.",
)
group._addoption(
"--continue-on-collection-errors",

View File

@ -22,6 +22,7 @@ import _pytest._code
from _pytest._code import getfslineno
from _pytest._code.code import ExceptionInfo
from _pytest._code.code import TerminalRepr
from _pytest._code.code import Traceback
from _pytest.compat import cached_property
from _pytest.compat import LEGACY_PATH
from _pytest.config import Config
@ -432,8 +433,8 @@ class Node(metaclass=NodeMeta):
assert current is None or isinstance(current, cls)
return current
def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None:
pass
def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback:
return excinfo.traceback
def _repr_failure_py(
self,
@ -449,10 +450,13 @@ class Node(metaclass=NodeMeta):
style = "value"
if isinstance(excinfo.value, FixtureLookupError):
return excinfo.value.formatrepr()
tbfilter: Union[bool, Callable[[ExceptionInfo[BaseException]], Traceback]]
if self.config.getoption("fulltrace", False):
style = "long"
tbfilter = False
else:
self._prunetraceback(excinfo)
tbfilter = self._traceback_filter
if style == "auto":
style = "long"
# XXX should excinfo.getrepr record all data and toterminal() process it?
@ -483,7 +487,7 @@ class Node(metaclass=NodeMeta):
abspath=abspath,
showlocals=self.config.getoption("showlocals", False),
style=style,
tbfilter=False, # pruned already, or in --fulltrace mode.
tbfilter=tbfilter,
truncate_locals=truncate_locals,
)
@ -554,13 +558,14 @@ class Collector(Node):
return self._repr_failure_py(excinfo, style=tbstyle)
def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None:
def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback:
if hasattr(self, "path"):
traceback = excinfo.traceback
ntraceback = traceback.cut(path=self.path)
if ntraceback == traceback:
ntraceback = ntraceback.cut(excludepath=tracebackcutdir)
excinfo.traceback = ntraceback.filter()
return excinfo.traceback.filter(excinfo)
return excinfo.traceback
def _check_initialpaths_for_relpath(session: "Session", path: Path) -> Optional[str]:

View File

@ -35,6 +35,7 @@ from _pytest._code import filter_traceback
from _pytest._code import getfslineno
from _pytest._code.code import ExceptionInfo
from _pytest._code.code import TerminalRepr
from _pytest._code.code import Traceback
from _pytest._io import TerminalWriter
from _pytest._io.saferepr import saferepr
from _pytest.compat import ascii_escaped
@ -1838,7 +1839,7 @@ class Function(PyobjMixin, nodes.Item):
def setup(self) -> None:
self._request._fillfixtures()
def _prunetraceback(self, excinfo: ExceptionInfo[BaseException]) -> None:
def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback:
if hasattr(self, "_obj") and not self.config.getoption("fulltrace", False):
code = _pytest._code.Code.from_function(get_real_func(self.obj))
path, firstlineno = code.path, code.firstlineno
@ -1850,14 +1851,21 @@ class Function(PyobjMixin, nodes.Item):
ntraceback = ntraceback.filter(filter_traceback)
if not ntraceback:
ntraceback = traceback
ntraceback = ntraceback.filter(excinfo)
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.getoption("tbstyle", "auto") == "auto":
if len(excinfo.traceback) > 2:
for entry in excinfo.traceback[1:-1]:
entry.set_repr_style("short")
if len(ntraceback) > 2:
ntraceback = Traceback(
entry
if i == 0 or i == len(ntraceback) - 1
else entry.with_repr_style("short")
for i, entry in enumerate(ntraceback)
)
return ntraceback
return excinfo.traceback
# TODO: Type ignored -- breaks Liskov Substitution.
def repr_failure( # type: ignore[override]

View File

@ -334,15 +334,16 @@ class TestCaseFunction(Function):
finally:
delattr(self._testcase, self.name)
def _prunetraceback(
def _traceback_filter(
self, excinfo: _pytest._code.ExceptionInfo[BaseException]
) -> None:
super()._prunetraceback(excinfo)
traceback = excinfo.traceback.filter(
lambda x: not x.frame.f_globals.get("__unittest")
) -> _pytest._code.Traceback:
traceback = super()._traceback_filter(excinfo)
ntraceback = traceback.filter(
lambda x: not x.frame.f_globals.get("__unittest"),
)
if traceback:
excinfo.traceback = traceback
if not ntraceback:
ntraceback = traceback
return ntraceback
@hookimpl(tryfirst=True)

View File

@ -11,7 +11,7 @@ from typing import Tuple
from typing import TYPE_CHECKING
from typing import Union
import _pytest
import _pytest._code
import pytest
from _pytest._code.code import ExceptionChainRepr
from _pytest._code.code import ExceptionInfo
@ -186,7 +186,7 @@ class TestTraceback_f_g_h:
def test_traceback_filter(self):
traceback = self.excinfo.traceback
ntraceback = traceback.filter()
ntraceback = traceback.filter(self.excinfo)
assert len(ntraceback) == len(traceback) - 1
@pytest.mark.parametrize(
@ -217,7 +217,7 @@ class TestTraceback_f_g_h:
excinfo = pytest.raises(ValueError, h)
traceback = excinfo.traceback
ntraceback = traceback.filter()
ntraceback = traceback.filter(excinfo)
print(f"old: {traceback!r}")
print(f"new: {ntraceback!r}")
@ -290,7 +290,7 @@ class TestTraceback_f_g_h:
excinfo = pytest.raises(ValueError, fail)
assert excinfo.traceback.recursionindex() is None
def test_traceback_getcrashentry(self):
def test_getreprcrash(self):
def i():
__tracebackhide__ = True
raise ValueError
@ -306,15 +306,13 @@ class TestTraceback_f_g_h:
g()
excinfo = pytest.raises(ValueError, f)
tb = excinfo.traceback
entry = tb.getcrashentry()
assert entry is not None
reprcrash = excinfo._getreprcrash()
assert reprcrash is not None
co = _pytest._code.Code.from_function(h)
assert entry.frame.code.path == co.path
assert entry.lineno == co.firstlineno + 1
assert entry.frame.code.name == "h"
assert reprcrash.path == str(co.path)
assert reprcrash.lineno == co.firstlineno + 1 + 1
def test_traceback_getcrashentry_empty(self):
def test_getreprcrash_empty(self):
def g():
__tracebackhide__ = True
raise ValueError
@ -324,7 +322,7 @@ class TestTraceback_f_g_h:
g()
excinfo = pytest.raises(ValueError, f)
assert excinfo.traceback.getcrashentry() is None
assert excinfo._getreprcrash() is None
def test_excinfo_exconly():
@ -626,7 +624,7 @@ raise ValueError()
"""
)
excinfo = pytest.raises(ValueError, mod.func1)
excinfo.traceback = excinfo.traceback.filter()
excinfo.traceback = excinfo.traceback.filter(excinfo)
p = FormattedExcinfo()
reprtb = p.repr_traceback_entry(excinfo.traceback[-1])
@ -659,7 +657,7 @@ raise ValueError()
"""
)
excinfo = pytest.raises(ValueError, mod.func1, "m" * 90, 5, 13, "z" * 120)
excinfo.traceback = excinfo.traceback.filter()
excinfo.traceback = excinfo.traceback.filter(excinfo)
entry = excinfo.traceback[-1]
p = FormattedExcinfo(funcargs=True)
reprfuncargs = p.repr_args(entry)
@ -686,7 +684,7 @@ raise ValueError()
"""
)
excinfo = pytest.raises(ValueError, mod.func1, "a", "b", c="d")
excinfo.traceback = excinfo.traceback.filter()
excinfo.traceback = excinfo.traceback.filter(excinfo)
entry = excinfo.traceback[-1]
p = FormattedExcinfo(funcargs=True)
reprfuncargs = p.repr_args(entry)
@ -960,7 +958,7 @@ raise ValueError()
"""
)
excinfo = pytest.raises(ValueError, mod.f)
excinfo.traceback = excinfo.traceback.filter()
excinfo.traceback = excinfo.traceback.filter(excinfo)
repr = excinfo.getrepr()
repr.toterminal(tw_mock)
assert tw_mock.lines[0] == ""
@ -994,7 +992,7 @@ raise ValueError()
)
excinfo = pytest.raises(ValueError, mod.f)
tmp_path.joinpath("mod.py").unlink()
excinfo.traceback = excinfo.traceback.filter()
excinfo.traceback = excinfo.traceback.filter(excinfo)
repr = excinfo.getrepr()
repr.toterminal(tw_mock)
assert tw_mock.lines[0] == ""
@ -1026,7 +1024,7 @@ raise ValueError()
)
excinfo = pytest.raises(ValueError, mod.f)
tmp_path.joinpath("mod.py").write_text("asdf")
excinfo.traceback = excinfo.traceback.filter()
excinfo.traceback = excinfo.traceback.filter(excinfo)
repr = excinfo.getrepr()
repr.toterminal(tw_mock)
assert tw_mock.lines[0] == ""
@ -1123,9 +1121,11 @@ raise ValueError()
"""
)
excinfo = pytest.raises(ValueError, mod.f)
excinfo.traceback = excinfo.traceback.filter()
excinfo.traceback[1].set_repr_style("short")
excinfo.traceback[2].set_repr_style("short")
excinfo.traceback = excinfo.traceback.filter(excinfo)
excinfo.traceback = _pytest._code.Traceback(
entry if i not in (1, 2) else entry.with_repr_style("short")
for i, entry in enumerate(excinfo.traceback)
)
r = excinfo.getrepr(style="long")
r.toterminal(tw_mock)
for line in tw_mock.lines:
@ -1391,7 +1391,7 @@ raise ValueError()
with pytest.raises(TypeError) as excinfo:
mod.f()
# previously crashed with `AttributeError: list has no attribute get`
excinfo.traceback.filter()
excinfo.traceback.filter(excinfo)
@pytest.mark.parametrize("style", ["short", "long"])
@ -1603,3 +1603,48 @@ def test_all_entries_hidden(pytester: Pytester, tbstyle: str) -> None:
result.stdout.fnmatch_lines(["*ZeroDivisionError: division by zero"])
if tbstyle not in ("line", "native"):
result.stdout.fnmatch_lines(["All traceback entries are hidden.*"])
def test_hidden_entries_of_chained_exceptions_are_not_shown(pytester: Pytester) -> None:
"""Hidden entries of chained exceptions are not shown (#1904)."""
p = pytester.makepyfile(
"""
def g1():
__tracebackhide__ = True
str.does_not_exist
def f3():
__tracebackhide__ = True
1 / 0
def f2():
try:
f3()
except Exception:
g1()
def f1():
__tracebackhide__ = True
f2()
def test():
f1()
"""
)
result = pytester.runpytest(str(p), "--tb=short")
assert result.ret == 1
result.stdout.fnmatch_lines(
[
"*.py:11: in f2",
" f3()",
"E ZeroDivisionError: division by zero",
"",
"During handling of the above exception, another exception occurred:",
"*.py:20: in test",
" f1()",
"*.py:13: in f2",
" g1()",
"E AttributeError:*'does_not_exist'",
],
consecutive=True,
)

View File

@ -1234,3 +1234,100 @@ def test_log_disabling_works_with_log_cli(pytester: Pytester) -> None:
"WARNING disabled:test_log_disabling_works_with_log_cli.py:7 This string will be suppressed."
)
assert not result.stderr.lines
def test_without_date_format_log(pytester: Pytester) -> None:
"""Check that date is not printed by default."""
pytester.makepyfile(
"""
import logging
logger = logging.getLogger(__name__)
def test_foo():
logger.warning('text')
assert False
"""
)
result = pytester.runpytest()
assert result.ret == 1
result.stdout.fnmatch_lines(
["WARNING test_without_date_format_log:test_without_date_format_log.py:6 text"]
)
def test_date_format_log(pytester: Pytester) -> None:
"""Check that log_date_format affects output."""
pytester.makepyfile(
"""
import logging
logger = logging.getLogger(__name__)
def test_foo():
logger.warning('text')
assert False
"""
)
pytester.makeini(
"""
[pytest]
log_format=%(asctime)s; %(levelname)s; %(message)s
log_date_format=%Y-%m-%d %H:%M:%S
"""
)
result = pytester.runpytest()
assert result.ret == 1
result.stdout.re_match_lines([r"^[0-9-]{10} [0-9:]{8}; WARNING; text"])
def test_date_format_percentf_log(pytester: Pytester) -> None:
"""Make sure that microseconds are printed in log."""
pytester.makepyfile(
"""
import logging
logger = logging.getLogger(__name__)
def test_foo():
logger.warning('text')
assert False
"""
)
pytester.makeini(
"""
[pytest]
log_format=%(asctime)s; %(levelname)s; %(message)s
log_date_format=%Y-%m-%d %H:%M:%S.%f
"""
)
result = pytester.runpytest()
assert result.ret == 1
result.stdout.re_match_lines([r"^[0-9-]{10} [0-9:]{8}.[0-9]{6}; WARNING; text"])
def test_date_format_percentf_tz_log(pytester: Pytester) -> None:
"""Make sure that timezone and microseconds are properly formatted together."""
pytester.makepyfile(
"""
import logging
logger = logging.getLogger(__name__)
def test_foo():
logger.warning('text')
assert False
"""
)
pytester.makeini(
"""
[pytest]
log_format=%(asctime)s; %(levelname)s; %(message)s
log_date_format=%Y-%m-%d %H:%M:%S.%f%z
"""
)
result = pytester.runpytest()
assert result.ret == 1
result.stdout.re_match_lines(
[r"^[0-9-]{10} [0-9:]{8}.[0-9]{6}[+-][0-9\.]+; WARNING; text"]
)

View File

@ -1,8 +1,8 @@
anyio[curio,trio]==3.6.2
anyio[curio,trio]==3.7.0
django==4.2.1
pytest-asyncio==0.21.0
pytest-bdd==6.1.1
pytest-cov==4.0.0
pytest-cov==4.1.0
pytest-django==4.5.2
pytest-flakes==4.0.5
pytest-html==3.2.0

View File

@ -1003,9 +1003,9 @@ class TestTracebackCutting:
with pytest.raises(pytest.skip.Exception) as excinfo:
pytest.skip("xxx")
assert excinfo.traceback[-1].frame.code.name == "skip"
assert excinfo.traceback[-1].ishidden()
assert excinfo.traceback[-1].ishidden(excinfo)
assert excinfo.traceback[-2].frame.code.name == "test_skip_simple"
assert not excinfo.traceback[-2].ishidden()
assert not excinfo.traceback[-2].ishidden(excinfo)
def test_traceback_argsetup(self, pytester: Pytester) -> None:
pytester.makeconftest(

View File

@ -1436,6 +1436,96 @@ class TestIssue10743:
assert result.ret == 0
@pytest.mark.skipif(
sys.version_info < (3, 8), reason="walrus operator not available in py<38"
)
class TestIssue11028:
def test_assertion_walrus_operator_in_operand(self, pytester: Pytester) -> None:
pytester.makepyfile(
"""
def test_in_string():
assert (obj := "foo") in obj
"""
)
result = pytester.runpytest()
assert result.ret == 0
def test_assertion_walrus_operator_in_operand_json_dumps(
self, pytester: Pytester
) -> None:
pytester.makepyfile(
"""
import json
def test_json_encoder():
assert (obj := "foo") in json.dumps(obj)
"""
)
result = pytester.runpytest()
assert result.ret == 0
def test_assertion_walrus_operator_equals_operand_function(
self, pytester: Pytester
) -> None:
pytester.makepyfile(
"""
def f(a):
return a
def test_call_other_function_arg():
assert (obj := "foo") == f(obj)
"""
)
result = pytester.runpytest()
assert result.ret == 0
def test_assertion_walrus_operator_equals_operand_function_keyword_arg(
self, pytester: Pytester
) -> None:
pytester.makepyfile(
"""
def f(a='test'):
return a
def test_call_other_function_k_arg():
assert (obj := "foo") == f(a=obj)
"""
)
result = pytester.runpytest()
assert result.ret == 0
def test_assertion_walrus_operator_equals_operand_function_arg_as_function(
self, pytester: Pytester
) -> None:
pytester.makepyfile(
"""
def f(a='test'):
return a
def test_function_of_function():
assert (obj := "foo") == f(f(obj))
"""
)
result = pytester.runpytest()
assert result.ret == 0
def test_assertion_walrus_operator_gt_operand_function(
self, pytester: Pytester
) -> None:
pytester.makepyfile(
"""
def add_one(a):
return a + 1
def test_gt():
assert (obj := 4) > add_one(obj)
"""
)
result = pytester.runpytest()
assert result.ret == 1
result.stdout.fnmatch_lines(["*assert 4 > 5", "*where 5 = add_one(4)"])
@pytest.mark.skipif(
sys.maxsize <= (2**31 - 1), reason="Causes OverflowError on 32bit systems"
)

View File

@ -420,7 +420,13 @@ class TestLastFailed:
result = pytester.runpytest()
result.stdout.fnmatch_lines(["*1 failed in*"])
def test_terminal_report_lastfailed(self, pytester: Pytester) -> None:
@pytest.mark.parametrize("parent", ("session", "package"))
def test_terminal_report_lastfailed(self, pytester: Pytester, parent: str) -> None:
if parent == "package":
pytester.makepyfile(
__init__="",
)
test_a = pytester.makepyfile(
test_a="""
def test_a1(): pass

View File

@ -179,6 +179,23 @@ class TestParseIni:
assert result.ret != 0
result.stderr.fnmatch_lines("ERROR: *pyproject.toml: Invalid statement*")
def test_confcutdir_default_without_configfile(self, pytester: Pytester) -> None:
# If --confcutdir is not specified, and there is no configfile, default
# to the roothpath.
sub = pytester.mkdir("sub")
os.chdir(sub)
config = pytester.parseconfigure()
assert config.pluginmanager._confcutdir == sub
def test_confcutdir_default_with_configfile(self, pytester: Pytester) -> None:
# If --confcutdir is not specified, and there is a configfile, default
# to the configfile's directory.
pytester.makeini("[pytest]")
sub = pytester.mkdir("sub")
os.chdir(sub)
config = pytester.parseconfigure()
assert config.pluginmanager._confcutdir == pytester.path
@pytest.mark.xfail(reason="probably not needed")
def test_confcutdir(self, pytester: Pytester) -> None:
sub = pytester.mkdir("sub")
@ -514,6 +531,8 @@ class TestConfigCmdlineParsing:
)
config = pytester.parseconfig("-c", "custom.ini")
assert config.getini("custom") == "1"
config = pytester.parseconfig("--config-file", "custom.ini")
assert config.getini("custom") == "1"
pytester.makefile(
".cfg",
@ -524,6 +543,8 @@ class TestConfigCmdlineParsing:
)
config = pytester.parseconfig("-c", "custom_tool_pytest_section.cfg")
assert config.getini("custom") == "1"
config = pytester.parseconfig("--config-file", "custom_tool_pytest_section.cfg")
assert config.getini("custom") == "1"
pytester.makefile(
".toml",
@ -536,6 +557,8 @@ class TestConfigCmdlineParsing:
)
config = pytester.parseconfig("-c", "custom.toml")
assert config.getini("custom") == "1"
config = pytester.parseconfig("--config-file", "custom.toml")
assert config.getini("custom") == "1"
def test_absolute_win32_path(self, pytester: Pytester) -> None:
temp_ini_file = pytester.makefile(
@ -550,6 +573,8 @@ class TestConfigCmdlineParsing:
temp_ini_file_norm = normpath(str(temp_ini_file))
ret = pytest.main(["-c", temp_ini_file_norm])
assert ret == ExitCode.OK
ret = pytest.main(["--config-file", temp_ini_file_norm])
assert ret == ExitCode.OK
class TestConfigAPI:
@ -1907,6 +1932,9 @@ class TestSetupCfg:
with pytest.raises(pytest.fail.Exception):
pytester.runpytest("-c", "custom.cfg")
with pytest.raises(pytest.fail.Exception):
pytester.runpytest("--config-file", "custom.cfg")
class TestPytestPluginsVariable:
def test_pytest_plugins_in_non_top_level_conftest_unsupported(

View File

@ -594,7 +594,13 @@ class TestConftestVisibility:
print("pytestarg : %s" % testarg)
print("expected pass : %s" % expect_ntests_passed)
os.chdir(dirs[chdir])
reprec = pytester.inline_run(testarg, "-q", "--traceconfig")
reprec = pytester.inline_run(
testarg,
"-q",
"--traceconfig",
"--confcutdir",
pytester.path,
)
reprec.assertoutcome(passed=expect_ntests_passed)

View File

@ -777,6 +777,20 @@ class TestStackLevel:
)
def test_warning_on_testpaths_not_found(pytester: Pytester) -> None:
# Check for warning when testpaths set, but not found by glob
pytester.makeini(
"""
[pytest]
testpaths = absent
"""
)
result = pytester.runpytest()
result.stdout.fnmatch_lines(
["*ConfigWarning: No files were found in testpaths*", "*1 warning*"]
)
def test_resource_warning(pytester: Pytester, monkeypatch: pytest.MonkeyPatch) -> None:
# Some platforms (notably PyPy) don't have tracemalloc.
# We choose to explicitly not skip this in case tracemalloc is not