diff options
author | Armin Ronacher <armin.ronacher@active-4.com> | 2014-08-12 22:50:21 +0200 |
---|---|---|
committer | Armin Ronacher <armin.ronacher@active-4.com> | 2014-08-12 22:50:21 +0200 |
commit | 61b6ffa13f3d1b471847c57b44bf0c5ac29c0244 (patch) | |
tree | 02b2432f3d716b1b795215d5359b071926a8adb1 /docs/setuptools.rst | |
parent | a4d02ff64c328e7a7693b8d8dbeecfed1c704f6f (diff) | |
download | click-61b6ffa13f3d1b471847c57b44bf0c5ac29c0244.tar.gz |
Rewrote the setuptools documentation.
Diffstat (limited to 'docs/setuptools.rst')
-rw-r--r-- | docs/setuptools.rst | 110 |
1 files changed, 83 insertions, 27 deletions
diff --git a/docs/setuptools.rst b/docs/setuptools.rst index 1f4a8ac..7dfa591 100644 --- a/docs/setuptools.rst +++ b/docs/setuptools.rst @@ -1,33 +1,54 @@ .. _setuptools-integration: -Usage with Setuptools -===================== +Setuptools Integration +====================== When writing command line utilities, it's recommended to write them as modules that are distributed with setuptools instead of using Unix -shebangs. There are many reasons for this. - -The first one is that setuptools automatically generates executable -wrappers for Windows so your command line utilities work on Windows too. - -The second reason is that setuptools scripts work with virtualenv on Unix -without the virtualenv having to be activated. This is a very useful -concept which allows you to bundle your scripts with all requirements into -a virtualenv. +shebangs. + +Why would you want to do that? There are a bunch of reasons: + +1. One of the problems with the traditional approach is that the first + module the Python interpreter loads has an incorrect name. This might + sound like a small issue but it has quite significant implications. + + The first module is not called by it's actual name, but the + interpreter renames it to ``__main__``. While that is a perfectly + valid name it means that if another piece of code wants to import from + that module it will trigger the import a second time under it's real + name and all the sudden your code is imported twice. + +2. Not on all platforms are things that easy to execute. On Linux and OS + X you can add a comment to the beginning of the file (``#/usr/bin/env + python``) and your script works like an executable (assuming it has + the executable bit set). This however does not work on Windows. + While on Windows you can associate interpreters with file extensions + (like having everything ending in ``.py`` execute through the Python + interpreter) you will then run into issues if you want to use the + script in a virtualenv. + + In fact running a script in a virtualenv is an issue with OS X and + Linux as well. With the traditional approach you need to have the + whole virtualenv activated so that the correct Python interpreter is + used. Not very user friendly. + +3. The main trick only works if the script is a Python module. If your + application grows too large and you want to start using a package you + will run into issues. Introduction ------------ -To bundle your script with setuptools, all you need is the script in a Python -package and a ``setup.py`` file. +To bundle your script with setuptools, all you need is the script in a +Python package and a ``setup.py`` file. Imagine this directory structure:: - yourpackage/ - cli.py + yourscript.py setup.py -Contents of ``cli.py``: +Contents of ``yourscript.py``: .. click:example:: @@ -40,27 +61,26 @@ Contents of ``cli.py``: Contents of ``setup.py``:: - from setuptools import setup, find_packages + from setuptools import setup setup( - name='yourpackage', + name='yourscript', version='0.1', - packages=find_packages(), - include_package_data=True, + py_modules=['yourscript'], install_requires=[ 'Click', ], entry_points=''' [console_scripts] - yourscript=yourpackage.cli:cli + yourscript=yourscript:cli ''', ) -The magic is in the ``entry_points`` parameter. Below ``console_scripts``, -each line identifies one console script. The first part before the equals -sign (``=``) is the name of the script that should be generated, the second -part is the import path followed by a colon (``:``) with the Click -command. +The magic is in the ``entry_points`` parameter. Below +``console_scripts``, each line identifies one console script. The first +part before the equals sign (``=``) is the name of the script that should +be generated, the second part is the import path followed by a colon +(``:``) with the Click command. That's it. @@ -78,4 +98,40 @@ Afterwards, your command should be available: .. click:run:: - invoke(cli, prog_name='yourscript', prog_prefix='') + invoke(cli, prog_name='yourscript') + +Scripts in Packages +------------------- + +If your script is growing and you want to switch over to your script being +contained in a Python package the changes necessary are minimal. Let's +assume your directory structure changed to this:: + + yourpackage/ + main.py + utils.py + scripts/ + yourscript.py + +In this case instead of using ``py_modules`` in your ``setup.py`` file you +can use ``packages`` and the automatic package finding support of +setuptools. In addition to that it's also recommended to include other +package data. + +These would be the modified contents of ``setup.py``:: + + from setuptools import setup, find_packages + + setup( + name='yourpackage', + version='0.1', + packages=find_packages(), + include_package_data=True, + install_requires=[ + 'Click', + ], + entry_points=''' + [console_scripts] + yourscript=yourpackage.scripts.yourscript:cli + ''', + ) |