2015-01-22 22:05:35 +00:00
<!DOCTYPE html>
< html >
< head >
< meta charset = "utf-8" >
< meta http-equiv = "X-UA-Compatible" content = "IE=edge,chrome=1" >
2015-12-08 15:40:50 +00:00
< title > balkian.com - Publishing on PyPi
2015-12-08 14:19:11 +00:00
< / title >
2015-01-22 22:05:35 +00:00
< meta name = "viewport" content = "width=device-width" >
<!-- syntax highlighting CSS -->
2015-01-22 23:22:30 +00:00
< link rel = "stylesheet" href = "/theme/css/solarized.css" >
2015-01-22 22:05:35 +00:00
<!-- <link href="/css/bootstrap.css" rel="stylesheet"> -->
< link rel = "stylesheet" href = "/theme/font-awesome/css/font-awesome.min.css" >
<!-- <link rel="stylesheet" href="/css/bootstrap - responsive.min.css"> -->
<!-- Custom CSS -->
< link rel = "stylesheet" media = "only screen" href = "/theme/css/main.css" >
< link rel = "stylesheet" media = "only screen and (min-width: 0px) and (max-width: 599px)" href = "/theme/css/main-xs.css" >
< link rel = "stylesheet" media = "only screen and (min-width: 600px) and (max-width: 1199px)" href = "/theme/css/main-medium.css" >
< link rel = "stylesheet" media = "only screen and (min-width: 1200px)" href = "/theme/css/main-desktop.css" >
< link href = 'http://fonts.googleapis.com/css?family=Open+Sans:300|Comfortaa' rel = 'stylesheet' type = 'text/css' >
< / head >
< body >
< div id = "container" class = "container" >
< header id = "header" >
< div id = "navbar" class = "navbar navbar-inverse navbar-static-bottom" >
< div class = "container" >
< div class = "navbar-header" >
< ul class = "nav navbar-nav" >
< li class = "active" >
2015-12-08 16:13:36 +00:00
< a href = "/" > < i class = "fa fa-home fa-large" > < / i > < / a >
2015-12-07 22:12:27 +00:00
< / li >
< li >
< a href = "/pages/projects.html" > Projects< / a >
< / li >
2015-12-07 20:57:42 +00:00
< li >
2015-12-08 00:06:02 +00:00
< a href = "//jfernando.es" target = "_blank" > CV< / a >
2015-12-07 20:57:42 +00:00
< / li >
2015-01-22 22:05:35 +00:00
< / ul >
2015-12-07 22:12:27 +00:00
< / div >
2015-01-22 22:05:35 +00:00
< / div >
< / div >
< / header >
< div id = "contentwrapper" >
< div id = "sidebar" >
< div id = "badge" class = "flip-container" ontouchstart = "this.classList.toggle('hover');" >
< div class = "flipper sticky" >
< div class = "front" >
<!-- front content -->
< img id = "avatar" width = 100% src = "/theme/img/me.png" >
< / div >
< div class = "back" >
<!-- back content -->
2015-12-07 20:57:42 +00:00
< img id = "picture" width = 100% src = "/theme/img/me-bat.png" >
2015-01-22 22:05:35 +00:00
< / div >
< / div >
< / div >
2015-12-08 12:42:59 +00:00
< div id = "about" style = "clear:both;" >
<!-- <h1 class="title">Interests</h1> -->
< div class = "icons" >
2015-12-08 16:13:36 +00:00
< span class = "coolicon" > < span class = "fa fa-stack" > < i class = "fa fa-square-o fa-stack-2x" > < / i > < i class = "fa fa-stack-1x fa-linux" > < / i > < / span > < span class = "explanation" > Linux lover< / span > < / span >
< span class = "coolicon" > < span class = "fa fa-stack" > < i class = "fa fa-square-o fa fa-stack-2x" > < / i > < i class = "fa fa-android" > < / i > < / span > < span class = "explanation" > Android dev< / span > < / span >
< span class = "coolicon" > < span class = "fa fa-stack" > < i class = "fa fa-square-o fa fa-stack-2x" > < / i > < i class = "fa fa-github-alt" > < / i > < / span > < span class = "explanation" > GitHub user< / span > < / span >
< span class = "coolicon" > < span class = "fa fa-stack" > < i class = "fa fa-square-o fa fa-stack-2x" > < / i > < i class = "fa fa-stack-exchange" > < / i > < / span > < span class = "explanation" > StackExchange fan< / span > < / span >
< span class = "coolicon" > < span class = "fa fa-stack" > < i class = "fa fa-square-o fa fa-stack-2x" > < / i > < i class = "fa fa-music" > < / i > < / span > < span class = "explanation" > Music lover< / span > < / span >
< span class = "coolicon" > < span class = "fa fa-stack" > < i class = "fa fa-square-o fa fa-stack-2x" > < / i > < i class = "fa fa-film" > < / i > < / span > < span class = "explanation" > Movie fan< / span > < / span >
< span class = "coolicon" > < span class = "fa fa-stack" > < i class = "fa fa-square-o fa fa-stack-2x" > < / i > < i class = "fa fa-comments" > < / i > < / span > < span class = "explanation" > Always on IM< / span > < / span >
< span class = "coolicon" > < span class = "fa fa-stack" > < i class = "fa fa-square-o fa fa-stack-2x" > < / i > < i class = "fa fa-laptop" > < / i > < / span > < span class = "explanation" > Always on a PC< / span > < / span >
< span class = "coolicon" > < span class = "fa fa-stack" > < i class = "fa fa-square-o fa fa-stack-2x" > < / i > < i class = "fa fa-pencil" > < / i > < / span > < span class = "explanation" > Occassional writter< / span > < / span >
< span class = "coolicon" > < span class = "fa fa-stack" > < i class = "fa fa-square-o fa fa-stack-2x" > < / i > < i class = "fa fa-moon-o" > < / i > < / span > < span class = "explanation" > Night owl< / span > < / span >
< span class = "coolicon" > < span class = "fa fa-stack" > < i class = "fa fa-square-o fa fa-stack-2x" > < / i > < i class = "fa fa-terminal" > < / i > < / span > < span class = "explanation" > CLI user< / span > < / span >
< span class = "coolicon" > < span class = "fa fa-stack" > < i class = "fa fa-square-o fa fa-stack-2x" > < / i > < i class = "fa fa-flag" > < / i > < / span > < span class = "explanation" > Linguist wannabe< / span > < / span >
< span class = "coolicon" > < span class = "fa fa-stack" > < i class = "fa fa-square-o fa fa-stack-2x" > < / i > < i class = "fa fa-code" > < / i > < / span > < span class = "explanation" > Love to code< / span > < / span >
< span class = "coolicon" > < span class = "fa fa-stack" > < i class = "fa fa-square-o fa fa-stack-2x" > < / i > < i class = "fa fa-book" > < / i > < / span > < span class = "explanation" > Keen reader< / span > < / span >
< span class = "coolicon" > < span class = "fa fa-stack" > < i class = "fa fa-square-o fa fa-stack-2x" > < / i > < i class = "fa fa-quote-right" > < / i > < / span > < span class = "explanation" > Quotes on demand< / span > < / span >
2015-12-08 12:42:59 +00:00
< / div >
< / div >
2015-01-22 22:05:35 +00:00
< div class = "entries" >
2015-12-08 12:42:59 +00:00
< h2 class = "title" > Latest entries< / h2 >
2015-01-22 22:05:35 +00:00
< dl >
2015-03-11 01:55:29 +00:00
< dt > < a href = "/sharing-dotfiles.html" > Sharing dotfiles< / a > < / dt >
< a class = "tag" href = "/tag/github.html" > < dd class = "label label-default" > github< / dd > < / a >
< a class = "tag" href = "/tag/git.html" > < dd class = "label label-default" > git< / dd > < / a >
< a class = "tag" href = "/tag/dotfiles.html" > < dd class = "label label-default" > dotfiles< / dd > < / a >
2015-01-22 22:28:51 +00:00
< dt > < a href = "/zotero.html" > Zotero< / a > < / dt >
2015-01-22 22:05:35 +00:00
< a class = "tag" href = "/tag/zotero.html" > < dd class = "label label-default" > zotero< / dd > < / a >
< a class = "tag" href = "/tag/webdav.html" > < dd class = "label label-default" > webdav< / dd > < / a >
< a class = "tag" href = "/tag/nginx.html" > < dd class = "label label-default" > nginx< / dd > < / a >
< a class = "tag" href = "/tag/apache.html" > < dd class = "label label-default" > apache< / dd > < / a >
2015-01-22 22:28:51 +00:00
< dt > < a href = "/proxies-with-apache-and-python.html" > Proxies with Apache and python< / a > < / dt >
2015-01-22 22:05:35 +00:00
< a class = "tag" href = "/tag/python.html" > < dd class = "label label-default" > python< / dd > < / a >
< a class = "tag" href = "/tag/apache.html" > < dd class = "label label-default" > apache< / dd > < / a >
< a class = "tag" href = "/tag/proxy.html" > < dd class = "label label-default" > proxy< / dd > < / a >
< a class = "tag" href = "/tag/gunicorn.html" > < dd class = "label label-default" > gunicorn< / dd > < / a >
< a class = "tag" href = "/tag/uwsgi.html" > < dd class = "label label-default" > uwsgi< / dd > < / a >
2015-12-08 15:40:50 +00:00
< dt > < a href = "/publishing-on-pypi.html" > Publishing on PyPi< / a > < / dt >
2015-01-22 22:51:14 +00:00
< a class = "tag" href = "/tag/github.html" > < dd class = "label label-default" > github< / dd > < / a >
< a class = "tag" href = "/tag/python.html" > < dd class = "label label-default" > python< / dd > < / a >
< a class = "tag" href = "/tag/pypi.html" > < dd class = "label label-default" > pypi< / dd > < / a >
< dt > < a href = "/updating-eurolovemap.html" > Updating EuroLoveMap< / a > < / dt >
< a class = "tag" href = "/tag/javascript.html" > < dd class = "label label-default" > javascript< / dd > < / a >
< a class = "tag" href = "/tag/python.html" > < dd class = "label label-default" > python< / dd > < / a >
< a class = "tag" href = "/tag/heroku.html" > < dd class = "label label-default" > heroku< / dd > < / a >
2015-01-22 22:05:35 +00:00
< / dl >
< / div >
2015-12-08 12:42:59 +00:00
<!-- Sidebar content -->
2015-01-22 22:05:35 +00:00
< / div >
< div id = "content" >
<!-- Body content -->
< div class = "postnav" >
2015-12-08 16:13:36 +00:00
< span class = "previouspost" > < i class = "fa fa-chevron-left" > < / i > < a href = "updating-eurolovemap.html" > Updating EuroLoveMap< / a > < / span >
< span class = 'nextpost' > < a href = "/proxies-with-apache-and-python.html" > Proxies with Apache and python< / a > < i class = "fa fa-chevron-right" > < / i > < / span >
2015-01-22 22:05:35 +00:00
< / div >
< div class = "posthead" >
2015-12-08 15:40:50 +00:00
< h2 class = "title" > Publishing on PyPi< / h2 >
2015-01-22 22:05:35 +00:00
< span class = "meta date" > 2014-09-27< / span >
< a class = "tag" href = "/tag/github.html" > < span class = "label label-default" > github< / span > < / a >
< a class = "tag" href = "/tag/python.html" > < span class = "label label-default" > python< / span > < / a >
< a class = "tag" href = "/tag/pypi.html" > < span class = "label label-default" > pypi< / span > < / a >
< / div >
< div class = "post" >
< p > Developing a python module and publishing it on Github is cool, but most
of the times you want others to download and use it easily. That is the
role of PyPi, the python package repository. In this post I show you how
to publish your package in less than 10 minutes.< / p >
< div class = "section" id = "choose-a-fancy-name" >
< h2 > Choose a fancy name< / h2 >
< p > If you haven't done so yet, take a minute or two to think about this. To
publish on PyPi you need a name for your package that isn't taken.
What's more, a catchy and unique name will help people remember your
module and feel more inclined to at least try it.< / p >
< p > The package name should hint what your module does, but that's not
always the case. That's your call. I personally put uniqueness and
memorability over describing the functionality.< / p >
< / div >
< div class = "section" id = "create-a-pypirc-configuration-file" >
< h2 > Create a .pypirc configuration file< / h2 >
2015-12-08 00:39:33 +00:00
< table class = "highlighttable" > < tr > < td class = "linenos" > < div class = "linenodiv" > < pre > 1
2
3
4
5
6
7
8
9
10
11
12
13< / pre > < / div > < / td > < td class = "code" > < div class = "highlight" > < pre > < span class = "err" > [distutils]< / span > < span class = "c1" > # this tells distutils what package indexes you can push to< / span >
< span class = "na" > index-servers< / span > < span class = "o" > =< / span > < span class = "s" > < / span >
< span class = "s" > pypi # the live PyPI< / span >
< span class = "s" > pypitest # test PyPI< / span >
2015-01-22 22:05:35 +00:00
< span class = "err" > [pypi]< / span > < span class = "c1" > # authentication details for live PyPI< / span >
< span class = "na" > repository< / span > < span class = "o" > =< / span > < span class = "s" > https://pypi.python.org/pypi< / span >
< span class = "na" > username< / span > < span class = "o" > =< / span > < span class = "s" > { your_username }< / span >
< span class = "na" > password< / span > < span class = "o" > =< / span > < span class = "s" > { your_password } # not necessary< / span >
< span class = "err" > [pypitest]< / span > < span class = "c1" > # authentication details for test PyPI< / span >
< span class = "na" > repository< / span > < span class = "o" > =< / span > < span class = "s" > https://testpypi.python.org/pypi< / span >
< span class = "na" > username< / span > < span class = "o" > =< / span > < span class = "s" > { your_username }< / span >
2015-12-08 00:39:33 +00:00
< / pre > < / div >
< / td > < / tr > < / table > < p > As you can see, you need to register both in the < a class = "reference external" href = "https://pypi.python.org/pypi?%3Aaction=register_form" > main pypi
2015-01-22 22:05:35 +00:00
repository< / a > and
the < a class = "reference external" href = "https://testpypi.python.org/pypi?%3Aaction=register_form" > testing
server< / a > .
The usernames and passwords might be different, that is up to you!< / p >
< / div >
< div class = "section" id = "prepare-your-package" >
< h2 > Prepare your package< / h2 >
2015-12-08 00:39:33 +00:00
< p > This should be the structure:< / p >
2015-01-22 22:05:35 +00:00
< pre class = "literal-block" >
root-dir/ # Any name you want
setup.py
setup.cfg
LICENSE.txt
README.md
mypackage/
__init__.py
foo.py
bar.py
baz.py
< / pre >
< div class = "section" id = "setup-cfg" >
< h3 > setup.cfg< / h3 >
2015-12-08 00:39:33 +00:00
< table class = "highlighttable" > < tr > < td class = "linenos" > < div class = "linenodiv" > < pre > 1
2< / pre > < / div > < / td > < td class = "code" > < div class = "highlight" > < pre > < span class = "k" > [metadata]< / span >
2015-01-22 22:05:35 +00:00
< span class = "na" > description-file< / span > < span class = "o" > =< / span > < span class = "s" > README.md< / span >
2015-12-08 00:39:33 +00:00
< / pre > < / div >
< / td > < / tr > < / table > < p > The markdown README is the < em > de facto< / em > standard in Github, but you can
2015-01-22 22:05:35 +00:00
also use rST (reStructuredText), the standard in the python community.< / p >
< / div >
< div class = "section" id = "setup-py" >
< h3 > setup.py< / h3 >
2015-12-08 00:39:33 +00:00
< table class = "highlighttable" > < tr > < td class = "linenos" > < div class = "linenodiv" > < pre > 1
2
3
4
5
6
7
8
9
10
11
12< / pre > < / div > < / td > < td class = "code" > < div class = "highlight" > < pre > < span class = "kn" > from< / span > < span class = "nn" > distutils.core< / span > < span class = "kn" > import< / span > < span class = "n" > setup< / span >
< span class = "n" > setup< / span > < span class = "p" > (< / span > < span class = "n" > name< / span > < span class = "o" > =< / span > < span class = "s" > ' mypackage' < / span > < span class = "p" > ,< / span >
< span class = "n" > packages< / span > < span class = "o" > =< / span > < span class = "p" > [< / span > < span class = "s" > ' mypackage' < / span > < span class = "p" > ],< / span > < span class = "c" > # this must be the same as the name above< / span >
< span class = "n" > version< / span > < span class = "o" > =< / span > < span class = "s" > ' { version }' < / span > < span class = "p" > ,< / span >
< span class = "n" > description< / span > < span class = "o" > =< / span > < span class = "s" > ' { description }' < / span > < span class = "p" > ,< / span >
< span class = "n" > author< / span > < span class = "o" > =< / span > < span class = "s" > ' { name }' < / span > < span class = "p" > ,< / span >
< span class = "n" > email< / span > < span class = "o" > =< / span > < span class = "s" > ' { email }' < / span > < span class = "p" > ,< / span >
< span class = "n" > url< / span > < span class = "o" > =< / span > < span class = "s" > ' https://github.com/{user}/{package}' < / span > < span class = "p" > ,< / span > < span class = "c" > # URL to the github repo< / span >
< span class = "n" > download< / span > \< span class = "n" > _url< / span > < span class = "o" > =< / span > < span class = "s" > ' https://github.com/{user}/{repo}/tarball/{version}' < / span > < span class = "p" > ,< / span >
< span class = "n" > keywords< / span > < span class = "o" > =< / span > < span class = "p" > [< / span > < span class = "s" > ' websockets' < / span > < span class = "p" > ,< / span > < span class = "s" > ' display' < / span > < span class = "p" > ,< / span > < span class = "s" > ' d3' < / span > < span class = "p" > ],< / span > < span class = "c" > # list of keywords that represent your package< / span >
< span class = "n" > classifiers< / span > < span class = "o" > =< / span > < span class = "p" > [],< / span > < span class = "p" > )< / span >
< / pre > < / div >
< / td > < / tr > < / table > < p > You might notice that the download_url points to a Github URL. We could
2015-01-22 22:05:35 +00:00
host our package anywhere, but Github is a convenient option. To create
the tarball and the zip packages, you only need to tag a tag in your
repository and push it to github:< / p >
2015-12-08 00:39:33 +00:00
< table class = "highlighttable" > < tr > < td class = "linenos" > < div class = "linenodiv" > < pre > 1
2< / pre > < / div > < / td > < td class = "code" > < div class = "highlight" > < pre > git tag < span class = "o" > {< / span > version< span class = "o" > }< / span > -m < span class = "s2" > " { Description of this tag/version}" < / span >
2015-01-22 22:05:35 +00:00
git push --tags origin master
2015-12-08 00:39:33 +00:00
< / pre > < / div >
< / td > < / tr > < / table > < / div >
2015-01-22 22:05:35 +00:00
< / div >
< div class = "section" id = "push-to-the-testing-main-pypi-server" >
< h2 > Push to the testing/main pypi server< / h2 >
< p > It is advisable that you try your package on the test repository and fix
any problems first. The process is simple:
< tt class = "docutils literal" > python setup.py register < span class = "pre" > -r< / span > {pypitest/pypi} python setup.py sdist upload < span class = "pre" > -r< / span > {pypitest/pypi}< / tt > < / p >
< p > If everything went as expected, you can now install your package through
pip and browse your package's page. For instance, check my senpy
package: < a class = "reference external" href = "https://pypi.python.org/pypi/senpy" > https://pypi.python.org/pypi/senpy< / a > < tt class = "docutils literal" > pip install senpy< / tt > < / p >
< / div >
< / div >
< / div >
< div class = "clear" > < / div >
< / div >
< footer role = "contentinfo" >
< div class = "contact" >
< p >
J. Fernando Sánchez Rada | balkian
< / p >
< / div >
< ul id = "social" >
2015-12-08 16:13:36 +00:00
< li > < a href = "http://github.com/balkian" > < i class = "fa fa-github" > < / i > < / a > < / li >
< li > < a href = "http://bitbucket.com/balkian" > < i class = "fa fa-bitbucket" > < / i > < / a > < / li >
< li > < a href = "http://twitter.com/balkian" > < i class = "fa fa-twitter" > < / i > < / a > < / li >
< li > < a href = "https://plus.google.com/u/0/111897020957944410316" > < i class = "fa fa-google-plus" > < / i > < / a > < / li >
< li > < a href = "http://linkedin.com/in/jfsanchezrada" > < i class = "fa fa-linkedin" > < / i > < / a > < / li >
< li > < a href = "http://facebook.com/balkian" > < i class = "fa fa-facebook" > < / i > < / a > < / li >
2015-01-22 22:05:35 +00:00
< / ul >
< p >
Creative Commons A-SA-NC
< / p >
< / footer >
< / div >
< script src = "/theme/js/jquery-2.0.2.min.js" > < / script >
2015-12-08 13:57:44 +00:00
<!-- Piwik -->
< script type = "text/javascript" >
var _paq = _paq || [];
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//piwik.sinpapel.es/";
_paq.push(['setTrackerUrl', u+'piwik.php']);
_paq.push(['setSiteId', 2]);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
})();
< / script >
< noscript > < p > < img src = "//piwik.sinpapel.es/piwik.php?idsite=2" style = "border:0;" alt = "" / > < / p > < / noscript >
<!-- End Piwik Code -->
2015-01-22 22:05:35 +00:00
<!-- <script src="/js/bootstrap.min.js"></script> -->
< / body >
< / html >