26

I'm using python 2.7.6 on Ubuntu 14.04.2 LTS. I'm using mock to mock some unittests and noticing when I import mock it fails importing wraps.

Not sure if there's a different version of mock or six I should be using for it's import to work? Couldn't find any relevant answers and I'm not using virtual environments.

mock module says it's compatible with python 2.7.x: https://pypi.python.org/pypi/mock

mock==1.1.3 six==1.9.0

Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from mock import Mock
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/mock/__init__.py", line 2, in <module>
    import mock.mock as _mock
  File "/usr/local/lib/python2.7/dist-packages/mock/mock.py", line 68, in <module>
    from six import wraps
ImportError: cannot import name wraps

also tried with sudo with no luck.

$ sudo python -c 'from six import wraps'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: cannot import name wraps
Michael
  • 1,577
  • 1
  • 18
  • 33

9 Answers9

31

Installed mock==1.0.1 and that worked for some reason. (shrugs)

edit: The real fix for me was to updated setuptools to the latest and it allowed me to upgrade mock and six to the latest. I was on setuptools 3.3. In my case I also had to remove said modules by hand because they were owned by OS in '/usr/local/lib/python2.7/dist-packages/'

check versions of everything

pip freeze | grep -e six -e mock
easy_install --version

Update everything

wget https://bootstrap.pypa.io/ez_setup.py -O - | sudo python
pip install mock --upgrade
pip install six --upgrade

Thanks @lifeless

Michael
  • 1,577
  • 1
  • 18
  • 33
  • 2
    Thats because mock 1.0.1 didn't depend on six. – lifeless Jul 28 '15 at 22:07
  • ok, so I think this means we have to look at the minimum version handling logic again. I'll open a ticket – lifeless Jul 28 '15 at 23:28
  • 2
    hmm now I have the same problem on my Mac even with the last versions so I'm not sure what that means. setuptools==18.0.1 , mock==1.3.0, six==1.9.0 – Michael Jul 28 '15 at 23:33
  • 2
    Thanks, `pip install mock==1.0.1` helps. – Bunyk Sep 01 '15 at 12:39
  • 2
    I've come back to this so many times. If I could vote it up more than once I would. Thank you for this answer. – emptyflash Dec 16 '15 at 17:30
  • 1
    Does the 'remove said modules by hand' part bug anyone else? It bugs me. With the python ecosystem we have at our disposal, I feel like we shouldn't have to resort to such tactics. – killthrush Aug 27 '16 at 14:00
19

I encountered the same issue on my mac, which I was able to fix by realizing that my python's sys.path contained both

/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/

and

/Library/Python/2.7/site-packages/

with the former earlier than the latter.

You can test if this is happening to you by running the following in the python console.

import six
six.__version__

my python was loading an outdated six.py from the former directory (which didn't have wrapper), even though pip had installed a newer version six in the second directory. (It seems mac's framework comes with a version of six by default.)

I was able to fix it by moving six.py and six.pyc out of the first directory (requires sudo access), so that python would find the newer version of six in the second directory. I'm sure you could also change the ordering of the paths in sys.path.

To find the older version of six that need to be deleted run this from the terminal console

find /System/Library/Frameworks/Python.framework/Versions -name six.py*
galv
  • 210
  • 2
  • 7
6

so mock 1.1.1 and above defines a versioned requirement on six 1.7 or above:

https://github.com/testing-cabal/mock/blob/master/requirements.txt#L6

This gets reflected into setuptools metadata by pbr, which there is a versioned setup_requires dependency on:

https://github.com/testing-cabal/mock/blob/master/setup.py#L17

So there are a couple of possibilities: 1) six 1.7 is not new enough 2) there's a distro six package claiming to be 1.9.0 that doesn't have wraps for some reason 3) the setuptools in use didn't integrate properly with pbr and deps are missing 4) the wheel metadata isn't being interrogated properly by your pip/setuptools combination.

We do have a hard requirement for setuptools 17.1, and that was only explicitly reported by setup.py more recently. I'd love it if you can figure which of these is the case and update https://github.com/testing-cabal/mock/issues/298 so that we can fix whatever interaction is leading to this silent failure of setup.py / wheels.

