Skip to content

Commit 56998a6

Browse files
committed
DOC: fix data package pages for doctests
Make doctests pass by disabling some tests, fixing others, and making a nipy test data directory framework on the fly to test against. Some typos and bad formatting. Reflow of paragraphs with 78 char width.
1 parent cceb624 commit 56998a6

File tree

2 files changed

+115
-86
lines changed

2 files changed

+115
-86
lines changed

doc/source/devel/data_pkg_design.rst

Lines changed: 74 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,42 @@
33
Design of data packages for the nipy suite
44
==========================================
55

6-
See :ref:`data-package-discuss` for a more general discussion of design issues.
6+
See :ref:`data-package-discuss` for a more general discussion of design
7+
issues.
78

8-
When developing or using nipy, many data files can be useful. We divide
9-
the data files nipy uses into at least 3 categories
9+
When developing or using nipy, many data files can be useful. We divide the
10+
data files nipy uses into at least 3 categories
1011

1112
#. *test data* - data files required for routine code testing
1213
#. *template data* - data files required for algorithms to function,
1314
such as templates or atlases
1415
#. *example data* - data files for running examples, or optional tests
1516

1617
Files used for routine testing are typically very small data files. They are
17-
shipped with the software, and live in the code repository. For example, in the
18-
case of ``nipy`` itself, there are some test files that live in the module path
19-
``nipy.testing.data``.
18+
shipped with the software, and live in the code repository. For example, in
19+
the case of ``nipy`` itself, there are some test files that live in the module
20+
path ``nipy.testing.data``.
2021

2122
*template data* and *example data* are example of *data packages*. What
2223
follows is a discussion of the design and use of data packages.
2324

25+
.. testsetup::
26+
27+
# Make fake data and template directories
28+
import os
29+
from os.path import join as pjoin
30+
import tempfile
31+
tmpdir = tempfile.mkdtemp()
32+
os.environ['NIPY_USER_DIR'] = tmpdir
33+
for subdir in ('data', 'templates'):
34+
files_dir = pjoin(tmpdir, 'nipy', subdir)
35+
os.makedirs(files_dir)
36+
with open(pjoin(files_dir, 'config.ini'), 'wt') as fobj:
37+
fobj.write(
38+
"""[DEFAULT]
39+
version = 0.2
40+
""")
41+
2442
Use cases for data packages
2543
+++++++++++++++++++++++++++
2644

@@ -33,28 +51,29 @@ The programmer will want to use the data something like this:
3351

3452
from nibabel.data import make_datasource
3553

36-
templates = make_datasource('nipy', 'templates')
54+
templates = make_datasource(dict(relpath='nipy/templates'))
3755
fname = templates.get_filename('ICBM152', '2mm', 'T1.nii.gz')
38-
56+
3957
where ``fname`` will be the absolute path to the template image
40-
``ICBM152/2mm/T1.nii.gz``.
58+
``ICBM152/2mm/T1.nii.gz``.
4159

4260
The programmer can insist on a particular version of a ``datasource``:
4361

44-
.. testcode::
45-
46-
if templates.version < '0.4':
47-
raise ValueError('Need datasource version at least 0.4')
62+
>>> if templates.version < '0.4':
63+
... raise ValueError('Need datasource version at least 0.4')
64+
Traceback (most recent call last):
65+
...
66+
ValueError: Need datasource version at least 0.4
4867

4968
If the repository cannot find the data, then:
5069

51-
>>> make_datasource('nipy', 'implausible')
52-
Traceback
70+
>>> make_datasource(dict(relpath='nipy/implausible'))
71+
Traceback (most recent call last):
5372
...
54-
nibabel.data.DataError
73+
nibabel.data.DataError: ...
5574

5675
where ``DataError`` gives a helpful warning about why the data was not
57-
found, and how it should be installed.
76+
found, and how it should be installed.
5877

