Many companies use an internal PyPI server for storing their proprietary python packages. This makes managing python libraries and application dependencies so much easier. But unfortunately this also makes it easy for people to accidentally upload their private code to the public PyPI unintentionally.
Lucky for us, there’s a cool extension to setuptools called restricted_pkg! Unlucky for us, it leaves something to be desired in terms of user experience. Let’s say we have an example library called xl which uses restricted_pkg to prevent accidental uploads. Building on the usage given in restricted_pkg‘s docs, our setup.py will go like this:
from setuptools import find_packages from restricted_pkg import setup setup(name='xl', version='0.1.0', packages=['xl'], private_repository="https://pypi.example.com", install_requires=[ "distribute", "restricted_pkg", ], ) |
So far so good. But when we try to pip install that in a clean virtualenv, its going to fail.
$ pip install -e xl/ Obtaining file:///Users/codyaray/xl Complete output from command python setup.py egg_info: Traceback (most recent call last): File "", line 20, in File "/Users/codyaray/xl/setup.py", line 2, in from restricted_pkg import setup ImportError: No module named restricted_pkg ---------------------------------------- Command "python setup.py egg_info" failed with error code 1 in /Users/codyaray/xl |
That makes us sad. Why must restricted_pkg make our users do more work? No!
The workaround I’ve developed is to check whether restricted_pkg is already installed and auto-install it if its missing. Since this is a standard python import, we can’t really rely on setuptools magic. The simplest most concise way I’ve found so far is to wrap the import in a try/catch and programmatically invoke pip (in a hacky abusive way).
try: from restricted_pkg import setup except ImportError: import pip pip.main(['install', 'restricted_pkg']) from restricted_pkg import setup setup(name='xl', version='0.1.0', packages=['xl'], private_repository='https://pypi.example.com') |
Its a minimum of boilerplate, very comprehensible, and gets the job done.
0 Responses
Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.