[hdf-compass] 131/295: Initial BAG model implementation (w/o Text/Xml nodes)

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Sun May 8 10:35:35 UTC 2016


This is an automated email from the git hooks/post-receive script.

ghisvail-guest pushed a commit to branch debian/master
in repository hdf-compass.

commit 476be8b443e3987599324c036a4c7303fc4a50e0
Author: giumas <giumas at yahoo.it>
Date:   Fri Oct 9 21:30:11 2015 -0400

    Initial BAG model implementation (w/o Text/Xml nodes)
---
 README.md                                        |  16 +-
 hdf_compass/array_model/__init__.py              |  30 +-
 hdf_compass/asc_model/__init__.py                |  24 +-
 hdf_compass/bag_model/__init__.py                |  21 +
 hdf_compass/bag_model/model.py                   | 613 +++++++++++++++++++++++
 hdf_compass/compass_model/__init__.py            |  24 +-
 hdf_compass/compass_model/test.py                |  34 +-
 hdf_compass/compass_viewer/__init__.py           |  11 +-
 hdf_compass/compass_viewer/array/__init__.py     |   2 +-
 hdf_compass/compass_viewer/container/__init__.py |   4 +-
 hdf_compass/compass_viewer/container/list.py     |   8 +-
 hdf_compass/compass_viewer/frame.py              |   2 +-
 hdf_compass/compass_viewer/image/__init__.py     |   2 +-
 hdf_compass/compass_viewer/info.py               |   4 +-
 hdf_compass/compass_viewer/keyvalue/__init__.py  |   2 +-
 hdf_compass/filesystem_model/__init__.py         |  22 +-
 hdf_compass/hdf5_model/__init__.py               |  42 +-
 hdf_compass/opendap_model/__init__.py            |  30 +-
 hdf_compass/utils/__init__.py                    |  19 +
 hdf_compass/utils/utils.py                       |  32 ++
 20 files changed, 814 insertions(+), 128 deletions(-)

diff --git a/README.md b/README.md
index f036288..a8c0b5f 100644
--- a/README.md
+++ b/README.md
@@ -22,16 +22,18 @@ Development Environment
 
 You will need:
 
