Using a private pypi repository with pypiserver (and alternatives)
- Create your own PyPi server
- Use Dumb PyPi to generate and farm out the context to a simple web server.
- Some other options such as PyPiCloud which falls in between the two above.
Depending on your workflow, and how frequently and many packages are updated, PyPi server may be the most suitable, it does require an application server (python/bottle) to function, but does not require the whole thing to be rebuilt and pushed as the static version, and can handle authentication for actions (configurable).
For this case, to make things even easier, we will use the PyPiServer docker image to get going even faster, if you do not use Docker then the full installation can be achieved, or use of the static solutions mentioned.
On your Docker host extract or checkout the docker project for PyPiServer.
$ mkdir /srv/pypi $ printf "USER:$(openssl passwd -crypt PASSWORD)\n" >> .htpasswd $ docker run -t -i --rm \ -h pypi.mydomain.com \ -v /srv/pypi:/srv/pypi:rw \ -p <some_external_port>:80 \ --name pypi \ codekoala/pypi
You should now have a pypi server accessible on localhost:
Uploading to your server
The standard layour for any package to upload to PyPi looks like:
The setup.cfg file is rather simple and looks like so:
[metadata] description-file = README.md
As for setup.py, it will look like:
from distutils.core import setup setup( name = 'my_package', packages = ['my_package'], # this must be the same as the name above install_requires=, # list any dependencies that must be installed to use this version = '0.0.1', description = 'My useful python library', author = 'Your Name Here', author_email = 'firstname.lastname@example.org', url = 'https://gitlab.com/your_name/your_repo', # Where the repo is download_url = 'https://gitlab.com/your_name/your_repo/some_archive.tar.gz', # Archive you can curl keywords = ['utilities'], # any useful keywords classifiers =  )
__init__.py will expose the classes like:
from some_utility import Widget
Also, that is assuming some_utility.py looks like :
class Widget: def __init__(self): pass
One more thing, edit your ~/.pypirc :::ini [server-login] repository: https://pypi.mydomain.com username: USER password: PASSWORD
Now we can upload!
$ python3 setup.py sdist upload -r https://pypi.mydomain.com
Using pip to install
There are a couple of ways to do this:
Command line options
When you invoke pip, you can specify the private server as per below:
$ pip3 install my_package--trusted-host pypi.mydomain.com --index-url https://pypi.mydomain.com
[global] extra-index-url = http://pypi.mydomain.com/simple/
That's it, fire it up and you should see it go. You can also install packages that are on the regular pypi even if you have specified your private server, however I imagine conflicting names would install first from the private repo.
Using Dumb PyPi, etc
I could not get Dumb PyPi to work due to an import error with pip.wheel (not sure if a versioning issue, so I will not cover it in detail.
The layout of the python package is the same as the above when using the PyPiServer, as well as the client side installation using pip.
So the generation of the static html and upload to a webserver (and subsequent location of web content) will be what is different, depending on your needs.
Using a custom/private PyPi to distribute your python packages is fairly straight forward. It is cleaner and more elegant than using things such as git submodules and allows the packages to be delivered to almost any python installation.