(window.webpackJsonp=window.webpackJsonp||[]).push([[2682],{3090:function(t,a,s){"use strict";s.r(a);var e=s(31),n=Object(e.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"creating-python-packages"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#creating-python-packages"}},[t._v("#")]),t._v(" Creating Python packages")]),t._v(" "),s("h2",{attrs:{id:"introduction"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),s("p",[t._v("Every package requires a "),s("a",{attrs:{href:"https://docs.python.org/3/distutils/setupscript.html#writing-the-setup-script",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("setup.py")]),s("OutboundLink")],1),t._v(" file which describes the package.")]),t._v(" "),s("p",[t._v("Consider the following directory structure for a simple package:")]),t._v(" "),s("div",{staticClass:"language-py extra-class"},[s("pre",{pre:!0,attrs:{class:"language-py"}},[s("code",[s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" package_name\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" __init__"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("py\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" \n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" setup"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("py\n\n")])])]),s("p",[t._v("The "),s("code",[t._v("__init__.py")]),t._v(" contains only the line "),s("code",[t._v("def foo(): return 100")]),t._v(".")]),t._v(" "),s("p",[t._v("The following "),s("code",[t._v("setup.py")]),t._v(" will define the package:")]),t._v(" "),s("div",{staticClass:"language-py extra-class"},[s("pre",{pre:!0,attrs:{class:"language-py"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" setuptools "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" setup\n\n\nsetup"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package_name'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# package name")]),t._v("\n version"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'0.1'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# version")]),t._v("\n description"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'Package Description'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# short description")]),t._v("\n url"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'http://example.com'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# package URL")]),t._v("\n install_requires"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# list of packages this package depends")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# on.")]),t._v("\n packages"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package_name'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# List of module names that installing")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# this package will provide.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n")])])]),s("p",[s("a",{attrs:{href:"https://virtualenv.pypa.io/en/stable/",target:"_blank",rel:"noopener noreferrer"}},[t._v("virtualenv"),s("OutboundLink")],1),t._v(" is great to test package installs without modifying your other Python environments:")]),t._v(" "),s("div",{staticClass:"language-py extra-class"},[s("pre",{pre:!0,attrs:{class:"language-py"}},[s("code",[t._v("$ virtualenv "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("virtualenv\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n$ source "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("virtualenv"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bin")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("activate\n$ python setup"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("py install\nrunning install\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\nInstalled "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("package_name"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.1")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("egg\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n$ python\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" package_name\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" package_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("foo"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n"),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),t._v("\n\n")])])]),s("h2",{attrs:{id:"uploading-to-pypi"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#uploading-to-pypi"}},[t._v("#")]),t._v(" Uploading to PyPI")]),t._v(" "),s("p",[t._v("Once your "),s("code",[t._v("setup.py")]),t._v(" is fully functional (see "),s("a",{attrs:{href:"http://stackoverflow.com/documentation/python/1381/creating-python-packages/4500/introduction",target:"_blank",rel:"noopener noreferrer"}},[t._v("Introduction"),s("OutboundLink")],1),t._v("), it is very easy to upload your package to "),s("a",{attrs:{href:"https://pypi.python.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("PyPI"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("h3",{attrs:{id:"setup-a-pypirc-file"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#setup-a-pypirc-file"}},[t._v("#")]),t._v(" Setup a .pypirc File")]),t._v(" "),s("p",[t._v("This file stores logins and passwords to authenticate your accounts. It is typically stored in your home directory.")]),t._v(" "),s("div",{staticClass:"language-py extra-class"},[s("pre",{pre:!0,attrs:{class:"language-py"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# .pypirc file")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("distutils"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\nindex"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("servers "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n pypi\n pypitest\n\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("pypi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\nrepository"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("https"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("//")]),t._v("pypi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("python"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("org"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("pypi\nusername"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("your_username\npassword"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("your_password\n\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("pypitest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\nrepository"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("https"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("//")]),t._v("testpypi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("python"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("org"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("pypi\nusername"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("your_username\npassword"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("your_password\n\n")])])]),s("p",[t._v("It is "),s("a",{attrs:{href:"https://packaging.python.org/distributing/#upload-your-distributions",target:"_blank",rel:"noopener noreferrer"}},[t._v("safer"),s("OutboundLink")],1),t._v(" to use "),s("code",[t._v("twine")]),t._v(" for uploading packages, so make sure that is installed.")]),t._v(" "),s("div",{staticClass:"language-py extra-class"},[s("pre",{pre:!0,attrs:{class:"language-py"}},[s("code",[t._v("$ pip install twine\n\n")])])]),s("h3",{attrs:{id:"register-and-upload-to-testpypi-optional"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#register-and-upload-to-testpypi-optional"}},[t._v("#")]),t._v(" Register and Upload to testpypi (optional)")]),t._v(" "),s("p",[s("strong",[t._v("Note")]),t._v(": "),s("a",{attrs:{href:"https://bitbucket.org/pypa/pypi/issues/206/cannot-overwrite-package-files",target:"_blank",rel:"noopener noreferrer"}},[t._v("PyPI does not allow overwriting uploaded packages"),s("OutboundLink")],1),t._v(", so it is prudent to first test your deployment on a dedicated test server, e.g. testpypi. This option will be discussed. Consider a "),s("a",{attrs:{href:"https://caremad.io/2016/02/versioning-software/",target:"_blank",rel:"noopener noreferrer"}},[t._v("versioning scheme"),s("OutboundLink")],1),t._v(" for your package prior to uploading such as "),s("a",{attrs:{href:"http://sedimental.org/designing_a_version.html#calendar_versioning",target:"_blank",rel:"noopener noreferrer"}},[t._v("calendar versioning"),s("OutboundLink")],1),t._v(" or "),s("a",{attrs:{href:"http://semver.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("semantic versioning"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("p",[t._v("Either log in, or create a new account at "),s("a",{attrs:{href:"https://testpypi.python.org/pypi",target:"_blank",rel:"noopener noreferrer"}},[t._v("testpypi"),s("OutboundLink")],1),t._v(". Registration is only required the first time, although registering more than once is not harmful.")]),t._v(" "),s("div",{staticClass:"language-py extra-class"},[s("pre",{pre:!0,attrs:{class:"language-py"}},[s("code",[t._v("$ python setup"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("py register "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("r pypitest\n\n")])])]),s("p",[t._v("While in the root directory of your package:")]),t._v(" "),s("div",{staticClass:"language-py extra-class"},[s("pre",{pre:!0,attrs:{class:"language-py"}},[s("code",[t._v("$ twine upload dist"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("r pypitest\n\n")])])]),s("p",[t._v("Your package should now be accessible through your account.")]),t._v(" "),s("h3",{attrs:{id:"testing"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#testing"}},[t._v("#")]),t._v(" Testing")]),t._v(" "),s("p",[t._v("Make a test virtual environment. Try to "),s("code",[t._v("pip install")]),t._v(" your package from either testpypi or PyPI.")]),t._v(" "),s("div",{staticClass:"language-py extra-class"},[s("pre",{pre:!0,attrs:{class:"language-py"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# Using virtualenv")]),t._v("\n$ mkdir testenv\n$ cd testenv\n$ virtualenv "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("virtualenv\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n$ source "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("virtualenv"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bin")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("activate\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# Test from testpypi")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("virtualenv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" pip install "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("verbose "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("extra"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("index"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("url https"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("//")]),t._v("testpypi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("python"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("org"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("pypi package_name\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# Or test from PyPI")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("virtualenv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" $ pip install package_name\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("virtualenv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" $ python\nPython "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3.5")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v(".1")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("default"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Jan "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("27")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2016")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("19")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("16")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("39")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("GCC "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4.2")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v(".1")]),t._v(" Compatible Apple LLVM "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("7.0")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v(".2")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("clang"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("700.1")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v(".81")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" on darwin\nType "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"help"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"copyright"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"credits"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("or")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"license"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" more information"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" package_name\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" package_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("foo"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),t._v("\n\n")])])]),s("p",[t._v("If successful, your package is least importable. You might consider testing your API as well before your final upload to PyPI. If you package failed during testing, do not worry. You can still fix it, re-upload to testpypi and test again.")]),t._v(" "),s("h3",{attrs:{id:"register-and-upload-to-pypi"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#register-and-upload-to-pypi"}},[t._v("#")]),t._v(" Register and Upload to PyPI")]),t._v(" "),s("p",[t._v("Make sure "),s("code",[t._v("twine")]),t._v(" is installed:")]),t._v(" "),s("div",{staticClass:"language-py extra-class"},[s("pre",{pre:!0,attrs:{class:"language-py"}},[s("code",[t._v("$ pip install twine\n\n")])])]),s("p",[t._v("Either log in, or create a new account at "),s("a",{attrs:{href:"https://pypi.python.org/pypi",target:"_blank",rel:"noopener noreferrer"}},[t._v("PyPI"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("div",{staticClass:"language-py extra-class"},[s("pre",{pre:!0,attrs:{class:"language-py"}},[s("code",[t._v("$ python setup"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("py register "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("r pypi\n$ twine upload dist"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n\n")])])]),s("p",[t._v("That's it! Your package is "),s("a",{attrs:{href:"https://pypi.python.org/pypi/package_name",target:"_blank",rel:"noopener noreferrer"}},[t._v("now live"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("p",[t._v("If you discover a bug, simply upload a new version of your package.")]),t._v(" "),s("h3",{attrs:{id:"documentation"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#documentation"}},[t._v("#")]),t._v(" Documentation")]),t._v(" "),s("p",[t._v("Don't forget to include at least some kind of documentation for your package. PyPi takes as the default formatting language "),s("a",{attrs:{href:"http://stackoverflow.com/documentation/restructuredtext",target:"_blank",rel:"noopener noreferrer"}},[t._v("reStructuredText"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("h3",{attrs:{id:"readme"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#readme"}},[t._v("#")]),t._v(" Readme")]),t._v(" "),s("p",[t._v("If your package doesn't have a big documentation, include what can help other users in "),s("code",[t._v("README.rst")]),t._v(" file. When the file is ready, another one is needed to tell PyPi to show it.")]),t._v(" "),s("p",[t._v("Create "),s("code",[t._v("setup.cfg")]),t._v(" file and put these two lines in it:")]),t._v(" "),s("div",{staticClass:"language-py extra-class"},[s("pre",{pre:!0,attrs:{class:"language-py"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("metadata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\ndescription"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("file")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" README"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("rst\n\n")])])]),s("p",[t._v("Note that if you try to put "),s("a",{attrs:{href:"http://stackoverflow.com/documentation/markdown",target:"_blank",rel:"noopener noreferrer"}},[t._v("Markdown"),s("OutboundLink")],1),t._v(" file into your package, PyPi will read it as a pure text file without any formatting.")]),t._v(" "),s("h3",{attrs:{id:"licensing"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#licensing"}},[t._v("#")]),t._v(" Licensing")]),t._v(" "),s("p",[t._v("It's often more than welcome to put a "),s("code",[t._v("LICENSE.txt")]),t._v(" file in your package with one of the "),s("a",{attrs:{href:"https://opensource.org/licenses",target:"_blank",rel:"noopener noreferrer"}},[t._v("OpenSource licenses"),s("OutboundLink")],1),t._v(" to tell users if they can use your package for example in commercial projects or if your code is usable with their license.")]),t._v(" "),s("p",[t._v("In more readable way some licenses are explained at "),s("a",{attrs:{href:"https://tldrlegal.com/",target:"_blank",rel:"noopener noreferrer"}},[t._v("TL;DR"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("h2",{attrs:{id:"making-package-executable"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#making-package-executable"}},[t._v("#")]),t._v(" Making package executable")]),t._v(" "),s("p",[t._v("If your package isn't only a library, but has a piece of code that can be used either as a showcase or a standalone application when your package is installed, put that piece of code into "),s("code",[t._v("__main__.py")]),t._v(" file.")]),t._v(" "),s("p",[t._v("Put the "),s("code",[t._v("__main__.py")]),t._v(" in the "),s("code",[t._v("package_name")]),t._v(" folder. This way you will be able to run it directly from console:")]),t._v(" "),s("div",{staticClass:"language-py extra-class"},[s("pre",{pre:!0,attrs:{class:"language-py"}},[s("code",[t._v("python "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("m package_name\n\n")])])]),s("p",[t._v("If there's no "),s("code",[t._v("__main__.py")]),t._v(" file available, the package won't run with this command and this error will be printed:")]),t._v(" "),s("blockquote"),t._v(" "),s("p",[t._v("python: No module named `package_name.__main__;` 'package_name' is a package\nand cannot be directly executed.")]),t._v(" "),s("h4",{attrs:{id:"remarks"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#remarks"}},[t._v("#")]),t._v(" Remarks")]),t._v(" "),s("p",[t._v("The "),s("a",{attrs:{href:"https://github.com/pypa/sampleproject",target:"_blank",rel:"noopener noreferrer"}},[t._v("pypa sample project"),s("OutboundLink")],1),t._v(" contains a complete, easily modifiable template "),s("code",[t._v("setup.py")]),t._v(" that demonstrates a large range of capabilities setup-tools has to offer.")])])}),[],!1,null,null,null);a.default=n.exports}}]);