pkgcore / pychroot

a python library and cli tool that simplify chroot handling
https://pkgcore.github.io/pychroot/
BSD 3-Clause "New" or "Revised" License
32 stars 7 forks source link

Using pchroot in pytest script fails #28

Open BrendanSimon opened 4 years ago

BrendanSimon commented 4 years ago

The following script run with pytest fails with:

E               io.UnsupportedOperation: redirected stdin is pseudofile, has no fileno()

from pychroot import Chroot
import os

chroot_path = '/tmp/foo/bar'

os.makedirs( chroot_path, exist_ok=True)

def test_chroot () :
    with Chroot( chroot_path ) :
        answer = 42
        print( answer )

Output:

$ pytest chroot_test.py 
========================== test session starts ===========================
platform linux -- Python 3.6.7, pytest-5.3.2, py-1.8.1, pluggy-0.13.1
rootdir: /tmp
collected 1 item                                                         

chroot_test.py F                                                   [100%]

================================ FAILURES ================================
______________________________ test_chroot _______________________________

    def test_chroot () :
        with Chroot( chroot_path ) :
>           answer = 42

chroot_test.py:10: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def test_chroot () :
        with Chroot( chroot_path ) :
>           answer = 42

chroot_test.py:10: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pychroot.base.Chroot object at 0x7fe1ec9d0ef0>
frame = <frame object at 0x7fe1eb906048>, event = 'line', arg = None

    def __invoke_trace_funcs(self, frame, event, arg):
        """Invoke all trace funcs that have been injected.

        Once the injected functions have been executed all trace hooks are
        removed in order to minimize overhead.
        """
        try:
            for func in self.__injected_trace_funcs[frame]:
>               func(frame, event, arg)

/home/brendan/SEPL/brickstrap/brickstrap/ind-efd/venv_3.6.7/lib/python3.6/site-packages/snakeoil/contexts.py:237: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pychroot.base.Chroot object at 0x7fe1ec9d0ef0>
frame = <frame object at 0x7fe1eb906048>, event = 'line', arg = None

    def __exit_context(self, frame, event, arg):
        """Simple function to throw a ParentException."""
>       raise self.ParentException()
E       snakeoil.contexts.SplitExec.ParentException

/home/brendan/SEPL/brickstrap/brickstrap/ind-efd/venv_3.6.7/lib/python3.6/site-packages/snakeoil/contexts.py:212: ParentException

During handling of the above exception, another exception occurred:

    def test_chroot () :
        with Chroot( chroot_path ) :
            answer = 42
>           print(answer)

chroot_test.py:11: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pychroot.base.Chroot object at 0x7fe1ec9d0ef0>
exc_type = <class 'snakeoil.contexts.SplitExec.ParentException'>
exc_value = ParentException()
exc_traceback = <traceback object at 0x7fe1eb8f3308>

    def __exit__(self, exc_type, exc_value, exc_traceback):
        if self.childpid is not None:
            # make sure system tracing function is reset
            self.__revert_tracing(inspect.currentframe())
            # re-raise unknown exceptions from the parent
            if exc_type is not self.ParentException:
                raise exc_value

            # get exception from the child
            try:
                exc = self.__pipe.recv()
                self.locals = exc._locals
            except EOFError as e:
                exc = SystemExit(e)

            # handle child exiting abnormally
            if not isinstance(exc, SystemExit):
                os.waitpid(self.childpid, 0)
                self._exception_cleanup()
                sys.excepthook = self.__excepthook
>               raise exc
E               io.UnsupportedOperation: redirected stdin is pseudofile, has no fileno()

/home/brendan/SEPL/brickstrap/brickstrap/ind-efd/venv_3.6.7/lib/python3.6/site-packages/snakeoil/contexts.py:163: UnsupportedOperation
=========================== 1 failed in 0.11s ============================
(venv_3.6.7) brendan@osboxes:/tmp$ 
radhermit commented 4 years ago

pychroot often doesn't handle running within pytest's modified testing environment at this point without mocking out various aspects. In this case you'd need to run the tests with pytest's stdin/stdout capturing disabled (use the -s argument for pytest).

Patches accepted if you can figure out how to improve the situation, but I don't want to insert hacks into the codebase to work around specific test platform quirks.