Fonttools: Installation on macOS 10.12 with pip fails

Created on 6 Jan 2017  路  7Comments  路  Source: fonttools/fonttools

I鈥檓 trying to install fontTools system-wide using the command sudo -H pip install fonttools.

I think the system integrity protection disallows writing into /System/Library/Frameworks/Python.framework/Versions/2.7/share. If you run the same command sudo -H pip install fonttools again, no traceback happens, but fontTools are left in a broken state, e.g. the command line tools are not installed in /usr/bin/local.

$ sudo -H pip install fonttools
Collecting fonttools
  Using cached fonttools-3.4.0-py2.py3-none-any.whl
Installing collected packages: fonttools
Exception:
Traceback (most recent call last):
  File "/Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg/pip/basecommand.py", line 215, in main
    status = self.run(options, args)
  File "/Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg/pip/commands/install.py", line 342, in run
    prefix=options.prefix_path,
  File "/Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg/pip/req/req_set.py", line 784, in install
    **kwargs
  File "/Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg/pip/req/req_install.py", line 851, in install
    self.move_wheel_files(self.source_dir, root=root, prefix=prefix)
  File "/Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg/pip/req/req_install.py", line 1064, in move_wheel_files
    isolated=self.isolated,
  File "/Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg/pip/wheel.py", line 377, in move_wheel_files
    clobber(source, dest, False, fixer=fixer, filter=filter)
  File "/Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg/pip/wheel.py", line 316, in clobber
    ensure_dir(destdir)
  File "/Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg/pip/utils/__init__.py", line 83, in ensure_dir
    os.makedirs(path)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py", line 150, in makedirs
    makedirs(head, mode)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py", line 150, in makedirs
    makedirs(head, mode)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py", line 157, in makedirs
    mkdir(name, mode)
OSError: [Errno 1] Operation not permitted: '/System/Library/Frameworks/Python.framework/Versions/2.7/share'

Most helpful comment

Never install third party packages with sudo to the system python, use homebrew python or the python installer from Python.org; if you do want to use the system python pip install with --user option.

All 7 comments

Never install third party packages with sudo to the system python, use homebrew python or the python installer from Python.org; if you do want to use the system python pip install with --user option.

The system python is managed by the OS vendor (Apple, Canonical, etc), and is meant to be used by other OS built-in tools. Having pip mess things up in the vendored python is dangerous. The SIP protection since El Capital makes it harder to break these things, and for good reasons.
Installing a separate python distribution, or
using pip with --user option circumvents the need to require elevated root access. You may still have to add the user's bin folder to the $PATH -- there are plenty of tutorials online and it's not fonttools job to explain how to setup one's shell.

Having said that.. the problem in this particular case has to do with that manpage file which I tried once to get rid of, and which is trying to install itself in share folder in the framework python's prefix (controlled by SIP). We did put a conditional statement in setup.py to only install the manpage if on Linux, however the universal wheel is generated on a Linux CI. :(

The presence/absence of the man page is not worth making platform specific wheels.

So we have to decide:

  • either we build the universal wheel on the OSX travis, so that it will not contain the Linux-only man page; note that the sdist will still contain the man page, which will be installed depending on the platform which setup.py is run from;
  • or leave things as they are, and we ignore that a man page file is also installed on OSX and Windows (where it can't be used as such) from a Linux-generated wheel; but this creates the problem Jens is experiencing, whereby the share folder is SIP-protected on El Capitan and above.

of course, there's also a third option: i.e. don't install the man page, as it's outdated and only works on Linux.

The --user option works well for my use case, thank you :)

sudo -H pip install FontTools puts the module code into Library/Python/2.7/site-packages, which as far as I know is a valid location for system-wide module installations. So as you say, the problem is only the man page that pip attempts to install in a protected folder.

@jenskutilek another workaround if you wish to install fonttools==3.4.0 globally with the system /usr/bin/python, would be to tell pip to not use the pre-compiled wheel (as it normally does), but install from the source distribution (*.zip) instead, also available on PyPI repo.
The --no-binary option does just that (cf pip install --help for more info`):

sudo -H /usr/bin/python -m pip install --no-binary=fonttools fonttools==3.4.0

Since the current setup.py only installs the manpage if sys.platform == "linux2", and you run the abobe command on OSX, you don't get the man page installed.

However, I'm about to change that in the next release.

I think man pages are useful to have and it'd be bad to drop them just because Windows doesn't care, or Sierra has a SIP... Other projects like IPython or Sympy also offer man pages, and they install them unconditionally to $prefix/share/man, just like we used to do. I'll explain better later when I draft the PR.

To recap, the workarounds for installing fonttools outside of a virtualenv with the Apple Python for El Capitan or above are:

1) install without sudo for the current user only via pip install --user fonttools; make sure you also add /Users/$USER/Library/Python/2.7/bin/ to the $PATH in your .bash_profile, .bashrc, etc.

2) if you do do need to install globally in "/Library/Python/..." with sudo, you can tell pip to install the data files into a directory which is outside SIP protection, e.g. "/usr/local"

    sudo -H /usr/bin/python -m pip install --install-option="--install-data=/usr/local" fonttools

Let me know if something is not clear.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ivanov-v picture ivanov-v  路  11Comments

anthrotype picture anthrotype  路  7Comments

antonxheight picture antonxheight  路  3Comments

madig picture madig  路  10Comments

khaledhosny picture khaledhosny  路  11Comments