Last active
September 17, 2015 09:32
-
-
Save code-of-kpp/43168d081dc969c40c63 to your computer and use it in GitHub Desktop.
PyCon Russia 2015 talk on setup.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "skip" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"\n", | |
"<style>\n", | |
".cm-s-ipython span.cm-keyword { color: #2306FF;}\n", | |
".cm-s-ipython span.cm-string { color: #0B7208;}\n", | |
".cm-s-ipython span.cm-comment {color: #4F6ACA;}\n", | |
".cm-s-ipython span.cm-operator {color: #FF22CD;}\n", | |
".cm-s-ipython span.cm-builtin {color: #1600BE;}\n", | |
".cm-s-ipython span.cm-def {color: #632B97;}\n", | |
".cm-s-ipython span.cm-quote {color: #93248A;}\n", | |
".cm-s-ipython span.cm-attribute {color: #FF0083;}\n", | |
"\n", | |
".rendered_html code { color: #64006C;}\n", | |
"div.input_prompt { color: #C0C0E9;}\n", | |
"div.output_prompt { color: #F7BCBC;}\n", | |
"div.output_stderr { background: #FDEBEB;}\n", | |
"\n", | |
"</style>" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"%%html\n", | |
"\n", | |
"<style>\n", | |
".cm-s-ipython span.cm-keyword { color: #2306FF;}\n", | |
".cm-s-ipython span.cm-string { color: #0B7208;}\n", | |
".cm-s-ipython span.cm-comment {color: #4F6ACA;}\n", | |
".cm-s-ipython span.cm-operator {color: #FF22CD;}\n", | |
".cm-s-ipython span.cm-builtin {color: #1600BE;}\n", | |
".cm-s-ipython span.cm-def {color: #632B97;}\n", | |
".cm-s-ipython span.cm-quote {color: #93248A;}\n", | |
".cm-s-ipython span.cm-attribute {color: #FF0083;}\n", | |
"\n", | |
".rendered_html code { color: #64006C;}\n", | |
"div.input_prompt { color: #C0C0E9;}\n", | |
"div.output_prompt { color: #F7BCBC;}\n", | |
"div.output_stderr { background: #FDEBEB;}\n", | |
"\n", | |
"</style>" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "skip" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"import sys\n", | |
"\n", | |
"sys.argv = ['setup.py', '--description']" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Don't forget setup.py\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"<setuptools.dist.Distribution at 0x7fd9b80e8048>" | |
] | |
}, | |
"execution_count": 3, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"from setuptools import setup\n", | |
"\n", | |
"setup(\n", | |
" name=\"setup-py-pycon-ru-2015\",\n", | |
"\n", | |
" description=\"Don't forget setup.py\",\n", | |
"\n", | |
" author='Konstantin Ignatov', # hello\n", | |
" author_email='[email protected]', \n", | |
"\n", | |
" version=\"2015.9.18\",\n", | |
"\n", | |
" packages = ['talk'],\n", | |
"\n", | |
" classifiers=[\n", | |
" 'Intended Audience :: Developers',\n", | |
" 'Topic :: Software Development :: Build Tools',\n", | |
"\n", | |
" 'Programming Language :: Python :: 2',\n", | |
" 'Programming Language :: Python :: 3',\n", | |
" ],\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"3:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"# История\n", | |
"\n", | |
"* `distutils`: в стандартной библиотеке с Python 1.6\n", | |
"* `setuptools`\n", | |
"* `|-- distribute` (fork)\n", | |
"* `setuptools-7.0` (merge)\n", | |
"* Python Packaging Authority: [pypa.io](http://www.pypa.io)\n", | |
"<div style=\"overflow: hidden;\"><img style=\"margin: -140px 0px 0px 0px;\" src=\"https://pythonhosted.org/Distutils2/giphy.gif\" /></div>\n", | |
"* Standard?" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"https://www.pypa.io/en/latest/history/" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "skip" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"/home/kpp/build/pyconru-setup-py/simple\n" | |
] | |
} | |
], | |
"source": [ | |
"import sys\n", | |
"\n", | |
"sys.argv = ['setup.py', '--name']\n", | |
"\n", | |
"%mkdir -p simple\n", | |
"%cd simple" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"5:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"# Аперитив: микропроекты" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Overwriting foo.py\n" | |
] | |
} | |
], | |
"source": [ | |
"%%file foo.py\n", | |
"\n", | |
"def foo():\n", | |
" print(\"I'm in your system now\")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Overwriting setup.py\n" | |
] | |
} | |
], | |
"source": [ | |
"%%file setup.py\n", | |
"\n", | |
"from distutils.core import setup\n", | |
"\n", | |
"setup(\n", | |
" name='foo',\n", | |
" version='1.0',\n", | |
" py_modules=['foo'], # foo.py is the original gist\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"foo.py setup.py\r\n" | |
] | |
} | |
], | |
"source": [ | |
"ls *py" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"7:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"source": [ | |
"## В принципе, можно и без `setup.py`..." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": { | |
"collapsed": false, | |
"scrolled": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Processing foo.py\n", | |
"Writing /tmp/easy_install-x4elgo01/setup.cfg\n", | |
"Running setup.py -q bdist_egg --dist-dir /tmp/easy_install-x4elgo01/egg-dist-tmp-_wlf3tzo\n", | |
"Moving foo-1.0.dev0-py3.4.egg to /home/kpp/build/pyconru-setup-py/venv/lib/python3.4/site-packages\n", | |
"Adding foo 1.0.dev0 to easy-install.pth file\n", | |
"\n", | |
"Installed /home/kpp/build/pyconru-setup-py/venv/lib/python3.4/site-packages/foo-1.0.dev0-py3.4.egg\n", | |
"Processing dependencies for foo==1.0.dev0\n", | |
"Finished processing dependencies for foo==1.0.dev0\n" | |
] | |
}, | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"zip_safe flag not set; analyzing archive contents...\n" | |
] | |
} | |
], | |
"source": [ | |
"%%bash\n", | |
"easy_install \"file://$(pwd)/foo.py#egg=foo-1.0dev\"" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"metadata": { | |
"collapsed": false, | |
"scrolled": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"I'm in your system now\n" | |
] | |
} | |
], | |
"source": [ | |
"%%bash\n", | |
"cd .. # we don't want foo.py in our pwd\n", | |
"python -c \"import foo; foo.foo()\"" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"source": [ | |
"**Но...**" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"metadata": { | |
"collapsed": false, | |
"scrolled": true, | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Uninstalling foo-1.0.dev0:\n", | |
" Successfully uninstalled foo-1.0.dev0\n", | |
"Traceback (most recent call last):\n", | |
" File \"/home/kpp/build/pyconru-setup-py/venv/bin/pip\", line 11, in <module>\n", | |
" sys.exit(main())\n", | |
" File \"/home/kpp/build/pyconru-setup-py/venv/lib/python3.4/site-packages/pip/__init__.py\", line 217, in main\n", | |
" return command.main(cmd_args)\n", | |
" File \"/home/kpp/build/pyconru-setup-py/venv/lib/python3.4/site-packages/pip/basecommand.py\", line 248, in main\n", | |
" pip_version_check(session)\n", | |
" File \"/home/kpp/build/pyconru-setup-py/venv/lib/python3.4/site-packages/pip/utils/outdated.py\", line 102, in pip_version_check\n", | |
" installed_version = get_installed_version(\"pip\")\n", | |
" File \"/home/kpp/build/pyconru-setup-py/venv/lib/python3.4/site-packages/pip/utils/__init__.py\", line 858, in get_installed_version\n", | |
" working_set = pkg_resources.WorkingSet()\n", | |
" File \"/home/kpp/build/pyconru-setup-py/venv/lib/python3.4/site-packages/pip/_vendor/pkg_resources/__init__.py\", line 629, in __init__\n", | |
" self.add_entry(entry)\n", | |
" File \"/home/kpp/build/pyconru-setup-py/venv/lib/python3.4/site-packages/pip/_vendor/pkg_resources/__init__.py\", line 685, in add_entry\n", | |
" for dist in find_distributions(entry, True):\n", | |
" File \"/home/kpp/build/pyconru-setup-py/venv/lib/python3.4/site-packages/pip/_vendor/pkg_resources/__init__.py\", line 2075, in find_eggs_in_zip\n", | |
" if metadata.has_metadata('PKG-INFO'):\n", | |
" File \"/home/kpp/build/pyconru-setup-py/venv/lib/python3.4/site-packages/pip/_vendor/pkg_resources/__init__.py\", line 1605, in has_metadata\n", | |
" return self.egg_info and self._has(self._fn(self.egg_info, name))\n", | |
" File \"/home/kpp/build/pyconru-setup-py/venv/lib/python3.4/site-packages/pip/_vendor/pkg_resources/__init__.py\", line 1963, in _has\n", | |
" return zip_path in self.zipinfo or zip_path in self._index()\n", | |
" File \"/home/kpp/build/pyconru-setup-py/venv/lib/python3.4/site-packages/pip/_vendor/pkg_resources/__init__.py\", line 1843, in zipinfo\n", | |
" return self._zip_manifests.load(self.loader.archive)\n", | |
" File \"/home/kpp/build/pyconru-setup-py/venv/lib/python3.4/site-packages/pip/_vendor/pkg_resources/__init__.py\", line 1783, in load\n", | |
" mtime = os.stat(path).st_mtime\n", | |
"FileNotFoundError: [Errno 2] No such file or directory: '/home/kpp/build/pyconru-setup-py/venv/lib/python3.4/site-packages/foo-1.0.dev0-py3.4.egg'\n" | |
] | |
} | |
], | |
"source": [ | |
"!pip uninstall -y foo" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"I'm in your system now\n" | |
] | |
} | |
], | |
"source": [ | |
"%%bash\n", | |
"cd .. # go outside working directory\n", | |
"python -c \"import foo; foo.foo()\"" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"8:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"# Терминология\n", | |
"\n", | |
"* module / модуль\n", | |
" * pure Python module / чистый модуль\n", | |
" * extension module / модуль расширения\n", | |
" * package / пакет\n", | |
"* root package / корневой пакет:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 12, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"['',\n", | |
" '/home/kpp/build/pyconru-setup-py/venv/lib/python3.4',\n", | |
" '/home/kpp/build/pyconru-setup-py/venv/lib/python3.4/plat-x86_64-linux-gnu',\n", | |
" '/home/kpp/build/pyconru-setup-py/venv/lib/python3.4/lib-dynload',\n", | |
" '/usr/lib/python3.4',\n", | |
" '/usr/lib/python3.4/plat-x86_64-linux-gnu',\n", | |
" '/home/kpp/build/pyconru-setup-py/venv/lib/python3.4/site-packages',\n", | |
" '/home/kpp/build/pyconru-setup-py/venv/lib/python3.4/site-packages/IPython/extensions',\n", | |
" '/home/kpp/.ipython']" | |
] | |
}, | |
"execution_count": 12, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"import sys\n", | |
"sys.path # this is a \"working set\"" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"source": [ | |
"# Терминология\n", | |
"* \"пакет\" с `__init__.py` и \"module distribution\"\n", | |
"\n", | |
"* distribution root: место, где лежит `setup.py`\n", | |
"\n", | |
"* source distribution\n", | |
"\n", | |
"* binary distribution" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"10:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"# Пакеты" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 13, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "skip" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"/home/kpp/build/pyconru-setup-py/packs\n" | |
] | |
} | |
], | |
"source": [ | |
"%mkdir -p ../packs\n", | |
"%cd ../packs" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 14, | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "skip" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"%%bash\n", | |
"rm -rf foo.egg-info temp build dist MANIFEST setup.cfg .git *.pyc */*.pyc\n", | |
"\n", | |
"mkdir -p {one,two,three}\n", | |
"touch {one,two,three}/__init__.py\n", | |
"\n", | |
"mkdir -p one/four\n", | |
"touch one/four/__init__.py\n", | |
"touch one/four/data.csv\n", | |
"\n", | |
"cp -f ../simple/foo.py one/four/foo.py" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 15, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "skip" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Initialized empty Git repository in /home/kpp/build/pyconru-setup-py/packs/.git/\n", | |
"[master (root-commit) e5835e7] initial\n", | |
" 8 files changed, 11 insertions(+)\n", | |
" create mode 100644 README.txt\n", | |
" create mode 100644 one/__init__.py\n", | |
" create mode 100644 one/four/__init__.py\n", | |
" create mode 100644 one/four/data.csv\n", | |
" create mode 100644 one/four/foo.py\n", | |
" create mode 100644 setup.py\n", | |
" create mode 100644 three/__init__.py\n", | |
" create mode 100644 two/__init__.py\n" | |
] | |
} | |
], | |
"source": [ | |
"%%bash\n", | |
"touch setup.py\n", | |
"touch README.txt\n", | |
"\n", | |
"git init\n", | |
"git add *\n", | |
"git commit -m \"initial\"" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 16, | |
"metadata": { | |
"collapsed": false, | |
"scrolled": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"\u001b[01;34m.\u001b[00m\n", | |
"├── \u001b[01;34mthree\u001b[00m\n", | |
"│ └── __init__.py\n", | |
"├── \u001b[01;34mtwo\u001b[00m\n", | |
"│ └── __init__.py\n", | |
"├── \u001b[01;34mone\u001b[00m\n", | |
"│ ├── \u001b[01;34mfour\u001b[00m\n", | |
"│ │ ├── data.csv\n", | |
"│ │ ├── foo.py\n", | |
"│ │ └── __init__.py\n", | |
"│ └── __init__.py\n", | |
"├── README.txt\n", | |
"└── setup.py\n" | |
] | |
} | |
], | |
"source": [ | |
"%%bash\n", | |
"tree --sort=ctime -I \"*.pyc\" --noreport -C" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 17, | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "skip" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"import sys\n", | |
"sys.argv = [\"setup.py\", \"sdist\"]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 18, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Overwriting setup.py\n" | |
] | |
} | |
], | |
"source": [ | |
"%%file setup.py\n", | |
"from distutils.core import setup\n", | |
"\n", | |
"setup(\n", | |
" name=\"foo\", version=\"1.0\",\n", | |
" packages=['one', 'two', 'three', 'one.four'],\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 19, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"running sdist\r\n", | |
"running check\r\n", | |
"warning: check: missing required meta-data: url\r\n", | |
"\r\n", | |
"warning: check: missing meta-data: either (author and author_email) or (maintainer and maintainer_email) must be supplied\r\n", | |
"\r\n", | |
"warning: sdist: manifest template 'MANIFEST.in' does not exist (using default file list)\r\n", | |
"\r\n", | |
"writing manifest file 'MANIFEST'\r\n", | |
"creating foo-1.0\r\n", | |
"creating foo-1.0/one\r\n", | |
"creating foo-1.0/one/four\r\n", | |
"creating foo-1.0/three\r\n", | |
"creating foo-1.0/two\r\n", | |
"making hard links in foo-1.0...\r\n", | |
"hard linking README.txt -> foo-1.0\r\n", | |
"hard linking setup.py -> foo-1.0\r\n", | |
"hard linking one/__init__.py -> foo-1.0/one\r\n", | |
"hard linking one/four/__init__.py -> foo-1.0/one/four\r\n", | |
"hard linking one/four/foo.py -> foo-1.0/one/four\r\n", | |
"hard linking three/__init__.py -> foo-1.0/three\r\n", | |
"hard linking two/__init__.py -> foo-1.0/two\r\n", | |
"creating dist\r\n", | |
"Creating tar archive\r\n", | |
"removing 'foo-1.0' (and everything under it)\r\n" | |
] | |
} | |
], | |
"source": [ | |
"!python setup.py sdist" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"source": [ | |
"`Distutils` генерирует `MANIFEST`\n", | |
"со списком всех файлов пакета:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 20, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"# file GENERATED by distutils, do NOT edit\r\n", | |
"README.txt\r\n", | |
"setup.py\r\n", | |
"one/__init__.py\r\n", | |
"one/four/__init__.py\r\n", | |
"one/four/foo.py\r\n", | |
"three/__init__.py\r\n", | |
"two/__init__.py\r\n" | |
] | |
} | |
], | |
"source": [ | |
"%cat MANIFEST" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"11:00" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 21, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Overwriting setup.py\n" | |
] | |
} | |
], | |
"source": [ | |
"%%file setup.py\n", | |
"from setuptools import setup, find_packages\n", | |
"\n", | |
"setup(\n", | |
" name=\"foo\",\n", | |
" version=\"1.0\",\n", | |
" packages=find_packages(),\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 22, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "skip" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"rm: cannot remove ‘*/*/*.pyc’: No such file or directory\r\n" | |
] | |
} | |
], | |
"source": [ | |
"!rm */*/*.pyc" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 23, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"running sdist\n", | |
"running egg_info\n", | |
"creating foo.egg-info\n", | |
"writing dependency_links to foo.egg-info/dependency_links.txt\n", | |
"writing top-level names to foo.egg-info/top_level.txt\n", | |
"writing foo.egg-info/PKG-INFO\n", | |
"writing manifest file 'foo.egg-info/SOURCES.txt'\n", | |
"writing manifest file 'foo.egg-info/SOURCES.txt'\n", | |
"running check\n", | |
"warning: check: missing required meta-data: url\n", | |
"\n", | |
"warning: check: missing meta-data: either (author and author_email) or (maintainer and maintainer_email) must be supplied\n", | |
"\n", | |
"creating foo-1.0\n", | |
"creating foo-1.0/foo.egg-info\n", | |
"creating foo-1.0/one\n", | |
"creating foo-1.0/one/four\n", | |
"creating foo-1.0/three\n", | |
"creating foo-1.0/two\n", | |
"making hard links in foo-1.0...\n", | |
"hard linking README.txt -> foo-1.0\n", | |
"hard linking setup.py -> foo-1.0\n", | |
"hard linking foo.egg-info/PKG-INFO -> foo-1.0/foo.egg-info\n", | |
"hard linking foo.egg-info/SOURCES.txt -> foo-1.0/foo.egg-info\n", | |
"hard linking foo.egg-info/dependency_links.txt -> foo-1.0/foo.egg-info\n", | |
"hard linking foo.egg-info/top_level.txt -> foo-1.0/foo.egg-info\n", | |
"hard linking one/__init__.py -> foo-1.0/one\n", | |
"hard linking one/four/__init__.py -> foo-1.0/one/four\n", | |
"hard linking one/four/data.csv -> foo-1.0/one/four\n", | |
"hard linking one/four/foo.py -> foo-1.0/one/four\n", | |
"hard linking three/__init__.py -> foo-1.0/three\n", | |
"hard linking two/__init__.py -> foo-1.0/two\n", | |
"Writing foo-1.0/setup.cfg\n", | |
"Creating tar archive\n", | |
"removing 'foo-1.0' (and everything under it)\n" | |
] | |
} | |
], | |
"source": [ | |
"!python setup.py sdist" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"source": [ | |
"`Setuptools` генерирует manifest в другом месте:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 24, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"README.txt\r\n", | |
"setup.py\r\n", | |
"foo.egg-info/PKG-INFO\r\n", | |
"foo.egg-info/SOURCES.txt\r\n", | |
"foo.egg-info/dependency_links.txt\r\n", | |
"foo.egg-info/top_level.txt\r\n", | |
"one/__init__.py\r\n", | |
"one/four/__init__.py\r\n", | |
"one/four/data.csv\r\n", | |
"one/four/foo.py\r\n", | |
"three/__init__.py\r\n", | |
"two/__init__.py" | |
] | |
} | |
], | |
"source": [ | |
"%cat foo.egg-info/SOURCES.txt" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"12:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"source": [ | |
"## Добавляем файлы данных \n", | |
"\n", | |
"Иногда программе нужны дополнительные файлы.\n", | |
"\n", | |
"В нашем примере: `one/four/data.csv` содержит константы.\n", | |
"\n", | |
"Параметры `setup.py`:\n", | |
"* `package_data` (из `distutils`):\n", | |
"```python\n", | |
"setup(...,\n", | |
" package_data={'one.four': ['*.csv']},\n", | |
" # package_name => list of globs\n", | |
" # \"\" for all packages\n", | |
")\n", | |
"```\n", | |
"* `include_package_data`\n", | |
"* `exclude_package_data`" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"source": [ | |
"Практически универсальный `setup.py`:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 25, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Overwriting setup.py\n" | |
] | |
} | |
], | |
"source": [ | |
"%%file setup.py\n", | |
"from setuptools import setup, find_packages\n", | |
"\n", | |
"setup(\n", | |
" name=\"foo\",\n", | |
" version=\"1.0\",\n", | |
" packages=find_packages(),\n", | |
" include_package_data=True,\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"source": [ | |
"Чтобы это сработало, файлы данных должны быть в VCS.\n", | |
"\n", | |
"По умолчанию `setuptools` поддерживает только SVN и CVS\n", | |
"\n", | |
"```\n", | |
"pip install setuptools-git\n", | |
"pip install setuptools-bzr\n", | |
"pip install setuptools-hg\n", | |
"...\n", | |
"```" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 26, | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "skip" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"rm -rf foo.egg-info/" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 27, | |
"metadata": { | |
"collapsed": false, | |
"scrolled": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Processing /home/kpp/build/pyconru-setup-py/packs\n", | |
"Installing collected packages: foo\n", | |
" Found existing installation: foo 1.0\n", | |
" Uninstalling foo-1.0:\n", | |
" Successfully uninstalled foo-1.0\n", | |
" Running setup.py install for foo\n", | |
"Successfully installed foo-1.0\n" | |
] | |
} | |
], | |
"source": [ | |
"!pip install . -U" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"14:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"source": [ | |
"### Как использовать эти данные\n", | |
"\n", | |
"```python\n", | |
"os.path.join(__file__, ...)\n", | |
"```\n", | |
"будет работать не всегда" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 28, | |
"metadata": { | |
"collapsed": false, | |
"scrolled": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"(Requirement.parse('foo'),\n", | |
" {'_Requirement__hash': 393189115900593882,\n", | |
" 'extras': (),\n", | |
" 'hashCmp': ('foo', <SpecifierSet('')>, frozenset()),\n", | |
" 'key': 'foo',\n", | |
" 'project_name': 'foo',\n", | |
" 'specifier': <SpecifierSet('')>,\n", | |
" 'specs': [],\n", | |
" 'unsafe_name': 'foo'})" | |
] | |
}, | |
"execution_count": 28, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"from pkg_resources import Requirement, resource_stream, resource_filename\n", | |
"\n", | |
"req = Requirement.parse('foo') # any distrubution name\n", | |
"\n", | |
"req, req.__dict__" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 29, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"<_io.BufferedReader name='/home/kpp/build/pyconru-setup-py/venv/lib/python3.4/site-packages/one/four/data.csv'>" | |
] | |
}, | |
"execution_count": 29, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"resource_stream(req, 'one/four/data.csv')" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 30, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "skip" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"/home/kpp/build/pyconru-setup-py/c_exts\n" | |
] | |
} | |
], | |
"source": [ | |
"%mkdir -p ../c_exts\n", | |
"%cd ../c_exts\n", | |
"!touch setup.py\n", | |
"!touch README" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"16:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"## Модули расширения" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 31, | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "skip" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"import sys\n", | |
"\n", | |
"# workaround for IPython bug\n", | |
"sys.stderr.errors = None\n", | |
"sys.stdout.errors = None" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 32, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"running sdist\n", | |
"running egg_info\n", | |
"writing dependency_links to foo.egg-info/dependency_links.txt\n", | |
"writing top-level names to foo.egg-info/top_level.txt\n", | |
"writing foo.egg-info/PKG-INFO\n", | |
"reading manifest file 'foo.egg-info/SOURCES.txt'\n", | |
"writing manifest file 'foo.egg-info/SOURCES.txt'\n", | |
"running check\n" | |
] | |
}, | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"warning: check: missing required meta-data: url\n", | |
"\n", | |
"warning: check: missing meta-data: either (author and author_email) or (maintainer and maintainer_email) must be supplied\n", | |
"\n" | |
] | |
}, | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"creating foo-1.0\n", | |
"creating foo-1.0/foo.egg-info\n", | |
"making hard links in foo-1.0...\n", | |
"hard linking README -> foo-1.0\n", | |
"hard linking setup.py -> foo-1.0\n", | |
"hard linking foo.egg-info/PKG-INFO -> foo-1.0/foo.egg-info\n", | |
"hard linking foo.egg-info/SOURCES.txt -> foo-1.0/foo.egg-info\n", | |
"hard linking foo.egg-info/dependency_links.txt -> foo-1.0/foo.egg-info\n", | |
"hard linking foo.egg-info/top_level.txt -> foo-1.0/foo.egg-info\n", | |
"Writing foo-1.0/setup.cfg\n", | |
"Creating tar archive\n", | |
"removing 'foo-1.0' (and everything under it)\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"<setuptools.dist.Distribution at 0x7fd9aa6612b0>" | |
] | |
}, | |
"execution_count": 32, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"from distutils.core import setup, Extension\n", | |
"\n", | |
"setup(\n", | |
" name='foo',\n", | |
" version='1.0',\n", | |
" ext_modules=[Extension('foo', ['foo.c'])],\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"source": [ | |
"+см. документацию к Cython, cffi, numpy (как найти флаги компилятора) и др." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 33, | |
"metadata": { | |
"collapsed": false, | |
"scrolled": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Help on class Extension in module distutils.extension:\n", | |
"\n", | |
"class Extension(builtins.object)\n", | |
" | Just a collection of attributes that describes an extension\n", | |
" | module and everything needed to build it (hopefully in a portable\n", | |
" | way, but there are hooks that let you be as unportable as you need).\n", | |
" | \n", | |
" | Instance attributes:\n", | |
" | name : string\n", | |
" | the full name of the extension, including any packages -- ie.\n", | |
" | *not* a filename or pathname, but Python dotted name\n", | |
" | sources : [string]\n", | |
" | list of source filenames, relative to the distribution root\n", | |
" | (where the setup script lives), in Unix form (slash-separated)\n", | |
" | for portability. Source files may be C, C++, SWIG (.i),\n", | |
" | platform-specific resource files, or whatever else is recognized\n", | |
" | by the \"build_ext\" command as source for a Python extension.\n", | |
" | include_dirs : [string]\n", | |
" | list of directories to search for C/C++ header files (in Unix\n", | |
" | form for portability)\n", | |
" | define_macros : [(name : string, value : string|None)]\n", | |
" | list of macros to define; each macro is defined using a 2-tuple,\n", | |
" | where 'value' is either the string to define it to or None to\n", | |
" | define it without a particular value (equivalent of \"#define\n", | |
" | FOO\" in source or -DFOO on Unix C compiler command line)\n", | |
" | undef_macros : [string]\n", | |
" | list of macros to undefine explicitly\n", | |
" | library_dirs : [string]\n", | |
" | list of directories to search for C/C++ libraries at link time\n", | |
" | libraries : [string]\n", | |
" | list of library names (not filenames or paths) to link against\n", | |
" | runtime_library_dirs : [string]\n", | |
" | list of directories to search for C/C++ libraries at run time\n", | |
" | (for shared extensions, this is when the extension is loaded)\n", | |
" | extra_objects : [string]\n", | |
" | list of extra files to link with (eg. object files not implied\n", | |
" | by 'sources', static library that must be explicitly specified,\n", | |
" | binary resource files, etc.)\n", | |
" | extra_compile_args : [string]\n", | |
" | any extra platform- and compiler-specific information to use\n", | |
" | when compiling the source files in 'sources'. For platforms and\n", | |
" | compilers where \"command line\" makes sense, this is typically a\n", | |
" | list of command-line arguments, but for other platforms it could\n", | |
" | be anything.\n", | |
" | extra_link_args : [string]\n", | |
" | any extra platform- and compiler-specific information to use\n", | |
" | when linking object files together to create the extension (or\n", | |
" | to create a new static Python interpreter). Similar\n", | |
" | interpretation as for 'extra_compile_args'.\n", | |
" | export_symbols : [string]\n", | |
" | list of symbols to be exported from a shared extension. Not\n", | |
" | used on all platforms, and not generally necessary for Python\n", | |
" | extensions, which typically export exactly one symbol: \"init\" +\n", | |
" | extension_name.\n", | |
" | swig_opts : [string]\n", | |
" | any extra options to pass to SWIG if a source file has the .i\n", | |
" | extension.\n", | |
" | depends : [string]\n", | |
" | list of files that the extension depends on\n", | |
" | language : string\n", | |
" | extension language (i.e. \"c\", \"c++\", \"objc\"). Will be detected\n", | |
" | from the source extensions if not provided.\n", | |
" | optional : boolean\n", | |
" | specifies that a build failure in the extension should not abort the\n", | |
" | build process, but simply not install the failing extension.\n", | |
" | \n", | |
" | Methods defined here:\n", | |
" | \n", | |
" | __init__(self, name, sources, include_dirs=None, define_macros=None, undef_macros=None, library_dirs=None, libraries=None, runtime_library_dirs=None, extra_objects=None, extra_compile_args=None, extra_link_args=None, export_symbols=None, swig_opts=None, depends=None, language=None, optional=None, **kw)\n", | |
" | # When adding arguments to this constructor, be sure to update\n", | |
" | # setup_keywords in core.py.\n", | |
" | \n", | |
" | ----------------------------------------------------------------------\n", | |
" | Data descriptors defined here:\n", | |
" | \n", | |
" | __dict__\n", | |
" | dictionary for instance variables (if defined)\n", | |
" | \n", | |
" | __weakref__\n", | |
" | list of weak references to the object (if defined)\n", | |
"\n" | |
] | |
} | |
], | |
"source": [ | |
"%%python3\n", | |
"import distutils.core\n", | |
"help(distutils.core.Extension)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"source": [ | |
"## Бывает сложнее...\n", | |
"\n", | |
"* `autotools`, `autoconf`, `CMake`...\n", | |
"* мир (пока) не крутится вокург Python\n", | |
"* попробуйте отделить начинку от bindings\n", | |
"* обычно нужно генерировать `setup.py`\n", | |
"* параметр `eager_resources` в `setup()`, если расширениям нужны файлы данных" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"18:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"# Взаимодействие с дргуими пакетами-дистрибутивами\n", | |
"\n", | |
"* require / зависимость\n", | |
" * `install_requires`\n", | |
" * `setup_requires`\n", | |
" * `tests_require`\n", | |
" * `extras_require`\n", | |
"* через `pkg_resources`\n", | |
" * через `entry_points`\n", | |
"\n", | |
"* obsolete\n", | |
"* provides" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 34, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "skip" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"/home/kpp/build/pyconru-setup-py/deps\n" | |
] | |
} | |
], | |
"source": [ | |
"%mkdir -p ../deps\n", | |
"%cd ../deps\n", | |
"%cp ../simple/foo.py ." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"20:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"source": [ | |
"### О версиях\n", | |
"\n", | |
"`pip` и `setuptools` используют PEP 440, реализованый в пакете `packaging`.\n", | |
"```json\n", | |
"Final:\n", | |
" 0.1.1, 9.0.3, 2015.09, ...\n", | |
"Pre:\n", | |
" 1.2_a3, 2015.09_beta, 1.2rc2, ...\n", | |
"Post:\n", | |
" 1.1-post1, 2015-rev2, 0.1.r5, 10-2, ...\n", | |
"Dev:\n", | |
" 9.6-dev0, 11.15.post7.dev, ...\n", | |
"Epoch:\n", | |
" 1!0.1, 2!8.4.4, ...\n", | |
"Local:\n", | |
" 1.0+abc.5, 1.0+ubuntu-1, 2015-r7+5, ...\n", | |
"\n", | |
"9.01.0-1 == 9.1-r1 == 0!9.1.post1\n", | |
"```" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 35, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"<Version('9.1.0.post1')>" | |
] | |
}, | |
"execution_count": 35, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"import pkg_resources\n", | |
"\n", | |
"v1 = pkg_resources.parse_version('9.01.0-1')\n", | |
"v1" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 36, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"<Version('9.1.post1')>" | |
] | |
}, | |
"execution_count": 36, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"v2 = pkg_resources.parse_version('9.1-r1')\n", | |
"v2" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 37, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"<Version('9.1.post1')>" | |
] | |
}, | |
"execution_count": 37, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"v3 = pkg_resources.parse_version('0!9.1.post1')\n", | |
"v3" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 38, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"True" | |
] | |
}, | |
"execution_count": 38, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"v1 == v2 == v3" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"22:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"source": [ | |
"### Спецификация версий в зависимостях\n", | |
"\n", | |
"```\n", | |
"~= == != <= >= < > ===\n", | |
"```\n", | |
"\n", | |
"Специальные символы:\n", | |
"\n", | |
"\n", | |
"```\n", | |
" , *\n", | |
"```\n", | |
"\n", | |
"Примеры:\n", | |
"\n", | |
"```\n", | |
" packagename == 3.1.* packagename~=3.1.0\n", | |
" HelloWorld ~=3.1.0, != 3.1.3\n", | |
"```\n", | |
"\n" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"source": [ | |
"#### Не ломайте мне систему слишком жёсткими зависимостями!!!!!!!!!!!!!!!!!!!!!!!!!!!1111111111111\n", | |
"* Адекватно оценивайте важность своего пакета" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 39, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"<Specifier('==3.1.*')>" | |
] | |
}, | |
"execution_count": 39, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"from packaging import specifiers\n", | |
"\n", | |
"x = specifiers.Specifier('==3.1.*')\n", | |
"x" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 40, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"<SpecifierSet('!=3.1.1,~=3.1.0')>" | |
] | |
}, | |
"execution_count": 40, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"y = specifiers.SpecifierSet('~=3.1.0, !=3.1.1')\n", | |
"y" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 41, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"True" | |
] | |
}, | |
"execution_count": 41, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"'3.1.2-post' in y" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"24:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"source": [ | |
"### Зависимости не из PyPI\n", | |
"\n", | |
"```python\n", | |
"setup(\n", | |
" name=\"foo\", version=\"1.0\",\n", | |
" \n", | |
" install_requires=[\n", | |
" \"something\",\n", | |
" \"related_thing\",\n", | |
" ],\n", | |
"\n", | |
" dependency_links=[\n", | |
" \"file:///path/to/something-none-any.whl\"\n", | |
" \"#egg=something-1.0\",\n", | |
"\n", | |
" \"git+ssh://git@gitserver/relthing.git\"\n", | |
" \"@master\"\n", | |
" \"#egg=related_thing-0.1dev\",\n", | |
" ],\n", | |
")\n", | |
"```" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"source": [ | |
"```bash\n", | |
"python setup.py install\n", | |
"\n", | |
"easy_install .\n", | |
"\n", | |
"easy_install git+ssh://git@gitserver/foo.git\n", | |
"\n", | |
"pip install \\\n", | |
" --process-dependency-links \\\n", | |
" --trusted-host gitserver \\\n", | |
" git+ssh://git@gitserver/foo.git\n", | |
"\n", | |
"```\n", | |
"\n", | |
"С выходом нового формата метаданных, вещи немного поменяются..." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"26:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"source": [ | |
"# Extras\n", | |
"\n", | |
"Необязательные зависимости и параметризация поведения `setup()`\n", | |
"\n", | |
"```python\n", | |
"setup(\n", | |
" name='foo', ...\n", | |
" extras_require={\n", | |
" 'tools': [], # Just add param\n", | |
" ':python_version==\"2.6\"': ['argparse'],\n", | |
" 'export': ['msgpack', 'pyYAML', ''],\n", | |
" }\n", | |
")\n", | |
"```\n", | |
"\n", | |
"При установке: `$ pip install . [tools]`\n", | |
"\n", | |
"В зависимостях:\n", | |
"```python\n", | |
" install_requires=[\"foo[export,tools]\"],\n", | |
"```" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"29:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"source": [ | |
"## А как же `requirements.txt`?\n", | |
"\n", | |
"* Используется для воссоздания окружения при помощи\n", | |
"\n", | |
"```bash\n", | |
" pip -r requirements.txt\n", | |
"```\n", | |
"\n", | |
"* Каждая строка содержит аргументы для `pip`, например:\n", | |
"\n", | |
"```bash\n", | |
" numpy\n", | |
" --pre theano\n", | |
"```\n", | |
"\n", | |
"* API для парсинга `pip.req.req_file` постоянно меняется\n", | |
"\n", | |
"* Если всё же конвертируете в параметры `setup()`:\n", | |
" * убедитесь, что `requirements.txt` попадает в `sdist`" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"31:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"## Development mode\n", | |
"\n", | |
"Добавить ссылку на текущий каталог в `sys.path`, установить зависимости и скрипты:\n", | |
"```bash\n", | |
"pip install -e .\n", | |
"```\n", | |
"\n", | |
"Сделать `git clone` в папке `$VIRTUAL_ENV/src`, добавить ссылку в `sys.path`, установить зависимости и скрипты:\n", | |
"```bash\n", | |
"pip install -e git+http://github.com/your/project\n", | |
"```\n", | |
"\n", | |
"Изменения в коде сразу отражаются в скриптах и при `import`\n", | |
"\n", | |
"Параметр `-e` можно указывать в `requirements.txt`" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"33:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"## Если `setup.py` написан без `setuptools`" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 42, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "skip" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"!touch setup.py" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 43, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"running develop\n", | |
"running egg_info\n", | |
"writing foo.egg-info/PKG-INFO\n", | |
"deleting foo.egg-info/requires.txt\n", | |
"writing dependency_links to foo.egg-info/dependency_links.txt\n", | |
"writing entry points to foo.egg-info/entry_points.txt\n", | |
"writing top-level names to foo.egg-info/top_level.txt\n", | |
"reading manifest file 'foo.egg-info/SOURCES.txt'\n", | |
"writing manifest file 'foo.egg-info/SOURCES.txt'\n", | |
"running build_ext\n", | |
"Creating /home/kpp/build/pyconru-setup-py/venv/lib/python3.4/site-packages/foo.egg-link (link to .)\n", | |
"Adding foo 1.0 to easy-install.pth file\n", | |
"Installing foo_util script to /home/kpp/build/pyconru-setup-py/venv/bin\n", | |
"\n", | |
"Installed /home/kpp/build/pyconru-setup-py/deps\n", | |
"Processing dependencies for foo==1.0\n", | |
"Finished processing dependencies for foo==1.0\n" | |
] | |
}, | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"warning: manifest_maker: standard file '-c' not found\n", | |
"\n" | |
] | |
} | |
], | |
"source": [ | |
"%%bash\n", | |
"python -c \"import setuptools; exec(open('setup.py').read())\" develop" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"34:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"# Скрипты" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 44, | |
"metadata": { | |
"collapsed": true, | |
"slideshow": { | |
"slide_type": "skip" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"!touch README" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 45, | |
"metadata": { | |
"collapsed": false, | |
"scrolled": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Overwriting main.py\n" | |
] | |
} | |
], | |
"source": [ | |
"%%file main.py\n", | |
"\n", | |
"if __name__ == '__main__':\n", | |
" import foo\n", | |
" foo.foo()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 46, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"running sdist\n", | |
"running egg_info\n", | |
"writing dependency_links to foo.egg-info/dependency_links.txt\n", | |
"deleting foo.egg-info/entry_points.txt\n", | |
"writing top-level names to foo.egg-info/top_level.txt\n", | |
"writing foo.egg-info/PKG-INFO\n", | |
"reading manifest file 'foo.egg-info/SOURCES.txt'\n", | |
"writing manifest file 'foo.egg-info/SOURCES.txt'\n", | |
"running check\n" | |
] | |
}, | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"warning: check: missing required meta-data: url\n", | |
"\n", | |
"warning: check: missing meta-data: either (author and author_email) or (maintainer and maintainer_email) must be supplied\n", | |
"\n" | |
] | |
}, | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"creating foo-1.0\n", | |
"creating foo-1.0/foo.egg-info\n", | |
"making hard links in foo-1.0...\n", | |
"hard linking README -> foo-1.0\n", | |
"hard linking foo.py -> foo-1.0\n", | |
"hard linking main.py -> foo-1.0\n", | |
"hard linking setup.cfg -> foo-1.0\n", | |
"hard linking setup.py -> foo-1.0\n", | |
"hard linking foo.egg-info/PKG-INFO -> foo-1.0/foo.egg-info\n", | |
"hard linking foo.egg-info/SOURCES.txt -> foo-1.0/foo.egg-info\n", | |
"hard linking foo.egg-info/dependency_links.txt -> foo-1.0/foo.egg-info\n", | |
"hard linking foo.egg-info/top_level.txt -> foo-1.0/foo.egg-info\n", | |
"copying setup.cfg -> foo-1.0\n", | |
"Writing foo-1.0/setup.cfg\n", | |
"Creating tar archive\n", | |
"removing 'foo-1.0' (and everything under it)\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"<setuptools.dist.Distribution at 0x7fd9aa6388d0>" | |
] | |
}, | |
"execution_count": 46, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"setup(\n", | |
" name='foo', version=\"1.0\",\n", | |
" py_modules=['foo'],\n", | |
" scripts=['main.py'],\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 47, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"running sdist\n", | |
"running egg_info\n", | |
"writing dependency_links to foo.egg-info/dependency_links.txt\n", | |
"writing entry points to foo.egg-info/entry_points.txt\n", | |
"writing top-level names to foo.egg-info/top_level.txt\n", | |
"writing foo.egg-info/PKG-INFO\n", | |
"reading manifest file 'foo.egg-info/SOURCES.txt'\n", | |
"writing manifest file 'foo.egg-info/SOURCES.txt'\n", | |
"running check\n" | |
] | |
}, | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"warning: check: missing required meta-data: url\n", | |
"\n", | |
"warning: check: missing meta-data: either (author and author_email) or (maintainer and maintainer_email) must be supplied\n", | |
"\n" | |
] | |
}, | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"creating foo-1.0\n", | |
"creating foo-1.0/foo.egg-info\n", | |
"making hard links in foo-1.0...\n", | |
"hard linking README -> foo-1.0\n", | |
"hard linking foo.py -> foo-1.0\n", | |
"hard linking main.py -> foo-1.0\n", | |
"hard linking setup.cfg -> foo-1.0\n", | |
"hard linking setup.py -> foo-1.0\n", | |
"hard linking foo.egg-info/PKG-INFO -> foo-1.0/foo.egg-info\n", | |
"hard linking foo.egg-info/SOURCES.txt -> foo-1.0/foo.egg-info\n", | |
"hard linking foo.egg-info/dependency_links.txt -> foo-1.0/foo.egg-info\n", | |
"hard linking foo.egg-info/entry_points.txt -> foo-1.0/foo.egg-info\n", | |
"hard linking foo.egg-info/top_level.txt -> foo-1.0/foo.egg-info\n", | |
"copying setup.cfg -> foo-1.0\n", | |
"Writing foo-1.0/setup.cfg\n", | |
"Creating tar archive\n", | |
"removing 'foo-1.0' (and everything under it)\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"<setuptools.dist.Distribution at 0x7fd9aa5c2588>" | |
] | |
}, | |
"execution_count": 47, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"\n", | |
"setup(\n", | |
" name='foo', version=\"1.0\",\n", | |
" py_modules=['foo'],\n", | |
" entry_points={\n", | |
" 'console_scripts': [\n", | |
" 'foo_util = foo:foo',\n", | |
" ],\n", | |
" }\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"source": [ | |
"#### Extras и скрипты" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 48, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"running sdist\n", | |
"running egg_info\n", | |
"writing dependency_links to foo.egg-info/dependency_links.txt\n", | |
"writing entry points to foo.egg-info/entry_points.txt\n", | |
"writing top-level names to foo.egg-info/top_level.txt\n", | |
"writing requirements to foo.egg-info/requires.txt\n", | |
"writing foo.egg-info/PKG-INFO\n", | |
"reading manifest file 'foo.egg-info/SOURCES.txt'\n", | |
"writing manifest file 'foo.egg-info/SOURCES.txt'\n", | |
"running check\n" | |
] | |
}, | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"warning: check: missing required meta-data: url\n", | |
"\n", | |
"warning: check: missing meta-data: either (author and author_email) or (maintainer and maintainer_email) must be supplied\n", | |
"\n" | |
] | |
}, | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"creating foo-1.0\n", | |
"creating foo-1.0/foo.egg-info\n", | |
"making hard links in foo-1.0...\n", | |
"hard linking README -> foo-1.0\n", | |
"hard linking foo.py -> foo-1.0\n", | |
"hard linking main.py -> foo-1.0\n", | |
"hard linking setup.cfg -> foo-1.0\n", | |
"hard linking setup.py -> foo-1.0\n", | |
"hard linking foo.egg-info/PKG-INFO -> foo-1.0/foo.egg-info\n", | |
"hard linking foo.egg-info/SOURCES.txt -> foo-1.0/foo.egg-info\n", | |
"hard linking foo.egg-info/dependency_links.txt -> foo-1.0/foo.egg-info\n", | |
"hard linking foo.egg-info/entry_points.txt -> foo-1.0/foo.egg-info\n", | |
"hard linking foo.egg-info/requires.txt -> foo-1.0/foo.egg-info\n", | |
"hard linking foo.egg-info/top_level.txt -> foo-1.0/foo.egg-info\n", | |
"copying setup.cfg -> foo-1.0\n", | |
"Writing foo-1.0/setup.cfg\n", | |
"Creating tar archive\n", | |
"removing 'foo-1.0' (and everything under it)\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"<setuptools.dist.Distribution at 0x7fd9aa55e588>" | |
] | |
}, | |
"execution_count": 48, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"setup(\n", | |
" name='foo', version=\"1.0\",\n", | |
" py_modules=['foo'],\n", | |
" extras_require={'tools': []},\n", | |
" entry_points={\n", | |
" 'console_scripts': [\n", | |
" 'foo_util = foo:foo [tools]',\n", | |
" ],\n", | |
" }\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"39:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"# entry_points" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 49, | |
"metadata": { | |
"collapsed": false, | |
"scrolled": true, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Overwriting setup.py\n" | |
] | |
} | |
], | |
"source": [ | |
"%%file setup.py\n", | |
"from setuptools import setup\n", | |
"\n", | |
"setup(\n", | |
" name='foo', version=\"1.0\",\n", | |
" py_modules=['foo'],\n", | |
" entry_points='''\n", | |
" [console_scripts]\n", | |
" foo_util = foo:foo\n", | |
"\n", | |
" [reporting.tools]\n", | |
" foo_report = foo:foo\n", | |
" ''',\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 50, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "skip" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Uninstalling foo-1.0:\n", | |
" Successfully uninstalled foo-1.0\n", | |
"Uninstalling foo-1.0:\n", | |
" Successfully uninstalled foo-1.0\n" | |
] | |
} | |
], | |
"source": [ | |
"!pip uninstall foo -y\n", | |
"!pip uninstall foo -y" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 51, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Processing /home/kpp/build/pyconru-setup-py/deps\n", | |
"Installing collected packages: foo\n", | |
" Running setup.py install for foo\n", | |
"Successfully installed foo-1.0\n" | |
] | |
} | |
], | |
"source": [ | |
"!pip install . -U" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 52, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "subslide" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"I'm in your system now\n" | |
] | |
} | |
], | |
"source": [ | |
"%%bash \n", | |
"foo_util" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 53, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"#!/home/kpp/build/pyconru-setup-py/venv/bin/python3\n", | |
"# EASY-INSTALL-ENTRY-SCRIPT: 'foo==1.0','console_scripts','foo_util'\n", | |
"__requires__ = 'foo==1.0'\n", | |
"import sys\n", | |
"from pkg_resources import load_entry_point\n", | |
"\n", | |
"if __name__ == '__main__':\n", | |
" sys.exit(\n", | |
" load_entry_point('foo==1.0', 'console_scripts', 'foo_util')()\n", | |
" )\n" | |
] | |
} | |
], | |
"source": [ | |
"%%bash\n", | |
"cat `which foo_util`" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 54, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Reporter foo_report:\n", | |
"I'm in your system now\n" | |
] | |
} | |
], | |
"source": [ | |
"from pkg_resources import iter_entry_points\n", | |
"\n", | |
"for ep in iter_entry_points('reporting.tools'):\n", | |
"\n", | |
" print('Reporter {}:'.format(ep.name))\n", | |
" func = ep.load()\n", | |
" \n", | |
" func()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"43:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"# setup.cfg\n", | |
"\n", | |
"```bash\n", | |
"python setup.py ... saveopts\n", | |
"```\n", | |
"\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 55, | |
"metadata": { | |
"collapsed": false, | |
"slideshow": { | |
"slide_type": "fragment" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Overwriting setup.cfg\n" | |
] | |
} | |
], | |
"source": [ | |
"%%file setup.cfg\n", | |
"\n", | |
"[bdist_wheel]\n", | |
"universal = 1\n", | |
"\n", | |
"[nosetests]\n", | |
"exe = 1\n", | |
"with-coverage = 1\n", | |
"with-tissue = 1\n", | |
"\n", | |
"[coverage:run]\n", | |
"omit = *numpy*\n" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "notes" | |
} | |
}, | |
"source": [ | |
"45:00" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"slideshow": { | |
"slide_type": "slide" | |
} | |
}, | |
"source": [ | |
"# Thank you\n", | |
"\n", | |
"```\n", | |
"```\n", | |
"\n", | |
"Константин Игнатов\n", | |
"\n", | |
"@podshumok\n", | |
"\n", | |
"\n", | |
"```\n", | |
"```\n", | |
"\n", | |
"\n", | |
"Qrator Labs\n", | |
"\n", | |
"[qrator.net](http://qrator.net)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 56, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"# Type your question here..." | |
] | |
} | |
], | |
"metadata": { | |
"celltoolbar": "Slideshow", | |
"kernelspec": { | |
"display_name": "Python 3", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.4.3" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 0 | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
notebook~=4.0 | |
packaging | |
setuptools>18.0 | |
pip>7.0 | |
setuptools-git | |
#git+https://github.com/damianavila/RISE |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment