source: trunk/anuga_core/source/anuga/utilities/file_utils.py @ 7814

Last change on this file since 7814 was 7778, checked in by James Hudson, 15 years ago

Cleaned up unit tests to use API.

File size: 10.0 KB
Line 
1""" Generic file utilities for creating, parsing deleting
2    and naming files in a manner consistent across ANUGA.
3"""
4
5
6import os, sys
7import csv
8import numpy as num
9import shutil
10
11def make_filename(s):
12    """Transform argument string into a standard filename
13   
14        Convert a possible filename into a standard form.
15        s Filename to process.
16        The new filename string.
17    """
18
19    s = s.strip()
20    s = s.replace(' ', '_')
21    s = s.replace('(', '')
22    s = s.replace(')', '')
23    s = s.replace('__', '_')
24
25    return s
26
27
28def check_dir(path, verbose=None):
29    """Check that specified path exists.
30    If path does not exist it will be created if possible
31
32    USAGE:
33       checkdir(path, verbose):
34
35    ARGUMENTS:
36        path -- Directory
37        verbose -- Flag verbose output (default: None)
38
39    RETURN VALUE:
40        Verified path including trailing separator
41    """
42
43    import os.path
44
45    if sys.platform in ['nt', 'dos', 'win32', 'what else?']:
46        unix = 0
47    else:
48        unix = 1
49
50    # add terminal separator, if it's not already there
51    if path[-1] != os.sep:
52        path = path + os.sep
53
54    # expand ~ or ~username in path
55    path = os.path.expanduser(path)
56
57    # create directory if required
58    if not (os.access(path, os.R_OK and os.W_OK) or path == ''):
59        try:
60            exitcode = os.mkdir(path)
61
62            # Change access rights if possible
63            if unix:
64                exitcode = os.system('chmod 775 ' + path)
65            else:
66                pass  # FIXME: What about access rights under Windows?
67
68            if verbose: log.critical('MESSAGE: Directory %s created.' % path)
69        except:
70            log.critical('WARNING: Directory %s could not be created.' % path)
71            if unix:
72                path = '/tmp/'
73            else:
74                path = 'C:' + os.sep
75
76            log.critical("Using directory '%s' instead" % path)
77
78    return path
79
80
81##
82# @brief Delete directory and all sub-directories.
83# @param path Path to the directory to delete.
84def del_dir(path):
85    """Recursively delete directory path and all its contents
86    """
87
88    if os.path.isdir(path):
89        for file in os.listdir(path):
90            X = os.path.join(path, file)
91
92            if os.path.isdir(X) and not os.path.islink(X):
93                del_dir(X)
94            else:
95                try:
96                    os.remove(X)
97                except:
98                    log.critical("Could not remove file %s" % X)
99
100        os.rmdir(path)
101
102
103##
104# @brief ??
105# @param path
106# @param __func__
107# @param verbose True if this function is to be verbose.
108# @note ANOTHER OPTION, IF NEED IN THE FUTURE, Nick B 7/2007
109def rmgeneric(path, func, verbose=False):
110    ERROR_STR= """Error removing %(path)s, %(error)s """
111
112    try:
113        func(path)
114        if verbose: log.critical('Removed %s' % path)
115    except OSError, (errno, strerror):
116        log.critical(ERROR_STR % {'path' : path, 'error': strerror })
117
118
119##
120# @brief Remove directory and all sub-directories.
121# @param path Filesystem path to directory to remove.
122# @param verbose True if this function is to be verbose.
123def removeall(path, verbose=False):
124    if not os.path.isdir(path):
125        return
126
127    for x in os.listdir(path):
128        fullpath = os.path.join(path, x)
129        if os.path.isfile(fullpath):
130            f = os.remove
131            rmgeneric(fullpath, f)
132        elif os.path.isdir(fullpath):
133            removeall(fullpath)
134            f = os.rmdir
135            rmgeneric(fullpath, f, verbose)
136
137
138##
139# @brief Create a standard filename.
140# @param datadir Directory where file is to be created.
141# @param filename Filename 'stem'.
142# @param format Format of the file, becomes filename extension.
143# @param size Size of file, becomes part of filename.
144# @param time Time (float), becomes part of filename.
145# @return The complete filename path, including directory.
146# @note The containing directory is created, if necessary.
147def create_filename(datadir, filename, format, size=None, time=None):
148    FN = check_dir(datadir) + filename
149
150    if size is not None:
151        FN += '_size%d' % size
152
153    if time is not None:
154        FN += '_time%.2f' % time
155
156    FN += '.' + format
157
158    return FN
159
160
161##
162# @brief Get all files with a standard name and a given set of attributes.
163# @param datadir Directory files must be in.
164# @param filename Filename stem.
165# @param format Filename extension.
166# @param size Filename size.
167# @return A list of fielnames (including directory) that match the attributes.
168def get_files(datadir, filename, format, size):
169    """Get all file (names) with given name, size and format
170    """
171
172    import glob
173
174    dir = check_dir(datadir)
175    pattern = dir + os.sep + filename + '_size=%d*.%s' % (size, format)
176
177    return glob.glob(pattern)
178
179
180##
181# @brief Find all files in a directory that contain a given string.
182# @param look_in_dir Path to the directory to look in.
183# @param base_name String that files must contain.
184# @param verbose True if this function is to be verbose.
185def get_all_directories_with_name(look_in_dir='', base_name='', verbose=False):
186    '''
187    Finds all the directories in a "look_in_dir" which contains a "base_name".
188
189    Returns: a list of strings
190
191    Usage:     iterate_over = get_all_directories_with_name(dir, name)
192    then:      for swwfile in iterate_over:
193                   do stuff
194
195    Check "export_grids" and "get_maximum_inundation_data" for examples
196    '''
197
198    if look_in_dir == "":
199        look_in_dir = "."                                  # Unix compatibility
200
201    dir_ls = os.listdir(look_in_dir)
202    iterate_over = [x for x in dir_ls if base_name in x]
203
204    if len(iterate_over) == 0:
205        msg = 'No files of the base name %s' % base_name
206        raise IOError, msg
207
208    if verbose: log.critical('iterate over %s' % iterate_over)
209
210    return iterate_over
211
212
213
214##
215# @brief Find all SWW files in a directory with given stem name.
216# @param look_in_dir The directory to look in.
217# @param base_name The file stem name.
218# @param verbose True if this function is to be verbose.
219# @return A list of found filename strings.
220# @note Will accept 'base_name' with or without '.sww' extension.
221# @note If no files found, raises IOError exception.
222def get_all_swwfiles(look_in_dir='', base_name='', verbose=False):
223    '''
224    Finds all the sww files in a "look_in_dir" which contains a "base_name".
225    will accept base_name with or without the extension ".sww"
226
227    Returns: a list of strings
228
229    Usage:     iterate_over = get_all_swwfiles(dir, name)
230    then
231               for swwfile in iterate_over:
232                   do stuff
233
234    Check "export_grids" and "get_maximum_inundation_data" for examples
235    '''
236
237    # plus tests the extension
238    name, extension = os.path.splitext(base_name)
239
240    if extension != '' and extension != '.sww':
241        msg = 'file %s%s must be a NetCDF sww file!' % (base_name, extension)
242        raise IOError, msg
243
244    if look_in_dir == "":
245        look_in_dir = "."                                   # Unix compatibility
246
247    dir_ls = os.listdir(look_in_dir)
248    iterate_over = [x[:-4] for x in dir_ls if name in x and x[-4:] == '.sww']
249    if len(iterate_over) == 0:
250        msg = 'No files of the base name %s' % name
251        raise IOError, msg
252
253    if verbose: log.critical('iterate over %s' % iterate_over)
254
255    return iterate_over
256
257
258##
259# @brief Find all files in a directory that contain a string and have extension.
260# @param look_in_dir Path to the directory to look in.
261# @param base_name Stem filename of the file(s) of interest.
262# @param extension Extension of the files to look for.
263# @param verbose True if this function is to be verbose.
264# @return A list of found filename strings.
265# @note If no files found, raises IOError exception.
266def get_all_files_with_extension(look_in_dir='',
267                                 base_name='',
268                                 extension='.sww',
269                                 verbose=False):
270    '''Find all files in a directory with given stem name.
271    Finds all the sww files in a "look_in_dir" which contains a "base_name".
272
273    Returns: a list of strings
274
275    Usage:     iterate_over = get_all_swwfiles(dir, name)
276    then
277               for swwfile in iterate_over:
278                   do stuff
279
280    Check "export_grids" and "get_maximum_inundation_data" for examples
281    '''
282
283    # plus tests the extension
284    name, ext = os.path.splitext(base_name)
285
286    if ext != '' and ext != extension:
287        msg = 'base_name %s must be a file with %s extension!' \
288              % (base_name, extension)
289        raise IOError, msg
290
291    if look_in_dir == "":
292        look_in_dir = "."                               # Unix compatibility
293
294    dir_ls = os.listdir(look_in_dir)
295    iterate_over = [x[:-4] for x in dir_ls if name in x and x[-4:] == extension]
296
297    if len(iterate_over) == 0:
298        msg = 'No files of the base name %s in %s' % (name, look_in_dir)
299        raise IOError, msg
300
301    if verbose: log.critical('iterate over %s' % iterate_over)
302
303    return iterate_over
304
305
306
307
308def copy_code_files(dir_name, filename1, filename2=None, verbose=False):
309    """Copies "filename1" and "filename2" to "dir_name".
310
311    Each 'filename' may be a string or list of filename strings.
312
313    Filenames must be absolute pathnames
314    """
315
316    ##
317    # @brief copies a file or sequence to destination directory.
318    # @param dest The destination directory to copy to.
319    # @param file A filename string or sequence of filename strings.
320    def copy_file_or_sequence(dest, file):
321        if hasattr(file, '__iter__'):
322            for f in file:
323                shutil.copy(f, dir_name)
324                if verbose:
325                    log.critical('File %s copied' % f)
326        else:
327            shutil.copy(file, dir_name)
328            if verbose:
329                log.critical('File %s copied' % file)
330
331    # check we have a destination directory, create if necessary
332    if not os.path.isdir(dir_name):
333        if verbose:
334            log.critical('Make directory %s' % dir_name)
335        mkdir(dir_name, 0777)
336
337    if verbose:
338        log.critical('Output directory: %s' % dir_name)       
339
340    copy_file_or_sequence(dir_name, filename1)
341
342    if not filename2 is None:
343        copy_file_or_sequence(dir_name, filename2)
Note: See TracBrowser for help on using the repository browser.