5978
Warnings during installation
6079
````````````````````````````
@@ -68,8 +87,8 @@ data when installing the package. Thus::
6887
will import nipy after installation to check whether these raise an error:
6988

7089
>>> from nibabel.data import make_datasource
71-
>>> template = make_datasource('nipy', 'templates')
72-
>>> example_data = make_datasource('nipy', 'data')
90+
>>> templates = make_datasource(dict(relpath='nipy/templates'))
91+
>>> example_data = make_datasource(dict(relpath='nipy/data'))
7392

7493
and warn the user accordingly, with some basic instructions for how to
7594
install the data.
@@ -82,7 +101,7 @@ Finding the data
82101
The routine ``make_datasource`` will need to be able to find the data
83102
that has been installed. For the following call:
84103

85-
>>> templates = make_datasource('nipy', 'templates')
104+
>>> templates = make_datasource(dict(relpath='nipy/templates'))
86105

87106
We propose to:
88107

@@ -130,8 +149,8 @@ umbrella of neuroimaging in python - and the NIPY package - the main
130149
code package in the NIPY project. Thus, if you want to install data
131150
under the NIPY *package* umbrella, your data might go to
132151
``/usr/share/nipy/nipy/packagename`` (on Unix). Note ``nipy`` twice -
133-
once for the project, once for the pacakge. If you want to install data
134-
under - say - the ```pbrain`` package umbrella, that would go in
152+
once for the project, once for the package. If you want to install data
153+
under - say - the ``pbrain`` package umbrella, that would go in
135154
``/usr/share/nipy/pbrain/packagename``.
136155

137156
Data package format
@@ -141,7 +160,7 @@ The following tree is an example of the kind of pattern we would expect
141160
in a data directory, where the ``nipy-data`` and ``nipy-templates``
142161
packages have been installed::
143162

144-
<ROOT>
163+
<ROOT>
145164
`-- nipy
146165
|-- data
147166
| |-- config.ini
@@ -191,8 +210,9 @@ For the example above this will result in these subdirectories::
191210
because ``nipy`` is both the project, and the package to which the data
192211
relates.
193212

194-
If you install to a particular location, you will need to add that
195-
location to the output of ``nipy.data.get_data_path()`` using one of the mechanisms above, for example, in your system configuration::
213+
If you install to a particular location, you will need to add that location to
214+
the output of ``nipy.data.get_data_path()`` using one of the mechanisms above,
215+
for example, in your system configuration::
196216

197217
export NIPY_DATA_PATH=/my/prefix/share/nipy
198218

@@ -202,13 +222,13 @@ Packaging for distributions
202222
For a particular data package - say ``nipy-templates`` - distributions
203223
will want to:
204224

205-
#. Install the data in set location. The default from ``python setup.py install`` for the data packages will be ``/usr/share/nipy`` on Unix.
206-
#. Point a system installation of NIPY to these data.
225+
#. Install the data in set location. The default from ``python setup.py
226+
install`` for the data packages will be ``/usr/share/nipy`` on Unix.
227+
#. Point a system installation of NIPY to these data.
207228

208-
For the latter, the most obvious route is to copy an ``.ini`` file named
209-
for the data package into the NIPY ``etc_dir``. In this case, on Unix,
210-
we will want a file called ``/etc/nipy/nipy_templates.ini`` with
211-
contents::
229+
For the latter, the most obvious route is to copy an ``.ini`` file named for
230+
the data package into the NIPY ``etc_dir``. In this case, on Unix, we will
231+
want a file called ``/etc/nipy/nipy_templates.ini`` with contents::
212232

213233
[DATA]
214234
path = /usr/share/nipy
@@ -219,16 +239,17 @@ Current implementation
219239
This section describes how we (the nipy community) implement data packages at
220240
the moment.
221241

222-
The data in the data packages will not usually be under source control. This is
223-
because images don't compress very well, and any change in the data will result
224-
in a large extra storage cost in the repository. If you're pretty clear that
225-
the data files aren't going to change, then a repository could work OK.
242+
The data in the data packages will not usually be under source control. This
243+
is because images don't compress very well, and any change in the data will
244+
result in a large extra storage cost in the repository. If you're pretty
245+
clear that the data files aren't going to change, then a repository could work
246+
OK.
226247

