Reputation: 2482
I have a situation where I need to mock an executable (pip) with a shell script I wrote (mock_pip) for a unit test, so I use the subprocess module to get access to the shell. I've tried a lot of things like:
subprocess.Popen("alias pip='/some/dir/mock_pip'", shell=True) # Create alias
subprocess.Popen("pip", shell=True) # Try to use new alias, but still points towards real pip instead
subprocess.Popen("alias pip='/some/dir/mock_pip'"; "pip", shell=True)
# Once again it uses the real pip instead of mock
I even tried this method by changing the ~/.bashrc
file in my home directory (also during the unit test using subprocess) but that doesn't work either.
I'm imagining the problem is that subprocess erases the environment after every command that is called, meaning my alias doesn't exist when I try calling it.
How can I cause mock_pip
to be used instead of pip
in a bash script started from my Python process?
Upvotes: 0
Views: 2757
Reputation: 295696
If your goal here is to provide a mock implementation of pip, you can do that in a few ways:
The former is shell-version-specific, so we'll cover the latter first:
subprocess.Popen('pip', env={'PATH': '/path/to/mock/dir:' + os.environ['PATH']})
...where your /path/to/mock/dir
is a location with a pip
executable that performs your desired operations.
The latter, for post-shellshock upstream bash releases (and prior versions of bash with shellshock fixes compatible with the protocol for exported functions that upstream arrived on):
env = dict(os.environ)
env['BASH_FUNC_pip%%'] = '() { mock_pip "$@"; }'
subprocess.Popen(['bash', '-c', 'pip'], shell=False, env=env)
Note the shell=False
here, with the explicit ['bash', '-c', ...]
-- that ensures that it's bash
(which will honor the exported function) rather than the default shell sh
invoked.
Upvotes: 3