Using sudo in commands ignores basepython

Issue #325 on hold
jtpereyda
created an issue

Problem

When using sudo in the commands list, the system default python is used instead of tox's basepython.

Example

tox.ini

[tox]
envlist = py27,py34

[testenv]
whitelist_externals=sudo
commands =
    python -c "import sys; print(sys.version)"
    sudo python -c "import sys; print(sys.version)"

Output

Notice that sudo python runs 2.7, regardless of tox's specification. Plain python switches as expected.

$ tox
GLOB sdist-make: /home/joshpere/code/tox-isolate/setup.py
py27 recreate: /home/joshpere/code/tox-isolate/.tox/py27
py27 inst: /home/joshpere/code/tox-isolate/.tox/dist/boofuzz-0.0.3.dev13.zip
py27 installed: backports.ssl-match-hostname==3.5.0.1,boofuzz==0.0.3.dev13,certifi==2016.2.28,Flask==0.10.1,future==0.15.2,impacket==0.9.14,itsdangerous==0.24,Jinja2==2.8,MarkupSafe==0.23,pydot2==1.0.33,pyparsing==2.1.1,pyserial==3.0.1,tornado==4.0.2,Werkzeug==0.11.5
py27 runtests: PYTHONHASHSEED='529845781'
py27 runtests: commands[0] | python -c import sys; print(sys.version)
2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2]
py27 runtests: commands[1] | sudo python -c import sys; print(sys.version)
2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2]
py34 inst-nodeps: /home/joshpere/code/tox-isolate/.tox/dist/boofuzz-0.0.3.dev13.zip
py34 installed: boofuzz==0.0.3.dev13,certifi==2016.2.28,Flask==0.10.1,future==0.15.2,impacket==0.9.14,itsdangerous==0.24,Jinja2==2.8,MarkupSafe==0.23,pydot2==1.0.33,pyparsing==2.1.1,pyserial==3.0.1,tornado==4.0.2,Werkzeug==0.11.5
py34 runtests: PYTHONHASHSEED='529845781'
py34 runtests: commands[0] | python -c import sys; print(sys.version)
3.4.3 (default, Oct 14 2015, 20:28:29) 
[GCC 4.8.4]
py34 runtests: commands[1] | sudo python -c import sys; print(sys.version)
2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2]
____________________________________________________________________________________ summary _____________________________________________________________________________________
  py27: commands succeeded
  py34: commands succeeded
  congratulations :)

Conclusion

Any ideas how to workaround? I'm not sure how tox controls what python is, but that somehow needs to get passed through sudo.

Didn't work:

  • sudo -E
  • sudo -E -H

Perhaps there's some way to access the current Python version through the environment.

Edit:

Use Case

Some of my unit tests require sudo. At first I was running sudo tox, but this results in build artifacts onwed by root. The funky workaround was to chown everything back to the normal user, but I'm looking for something a little cleaner.

I then switched to running just the test commands as sudo, which led to my current situation.

Comments (6)

  1. jtpereyda reporter

    TL;DR

    Solution: Use {envpython}, e.g. sudo {envpython} -m pytest. More on substitutions.

    Relevant Code for Reference

    I found some relevant code in tox/tox/venv.py VirtualEnv._pcall(). This method uses getcommandpath() to identify the executable, searching the virtualenv bin directory before doing a normal execuatable lookup.

    The catch here is that _pcall runs the lookup on args[0], which is the first executable. So if the command is sudo python ..., sudo gets the special lookup, but then sudo uses the system default python.

    Thankfully, tox provides a set of helpful substitutions, including {envpython}, which references the virtual environment python explicitly.

  2. Log in to comment