227-
The data packages will be available at a central release location. For
228-
now this will be: http://nipy.org/data-packages/ .
248+
The data packages will be available at a central release location. For now
249+
this will be: http://nipy.org/data-packages/ .
229250

230-
A package, such as ``nipy-templates-0.2.tar.gz`` will have the following
231-
sort of structure::
251+
A package, such as ``nipy-templates-0.2.tar.gz`` will have the following sort
252+
of structure::
232253

233254

234255
<ROOT>
@@ -248,26 +269,31 @@ sort of structure::
248269

249270

250271
There should be only one ``nipy/packagename`` directory delivered by a
251-
particular package. For example, this package installs
252-
``nipy/templates``, but does not contain ``nipy/data``.
272+
particular package. For example, this package installs ``nipy/templates``,
273+
but does not contain ``nipy/data``.
253274

254275
Making a new package tarball is simply:
255276

256-
#. Downloading and unpacking e.g ``nipy-templates-0.1.tar.gz`` to form
257-
the directory structure above.
258-
#. Making any changes to the directory
277+
#. Downloading and unpacking e.g. ``nipy-templates-0.1.tar.gz`` to form the
278+
directory structure above;
279+
#. Making any changes to the directory;
259280
#. Running ``setup.py sdist`` to recreate the package.
260281

261282
The process of making a release should be:
262283

263-
#. Increment the major or minor version number in the ``config.ini`` file
264-
#. Make a package tarball as above
265-
#. Upload to distribution site
284+
#. Increment the major or minor version number in the ``config.ini`` file;
285+
#. Make a package tarball as above;
286+
#. Upload to distribution site.
266287

267288
There is an example nipy data package ``nipy-examplepkg`` in the
268289
``examples`` directory of the NIPY repository.
269290

270291
The machinery for creating and maintaining data packages is available at
271-
http://github.com/nipy/data-packaging
292+
http://github.com/nipy/data-packaging.
272293

273294
See the ``README.txt`` file there for more information.
295+
296+
.. testcleanup::
297+
298+
import shutil
299+
shutil.rmtree(tmpdir)

doc/source/devel/data_pkg_uses.rst

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -26,44 +26,46 @@ We'll call our package `dang` - data package new generation.
2626
Create local-path prundle
2727
-------------------------
2828

29-
>>> import os
30-
>>> import tempfile
31-
>>> pth = tempfile.mkdtemp() # temporary directory
29+
::
3230

33-
Make a pinstance object
31+
>>> import os
32+
>>> import tempfile
33+
>>> pth = tempfile.mkdtemp() # temporary directory
3434

35-
>>> from dang import Pinstance
36-
>>> pri = Prundle(name='my-package')
37-
>>> pri.pkg_name
38-
'my-package'
39-
>>> pri.meta
40-
{}
35+
Make a pinstance object::
4136

42-
Now we make a prundle. First a directory to contain it
37+
>>> from dang import Pinstance
38+
>>> pri = Prundle(name='my-package')
39+
>>> pri.pkg_name
40+
'my-package'
41+
>>> pri.meta
42+
{}
43+
44+
Now we make a prundle. First a directory to contain it::
4345

44-
>>> import os
45-
>>> import tempfile
46-
>>> pth = tempfile.mkdtemp() # temporary directory
46+
>>> import os
47+
>>> import tempfile
48+
>>> pth = tempfile.mkdtemp() # temporary directory
4749

48-
>>> from dang.prundle import LocalPathPrundle
49-
>>> prun = LocalPathPrundle(pri, pth)
50+
>>> from dang.prundle import LocalPathPrundle
51+
>>> prun = LocalPathPrundle(pri, pth)
5052

