source: rtems-tools/rtemstoolkit/path.py @ 7e5cdea

Last change on this file since 7e5cdea was 7e5cdea, checked in by Chris Johns <chrisj@…>, on Nov 23, 2018 at 4:02:52 AM

rtemstoolkit: Add unit testing for the python modules

  • Add support to run the unit tests for the rtemstoolkit python modules from waf. Enter './waf test' for the tests to be run on python2 and python3.
  • Update the importing of rtemstoolkit modules to the standard method which works on python2 and python3.
  • Update the README.
  • Property mode set to 100644
File size: 7.7 KB
RevLine 
[50fdf12]1#
2# RTEMS Tools Project (http://www.rtems.org/)
[b0fa2ae]3# Copyright 2010-2016 Chris Johns (chrisj@rtems.org)
[50fdf12]4# All rights reserved.
5#
6# This file is part of the RTEMS Tools package in 'rtems-tools'.
7#
8# Redistribution and use in source and binary forms, with or without
9# modification, are permitted provided that the following conditions are met:
10#
11# 1. Redistributions of source code must retain the above copyright notice,
12# this list of conditions and the following disclaimer.
13#
14# 2. Redistributions in binary form must reproduce the above copyright notice,
15# this list of conditions and the following disclaimer in the documentation
16# and/or other materials provided with the distribution.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28# POSSIBILITY OF SUCH DAMAGE.
29#
30
31#
32# Manage paths locally. The internally the path is in Unix or shell format and
33# we convert to the native format when performing operations at the Python
34# level. This allows macro expansion to work.
35#
36
[b0fa2ae]37from __future__ import print_function
38
[50fdf12]39import glob
40import os
41import shutil
42import string
43
[7e5cdea]44from rtemstoolkit import error
45from rtemstoolkit import log
[50fdf12]46
47windows = os.name == 'nt'
48
49def host(path):
50    if path is not None:
51        while '//' in path:
52            path = path.replace('//', '/')
53        if windows and len(path) > 2:
54            if path[0] == '/' and path[2] == '/' and \
55                    (path[1] in string.ascii_lowercase or \
56                         path[1] in string.ascii_uppercase):
57                path = ('%s:%s' % (path[1], path[2:])).replace('/', '\\')
58    return path
59
60def shell(path):
61    if path is not None:
62        if windows and len(path) > 1 and path[1] == ':':
63            path = ('/%s%s' % (path[0], path[2:])).replace('\\', '/')
64        while '//' in path:
65            path = path.replace('//', '/')
66    return path
67
68def basename(path):
69    return shell(os.path.basename(path))
70
71def dirname(path):
72    return shell(os.path.dirname(path))
73
74def join(path, *args):
75    path = shell(path)
76    for arg in args:
77        if len(path):
78            path += '/' + shell(arg)
79        else:
80            path = shell(arg)
81    return shell(path)
82
83def abspath(path):
84    return shell(os.path.abspath(host(path)))
85
86def splitext(path):
87    root, ext = os.path.splitext(host(path))
88    return shell(root), ext
89
90def exists(paths):
91    if type(paths) == list:
92        results = []
93        for p in paths:
94            results += [os.path.exists(host(p))]
95        return results
96    return os.path.exists(host(paths))
97
98def isdir(path):
99    return os.path.isdir(host(path))
100
101def isfile(path):
102    return os.path.isfile(host(path))
103
104def isabspath(path):
105    return path[0] == '/'
106
107def iswritable(path):
108    return os.access(host(path), os.W_OK)
109
110def ispathwritable(path):
111    path = host(path)
112    while len(path) != 0:
113        if os.path.exists(path):
114            return iswritable(path)
115        path = os.path.dirname(path)
116    return False
117
118def mkdir(path):
119    path = host(path)
120    if exists(path):
121        if not isdir(path):
122            raise error.general('path exists and is not a directory: %s' % (path))
123    else:
124        if windows:
125            try:
126                os.makedirs(host(path))
[04a5204]127            except IOError:
[50fdf12]128                raise error.general('cannot make directory: %s' % (path))
[04a5204]129            except OSError:
[50fdf12]130                raise error.general('cannot make directory: %s' % (path))
[04a5204]131            except WindowsError:
[50fdf12]132                raise error.general('cannot make directory: %s' % (path))
133        else:
134            try:
135                os.makedirs(host(path))
[04a5204]136            except IOError:
[50fdf12]137                raise error.general('cannot make directory: %s' % (path))
[04a5204]138            except OSError:
[50fdf12]139                raise error.general('cannot make directory: %s' % (path))
140
141def removeall(path):
142
143    def _onerror(function, path, excinfo):
[04a5204]144        print('removeall error: (%s) %s' % (excinfo, path))
[50fdf12]145
146    path = host(path)
147    shutil.rmtree(path, onerror = _onerror)
148
149def expand(name, paths):
150    l = []
151    for p in paths:
152        l += [join(p, name)]
153    return l
154
[bf58911]155def expanduser(path):
156    path = host(path)
157    path = os.path.expanduser(path)
158    return shell(path)
159
[50fdf12]160def collect_files(path_):
161    #
162    # Convert to shell paths and return shell paths.
163    #
164    # @fixme should this use a passed in set of defaults and not
165    #        not the initial set of values ?
166    #
167    path_ = shell(path_)
168    if '*' in path_ or '?' in path_:
169        dir = dirname(path_)
170        base = basename(path_)
171        if len(base) == 0:
172            base = '*'
173        files = []
174        for p in dir.split(':'):
175            hostdir = host(p)
176            for f in glob.glob(os.path.join(hostdir, base)):
177                files += [host(f)]
178    else:
179        files = [host(path_)]
180    return sorted(files)
181
182def copy_tree(src, dst):
183    hsrc = host(src)
184    hdst = host(dst)
185
[f9a17cd]186    if os.path.exists(src) and os.path.isdir(src):
[50fdf12]187        names = os.listdir(src)
188    else:
[f9a17cd]189        names = [basename(src)]
190        src = dirname(src)
[50fdf12]191
192    if not os.path.isdir(dst):
193        os.makedirs(dst)
194
195    for name in names:
196        srcname = os.path.join(src, name)
197        dstname = os.path.join(dst, name)
198        try:
199            if os.path.islink(srcname):
200                linkto = os.readlink(srcname)
201                if os.path.exists(dstname):
202                    if os.path.islink(dstname):
203                        dstlinkto = os.readlink(dstname)
204                        if linkto != dstlinkto:
205                            log.warning('copying tree: update of link does not match: %s -> %s' % \
206                                            (dstname, dstlinkto))
207                            os.remove(dstname)
208                    else:
209                        log.warning('copying tree: destination is not a link: %s' % \
210                                        (dstname))
211                        os.remove(dstname)
212                else:
213                    os.symlink(linkto, dstname)
214            elif os.path.isdir(srcname):
215                copy_tree(srcname, dstname)
216            else:
217                shutil.copy2(srcname, dstname)
[04a5204]218        except shutil.Error as err:
[50fdf12]219            raise error.general('copying tree: %s -> %s: %s' % (src, dst, str(err)))
[04a5204]220        except EnvironmentError as why:
[50fdf12]221            raise error.general('copying tree: %s -> %s: %s' % (srcname, dstname, str(why)))
222    try:
223        shutil.copystat(src, dst)
[04a5204]224    except OSError as why:
[50fdf12]225        ok = False
226        if windows:
227            if WindowsError is not None and isinstance(why, WindowsError):
228                ok = True
229        if not ok:
230            raise error.general('copying tree: %s -> %s: %s' % (src, dst, str(why)))
231
232if __name__ == '__main__':
[04a5204]233    print(host('/a/b/c/d-e-f'))
234    print(host('//a/b//c/d-e-f'))
235    print(shell('/w/x/y/z'))
236    print(basename('/as/sd/df/fg/me.txt'))
237    print(dirname('/as/sd/df/fg/me.txt'))
238    print(join('/d', 'g', '/tyty/fgfg'))
[50fdf12]239    windows = True
[04a5204]240    print(host('/a/b/c/d-e-f'))
241    print(host('//a/b//c/d-e-f'))
242    print(shell('/w/x/y/z'))
243    print(shell('w:/x/y/z'))
244    print(basename('x:/sd/df/fg/me.txt'))
245    print(dirname('x:/sd/df/fg/me.txt'))
246    print(join('s:/d/', '/g', '/tyty/fgfg'))
Note: See TracBrowser for help on using the repository browser.