Skip to content

RF: remove imageopener decorator #361

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 24, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions nibabel/freesurfer/mghformat.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,13 +454,13 @@ def writeftr_to(self, fileobj):
fileobj.write(ftr_nd.tostring())


# Register .mgz extension as compressed
@ImageOpener.register_ext_from_image('.mgz', ImageOpener.gz_def)
class MGHImage(SpatialImage):
""" Class for MGH format image
"""
header_class = MGHHeader
valid_exts = ('.mgh',)
valid_exts = ('.mgh', '.mgz')
# Register that .mgz extension signals gzip compression
ImageOpener.compress_ext_map['.mgz'] = ImageOpener.gz_def
files_types = (('image', '.mgh'),)
_compressed_suffixes = ()

Expand Down
52 changes: 16 additions & 36 deletions nibabel/openers.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,42 +149,22 @@ def __exit__(self, exc_type, exc_val, exc_tb):


class ImageOpener(Opener):
""" Opener-type class passed to image classes to collect compressed extensions
""" Opener-type class to collect extra compressed extensions

This class allows itself to have image extensions added to its class
attributes, via the `register_ex_from_images`. The class can therefore
change state when image classes are defined.
A trivial sub-class of opener to which image classes can add extra
extensions with custom openers, such as compressed openers.

To add an extension, add a line to the class definition (not __init__):

ImageOpener.compress_ext_map[ext] = func_def

``ext`` is a file extension beginning with '.' and should be included in
the image class's ``valid_exts`` tuple.

``func_def`` is a `(function, (args,))` tuple, where `function accepts a
filename as the first parameter, and `args` defines the other arguments
that `function` accepts. These arguments must be any (unordered) subset of
`mode`, `compresslevel`, and `buffering`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice docstring.

"""
# Add new extensions to this dictionary
compress_ext_map = Opener.compress_ext_map.copy()

@classmethod
def register_ext_from_image(opener_klass, ext, func_def):
"""Decorator for adding extension / opener_function associations.

Should be used to decorate classes. Updates ImageOpener class with
desired extension / opener association. Updates decorated class by
adding ```ext``` to ```klass.alternate_exts```.

Parameters
----------
opener_klass : decorated class
ext : file extension to associate `func_def` with.
should start with '.'
func_def : opener function/parameter tuple
Should be a `(function, (args,))` tuple, where `function` accepts
a filename as the first parameter, and `args` defines the
other arguments that `function` accepts. These arguments must
be any (unordered) subset of `mode`, `compresslevel`,
and `buffering`.

Returns
-------
opener_klass
"""
def decorate(klass):
assert ext not in opener_klass.compress_ext_map, \
"Cannot redefine extension-function mappings."
opener_klass.compress_ext_map[ext] = func_def
klass.valid_exts += (ext,)
return klass
return decorate
7 changes: 1 addition & 6 deletions nibabel/tests/test_openers.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,6 @@ def test_BinOpener():


class TestImageOpener:
valid_exts = ()

def setUp(self):
self.compress_ext_map = ImageOpener.compress_ext_map.copy()

Expand All @@ -115,12 +113,9 @@ def file_opener(fileish, mode):

# Add the association
n_associations = len(ImageOpener.compress_ext_map)
dec = ImageOpener.register_ext_from_image('.foo',
(file_opener, ('mode',)))
dec(self.__class__)
ImageOpener.compress_ext_map['.foo'] = (file_opener, ('mode',))
assert_equal(n_associations + 1, len(ImageOpener.compress_ext_map))
assert_true('.foo' in ImageOpener.compress_ext_map)
assert_true('.foo' in self.valid_exts)

with InTemporaryDirectory():
with ImageOpener('test.foo', 'w'):
Expand Down