5153
At the moment there's nothing in the directory. The 'write' method will write
52-
the meta information - here just the package name.
54+
the meta information - here just the package name::
5355

54-
>>> prun.write() # writes meta.ini file
55-
>>> os.listdir(pth)
56-
['meta.ini']
56+
>>> prun.write() # writes meta.ini file
57+
>>> os.listdir(pth)
58+
['meta.ini']
5759

5860
The local path prundle data is just the set of files in the temporary directory
5961
named in ``pth`` above.
6062

6163
Now we've written the package, we can get it by a single call that reads in the
62-
``meta.ini`` file:
64+
``meta.ini`` file::
6365

64-
>>> prun_back = LocalPathPrundle.from_path(pth)
65-
>>> prun_back.pkg_name
66-
'my-package'
66+
>>> prun_back = LocalPathPrundle.from_path(pth)
67+
>>> prun_back.pkg_name
68+
'my-package'
6769

6870
Getting prundle data
6971
--------------------
@@ -79,8 +81,9 @@ In fact, local path distribution objects also have a ``path`` attribute::
7981

8082
>>> fname = os.path.join(prun.path, 'a_file.txt')
8183

82-
The ``path`` attribute might not make sense for objects with greater abstraction
83-
over the file-system - for example objects encapsulating web content.
84+
The ``path`` attribute might not make sense for objects with greater
85+
abstraction over the file-system - for example objects encapsulating web
86+
content.
8487

8588
*********
8689
Discovery
@@ -93,8 +96,8 @@ We want to be able to tell the system where prundles are - and the system will
9396
then be able to return a prundle on request - perhaps by package name. The
9497
system here is answering a :ref:`prundle-discovery` query.
9598

96-
We will then want to ask our packaging system whether it knows about the prundle
97-
we are interested in.
99+
We will then want to ask our packaging system whether it knows about the
100+
prundle we are interested in.
98101

99102
Discovery sources
100103
=================
@@ -150,8 +153,8 @@ from a list of sources. Something like this::
150153
>>> dq_res[0].pkg_name
151154
'my-package'
152155

153-
We'll often want to do exactly this, so we'll add this source pool to those that
154-
can be returned from our ``get_source`` convenience function::
156+
We'll often want to do exactly this, so we'll add this source pool to those
157+
that can be returned from our ``get_source`` convenience function::
155158

156159
>>> src_pool = dpkg.get_source('local-pool')
157160

@@ -202,7 +205,7 @@ Discovery sources
202205
=================
203206

204207
The discovery source has to be able to return prundle objects for the
205-
prundles it knows about.
208+
prundles it knows about::
206209

207210
[my-package]
208211
0 = /some/path
@@ -213,19 +216,19 @@ prundles it knows about.
213216
Registering a package
214217
=====================
215218

216-
So far we have a local path distribution, that is a directory with some files in
217-
it, and our own ``meta.ini`` file, containing the package name and version. How
218-
does this package register itself to the default sources? Of course, we could
219-
use ``dpkg`` as above::
219+
So far we have a local path distribution, that is a directory with some files
220+
in it, and our own ``meta.ini`` file, containing the package name and version.
221+
How does this package register itself to the default sources? Of course, we
222+
could use ``dpkg`` as above::
220223

221224
>>> dst = dpkg.LocalPathDistribution.from_path(path='/a/path')
222225
>>> local_usr = dpkg.get_source('local-user')
223226
>>> local_usr.register(dst)
224227
>>> local_usr.save()
225228

226-
but we wanted to be able to avoid using ``dpkg``. To do this, there might be a
227-
supporting script, in the distribution directory, called ``register_me.py``, of
228-
form given in :download:`register_me.py`.
229+
but we wanted to be able to avoid using ``dpkg``. To do this, there might be
230+
a supporting script, in the distribution directory, called ``register_me.py``,
231+
of form given in :download:`register_me.py`.
229232

230233
Using discovery sources without dpkg
231234
====================================

0 commit comments

Comments
 (0)