1.. _examples: 2 3******** 4Examples 5******** 6 7This chapter provides a number of basic examples to help get started with 8distutils. Additional information about using distutils can be found in the 9Distutils Cookbook. 10 11 12.. seealso:: 13 14 `Distutils Cookbook <https://wiki.python.org/moin/Distutils/Cookbook>`_ 15 Collection of recipes showing how to achieve more control over distutils. 16 17 18.. _pure-mod: 19 20Pure Python distribution (by module) 21==================================== 22 23If you're just distributing a couple of modules, especially if they don't live 24in a particular package, you can specify them individually using the 25``py_modules`` option in the setup script. 26 27In the simplest case, you'll have two files to worry about: a setup script and 28the single module you're distributing, :file:`foo.py` in this example:: 29 30 <root>/ 31 setup.py 32 foo.py 33 34(In all diagrams in this section, *<root>* will refer to the distribution root 35directory.) A minimal setup script to describe this situation would be:: 36 37 from distutils.core import setup 38 setup(name='foo', 39 version='1.0', 40 py_modules=['foo'], 41 ) 42 43Note that the name of the distribution is specified independently with the 44``name`` option, and there's no rule that says it has to be the same as 45the name of the sole module in the distribution (although that's probably a good 46convention to follow). However, the distribution name is used to generate 47filenames, so you should stick to letters, digits, underscores, and hyphens. 48 49Since ``py_modules`` is a list, you can of course specify multiple 50modules, eg. if you're distributing modules :mod:`foo` and :mod:`bar`, your 51setup might look like this:: 52 53 <root>/ 54 setup.py 55 foo.py 56 bar.py 57 58and the setup script might be :: 59 60 from distutils.core import setup 61 setup(name='foobar', 62 version='1.0', 63 py_modules=['foo', 'bar'], 64 ) 65 66You can put module source files into another directory, but if you have enough 67modules to do that, it's probably easier to specify modules by package rather 68than listing them individually. 69 70 71.. _pure-pkg: 72 73Pure Python distribution (by package) 74===================================== 75 76If you have more than a couple of modules to distribute, especially if they are 77in multiple packages, it's probably easier to specify whole packages rather than 78individual modules. This works even if your modules are not in a package; you 79can just tell the Distutils to process modules from the root package, and that 80works the same as any other package (except that you don't have to have an 81:file:`__init__.py` file). 82 83The setup script from the last example could also be written as :: 84 85 from distutils.core import setup 86 setup(name='foobar', 87 version='1.0', 88 packages=[''], 89 ) 90 91(The empty string stands for the root package.) 92 93If those two files are moved into a subdirectory, but remain in the root 94package, e.g.:: 95 96 <root>/ 97 setup.py 98 src/ foo.py 99 bar.py 100 101then you would still specify the root package, but you have to tell the 102Distutils where source files in the root package live:: 103 104 from distutils.core import setup 105 setup(name='foobar', 106 version='1.0', 107 package_dir={'': 'src'}, 108 packages=[''], 109 ) 110 111More typically, though, you will want to distribute multiple modules in the same 112package (or in sub-packages). For example, if the :mod:`foo` and :mod:`bar` 113modules belong in package :mod:`foobar`, one way to layout your source tree is 114:: 115 116 <root>/ 117 setup.py 118 foobar/ 119 __init__.py 120 foo.py 121 bar.py 122 123This is in fact the default layout expected by the Distutils, and the one that 124requires the least work to describe in your setup script:: 125 126 from distutils.core import setup 127 setup(name='foobar', 128 version='1.0', 129 packages=['foobar'], 130 ) 131 132If you want to put modules in directories not named for their package, then you 133need to use the ``package_dir`` option again. For example, if the 134:file:`src` directory holds modules in the :mod:`foobar` package:: 135 136 <root>/ 137 setup.py 138 src/ 139 __init__.py 140 foo.py 141 bar.py 142 143an appropriate setup script would be :: 144 145 from distutils.core import setup 146 setup(name='foobar', 147 version='1.0', 148 package_dir={'foobar': 'src'}, 149 packages=['foobar'], 150 ) 151 152Or, you might put modules from your main package right in the distribution 153root:: 154 155 <root>/ 156 setup.py 157 __init__.py 158 foo.py 159 bar.py 160 161in which case your setup script would be :: 162 163 from distutils.core import setup 164 setup(name='foobar', 165 version='1.0', 166 package_dir={'foobar': ''}, 167 packages=['foobar'], 168 ) 169 170(The empty string also stands for the current directory.) 171 172If you have sub-packages, they must be explicitly listed in ``packages``, 173but any entries in ``package_dir`` automatically extend to sub-packages. 174(In other words, the Distutils does *not* scan your source tree, trying to 175figure out which directories correspond to Python packages by looking for 176:file:`__init__.py` files.) Thus, if the default layout grows a sub-package:: 177 178 <root>/ 179 setup.py 180 foobar/ 181 __init__.py 182 foo.py 183 bar.py 184 subfoo/ 185 __init__.py 186 blah.py 187 188then the corresponding setup script would be :: 189 190 from distutils.core import setup 191 setup(name='foobar', 192 version='1.0', 193 packages=['foobar', 'foobar.subfoo'], 194 ) 195 196 197.. _single-ext: 198 199Single extension module 200======================= 201 202Extension modules are specified using the ``ext_modules`` option. 203``package_dir`` has no effect on where extension source files are found; 204it only affects the source for pure Python modules. The simplest case, a 205single extension module in a single C source file, is:: 206 207 <root>/ 208 setup.py 209 foo.c 210 211If the :mod:`foo` extension belongs in the root package, the setup script for 212this could be :: 213 214 from distutils.core import setup 215 from distutils.extension import Extension 216 setup(name='foobar', 217 version='1.0', 218 ext_modules=[Extension('foo', ['foo.c'])], 219 ) 220 221If the extension actually belongs in a package, say :mod:`foopkg`, then 222 223With exactly the same source tree layout, this extension can be put in the 224:mod:`foopkg` package simply by changing the name of the extension:: 225 226 from distutils.core import setup 227 from distutils.extension import Extension 228 setup(name='foobar', 229 version='1.0', 230 ext_modules=[Extension('foopkg.foo', ['foo.c'])], 231 ) 232 233Checking a package 234================== 235 236The ``check`` command allows you to verify if your package meta-data 237meet the minimum requirements to build a distribution. 238 239To run it, just call it using your :file:`setup.py` script. If something is 240missing, ``check`` will display a warning. 241 242Let's take an example with a simple script:: 243 244 from distutils.core import setup 245 246 setup(name='foobar') 247 248Running the ``check`` command will display some warnings: 249 250.. code-block:: shell-session 251 252 $ python setup.py check 253 running check 254 warning: check: missing required meta-data: version, url 255 warning: check: missing meta-data: either (author and author_email) or 256 (maintainer and maintainer_email) must be supplied 257 258 259If you use the reStructuredText syntax in the ``long_description`` field and 260`docutils`_ is installed you can check if the syntax is fine with the 261``check`` command, using the ``restructuredtext`` option. 262 263For example, if the :file:`setup.py` script is changed like this:: 264 265 from distutils.core import setup 266 267 desc = """\ 268 My description 269 ============== 270 271 This is the description of the ``foobar`` package. 272 """ 273 274 setup(name='foobar', version='1', author='tarek', 275 author_email='tarek@ziade.org', 276 url='http://example.com', long_description=desc) 277 278Where the long description is broken, ``check`` will be able to detect it 279by using the :mod:`docutils` parser: 280 281.. code-block:: shell-session 282 283 $ python setup.py check --restructuredtext 284 running check 285 warning: check: Title underline too short. (line 2) 286 warning: check: Could not finish the parsing. 287 288Reading the metadata 289===================== 290 291The :func:`distutils.core.setup` function provides a command-line interface 292that allows you to query the metadata fields of a project through the 293``setup.py`` script of a given project: 294 295.. code-block:: shell-session 296 297 $ python setup.py --name 298 distribute 299 300This call reads the ``name`` metadata by running the 301:func:`distutils.core.setup` function. Although, when a source or binary 302distribution is created with Distutils, the metadata fields are written 303in a static file called :file:`PKG-INFO`. When a Distutils-based project is 304installed in Python, the :file:`PKG-INFO` file is copied alongside the modules 305and packages of the distribution under :file:`NAME-VERSION-pyX.X.egg-info`, 306where ``NAME`` is the name of the project, ``VERSION`` its version as defined 307in the Metadata, and ``pyX.X`` the major and minor version of Python like 308``2.7`` or ``3.2``. 309 310You can read back this static file, by using the 311:class:`distutils.dist.DistributionMetadata` class and its 312:func:`read_pkg_file` method:: 313 314 >>> from distutils.dist import DistributionMetadata 315 >>> metadata = DistributionMetadata() 316 >>> metadata.read_pkg_file(open('distribute-0.6.8-py2.7.egg-info')) 317 >>> metadata.name 318 'distribute' 319 >>> metadata.version 320 '0.6.8' 321 >>> metadata.description 322 'Easily download, build, install, upgrade, and uninstall Python packages' 323 324Notice that the class can also be instantiated with a metadata file path to 325loads its values:: 326 327 >>> pkg_info_path = 'distribute-0.6.8-py2.7.egg-info' 328 >>> DistributionMetadata(pkg_info_path).name 329 'distribute' 330 331 332.. % \section{Multiple extension modules} 333.. % \label{multiple-ext} 334 335.. % \section{Putting it all together} 336 337 338.. _docutils: http://docutils.sourceforge.net 339