• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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