Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect confcutdir inferred when rootdir is under a symlink directory #12291

Open
buddly27 opened this issue May 6, 2024 · 0 comments
Open
Labels
topic: collection related to the collection phase type: bug problem that needs to be addressed

Comments

@buddly27
Copy link

buddly27 commented May 6, 2024

When a test directory is nested within a symlinked directory, it can lead to errors when the 'rootdir' or the invocation directory targets the unresolved path, especially when the symlink targets a different storage structure.

> ln -s /tmp/test /path/to/test/path
> cd /tmp/test
> pytest --rootdir=/tmp/test .

==================================== ERRORS ====================================
________________________ ERROR collecting test session _________________________
...
/usr/lib/python3.10/path lib.py:1097: PermissionError
=========================== Short test summary info ============================
ERROR ../../path/to/test/path::dir - PermissionError: [Errno 13] Permission denied: '/..../__init__.py'
=============================== 1 error in 0.14s ===============================

> pytest --rootdir=. /tmp/test 
# Same error ...

This issue does not occur when both the 'rootdir' and invocation directory use the same path (resolved or unresolved).

The invocation directory defaults to Path.cwd() which resolves the symlink, and relative entries seem to be normalized via pathlib.absolutepath (using os.path.abspath under the hood), which also returns a resolved path in some situations:

> pwd
/tmp/test

> python -c "import pathlib; print(pathlib.Path.cwd())"
/path/to/test/path

> python -c "import os; print(os.path.abspath('.'))"
/path/to/test/path

By default, the 'confcutdir' value is inferred from the 'rootdir' value, which is inferred from the invocation path, so it doesn't seem to be a problem. But in cases where the invocation path is defined to use the resolved path, while the 'rootdir' value is defined to use the unresolved path (or vice versa), the Session collector may encounter difficulties determining where to stop when searching for configs:

pytest/src/_pytest/main.py

Lines 861 to 869 in 84e59af

paths = [argpath]
# Add relevant parents of the path, from the root, e.g.
# /a/b/c.py -> [/, /a, /a/b, /a/b/c.py]
if module_name is None:
# Paths outside of the confcutdir should not be considered.
for path in argpath.parents:
if not pm._is_in_confcutdir(path):
break
paths.insert(0, path)

This issue could be solved by automatically resolving the value used for 'rootdir', but I'm not sure if there are any drawbacks to this approach (aside from performance).

I ran these tests on MacOS and Linux using Pytest 8.2.0 and Python 3.10.

I also setup a small repository to reproduce the errors via a Github workflow for more details:
https://github.com/buddly27/pytest-issue/actions/runs/8973032152/job/24642315352

buddly27 added a commit to python-cmake/pytest-cmake that referenced this issue May 6, 2024
buddly27 added a commit to python-cmake/pytest-cmake that referenced this issue May 6, 2024
@Zac-HD Zac-HD added type: bug problem that needs to be addressed topic: collection related to the collection phase labels May 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: collection related to the collection phase type: bug problem that needs to be addressed
Projects
None yet
Development

No branches or pull requests

2 participants