In order to allow users to type annotate fixtures they request, the
types need to be imported from the `pytest` namespace. They are/were
always available to import from the `_pytest` namespace, but that is
not guaranteed to be stable.
These types are only exported for the purpose of typing. Specifically,
the following are *not* public:
- Construction (`__init__`)
- Subclassing
- staticmethods and classmethods
We try to combat them being used anyway by:
- Marking the classes as `@final` when possible (already done).
- Not documenting private stuff in the API Reference.
- Using `_`-prefixed names or marking as `:meta private:` for private
stuff.
- Adding a keyword-only `_ispytest=False` to private constructors,
warning if False, and changing pytest itself to pass True. In the
future it will (hopefully) become a hard error.
Hopefully that will be enough.
An upcoming commit wants to import from `_pytest.pytester` in the public
`pytest` module. This means that `_pytest.pytester` would start to get
imported during import time, which it hasn't up to now -- it was
imported by the plugin loader (if requested). When a plugin is loaded,
it is subjected to assertion rewriting, but only if the module isn't
imported yet, it issues a warning "Module already imported so cannot be
rewritten" and skips the rewriting. So we'd end up with the pytester
plugin not being rewritten, but it wants to be.
Absent better ideas, the solution here is to split the pytester
assertions to their own plugin (which will always only be imported by
the plugin loader) and exclude pytester itself from plugin rewriting.
When --doctest-modules is used, an `__init__.py` file is not a `Package`
but a `DoctestModule`, but some collection code assumed that
`__init__.py` implies a `Package`. That code caused only a single test
to be collected in the scenario in the subject.
Tighten up this check to explicitly check for `Package`. There are
better solutions, but for another time.
Report & test by Nick Gates <nickgatzgates@gmail.com>.
We want to export `pytest.MonkeyPatch` for the purpose of
type-annotating the `monkeypatch` fixture. For other fixtures we export
in this way, we also make direct construction of them (e.g.
`MonkeyPatch()`) private. But unlike the others, `MonkeyPatch` is also
widely used directly already, mostly because the `monkeypatch` fixture
only works in `function` scope (issue #363), but also in other cases. So
making it private will be annoying and we don't offer a decent
replacement yet.
So, let's just make direct construction public & documented.
Don't import `pytest` from within some `_pytest` modules since an
upcoming commit will import from them into `pytest`.
It would have been nice not to have to do it, so that internal plugins
look more like external plugins, but with the existing layout this seems
unavoidable.
When pytest was run on a directory containing a recursive symlink it failed
with ELOOP as the library was not able to determine the type of the
direntry:
src/_pytest/main.py:685: in collect
if not direntry.is_file():
E OSError: [Errno 40] Too many levels of symbolic links: '/home/florian/proj/pytest/tests/recursive'
This is fixed by handling ELOOP and other errors in the visit function in
pathlib.py, so the entries whose is_file() call raises an OSError with the
pre-defined list of error numbers will be exluded from the result.
The _ignore_errors function was copied from Lib/pathlib.py of cpython 3.9.
Fixes#7951