h5fs.py

Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # 
00003 #  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00004 # 
00005 #                               Michael A.G. Aivazis
00006 #                        California Institute of Technology
00007 #                        (C) 1998-2002 All Rights Reserved
00008 # 
00009 #  <LicenseText>
00010 # 
00011 #  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00012 # 
00013 
00014 
00015 ## \namespace h5fs
00016 ## Provides python interface to hdf5 files
00017 ##
00018 ## hdf5 has an c++ API. This module provides python bindings to methods of
00019 ##  c++ class H5:H5File.
00020 ##  This hdf5fs package treats a hdf5 file as a "file system".
00021 ##  A group is seen as a directory in the "file system". A dataset is seen
00022 ##  as a file in the "file system".
00023 
00024 
00025 
00026 import hdf5fs as h5mod
00027 import h5file, h5dir, h5type, h5space
00028 
00029 import journal, sys
00030 debug = journal.debug("hdf5fs.h5fs")
00031 
00032 
00033 class H5fs:
00034 
00035 
00036     ### support methods
00037 
00038     def normpath(self, path):
00039         """
00040         normpath(path) -->  normalized path
00041         
00042         normalize given path
00043 
00044         @rtype:   string
00045         @return:  normalized path
00046         
00047         normpath from os.path is not useful here: '..' is not
00048         treated specially in HDF5
00049         """
00050         while 1:
00051             oldlen = len(path)
00052             path = path.replace('//', '/').replace('/./', '/')
00053             if oldlen == len(path):
00054                 if len(path) > 1:
00055                     if path[:2] == './': path = path[2:]
00056                     if path[-2:] == '/.': path = path[:-2]
00057                 return path
00058 
00059 
00060     def mkparents(self, dir, path):
00061         raise 'automatic path generation not supported yet'
00062 
00063         
00064     def path2hdf(self, path):
00065         """translate path to hdf5-compatible format
00066         @rtype:  string
00067         @return: hdf5-compatible path
00068         """
00069         if self.dirsep != '/':
00070             if path.find(self.slashrep) >= 0:
00071                 raise 'fix forward slash representation'
00072                 # TODO: use proper H5 exception
00073             path = path.replace('/', self.slashrep).replace(self.dirsep, '/')
00074         else: return path
00075 
00076 
00077     def hdf2path(self, path):
00078         """ translate path from hdf5 to external format
00079         @rtype:  string
00080         @return: path in external format
00081         """
00082         if self.dirsep != '/':
00083             return path.replace('/', self.dirsep).replace(self.slashrep, '/')
00084         else: return path
00085 
00086 
00087     def hdf2abspath(self, path):
00088         """ translate path from hdf5 to absolute path in external format
00089         @rtype:  string
00090         @return: absolute path in external format
00091         """
00092         if path[0] == '/': return self.hdf2path(path)
00093         else: return self.hdf2path(self.normpath(self.cwd+path))
00094 
00095 
00096     def refdir(self, path):
00097         """ translate path to a tuple of (group_ref, relpath)
00098         @type  path:  string
00099         @param path:  the path of the object
00100         @rtype:   tuple
00101         @return: (group_ref, relpath)
00102           - group_ref: PyCObject that refers to a H5:Group object in which relpath is relevant
00103           - relpath:  relative path inside the group refered to by group_ref
00104         """
00105         path = self.path2hdf(path)
00106         if path[0] == '/': return self.rootref, path
00107         else: return self.cwdref, path
00108 
00109 
00110     def refdir2(self, path1, path2):
00111         path1 = self.path2hdf(path1)
00112         path2 = self.path2hdf(path2)
00113         if path1[0] == '/' or path2[0] == '/':
00114             if path1[0] != '/': path1 = self.cwd+path1
00115             if path2[0] != '/': path2 = self.cwd+path2
00116             return self.rootref, path1, path2
00117         else: return self.cwdref, path1, path2
00118 
00119 
00120     ### user methods
00121 
00122     def chdir(self, path):
00123         """open directory specified by 'path'
00124         """
00125         dcomp = self.refdir(path)
00126         self.cwdref = h5mod.h5fs_open(dcomp[0], dcomp[1])[0]
00127         if dcomp[1][0] == '/': self.cwd = self.normpath(dcomp[1])
00128         else: self.cwd = self.normpath(self.cwd+dcomp[1])
00129         if self.cwd[-1] != '/': self.cwd += '/'
00130 
00131 
00132     def exists(self, path):
00133         try:
00134             self.open(path)
00135             return True
00136         except:
00137             return False
00138 
00139 
00140     def makedirs(self, path):
00141         if self.exists( path ): return
00142         path = self.normpath( path )
00143         import os
00144         base, last = os.path.split( path )
00145         if base == '':
00146             if not self.exists( path ): self.mkdir(path)
00147             return
00148         if not self.exists( base ):
00149             self.makedirs( base )
00150         self.mkdir( path )
00151         return
00152         
00153 
00154     def mkdir(self, path):
00155         """make a new directory at location specified by 'path'
00156         """
00157         dcomp = self.refdir(path)
00158         h5mod.h5fs_mkdir(dcomp[0], dcomp[1])
00159 
00160 
00161     def link(self, path, newpath):
00162         """link(path, newpath) --> make a link at newpath to path
00163         """
00164         dcomp = self.refdir2(path, newpath)
00165         h5mod.h5fs_link(dcomp[0], dcomp[1], dcomp[2])
00166 
00167 
00168     def symlink(self, path, newpath):
00169         """symlink(path, newpath) --> make a symbolic link at newpath to path
00170         """
00171         dcomp = self.refdir2(path, newpath)
00172         h5mod.h5fs_symlink(dcomp[0], dcomp[1], dcomp[2])
00173 
00174 
00175     def rename(self, path, newpath):
00176         """rename(path, newpath) --> rename an object at path to newpath
00177         """
00178         dcomp = self.refdir2(path, newpath)
00179         h5mod.h5fs_rename(dcomp[0], dcomp[1], dcomp[2])
00180 
00181 
00182     def mount(self, path, fs):
00183         """mount(path, fs) --> mount fs to path of current 'file system'
00184         """
00185         dcomp = self.refdir(path)
00186         h5mod.h5fs_mount(dcomp[0], dcomp[1], fs.h5ref)
00187 
00188 
00189     def open(self, path, type = None, space = None, compression=0, chunksize=100):
00190         """open the given path in the current file
00191             - If type is not specified
00192             depends on the type of the opened item, it returns instance of different
00193             types.
00194                 - if it is a directory(group), return instance of h5dir.H5dir
00195                 - if it is a file(dataset), return instance of h5file.H5file
00196                 - if it is a type???, return instance of h5type.H5type
00197 
00198             - If type is specified
00199             then a new file (dataset) will be created and returned!
00200         """
00201         dcomp = self.refdir(path)
00202         if not type:
00203             # open existing object
00204             ref, type = h5mod.h5fs_open(dcomp[0], dcomp[1])
00205             if type == 'directory':
00206                 return h5dir.H5dir(ref, self.hdf2abspath(path))
00207             elif type == 'file':
00208                 return h5file.H5file(ref, self.hdf2abspath(path))
00209             elif type == 'type':
00210                 return h5type.H5type(None, ref, self.hdf2abspath(path))
00211             else: return None
00212         else:
00213             # create file
00214             return h5file.H5file(
00215                 dcomp[0], dcomp[1], type, space,
00216                 compression=compression, chunksize=chunksize)
00217         
00218         
00219     def unlink(self, path):
00220         """unlink(path) --> remove the object at given path
00221         """
00222         dcomp = self.refdir(path)
00223         h5mod.h5fs_unlink(dcomp[0], dcomp[1])
00224 
00225 
00226     def rmdir(self, path):
00227         """rmdir(path) --> remove the directory at the given path
00228         """
00229         dcomp = self.refdir(path)
00230         h5mod.h5fs_unlink(dcomp[0], dcomp[1])
00231 
00232 
00233     def umount(self, path):
00234         """unmount(path) --> remove the mounted fs at the given path
00235         """
00236         dcomp = self.refdir(path)
00237         h5mod.h5fs_umount(dcomp[0], dcomp[1])
00238 
00239 
00240     def stat(self, path):
00241         """stat(path) --> status of the object at the given path
00242         - return:    a dictionary of descriptions of the status
00243                      {'type':???, 'numlinks':???}
00244         """
00245         dcomp = self.refdir(path)
00246         return h5mod.h5fs_stat(dcomp[0], dcomp[1])
00247     
00248 
00249     def __init__(self, filename, mode):
00250         """H5fs(filename, mode) -> create new H5fs
00251         Recognized modes: 'r' (read-only), 'w' (write-append),
00252         'c' (create/truncate-existing)"""
00253         self.type = 'filesystem'
00254         # get filesystem and root directory objects
00255         self.h5ref, self.rootref = h5mod.h5fs_new(filename, mode)
00256         debug.log( 'h5fs: filename=%s, mode=%s' % (filename, mode) )
00257         debug.log("ref count of h5ref: %s" % sys.getrefcount(self.h5ref))
00258         
00259         # current working directory path and its directory object
00260         self.cwd, self.cwdref = '/', h5mod.h5fs_open(self.rootref, '/')[0]
00261         # path component separator
00262         self.dirsep = '/'
00263         # forward slash representation for oddball dirsep
00264         self.slashrep = '__slash__'
00265         # automatic generation of missing path components
00266         self.autodir = 0
00267         # automatic generation of missing path components for chdir
00268         self.autocd = 0
00269 
00270 
00271 ##     def __del__(self):
00272 ##         h5mod.h5fs_del(self.h5ref)
00273 
00274 
00275     def getcwd(self): return self.hdf2path(self.cwd)
00276 
00277 #  End of file 

Generated on Mon Jun 22 01:31:04 2009 for hdf5fs by  doxygen 1.5.2