Description
We encountered an issue where socketserver
module that is installed by future
library completely shadows the built-in SocketServer
module and breaks imports.
Steps to reproduce
- We use Mac OS which has a case-insensitive file system
- Run a container with your working directory mounted into it
docker run -it --rm -v `pwd`:/opt/x python:2.7.15 bash
$ cd /opt/x/
- Create a venv and install
future
$ virtualenv test
$ source test/bin/activate
$$ pip install future
$$ deactivate
- Run following script
import os
import sys
activate_this = '/opt/x/test/bin/activate_this.py'
execfile(activate_this, dict(__file__=activate_this))
import SocketServer
print(SocketServer)
import socketserver
print(socketserver)
print(SocketServer.TCPServer)
Results
The above script is using the activate_this.py
method of activating the virtualenv. It's ugly but it is supported. It results in following sys.path
:
['/opt/x/test/lib/python2.7/site-packages', '/opt/x', '/usr/local/lib/python27.zip', '/usr/local/lib/python2.7', '/usr/local/lib/python2.7/plat-linux2', '/usr/local/lib/python2.7/lib-tk', '/usr/local/lib/python2.7/lib-old', '/usr/local/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/site-packages']
Note that site-packages
dir is searched first.
Both imports result in:
import SocketServer
print(SocketServer)
<module 'SocketServer' from '/opt/x/test/lib/python2.7/site-packages/SocketServer/__init__.pyc'>
import socketserver
print(socketserver)
<module 'socketserver' from '/opt/x/test/lib/python2.7/site-packages/socketserver/__init__.pyc'>
The statement from SocketServer import *
inside the socketserver/__init__.py
results in module importing itself, so the further attempt to access SocketServer.TCPServer
fails.
Expectation
Installing future
package doesn't break existing code on case-insensitive file systems.
Note: importing
SocketServer
from within virtualenv that is activated assource test/bin/activate
doesn't result in an issue, since it results (for some reason) in a differentsys.path
where the system lib directory is searched first, so built-in module is not shadowed.