aboutsummaryrefslogtreecommitdiff
path: root/content/weblog/2019-01-31_python-package-to-pypi/index.md
diff options
context:
space:
mode:
Diffstat (limited to 'content/weblog/2019-01-31_python-package-to-pypi/index.md')
-rw-r--r--content/weblog/2019-01-31_python-package-to-pypi/index.md176
1 files changed, 176 insertions, 0 deletions
diff --git a/content/weblog/2019-01-31_python-package-to-pypi/index.md b/content/weblog/2019-01-31_python-package-to-pypi/index.md
new file mode 100644
index 0000000..f0b14e0
--- /dev/null
+++ b/content/weblog/2019-01-31_python-package-to-pypi/index.md
@@ -0,0 +1,176 @@
++++
+title = "Packaging and distributing python apps and modules"
+date = 2019-01-31T08:10:00Z
++++
+
+There may come a time after some hacking and playing around with python that
+you feel like the piece of code you just created needs to be shared with the
+world, and so you might be thinking "Man, wouldn't it be sweet if anyone could
+install my app/module just by typing `pip install stuffimade'`. Well, it is
+actually easier than you might think (it certainly was in my case).
+
+<!-- more -->
+
+It basically boils down to these five things:
+
+1. Make an account on pypi.org
+1. Come up with an original name, that hasn't been taken on pypi (arguably the
+ hardest part of these instructions).
+1. Prepare a setup py file to package your app/module, choose a license, maybe
+ (preferably) write a readme.
+1. Package it.
+1. Upload it.
+
+The first step is really simple, just go the website (pypi.org) and click on
+the link that says "Register" on the top right corner. Be sure to not forget
+your password, especially after uploading your package, since you will need
+everything that you want to upload a new version of your package.
+
+The second step is all up to you, just use the search function in the website
+to make sure that your package name hasn't been taken.
+
+After having created your account on pypi.org, and decided on a name for your
+app/package, you'll proceed to create the necessary package files. Your package
+should consist of a folder with your actual module or app, inside which should
+also be a `__init__.py` file (it can be empty if you don't need to set any
+variables or anything), a `LICENSE` file with your license of choice (e.g. MIT,
+BSD, GPL, etc.), and a `README.rst` or `README.md` file containing a detailed
+description of your app/module.
+
+Your directory structure should look something like this
+
+```
+/my-app-package
+ /my-app
+ __init__.py
+ (other files and directories)
+ setup.py
+ LICENSE
+ README.md
+```
+
+Now, if your app is going to have files other than python files, and the
+aforementioned files, you might to add a `MANIFEST.in` in the root of you
+package directory specifying the files to include. This is true, for example,
+for Django apps, since they might contain template and static files (html, css,
+js, etc.) that the packaging tool we are going to use might not pick up. As an
+example I'll show you the `MANIFEST.in` file of my w3blog package
+
+```
+include LICENSE
+include README.md
+recursive-include weblog/static *
+recursive-include weblog/templates *
+recursive-include weblog/locale *
+```
+
+There I specified to, just in case, include the `LICENSE` and `README.md`
+files, and also include static files, templates, and the message files for
+localization, by recursively searching the directories of said files.
+
+Now on to the setup.py file. For this I am also going to use my project's file
+as an example
+
+```py
+#!/usr/bin/env python3
+import os
+from setuptools import find_packages, setup
+
+with open(os.path.join(os.path.dirname(__file__), 'README.md')) as readme:
+ README = readme.read()
+
+# allow setup.py to be run from any path
+os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
+
+setup(
+ name='w3blog',
+ version='0.5.2',
+ packages=find_packages(),
+ include_package_data=True,
+ license='BSD License',
+ description='A simple blog engine for Django with multilingual capabilities.',
+ long_description=README,
+ url='https://www.yaroslavps.com/',
+ author='Yaroslav de la Peña Smirnov',
+ author_email='contact@yaroslavps.com',
+ classifiers=[
+ 'Environment :: Web Environment',
+ 'Framework :: Django',
+ 'Framework :: Django :: 1.11',
+ 'Framework :: Django :: 2.0',
+ 'Framework :: Django :: 2.1',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: BSD License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Topic :: Internet :: WWW/HTTP',
+ 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
+ ],
+)
+```
+
+Of course, you should customize this file according to your app's details, for
+example, your classifiers list might look shorter, like this
+
+```py
+ classifiers=[
+ 'License :: OSI Approved :: BSD License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ ],
+```
+
+It will depend on which version of python you want to support, your license,
+some other required packages, etc. The rest of the setup function parameters
+should be self explanatory.
+
+Once you have you package files ready (don't forget about your readme and
+license), you'll need to proceed to package them, i.e. generate the
+distribution files. For that, we'll need to install a couple of packages, we
+cant install them inside a virtual environment, or you could install them
+system wide
+
+```sh
+$ sudo pip3 install --upgrade setuptools wheel twine
+```
+
+Now just run the following command from the same directory where setup.py is
+located
+
+```sh
+$ python3 setup.py sdist bdist_wheel
+```
+
+After running that command, you should now have a dist subdirectory with a
+.tar.gz archive and a .whl file. Those are the files that you'll need to
+upload. The twine package that we just installed is going to take care of that
+for us. Remember that you already should have an account on pypi.org to upload
+your package.
+
+So for example, when I just uploaded the first version of w3blog, and each time
+that I upload a new version I run a command (from the same directory as
+setup.py) that looks like this
+
+```sh
+$ python3 twine upload dist/w3blog-0.5.2*
+```
+
+Just replace "w3blog-0.5.2*" with your appropriate package name-version. After
+running that command, twine is going to ask you for your username and password,
+thence it is going to upload it to pypi. Once it is successfully uploaded, it
+should be a matter of seconds or minutes before you, and everybody else in the
+world with an internet connection (and capable of running python, of course),
+can install your package!
+
+If you need more detailed information about this process, check out the
+official documentation at
+[https://packaging.python.org/tutorials/packaging-projects/](https://packaging.python.org/tutorials/packaging-projects/)