-* Python 2.7
-* NumPy
-* Matplotlib
-* wxPython Phoenix *(2.9.5.0 or later)*
-* h5py
+* [Python 2.7](https://www.python.org/downloads/) *(support for Python 3.4+ in progress)*
+* [NumPy](https://github.com/numpy/numpy)
+* [Matplotlib](https://github.com/matplotlib/matplotlib)
+* [wxPython Phoenix](https://github.com/wxWidgets/Phoenix) *(2.9.5.0 or later)*
+* [h5py](https://github.com/h5py/h5py) *[HDF plugin]*
+* [hydroffice.bag](https://bitbucket.org/ccomjhc/hyo_bag) *[BAG plugin]*
+* [Pydap](https://github.com/robertodealmeida/pydap) *[OPeNDAP plugin]*
 
 For packaging the app:
 
-* PyInstaller (Linux & Windows, experimental for OS X) *(>= 3.0)*
-* Py2App (OS X)
+* [PyInstaller](https://github.com/pyinstaller/pyinstaller) (Linux & Windows, experimental for OS X) *(>= 3.0)*
+* [Py2App](https://bitbucket.org/ronaldoussoren/py2app) (OS X)
 
 Running the Program  
 --------------------
diff --git a/hdf_compass/array_model/__init__.py b/hdf_compass/array_model/__init__.py
index d6bae0c..7af030c 100644
--- a/hdf_compass/array_model/__init__.py
+++ b/hdf_compass/array_model/__init__.py
@@ -57,7 +57,7 @@ class ArrayStore(compass_model.Store):
         return self._url
 
     @property
-    def displayname(self):
+    def display_name(self):
         return "Testing arrays"
 
     @property
@@ -69,13 +69,13 @@ class ArrayStore(compass_model.Store):
         return True
 
     @staticmethod
-    def canhandle(url):
+    def can_handle(url):
         if url == "array://localhost":
             return True
         return False
 
     def __init__(self, url):
-        if not self.canhandle(url):
+        if not self.can_handle(url):
             raise ValueError(url)
         self._url = url
 
@@ -91,10 +91,10 @@ class ArrayContainer(compass_model.Container):
         Represents a directory in the filesystem.
     """
 
-    classkind = "Array Container"
+    class_kind = "Array Container"
 
     @staticmethod
-    def canhandle(store, key):
+    def can_handle(store, key):
         return key is None
 
     def __init__(self, store, key):
@@ -111,12 +111,12 @@ class ArrayContainer(compass_model.Container):
         return self._store
 
     @property
-    def displayname(self):
+    def display_name(self):
         return "Array Container"
 
     @property
     def description(self):
-        return self.displayname
+        return self.display_name
 
     def __len__(self):
         return len(DATA)
@@ -135,10 +135,10 @@ class Array(compass_model.Array):
         An N-D array
     """
 
-    classkind = "TestArray"
+    class_kind = "TestArray"
 
     @staticmethod
-    def canhandle(store, key):
+    def can_handle(store, key):
         return key in DATA
 
     def __init__(self, store, key):
@@ -155,12 +155,12 @@ class Array(compass_model.Array):
         return self._store
 
     @property
-    def displayname(self):
+    def display_name(self):
         return self.key
 
     @property
     def description(self):
-        return self.displayname
+        return self.display_name
 
     @property
     def shape(self):
@@ -175,10 +175,10 @@ class Array(compass_model.Array):
 
 
 class ArrayKV(compass_model.KeyValue):
-    classkind = "Array Key/Value Attrs"
+    class_kind = "Array Key/Value Attrs"
 
     @staticmethod
-    def canhandle(store, key):
+    def can_handle(store, key):
         return key in DATA
 
     def __init__(self, store, key):
@@ -195,12 +195,12 @@ class ArrayKV(compass_model.KeyValue):
         return self._store
 
     @property
-    def displayname(self):
+    def display_name(self):
         return self.key
 
     @property
     def description(self):
-        return self.displayname
+        return self.display_name
 
     @property
     def keys(self):
diff --git a/hdf_compass/asc_model/__init__.py b/hdf_compass/asc_model/__init__.py
index 2a2b719..10e9381 100644
--- a/hdf_compass/asc_model/__init__.py
+++ b/hdf_compass/asc_model/__init__.py
@@ -49,7 +49,7 @@ class AsciiGrid(compass_model.Store):
         return self._url
 
     @property
-    def displayname(self):
+    def display_name(self):
         return op.basename(self._url)
 
     @property
@@ -61,7 +61,7 @@ class AsciiGrid(compass_model.Store):
         return self._valid
 
     @staticmethod
-    def canhandle(url):
+    def can_handle(url):
         if not url.startswith('file://'):
             return False
         if not url.endswith('.asc'):
@@ -69,7 +69,7 @@ class AsciiGrid(compass_model.Store):
         return True
 
     def __init__(self, url):
-        if not self.canhandle(url):
+        if not self.can_handle(url):
             raise ValueError(url)
         self._url = url
         self._value = True
@@ -93,10 +93,10 @@ class ASCFile(compass_model.Array):
         Represents a .asc grid file.
     """
 
-    classkind = "ASCII Grid File"
+    class_kind = "ASCII Grid File"
 
     @staticmethod
-    def canhandle(store, key):
+    def can_handle(store, key):
         if key == '/':
             return True
         return False
@@ -118,12 +118,12 @@ class ASCFile(compass_model.Array):
         return self._store
 
     @property
-    def displayname(self):
-        return self._store.displayname
+    def display_name(self):
+        return self._store.display_name
 
     @property
     def description(self):
-        return 'File "%s", size %d bytes' % (self.displayname, op.getsize(self.key))
+        return 'File "%s", size %d bytes' % (self.display_name, op.getsize(self.key))
 
     @property
     def shape(self):
@@ -140,10 +140,10 @@ class ASCFile(compass_model.Array):
 
 
 class Attributes(compass_model.KeyValue):
-    classkind = "Attributes of ASC Grid File"
+    class_kind = "Attributes of ASC Grid File"
 
     @staticmethod
-    def canhandle(store, key):
+    def can_handle(store, key):
         if key == '/':
             return True
         return False
@@ -166,12 +166,12 @@ class Attributes(compass_model.KeyValue):
         return self._store
 
     @property
-    def displayname(self):
+    def display_name(self):
         return self.key
 
     @property
     def description(self):
-        return self.displayname
+        return self.display_name
 
     def close(self):
         self._valid = False
diff --git a/hdf_compass/bag_model/__init__.py b/hdf_compass/bag_model/__init__.py
new file mode 100644
index 0000000..1f22c6e
--- /dev/null
+++ b/hdf_compass/bag_model/__init__.py
@@ -0,0 +1,21 @@
+##############################################################################
+# Copyright by The HDF Group.                                                #
+# All rights reserved.                                                       #
+#                                                                            #
+# This file is part of the HDF Compass Viewer. The full HDF Compass          #
+# copyright notice, including terms governing use, modification, and         #
+# terms governing use, modification, and redistribution, is contained in     #
+# the file COPYING, which can be found at the root of the source code        #
+# distribution tree.  If you do not have access to this file, you may        #
+# request a copy from help at hdfgroup.org.                                     #
+##############################################################################
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+__version__ = "0.1.4"
+
+from .model import BAGStore, BAGDataset, BAGGroup, BAGImage, BAGKV
+
+import logging
+
+log = logging.getLogger(__name__)
+log.addHandler(logging.NullHandler())
diff --git a/hdf_compass/bag_model/model.py b/hdf_compass/bag_model/model.py
new file mode 100644
index 0000000..bdcef84
--- /dev/null
+++ b/hdf_compass/bag_model/model.py
@@ -0,0 +1,613 @@
+##############################################################################
+# Copyright by The HDF Group.                                                #
+# All rights reserved.                                                       #
+#                                                                            #
+# This file is part of the HDF Compass Viewer. The full HDF Compass          #
+# copyright notice, including terms governing use, modification, and         #
+# terms governing use, modification, and redistribution, is contained in     #
+# the file COPYING, which can be found at the root of the source code        #
+# distribution tree.  If you do not have access to this file, you may        #
+# request a copy from help at hdfgroup.org.                                     #
+##############################################################################
+"""
+Implementation of compass_model classes for BAG files.
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from itertools import groupby
+import sys
+import os.path as op
+import posixpath as pp
+import h5py
+
+from hydroffice.bag import is_bag
+from hydroffice.bag import BAGFile
+from hydroffice.bag import BAGError
+
+from hdf_compass import compass_model
+from hdf_compass.utils import url2path
+
+import logging
+log = logging.getLogger(__name__)
+
+
+def sort_key(name):
+    """ Sorting key for names in an BAG group.
+
+    We provide "natural" sort order; e.g. "7" comes before "12".
+    """
+    return [(int(''.join(g)) if k else ''.join(g)) for k, g in groupby(name, key=unicode.isdigit)]
+
+
+class BAGStore(compass_model.Store):
+    """
+    Data store implementation using a BAG file (closely mimicking HDF5Store).
+
+    Keys are the full names of objects in the file.
+    """
+    file_extensions = {'BAG File': ['*.bag']}
+
+    def __contains__(self, key):
+        return key in self.f
+
+    @property
+    def url(self):
+        return self._url
+
+    @property
+    def display_name(self):
+        return op.basename(self.f.filename)
+
+    @property
+    def root(self):
+        return self['/']
+
+    @property
+    def valid(self):
+        return bool(self.f)
+
+    @staticmethod
+    def can_handle(url):
+        log.debug("able to handle %s?" % url)
+        if not url.startswith('file://'):
+            log.debug("No")
+            return False
+
+        path = url2path(url)
+        if not is_bag(path):
+            log.debug("Yes")
+            return False
+
+        log.debug("OK")
+        return True
+
+    def __init__(self, url):
+        if not self.can_handle(url):
+            raise ValueError(url)
+        self._url = url
+        path = url2path(url)
+        self.f = BAGFile(path, 'r')
+
+    def close(self):
+        self.f.close()
+
+    def get_parent(self, key):
+        # HDFCompass requires the parent of the root container be None
+        if key == "" or key == "/":
+            return None
+        p_key = pp.dirname(key)
+        if p_key == "":
+            p_key = "/"
+        return self[p_key]
+
+
+class BAGGroup(compass_model.Container):
+    """ Represents an BAG group (closely mimicking HDF5Group). """
+    class_kind = "BAG Group"
+
+    @staticmethod
+    def can_handle(store, key):
+        return (key in store) and (isinstance(store.f[key], h5py.Group))
+
+    @property
+    def _names(self):
+
+        # Lazily build the list of names; this helps when browsing big files
+        if self._xnames is None:
+
+            self._xnames = list(self._group)
+
+            # Natural sort is expensive
+            if len(self._xnames) < 1000:
+                self._xnames.sort(key=sort_key)
+
+        return self._xnames
+
+    def __init__(self, store, key):
+        self._store = store
+        self._key = key
+        self._group = store.f[key]
+        self._xnames = None
+
+    @property
+    def key(self):
+        return self._key
+
+    @property
+    def store(self):
+        return self._store
+
+    @property
+    def display_name(self):
+        name = pp.basename(self.key)
+        if name == "":
+            name = '/'
+        return name
+
+    @property
+    def display_title(self):
+        return "%s %s" % (self.store.display_name, self.key)
+
+    @property
+    def description(self):
+        return 'Group "%s" (%d members)' % (self.display_name, len(self))
+
+    def __len__(self):
+        return len(self._group)
+
+    def __iter__(self):
+        for name in self._names:
+            yield self.store[pp.join(self.key, name)]
+
+    def __getitem__(self, idx):
+        name = self._names[idx]
+        return self.store[pp.join(self.key, name)]
+
+
+class BAGRoot(compass_model.Container):
+    """ Represents the BAG root. """
+    class_kind = "BAG Root"
+
+    @staticmethod
+    def can_handle(store, key):
+        return (key == "/BAG_root") and (key in store) and (isinstance(store.f[key], h5py.Group))
+
+    @property
+    def _names(self):
+
+        # Lazily build the list of names; this helps when browsing big files
+        if self._xnames is None:
+
+            self._xnames = list(self._group)
+
+            # Natural sort is expensive
+            if len(self._xnames) < 1000:
+                self._xnames.sort(key=sort_key)
+
+        return self._xnames
+
+    def __init__(self, store, key):
+        self._store = store
+        self._key = key
+        self._group = store.f[key]
+        self._xnames = None
+
+    @property
+    def key(self):
+        return self._key
+
+    @property
+    def store(self):
+        return self._store
+
+    @property
+    def display_name(self):
+        name = pp.basename(self.key)
+        return name
+
+    @property
+    def display_title(self):
+        return "%s %s" % (self.store.display_name, self.key)
+
+    @property
+    def description(self):
+        return 'Root Group "%s" (%d members)' % (self.display_name, len(self))
+
+    def __len__(self):
+        return len(self._group)
+
+    def __iter__(self):
+        for name in self._names:
+            yield self.store[pp.join(self.key, name)]
+
+    def __getitem__(self, idx):
+        name = self._names[idx]
+        return self.store[pp.join(self.key, name)]
+
+
+class BAGDataset(compass_model.Array):
+    """ Represents a BAG dataset (closely mimicking HDF5Dataset). """
+    class_kind = "BAG Dataset"
+
+    @staticmethod
+    def can_handle(store, key):
+        return key in store and isinstance(store.f[key], h5py.Dataset)
+
+    def __init__(self, store, key):
+        self._store = store
+        self._key = key
+        self._dset = store.f[key]
+
+    @property
+    def key(self):
+        return self._key
+
+    @property
+    def store(self):
+        return self._store
+
+    @property
+    def display_name(self):
+        return pp.basename(self.key)
+
+    @property
+    def description(self):
+        return 'Dataset "%s"' % (self.display_name,)
+
+    @property
+    def shape(self):
+        return self._dset.shape
+
+    @property
+    def dtype(self):
+        return self._dset.dtype
+
+    def __getitem__(self, args):
+        return self._dset[args]
+
+
+class BAGElevation(compass_model.Array):
+    """ Represents a BAG elevation. """
+    class_kind = "BAG Elevation"
+
+    @staticmethod
+    def can_handle(store, key):
+        return (key == "/BAG_root/elevation") and (key in store) and (isinstance(store.f[key], h5py.Dataset))
+
+    def __init__(self, store, key):
+        self._store = store
+        self._key = key
+        self._dset = store.f.elevation(mask_nan=True)
+
+    @property
+    def key(self):
+        return self._key
+
+    @property
+    def store(self):
+        return self._store
+
+    @property
+    def display_name(self):
+        return pp.basename(self.key)
+
+    @property
+    def description(self):
+        return 'Dataset "%s"' % (self.display_name,)
+
+    @property
+    def shape(self):
+        return self._dset.shape
+
+    @property
+    def dtype(self):
+        return self._dset.dtype
+
+    def __getitem__(self, args):
+        return self._dset[args]
+
+
+class BAGTrackinList(compass_model.Array):
+    """ Represents a BAG tracking list. """
+    class_kind = "BAG Tracking List"
+
+    @staticmethod
+    def can_handle(store, key):
+        return (key == "/BAG_root/tracking_list") and (key in store) and (isinstance(store.f[key], h5py.Dataset))
+
+    def __init__(self, store, key):
+        self._store = store
+        self._key = key
+        self._dset = store.f.tracking_list()
+
+    @property
+    def key(self):
+        return self._key
+
+    @property
+    def store(self):
+        return self._store
+
+    @property
+    def display_name(self):
+        return pp.basename(self.key)
+
+    @property
+    def description(self):
+        return 'Dataset "%s"' % (self.display_name,)
+
+    @property
+    def shape(self):
+        return self._dset.shape
+
+    @property
+    def dtype(self):
+        return self._dset.dtype
+
+    def __getitem__(self, args):
+        return self._dset[args]
+
+
+class BAGMetadataRaw(compass_model.Array):
+    """ Represents a raw BAG metadata. """
+    class_kind = "BAG Metadata [raw]"
+
+    @staticmethod
+    def can_handle(store, key):
+        return (key == "/BAG_root/metadata") and (key in store) and (isinstance(store.f[key], h5py.Dataset))
+
+    def __init__(self, store, key):
+        self._store = store
+        self._key = key
+        self._dset = store.f.metadata(as_string=False, as_pretty_xml=False)
+
+    @property
+    def key(self):
+        return self._key
+
+    @property
+    def store(self):
+        return self._store
+
+    @property
+    def display_name(self):
+        return pp.basename(self.key)
+
+    @property
+    def description(self):
+        return 'Dataset "%s"' % (self.display_name,)
+
+    @property
+    def shape(self):
+        return self._dset.shape
+
+    @property
+    def dtype(self):
+        return self._dset.dtype
+
+    def __getitem__(self, args):
+        return self._dset[args]
+
+
+# class BAGMetadataText(compass_model.Text):
+#     """ Represents a text BAG metadata. """
+#
+#     class_kind = "BAG Metadata [text]"
+#
+#     @staticmethod
+#     def can_handle(store, key):
+#         return (key == "/BAG_root/metadata") and (key in store) and (isinstance(store.f[key], h5py.Dataset))
+#
+#     def __init__(self, store, key):
+#         self._store = store
+#         self._key = key
+#         self._dset = store.f.metadata(as_string=True, as_pretty_xml=True)
+#
+#     @property
+#     def key(self):
+#         return self._key
+#
+#     @property
+#     def store(self):
+#         return self._store
+#
+#     @property
+#     def display_name(self):
+#         return pp.basename(self.key)
+#
+#     @property
+#     def description(self):
+#         return 'Dataset "%s"' % (self.display_name,)
+#
+#     @property
+#     def text(self):
+#         return self._dset
+#
+#
+# class BAGMetadataXml(compass_model.Xml):
+#     """ Represents a text BAG metadata. """
+#
+#     class_kind = "BAG Metadata [xml]"
+#
+#     @staticmethod
+#     def can_handle(store, key):
+#         return (key == "/BAG_root/metadata") and (key in store) and (isinstance(store.f[key], h5py.Dataset))
+#
+#     def __init__(self, store, key):
+#         self._store = store
+#         self._key = key
+#         self._dset = store.f.metadata(as_string=True, as_pretty_xml=True)
+#
+#     @property
+#     def key(self):
+#         return self._key
+#
+#     @property
+#     def store(self):
+#         return self._store
+#
+#     @property
+#     def display_name(self):
+#         return pp.basename(self.key)
+#
+#     @property
+#     def description(self):
+#         return 'Dataset "%s"' % (self.display_name,)
+#
+#     @property
+#     def text(self):
+#         return self._dset
+
+
+class BAGUncertainty(compass_model.Array):
+    """ Represents a BAG uncertainty. """
+    class_kind = "BAG Uncertainty"
+
+    @staticmethod
+    def can_handle(store, key):
+        return (key == "/BAG_root/uncertainty") and (key in store) and (isinstance(store.f[key], h5py.Dataset))
+
+    def __init__(self, store, key):
+        self._store = store
+        self._key = key
+        self._dset = store.f.uncertainty(mask_nan=True)
+
+    @property
+    def key(self):
+        return self._key
+
+    @property
+    def store(self):
+        return self._store
+
+    @property
+    def display_name(self):
+        return pp.basename(self.key)
+
+    @property
+    def description(self):
+        return 'Dataset "%s"' % (self.display_name,)
+
+    @property
+    def shape(self):
+        return self._dset.shape
+
+    @property
+    def dtype(self):
+        return self._dset.dtype
+
+    def __getitem__(self, args):
+        return self._dset[args]
+
+
+class BAGKV(compass_model.KeyValue):
+    """ A KeyValue node used for BAG attributes (closely mimicking HDF5KV). """
+    class_kind = "BAG Attributes"
+
+    @staticmethod
+    def can_handle(store, key):
+        return key in store.f
+
+    def __init__(self, store, key):
+        log.debug("init")
+        self._store = store
+        self._key = key
+        self._obj = store.f[key]
+        self._names = self._obj.attrs.keys()
+
+    @property
+    def key(self):
+        return self._key
+
+    @property
+    def store(self):
+        return self._store
+
+    @property
+    def display_name(self):
+        n = pp.basename(self.key)
+        return n if n != '' else '/'
+
+    @property
+    def description(self):
+        return self.display_name
+
+    @property
+    def keys(self):
+        return self._names[:]
+
+    def __getitem__(self, name):
+        return self._obj.attrs[name]
+
+
+class BAGImage(compass_model.Image):
+    """ BAG true-color images (closely mimicking HDF5Image). """
+    class_kind = "BAG Truecolor Image"
+
+    @staticmethod
+    def can_handle(store, key):
+        if key not in store:
+            return False
+        obj = store.f[key]
+        if obj.attrs.get('CLASS') != 'IMAGE':
+            return False
+        if obj.attrs.get('IMAGE_SUBCLASS') != 'IMAGE_TRUECOLOR':
+            return False
+        if obj.attrs.get('INTERLACE_MODE') != 'INTERLACE_PIXEL':
+            return False
+        return True
+
+    def __init__(self, store, key):
+        log.debug("init")
+        self._store = store
+        self._key = key
+        self._obj = store.f[key]
+
+    @property
+    def key(self):
+        return self._key
+
+    @property
+    def store(self):
+        return self._store
+
+    @property
+    def display_name(self):
+        n = pp.basename(self.key)
+        return n if n != '' else '/'
+
+    @property
+    def description(self):
+        return self.display_name
+
+    @property
+    def width(self):
+        return self._obj.shape[1]
+
+    @property
+    def height(self):
+        return self._obj.shape[0]
+
+    @property
+    def palette(self):
+        return None
+
+    @property
+    def data(self):
+        return self._obj[:]
+
+
+# Register handlers
+BAGStore.push(BAGKV)
+BAGStore.push(BAGDataset)
+BAGStore.push(BAGElevation)
+BAGStore.push(BAGUncertainty)
+BAGStore.push(BAGTrackinList)
+BAGStore.push(BAGMetadataRaw)
+# BAGStore.push(BAGMetadataText)
+# BAGStore.push(BAGMetadataXml)
+BAGStore.push(BAGGroup)
+BAGStore.push(BAGRoot)
+BAGStore.push(BAGImage)
+
+compass_model.push(BAGStore)
diff --git a/hdf_compass/compass_model/__init__.py b/hdf_compass/compass_model/__init__.py
index 4e4eeba..85d6b18 100644
--- a/hdf_compass/compass_model/__init__.py
+++ b/hdf_compass/compass_model/__init__.py
@@ -136,7 +136,7 @@ class Store(object):
         if key not in self:
             raise KeyError(key)
 
-        return [nc for nc in self.__nodeclasses if nc.canhandle(self, key)]
+        return [nc for nc in self.__nodeclasses if nc.can_handle(self, key)]
 
     # End plugin support
     # -------------------------------------------------------------------------
@@ -156,7 +156,7 @@ class Store(object):
         raise NotImplementedError
 
     @property
-    def displayname(self):
+    def display_name(self):
         """ Short name for display purposes.
 
         For example, for a file-based store you could implement this with
@@ -174,7 +174,7 @@ class Store(object):
         raise NotImplementedError
 
     @staticmethod
-    def canhandle(url):
+    def can_handle(url):
         """ Test if this class can open the resource.
 
         Returns True or False.  Note this may have side effects, but
@@ -231,10 +231,10 @@ class Node(object):
     # This will show up in e.g. the "Open As" context menu.
     # Example:  "HDF5 Image" or "Swath"
 
-    classkind = NotImplemented
+    class_kind = NotImplemented
 
     @staticmethod
-    def canhandle(store, key):
+    def can_handle(store, key):
         """ Determine whether this class can usefully represent the object.
 
         Keep in mind that keys are not technically required to be strings.
@@ -262,17 +262,17 @@ class Node(object):
         raise NotImplementedError
 
     @property
-    def displayname(self):
+    def display_name(self):
         """ A short name for display purposes """
         raise NotImplementedError
 
     @property
-    def displaytitle(self):
+    def display_title(self):
         """ A longer name appropriate for display in a window title.
 
-        Defaults to *displayname*.
+        Defaults to *display_name*.
         """
-        return self.displayname
+        return self.display_name
 
     @property
     def description(self):
@@ -420,10 +420,10 @@ class Unknown(Node):
     icons = {16: images.unknown_16,
              64: images.unknown_64}
 
-    classkind = "Unknown"
+    class_kind = "Unknown"
 
     @staticmethod
-    def canhandle(store, key):
+    def can_handle(store, key):
         return True
 
     def __init__(self, store, key):
@@ -439,7 +439,7 @@ class Unknown(Node):
         return self._store
 
     @property
-    def displayname(self):
+    def display_name(self):
         import os.path
         try:
             return os.path.basename(str(self.key))
diff --git a/hdf_compass/compass_model/test.py b/hdf_compass/compass_model/test.py
index db15ad0..8326d32 100644
--- a/hdf_compass/compass_model/test.py
+++ b/hdf_compass/compass_model/test.py
@@ -106,9 +106,9 @@ class _TestStore(ut.TestCase):
         """ Verify store.url produces a string """
         self.assertIsInstance(self.store.url, basestring)
 
-    def test_displayname(self):
-        """ Verify store.displayname produces a string. """
-        self.assertIsInstance(self.store.displayname, basestring)
+    def test_display_name(self):
+        """ Verify store.display_name produces a string. """
+        self.assertIsInstance(self.store.display_name, basestring)
 
     def test_root(self):
         """ Verify store.root exists and has no parent """
@@ -121,10 +121,10 @@ class _TestStore(ut.TestCase):
         self.store.close()
         self.assertFalse(self.store.valid)
 
-    def test_canhandle(self):
-        """ Verify canhandle() works properly """
-        self.assertTrue(self.storecls.canhandle(self.url))
-        self.assertFalse(self.storecls.canhandle("file:///no/such/path"))
+    def test_can_handle(self):
+        """ Verify can_handle() works properly """
+        self.assertTrue(self.storecls.can_handle(self.url))
+        self.assertFalse(self.storecls.can_handle("file:///no/such/path"))
 
     def test_handlers(self):
         """ The implementation has at least one Node handler registered """
@@ -174,14 +174,14 @@ class _TestNode(ut.TestCase):
         self.assertIn(16, self.nodecls.icons)
         self.assertIn(64, self.nodecls.icons)
 
-    def test_classkind(self):
-        """ classkind is present, and a string """
-        self.assertIsInstance(self.nodecls.classkind, basestring)
+    def test_class_kind(self):
+        """ class_kind is present, and a string """
+        self.assertIsInstance(self.nodecls.class_kind, basestring)
 
-    def test_canhandle(self):
-        """ canhandle() consistency check """
-        self.assertTrue(self.nodecls.canhandle(self.store, self.key))
-        self.assertFalse(self.nodecls.canhandle(self.store, "/some/random/key"))
+    def test_can_handle(self):
+        """ can_handle() consistency check """
+        self.assertTrue(self.nodecls.can_handle(self.store, self.key))
+        self.assertFalse(self.nodecls.can_handle(self.store, "/some/random/key"))
 
     def test_key(self):
         """ Node.key returns a hashable object.
@@ -197,9 +197,9 @@ class _TestNode(ut.TestCase):
         self.assertIsInstance(self.node.store, self.storecls)
         self.assertEqual(self.node.store.url, self.store.url)
 
-    def test_displayname(self):
-        """ displayname exists and is a string """
-        self.assertIsInstance(self.node.displayname, basestring)
+    def test_display_name(self):
+        """ display_name exists and is a string """
+        self.assertIsInstance(self.node.display_name, basestring)
 
 
 class _TestContainer(_TestNode):
diff --git a/hdf_compass/compass_viewer/__init__.py b/hdf_compass/compass_viewer/__init__.py
index 3c2145c..0631e0d 100644
--- a/hdf_compass/compass_viewer/__init__.py
+++ b/hdf_compass/compass_viewer/__init__.py
@@ -141,7 +141,7 @@ def open_store(url):
 
     Returns True if the url was successfully opened, False otherwise.
     """
-    stores = [x for x in compass_model.getstores() if x.canhandle(url)]
+    stores = [x for x in compass_model.getstores() if x.can_handle(url)]
 
     if len(stores) > 0:
         instance = stores[0](url)
@@ -171,11 +171,10 @@ def load_plugins():
     except ImportError:
         log.info("HDF plugin not loaded")
 
-    # Coming soon!
-    # try:
-    #     from hdf_compass import bag_model
-    # except ImportError:
-    #     log.info("BAG plugin not loaded")
+    try:
+        from hdf_compass import bag_model
+    except ImportError:
+        log.info("BAG plugin not loaded")
 
     try:
         from hdf_compass import asc_model
diff --git a/hdf_compass/compass_viewer/array/__init__.py b/hdf_compass/compass_viewer/array/__init__.py
index 5b0db3b..1408a59 100644
--- a/hdf_compass/compass_viewer/array/__init__.py
+++ b/hdf_compass/compass_viewer/array/__init__.py
@@ -47,7 +47,7 @@ class ArrayFrame(NodeFrame):
 
     def __init__(self, node, pos=None):
         """ Create a new array viewer, to display *node*. """
-        NodeFrame.__init__(self, node, size=(800, 400), title=node.displayname, pos=pos)
+        NodeFrame.__init__(self, node, size=(800, 400), title=node.display_name, pos=pos)
 
         self.node = node
 
diff --git a/hdf_compass/compass_viewer/container/__init__.py b/hdf_compass/compass_viewer/container/__init__.py
index 3e91ae3..a7f43c1 100644
--- a/hdf_compass/compass_viewer/container/__init__.py
+++ b/hdf_compass/compass_viewer/container/__init__.py
@@ -51,7 +51,7 @@ class ContainerFrame(NodeFrame):
         node:   Container instance to display.
         pos:    Screen position at which to display the window.
         """
-        NodeFrame.__init__(self, node, size=(800, 400), title=node.displaytitle, pos=pos)
+        NodeFrame.__init__(self, node, size=(800, 400), title=node.display_title, pos=pos)
 
         view_menu = wx.Menu()
         view_menu.Append(ID_VIEW_MENU_LIST, "List view")
@@ -165,7 +165,7 @@ class ContainerFrame(NodeFrame):
     def update_view(self):
         """ Refresh the entire contents of the frame according to self.node.
         """
-        self.SetTitle(self.node.displaytitle)
+        self.SetTitle(self.node.display_title)
         self.view = type(self.view)(self, self.node)
         self.update_info()
 
diff --git a/hdf_compass/compass_viewer/container/list.py b/hdf_compass/compass_viewer/container/list.py
index 338e1ae..2d1b11b 100644
--- a/hdf_compass/compass_viewer/container/list.py
+++ b/hdf_compass/compass_viewer/container/list.py
@@ -111,7 +111,7 @@ class ContainerList(wx.ListCtrl):
             for h in handlers:
                 id_ = wx.NewId()
                 self._menu_handlers[id_] = h
-                submenu.Append(id_, h.classkind)
+                submenu.Append(id_, h.class_kind)
                 self.Bind(wx.EVT_MENU, self.on_context_openas, id=id_)
             menu.AppendSubMenu(submenu, "Open As")
 
@@ -187,7 +187,7 @@ class ContainerIconList(ContainerList):
         for item in xrange(len(self.node)):
             subnode = self.node[item]
             image_index = self.il.get_index(type(subnode))
-            self.InsertImageStringItem(item, subnode.displayname, image_index)
+            self.InsertImageStringItem(item, subnode.display_name, image_index)
 
 
 class ContainerReportList(ContainerList):
@@ -224,9 +224,9 @@ class ContainerReportList(ContainerList):
     def OnGetItemText(self, item, col):
         """ Callback method to support virtual list ctrl """
         if col == 0:
-            return self.node[item].displayname
+            return self.node[item].display_name
         elif col == 1:
-            return type(self.node[item]).classkind
+            return type(self.node[item]).class_kind
         return ""
 
     def OnGetItemImage(self, item):
diff --git a/hdf_compass/compass_viewer/frame.py b/hdf_compass/compass_viewer/frame.py
index 20fd2a7..26cd41f 100644
--- a/hdf_compass/compass_viewer/frame.py
+++ b/hdf_compass/compass_viewer/frame.py
@@ -390,7 +390,7 @@ class NodeFrame(BaseFrame):
         for h in handlers:
             id_ = wx.NewId()
             self._menu_handlers[id_] = h
-            wm.Append(id_, "Reopen as " + h.classkind)
+            wm.Append(id_, "Reopen as " + h.class_kind)
             self.Bind(wx.EVT_MENU, self.on_menu_reopen, id=id_)
             
         self.GetMenuBar().Insert(1, wm, "&Window")
diff --git a/hdf_compass/compass_viewer/image/__init__.py b/hdf_compass/compass_viewer/image/__init__.py
index 9c5b4b9..d77b87d 100644
--- a/hdf_compass/compass_viewer/image/__init__.py
+++ b/hdf_compass/compass_viewer/image/__init__.py
@@ -32,7 +32,7 @@ class ImageFrame(NodeFrame):
 
     def __init__(self, node, **kwds):
         """ Create a new array viewer, to display *node*. """
-        NodeFrame.__init__(self, node, title=node.displayname, size=(800, 400), **kwds)
+        NodeFrame.__init__(self, node, title=node.display_name, size=(800, 400), **kwds)
         self.node = node
 
         p = ImagePanel(self, node)
diff --git a/hdf_compass/compass_viewer/info.py b/hdf_compass/compass_viewer/info.py
index 986b2a8..f258b09 100644
--- a/hdf_compass/compass_viewer/info.py
+++ b/hdf_compass/compass_viewer/info.py
@@ -69,7 +69,7 @@ class InfoPanel(wx.Panel):
         See the get* methods for specifics on what's displayed.
         """
 
-        self.nametext.SetLabel(node.displayname)
+        self.nametext.SetLabel(node.display_name)
         self.proptext.SetLabel(describe(node))
 
         if self.staticbitmap is not None:
@@ -89,7 +89,7 @@ class InfoPanel(wx.Panel):
 def describe(node):
     """ Return a (possibly multi-line) text description of a node.
     """
-    desc = "%s\n\n" % type(node).classkind
+    desc = "%s\n\n" % type(node).class_kind
 
     if isinstance(node, compass_model.Array):
         desc += "Shape\n%s\n\nType\n%s" % \
diff --git a/hdf_compass/compass_viewer/keyvalue/__init__.py b/hdf_compass/compass_viewer/keyvalue/__init__.py
index 9632d05..65eadee 100644
--- a/hdf_compass/compass_viewer/keyvalue/__init__.py
+++ b/hdf_compass/compass_viewer/keyvalue/__init__.py
@@ -37,7 +37,7 @@ class KeyValueFrame(NodeFrame):
 
         node:   Container instance to display.
         """
-        title = 'Attributes of "%s"' % node.displayname
+        title = 'Attributes of "%s"' % node.display_name
         NodeFrame.__init__(self, node, size=(800, 400), title=title, pos=pos)
 
         self.list = KeyValueList(self, node)
diff --git a/hdf_compass/filesystem_model/__init__.py b/hdf_compass/filesystem_model/__init__.py
index faf7be4..2efe2b6 100644
--- a/hdf_compass/filesystem_model/__init__.py
+++ b/hdf_compass/filesystem_model/__init__.py
@@ -45,7 +45,7 @@ class Filesystem(compass_model.Store):
         return self._url
 
     @property
-    def displayname(self):
+    def display_name(self):
         return "Local file system"
 
     @property
@@ -57,13 +57,13 @@ class Filesystem(compass_model.Store):
         return self._valid
 
     @staticmethod
-    def canhandle(url):
+    def can_handle(url):
         if url == "file://localhost":
             return True
         return False
 
     def __init__(self, url):
-        if not self.canhandle(url):
+        if not self.can_handle(url):
             raise ValueError(url)
         self._url = url
         self._valid = True
@@ -82,10 +82,10 @@ class Directory(compass_model.Container):
         Represents a directory in the filesystem.
     """
 
-    classkind = "Directory"
+    class_kind = "Directory"
 
     @staticmethod
-    def canhandle(store, key):
+    def can_handle(store, key):
         return op.isdir(key)
 
     def __init__(self, store, key):
@@ -105,7 +105,7 @@ class Directory(compass_model.Container):
         return self._store
 
     @property
-    def displayname(self):
+    def display_name(self):
         bn = op.basename(self.key)
         if len(bn) == 0:
             return "/"
@@ -113,7 +113,7 @@ class Directory(compass_model.Container):
 
     @property
     def description(self):
-        return 'Folder "%s" (%d members)' % (self.displayname, len(self))
+        return 'Folder "%s" (%d members)' % (self.display_name, len(self))
 
     def __len__(self):
         return len(self._names)
@@ -133,10 +133,10 @@ class File(compass_model.Array):
         Represents a file (all loaded as an array of bytes)
     """
 
-    classkind = "File"
+    class_kind = "File"
 
     @staticmethod
-    def canhandle(store, key):
+    def can_handle(store, key):
         return op.isfile(key)
 
     def __init__(self, store, key):
@@ -152,12 +152,12 @@ class File(compass_model.Array):
         return self._store
 
     @property
-    def displayname(self):
+    def display_name(self):
         return op.basename(self.key)
 
     @property
     def description(self):
-        return 'File "%s", size %d bytes' % (self.displayname, op.getsize(self.key))
+        return 'File "%s", size %d bytes' % (self.display_name, op.getsize(self.key))
 
     @property
     def shape(self):
diff --git a/hdf_compass/hdf5_model/__init__.py b/hdf_compass/hdf5_model/__init__.py
index cdb299f..8da410b 100644
--- a/hdf_compass/hdf5_model/__init__.py
+++ b/hdf_compass/hdf5_model/__init__.py
@@ -55,7 +55,7 @@ class HDF5Store(compass_model.Store):
         return self._url
 
     @property
-    def displayname(self):
+    def display_name(self):
         return op.basename(self.f.filename)
 
     @property
@@ -67,7 +67,7 @@ class HDF5Store(compass_model.Store):
         return bool(self.f)
 
     @staticmethod
-    def canhandle(url):
+    def can_handle(url):
         if not url.startswith('file://'):
             return False
         if sys.platform == 'win32':
@@ -79,7 +79,7 @@ class HDF5Store(compass_model.Store):
         return True
 
     def __init__(self, url):
-        if not self.canhandle(url):
+        if not self.can_handle(url):
             raise ValueError(url)
         self._url = url
         if sys.platform == 'win32':
@@ -106,10 +106,10 @@ class HDF5Group(compass_model.Container):
     Represents an HDF5 group, to be displayed in the browser view.
     """
 
-    classkind = "HDF5 Group"
+    class_kind = "HDF5 Group"
 
     @staticmethod
-    def canhandle(store, key):
+    def can_handle(store, key):
         return key in store and isinstance(store.f[key], h5py.Group)
 
     @property
@@ -141,19 +141,19 @@ class HDF5Group(compass_model.Container):
         return self._store
 
     @property
-    def displayname(self):
+    def display_name(self):
         name = pp.basename(self.key)
         if name == "":
             name = '/'
         return name
 
     @property
-    def displaytitle(self):
-        return "%s %s" % (self.store.displayname, self.key)
+    def display_title(self):
+        return "%s %s" % (self.store.display_name, self.key)
 
     @property
     def description(self):
-        return 'Group "%s" (%d members)' % (self.displayname, len(self))
+        return 'Group "%s" (%d members)' % (self.display_name, len(self))
 
     def __len__(self):
         return len(self._group)
@@ -172,10 +172,10 @@ class HDF5Dataset(compass_model.Array):
     Represents an HDF5 dataset.
     """
 
-    classkind = "HDF5 Dataset"
+    class_kind = "HDF5 Dataset"
 
     @staticmethod
-    def canhandle(store, key):
+    def can_handle(store, key):
         return key in store and isinstance(store.f[key], h5py.Dataset)
 
     def __init__(self, store, key):
@@ -192,12 +192,12 @@ class HDF5Dataset(compass_model.Array):
         return self._store
 
     @property
-    def displayname(self):
+    def display_name(self):
         return pp.basename(self.key)
 
     @property
     def description(self):
-        return 'Dataset "%s"' % (self.displayname,)
+        return 'Dataset "%s"' % (self.display_name,)
 
     @property
     def shape(self):
@@ -216,10 +216,10 @@ class HDF5KV(compass_model.KeyValue):
     A KeyValue node used for HDF5 attributes.
     """
 
-    classkind = "HDF5 Attributes"
+    class_kind = "HDF5 Attributes"
 
     @staticmethod
-    def canhandle(store, key):
+    def can_handle(store, key):
         return key in store.f
 
     def __init__(self, store, key):
@@ -237,13 +237,13 @@ class HDF5KV(compass_model.KeyValue):
         return self._store
 
     @property
-    def displayname(self):
+    def display_name(self):
         n = pp.basename(self.key)
         return n if n != '' else '/'
 
     @property
     def description(self):
-        return self.displayname
+        return self.display_name
 
     @property
     def keys(self):
@@ -258,10 +258,10 @@ class HDF5Image(compass_model.Image):
     True-color images.
     """
 
-    classkind = "HDF5 Truecolor Image"
+    class_kind = "HDF5 Truecolor Image"
 
     @staticmethod
-    def canhandle(store, key):
+    def can_handle(store, key):
         if key not in store:
             return False
         obj = store.f[key]
@@ -287,13 +287,13 @@ class HDF5Image(compass_model.Image):
         return self._store
 
     @property
-    def displayname(self):
+    def display_name(self):
         n = pp.basename(self.key)
         return n if n != '' else '/'
 
     @property
     def description(self):
-        return self.displayname
+        return self.display_name
 
     @property
     def width(self):
diff --git a/hdf_compass/opendap_model/__init__.py b/hdf_compass/opendap_model/__init__.py
index ef83af4..71ba37f 100644
--- a/hdf_compass/opendap_model/__init__.py
+++ b/hdf_compass/opendap_model/__init__.py
@@ -47,14 +47,14 @@ class Server(compass_model.Store):
         return new_key in new_dset
 
     @staticmethod
-    def canhandle(url):
+    def can_handle(url):
         try:
             return isinstance(open_url(url), dap.model.DatasetType)
         except Exception:
             return False
 
     def __init__(self, url):
-        if not self.canhandle(url):
+        if not self.can_handle(url):
             raise ValueError(url)
         self._url = url
         self._valid = True
@@ -73,7 +73,7 @@ class Server(compass_model.Store):
         return self._url
 
     @property
-    def displayname(self):
+    def display_name(self):
         return self.dataset.name
 
     @property
@@ -98,7 +98,7 @@ class Dataset(compass_model.Container):
         Represents Dataset/DatasetType Object in OpENDAP/Pydap.
     """
 
-    classkind = "Dataset"
+    class_kind = "Dataset"
 
     def __len__(self):
         return self._store.datalength
@@ -111,7 +111,7 @@ class Dataset(compass_model.Container):
         pass
 
     @staticmethod
-    def canhandle(store, key):
+    def can_handle(store, key):
         return key == ''
 
     def __init__(self, store, key):
@@ -131,7 +131,7 @@ class Dataset(compass_model.Container):
         return self._store
 
     @property
-    def displayname(self):
+    def display_name(self):
         return self._dset.name
 
     @property
@@ -148,7 +148,7 @@ class Structure(compass_model.Container):
         Represents Structure/StructureType Object in OpENDAP/Pydap.
     """
 
-    classkind = "Structure/Grid/Sequence"
+    class_kind = "Structure/Grid/Sequence"
 
     def __len__(self):
         return len(self._dset.data)
@@ -161,7 +161,7 @@ class Structure(compass_model.Container):
         pass
 
     @staticmethod
-    def canhandle(store, key):
+    def can_handle(store, key):
         new_key, new_dset = check_key(key, store.dataset)
         try:
             return new_key in new_dset and isinstance(new_dset[new_key], dap.model.StructureType)
@@ -185,7 +185,7 @@ class Structure(compass_model.Container):
         return self._store
 
     @property
-    def displayname(self):
+    def display_name(self):
         return self._dset.name
 
     @property
@@ -198,7 +198,7 @@ class Base(compass_model.Array):
         Represents Array/BaseType Object in OpENDAP/Pydap.
     """
 
-    classkind = "Array"
+    class_kind = "Array"
 
     @property
     def shape(self):
@@ -214,7 +214,7 @@ class Base(compass_model.Array):
         return self._data[index]
 
     @staticmethod
-    def canhandle(store, key):
+    def can_handle(store, key):
         new_key, new_dset = check_key(key, store.dataset)
         return new_key in new_dset and isinstance(new_dset[new_key], dap.model.BaseType)
 
@@ -241,7 +241,7 @@ class Base(compass_model.Array):
         return self._store
 
     @property
-    def displayname(self):
+    def display_name(self):
         return self._name
 
     @property
@@ -254,7 +254,7 @@ class Attributes(compass_model.KeyValue):
         Represents the Attributes member of Pydap Objects.
     """
 
-    classkind = "Attributes"
+    class_kind = "Attributes"
 
     @property
     def keys(self):
@@ -264,7 +264,7 @@ class Attributes(compass_model.KeyValue):
         return self._keys[name]
 
     @staticmethod
-    def canhandle(store, key):
+    def can_handle(store, key):
         new_key = check_key(key, store.dataset)
         return new_key != ''
 
@@ -284,7 +284,7 @@ class Attributes(compass_model.KeyValue):
         return self._store
 
     @property
-    def displayname(self):
+    def display_name(self):
         return "%s Attributes" % self._key
 
     @property
diff --git a/hdf_compass/utils/__init__.py b/hdf_compass/utils/__init__.py
new file mode 100644
index 0000000..70a6777
--- /dev/null
+++ b/hdf_compass/utils/__init__.py
@@ -0,0 +1,19 @@
+##############################################################################
+# Copyright by The HDF Group.                                                #
+# All rights reserved.                                                       #
+#                                                                            #
+# This file is part of the HDF Compass Viewer. The full HDF Compass          #
+# copyright notice, including terms governing use, modification, and         #
+# terms governing use, modification, and redistribution, is contained in     #
+# the file COPYING, which can be found at the root of the source code        #
+# distribution tree.  If you do not have access to this file, you may        #
+# request a copy from help at hdfgroup.org.                                     #
+##############################################################################
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from .utils import is_darwin, is_win, is_linux, url2path
+
+import logging
+
+log = logging.getLogger(__name__)
+log.addHandler(logging.NullHandler())
diff --git a/hdf_compass/utils/utils.py b/hdf_compass/utils/utils.py
new file mode 100644
index 0000000..c045044
--- /dev/null
+++ b/hdf_compass/utils/utils.py
@@ -0,0 +1,32 @@
+##############################################################################
+# Copyright by The HDF Group.                                                #
+# All rights reserved.                                                       #
+#                                                                            #
+# This file is part of the HDF Compass Viewer. The full HDF Compass          #
+# copyright notice, including terms governing use, modification, and         #
+# terms governing use, modification, and redistribution, is contained in     #
+# the file COPYING, which can be found at the root of the source code        #
+# distribution tree.  If you do not have access to this file, you may        #
+# request a copy from help at hdfgroup.org.                                     #
+##############################################################################
+"""
+Implementation of utils and helper functions
+"""
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+import sys
+
+import logging
+log = logging.getLogger(__name__)
+
+is_darwin = sys.platform == 'darwin'
+is_win = sys.platform == 'win32'
+is_linux = sys.platform == 'linux2'
+
+
+def url2path(url):
+    """Helper function that returns the file path from an url, dealing with Windows peculiarities"""
+    if is_win:
+        return url.replace('file:///', '')
+    else:
+        return url.replace('file://', '')

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/hdf-compass.git



More information about the debian-science-commits mailing list