lifeless
  • 4,045
  • 1
  • 17
  • 6
  • Thanks. I do see that this particular box has setuptools 3.3. Trying to upgrade that hoping that's the problem. – Michael Jul 28 '15 at 20:02
3

On Mac OSX, the previously installed version of six was blocking my upgraded version from being used. I verified this, as previously suggested by running the following in my interpreter:

import six
six.__version__

To fix this I moved the file:

mv/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/six.py 
/tmp/old_six.py

This is stated already in another answer on this site, but I wanted to provide a more streamlined response.

  • While your answer provides the solution, in cases like this the best thing you can do to make the other answer standout is to upvote and provide any other remarks in a comment. – TayTay Nov 12 '15 at 16:44
  • I cannot comment because my rep is too low. I cannot even upvote and affect the response. However, once my rep gets high enough I promise to do so. Thank you. – Control Complex Nov 12 '15 at 17:18
2

I originally had an issue with old "OS-owned" versions of and pip/setuptools. After I installed pip manually, like so:

wget https://bootstrap.pypa.io/get-pip.py
sudo python get-pip.py
sudo ln -s /usr/local/bin/pip /usr/bin/pip

And then installing the latest version of pip, mock and six, I still had the problem you've described above. Turns out that I had six installed twice in:

/usr/lib/python2.7/dist-packages/

and in

/usr/local/lib/python2.7/dist-packages/

After I removed the six from /usr/lib/ it worked fine: rm /usr/lib/python2.7/dist-packages/*six*

VitalyB
  • 12,397
  • 9
  • 72
  • 94
1

I did a pip install of six==1.9.0 and it took the new version. It seems like mock==1.3.0 doesn't properly define the version of six that it needs to get wraps support.

Jordan
  • 31,971
  • 6
  • 56
  • 67
  • We specify 1.7 - https://github.com/testing-cabal/mock/blob/master/requirements.txt#L6 - which does define wraps. All the reports that we've dug into in detail have actually had incorrect pre-existing installs of six being loaded. Happy to help you debug your case more if you can provide some details. – lifeless Sep 02 '15 at 10:00
  • @lifeless I'm pretty sure the issue is that you have a >= requirement, so if somehow in the requirements chain somebody already has an old version of six, < 1.9.0 but >= 1.7, it won't work properly, but if I *explicitly* version it separately in my requirements, it is set to 1.9.0, which mock is of course satisfied by. – Jordan Sep 02 '15 at 15:07
  • If you pip install a project X which depends on Y>=N, and Y < N is already installed, pip will install the current release of Y. e.g. >= is not the problem. However, if you are using a requirements file and already specify Y then the dependency that X has is ignored.... get me a transcript of what happens, so we can reproduce it and we can see what is happening. – lifeless Sep 02 '15 at 22:33
1

Another solution is setting your PYTHONPATH environment variable to point to the installed packages.

Setting my environment variable in my bash config so that:

PYTHONPATH=/Library/Python/2.7/site-packages

Allowed me to run tests in terminal (without removing/renaming any libraries, etc).

However, when using PyCharm, it was less-than-helpfully not correctly importing this environment variable. Even though PyCharm was showing as including parent variables (with that listed in the ones it showed importing), it seems this import wasn't working correctly.

Manually setting the environment variable to the above in the PyCharm run configuration resolves this.

I am unsure if PyCharm overwrites the PYTHONPATH variable after importing it from system environment variables or some other trickery, but this did resolve the error for me.

enderland
  • 13,825
  • 17
  • 98
  • 152
0

Though you aren't using a virtual environment like virtualenv, it's certainly a great use case for it. By sandboxing your Python installation and all the dependencies for your project, you can avoid hacking away at the global/default python installation entirely, which is where a lot of the complexity/difficulty comes from.

This is what I used when I got the wraps error - requirements.txt contains mock==2.0.0 and six==1.10.0:

cd <my_project>
virtualenv venv
source venv/bin/activate
sudo pip install -r requirements.txt

Not only is this simpler to use in my opinion, it's also simpler to document for people who might want to run your code.

killthrush
  • 4,859
  • 3
  • 35
  • 38
0

I found a interesting things! There is a file named "functools.py" in my project root path, and while I run my project , pycharm will raise ImportError. So I rename my file fix this problem~~