I'm packaging your module as an rpm package so I'm using the typical PEP517 based build, install and test cycle used on building packages from non-root account.
python3 -sBm build -w --no-isolation
because I'm calling build with --no-isolation I'm using during all processes only locally installed modules
install .whl file in </install/prefix> using 'installer` module
run pytest with $PYTHONPATH pointing to sitearch and sitelib inside </install/prefix>
build is performed in env which is cut off from access to the public network (pytest is executed with -m "not network")
Looks like failing unit is adapted to situation when pipdeptree script is in final its (final) installed destination.
Here is pytest output:
```console
+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-pipdeptree-2.10.0-2.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-pipdeptree-2.10.0-2.fc35.x86_64/usr/lib/python3.8/site-packages
+ /usr/bin/pytest -ra -m 'not network'
============================= test session starts ==============================
platform linux -- Python 3.8.17, pytest-7.4.0, pluggy-1.2.0
rootdir: /home/tkloczko/rpmbuild/BUILD/pipdeptree-2.10.0
plugins: mock-3.11.1
collected 61 items
tests/test_cli.py ............ [ 19%]
tests/test_models.py ................ [ 45%]
tests/test_non_host.py .. [ 49%]
tests/test_pipdeptree.py .F [ 52%]
tests/test_validate.py ...... [ 62%]
tests/render/test_graphviz.py ... [ 67%]
tests/render/test_mermaid.py .. [ 70%]
tests/render/test_text.py .................. [100%]
=================================== FAILURES ===================================
_________________________________ test_console _________________________________
def test_console() -> None:
> check_call([Path(sys.executable).parent / "pipdeptree", "--help"])
tests/test_pipdeptree.py:13:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib64/python3.8/subprocess.py:359: in check_call
retcode = call(*popenargs, **kwargs)
/usr/lib64/python3.8/subprocess.py:340: in call
with Popen(*popenargs, **kwargs) as p:
/usr/lib64/python3.8/subprocess.py:858: in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self =
args = [PosixPath('/usr/bin/pipdeptree'), '--help']
executable = b'/usr/bin/pipdeptree', preexec_fn = None, close_fds = True
pass_fds = (), cwd = None, env = None, startupinfo = None, creationflags = 0
shell = False, p2cread = -1, p2cwrite = -1, c2pread = -1, c2pwrite = -1
errread = -1, errwrite = -1, restore_signals = True, start_new_session = False
def _execute_child(self, args, executable, preexec_fn, close_fds,
pass_fds, cwd, env,
startupinfo, creationflags, shell,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite,
restore_signals, start_new_session):
"""Execute program (POSIX version)"""
if isinstance(args, (str, bytes)):
args = [args]
elif isinstance(args, os.PathLike):
if shell:
raise TypeError('path-like args is not allowed when '
'shell is true')
args = [args]
else:
args = list(args)
if shell:
# On Android the default shell is at '/system/bin/sh'.
unix_shell = ('/system/bin/sh' if
hasattr(sys, 'getandroidapilevel') else '/bin/sh')
args = [unix_shell, "-c"] + args
if executable:
args[0] = executable
if executable is None:
executable = args[0]
sys.audit("subprocess.Popen", executable, args, cwd, env)
if (_USE_POSIX_SPAWN
and os.path.dirname(executable)
and preexec_fn is None
and not close_fds
and not pass_fds
and cwd is None
and (p2cread == -1 or p2cread > 2)
and (c2pwrite == -1 or c2pwrite > 2)
and (errwrite == -1 or errwrite > 2)
and not start_new_session):
self._posix_spawn(args, executable, env, restore_signals,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite)
return
orig_executable = executable
# For transferring possible exec failure from child to parent.
# Data format: "exception name:hex errno:description"
# Pickle is not used; it is complex and involves memory allocation.
errpipe_read, errpipe_write = os.pipe()
# errpipe_write must not be in the standard io 0, 1, or 2 fd range.
low_fds_to_close = []
while errpipe_write < 3:
low_fds_to_close.append(errpipe_write)
errpipe_write = os.dup(errpipe_write)
for low_fd in low_fds_to_close:
os.close(low_fd)
try:
try:
# We must avoid complex work that could involve
# malloc or free in the child process to avoid
# potential deadlocks, thus we do all this here.
# and pass it to fork_exec()
if env is not None:
env_list = []
for k, v in env.items():
k = os.fsencode(k)
if b'=' in k:
raise ValueError("illegal environment variable name")
env_list.append(k + b'=' + os.fsencode(v))
else:
env_list = None # Use execv instead of execve.
executable = os.fsencode(executable)
if os.path.dirname(executable):
executable_list = (executable,)
else:
# This matches the behavior of os._execvpe().
executable_list = tuple(
os.path.join(os.fsencode(dir), executable)
for dir in os.get_exec_path(env))
fds_to_keep = set(pass_fds)
fds_to_keep.add(errpipe_write)
self.pid = _posixsubprocess.fork_exec(
args, executable_list,
close_fds, tuple(sorted(map(int, fds_to_keep))),
cwd, env_list,
p2cread, p2cwrite, c2pread, c2pwrite,
errread, errwrite,
errpipe_read, errpipe_write,
restore_signals, start_new_session, preexec_fn)
self._child_created = True
finally:
# be sure the FD is closed no matter what
os.close(errpipe_write)
self._close_pipe_fds(p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite)
# Wait for exec to fail or succeed; possibly raising an
# exception (limited in size)
errpipe_data = bytearray()
while True:
part = os.read(errpipe_read, 50000)
errpipe_data += part
if not part or len(errpipe_data) > 50000:
break
finally:
# be sure the FD is closed no matter what
os.close(errpipe_read)
if errpipe_data:
try:
pid, sts = os.waitpid(self.pid, 0)
if pid == self.pid:
self._handle_exitstatus(sts)
else:
self.returncode = sys.maxsize
except ChildProcessError:
pass
try:
exception_name, hex_errno, err_msg = (
errpipe_data.split(b':', 2))
# The encoding here should match the encoding
# written in by the subprocess implementations
# like _posixsubprocess
err_msg = err_msg.decode()
except ValueError:
exception_name = b'SubprocessError'
hex_errno = b'0'
err_msg = 'Bad exception data from child: {!r}'.format(
bytes(errpipe_data))
child_exception_type = getattr(
builtins, exception_name.decode('ascii'),
SubprocessError)
if issubclass(child_exception_type, OSError) and hex_errno:
errno_num = int(hex_errno, 16)
child_exec_never_called = (err_msg == "noexec")
if child_exec_never_called:
err_msg = ""
# The error must be from chdir(cwd).
err_filename = cwd
else:
err_filename = orig_executable
if errno_num != 0:
err_msg = os.strerror(errno_num)
> raise child_exception_type(errno_num, err_msg, err_filename)
E FileNotFoundError: [Errno 2] No such file or directory: PosixPath('/usr/bin/pipdeptree')
/usr/lib64/python3.8/subprocess.py:1720: FileNotFoundError
=============================== warnings summary ===============================
../../../../../usr/lib/python3.8/site-packages/pip/_vendor/pkg_resources/__init__.py:121
/usr/lib/python3.8/site-packages/pip/_vendor/pkg_resources/__init__.py:121: DeprecationWarning: pkg_resources is deprecated as an API
warnings.warn("pkg_resources is deprecated as an API", DeprecationWarning)
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================== short test summary info ============================
FAILED tests/test_pipdeptree.py::test_console - FileNotFoundError: [Errno 2] ...
=================== 1 failed, 60 passed, 1 warning in 3.58s ====================
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-a98a68de-c4dc-41aa-9fa7-c2b2bb9c212b/test_rmtree_errorhandler_rerai0
: [Errno 39] Directory not empty: 'test_rmtree_errorhandler_rerai0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-a98a68de-c4dc-41aa-9fa7-c2b2bb9c212b/test_rmtree_errorhandler_reado0
: [Errno 39] Directory not empty: 'test_rmtree_errorhandler_reado0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-a98a68de-c4dc-41aa-9fa7-c2b2bb9c212b/test_safe_delete_no_perms0
: [Errno 39] Directory not empty: 'test_safe_delete_no_perms0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-a98a68de-c4dc-41aa-9fa7-c2b2bb9c212b/test_safe_set_no_perms0
: [Errno 39] Directory not empty: 'test_safe_set_no_perms0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-a98a68de-c4dc-41aa-9fa7-c2b2bb9c212b/test_safe_get_no_perms0
: [Errno 39] Directory not empty: 'test_safe_get_no_perms0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-a98a68de-c4dc-41aa-9fa7-c2b2bb9c212b
: [Errno 39] Directory not empty: '/tmp/pytest-of-tkloczko/garbage-a98a68de-c4dc-41aa-9fa7-c2b2bb9c212b'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-243f61a2-9777-4aa0-8f48-fd41e57a7e57/test_rmtree_errorhandler_rerai0
: [Errno 39] Directory not empty: 'test_rmtree_errorhandler_rerai0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-243f61a2-9777-4aa0-8f48-fd41e57a7e57/test_rmtree_errorhandler_reado0
: [Errno 39] Directory not empty: 'test_rmtree_errorhandler_reado0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-243f61a2-9777-4aa0-8f48-fd41e57a7e57/test_safe_delete_no_perms0
: [Errno 39] Directory not empty: 'test_safe_delete_no_perms0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-243f61a2-9777-4aa0-8f48-fd41e57a7e57/test_safe_set_no_perms0
: [Errno 39] Directory not empty: 'test_safe_set_no_perms0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-243f61a2-9777-4aa0-8f48-fd41e57a7e57/test_safe_get_no_perms0
: [Errno 39] Directory not empty: 'test_safe_get_no_perms0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-243f61a2-9777-4aa0-8f48-fd41e57a7e57
: [Errno 39] Directory not empty: '/tmp/pytest-of-tkloczko/garbage-243f61a2-9777-4aa0-8f48-fd41e57a7e57'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-551a0838-a191-49d0-bf8d-74a9a73569a6/test_rmtree_errorhandler_rerai0
: [Errno 39] Directory not empty: 'test_rmtree_errorhandler_rerai0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-551a0838-a191-49d0-bf8d-74a9a73569a6/test_rmtree_errorhandler_reado0
: [Errno 39] Directory not empty: 'test_rmtree_errorhandler_reado0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-551a0838-a191-49d0-bf8d-74a9a73569a6/test_safe_delete_no_perms0
: [Errno 39] Directory not empty: 'test_safe_delete_no_perms0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-551a0838-a191-49d0-bf8d-74a9a73569a6/test_safe_set_no_perms0
: [Errno 39] Directory not empty: 'test_safe_set_no_perms0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-551a0838-a191-49d0-bf8d-74a9a73569a6/test_safe_get_no_perms0
: [Errno 39] Directory not empty: 'test_safe_get_no_perms0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-551a0838-a191-49d0-bf8d-74a9a73569a6
: [Errno 39] Directory not empty: '/tmp/pytest-of-tkloczko/garbage-551a0838-a191-49d0-bf8d-74a9a73569a6'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-22dd1b10-b531-47d8-bf63-536d87eb7560/test_rmtree_errorhandler_rerai0
: [Errno 39] Directory not empty: 'test_rmtree_errorhandler_rerai0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-22dd1b10-b531-47d8-bf63-536d87eb7560/test_rmtree_errorhandler_reado0
: [Errno 39] Directory not empty: 'test_rmtree_errorhandler_reado0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-22dd1b10-b531-47d8-bf63-536d87eb7560/test_safe_delete_no_perms0
: [Errno 39] Directory not empty: 'test_safe_delete_no_perms0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-22dd1b10-b531-47d8-bf63-536d87eb7560/test_safe_set_no_perms0
: [Errno 39] Directory not empty: 'test_safe_set_no_perms0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-22dd1b10-b531-47d8-bf63-536d87eb7560/test_safe_get_no_perms0
: [Errno 39] Directory not empty: 'test_safe_get_no_perms0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-22dd1b10-b531-47d8-bf63-536d87eb7560
: [Errno 39] Directory not empty: '/tmp/pytest-of-tkloczko/garbage-22dd1b10-b531-47d8-bf63-536d87eb7560'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-d2c4e759-c10c-48cc-b0c0-bbcef3995abe/test_rmtree_errorhandler_rerai0
: [Errno 39] Directory not empty: 'test_rmtree_errorhandler_rerai0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-d2c4e759-c10c-48cc-b0c0-bbcef3995abe/test_rmtree_errorhandler_reado0
: [Errno 39] Directory not empty: 'test_rmtree_errorhandler_reado0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-d2c4e759-c10c-48cc-b0c0-bbcef3995abe/test_safe_delete_no_perms0
: [Errno 39] Directory not empty: 'test_safe_delete_no_perms0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-d2c4e759-c10c-48cc-b0c0-bbcef3995abe/test_safe_set_no_perms0
: [Errno 39] Directory not empty: 'test_safe_set_no_perms0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-d2c4e759-c10c-48cc-b0c0-bbcef3995abe/test_safe_get_no_perms0
: [Errno 39] Directory not empty: 'test_safe_get_no_perms0'
warnings.warn(
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:95: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-d2c4e759-c10c-48cc-b0c0-bbcef3995abe
: [Errno 39] Directory not empty: '/tmp/pytest-of-tkloczko/garbage-d2c4e759-c10c-48cc-b0c0-bbcef3995abe'
warnings.warn(
```
I'm packaging your module as an rpm package so I'm using the typical PEP517 based build, install and test cycle used on building packages from non-root account.
python3 -sBm build -w --no-isolation
build
with--no-isolation
I'm using during all processes only locally installed modulescut off from access to the public network
(pytest is executed with-m "not network"
)Looks like failing unit is adapted to situation when
pipdeptree
script is in final its (final) installed destination. Here is pytest output:Here is list of installed modules in build env