'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.TP
-.RI env.AppendENVPath( name ", " newpath ", [" envname ", " sep ])
+.RI env.AppendENVPath( name ", " newpath ", [" envname ", " sep ", " preserve_old_paths ])
This appends new path elements to the given path in the
specified external environment
.RB ( ENV
case where the given old path variable is a list instead of a
string, in which case a list will be returned instead of a string.
+If
+.I preserve_old_paths
+is 1, then adding a path that already exists
+will not move it to the end; it will stay where it is in the list.
+
Example:
.ES
exists in a repository.
Returns a list of the target Node or Nodes.
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+\" .TP
+\" .RI env.MergeShellPaths( arg ", [" prepend ])
+\" Merges the elements of the specified
+\" .IR arg ,
+\" which must be a dictionary, to the construction
+\" environment's copy of the shell environment
+\" in env['ENV'].
+\" (This is the environment which is passed
+\" to subshells spawned by SCons.)
+\" Note that
+\" .I arg
+\" must be a single value,
+\" so multiple strings must
+\" be passed in as a list,
+\" not as separate arguments to
+\" .BR env.MergeShellPaths ().
+
+\" New values are prepended to the environment variable by default,
+\" unless prepend=0 is specified.
+\" Duplicate values are always eliminated,
+\" since this function calls
+\" .B AppendENVPath
+\" or
+\" .B PrependENVPath
+\" depending on the
+\" .I prepend
+\" argument. See those functions for more details.
+
+\" Examples:
+
+\" .ES
+\" # Prepend a path to the shell PATH.
+\" env.MergeShellPaths({'PATH':'/usr/local/bin'} )
+\" # Append two dirs to the shell INCLUDE.
+\" env.MergeShellPaths({'INCLUDE':['c:/inc1', 'c:/inc2']}, prepend=0 )
+
+.EE
+
'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.TP
.RI env.MergeFlags( arg ", [" unique ])
Merges the specified
.I arg
-values to the construction envrionment's construction variables.
+values to the construction environment's construction variables.
If the
.I arg
argument is not a dictionary,
'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.TP
-.RI env.PrependENVPath( name ", " newpath ", [" envname ", " sep ])
+.RI env.PrependENVPath( name ", " newpath ", [" envname ", " sep ", " preserve_old_paths ])
This appends new path elements to the given path in the
specified external environment
.RB ( ENV
case where the given old path variable is a list instead of a
string, in which case a list will be returned instead of a string.
+If
+.I preserve_old_paths
+is 1, then adding a path that already exists
+will not move it to the beginning;
+it will stay where it is in the list.
+
Example:
.ES
do_parse(arg, do_parse)
return dict
- def MergeFlags(self, args, unique=1):
+ def MergeFlags(self, args, unique=1, dict=None):
"""
- Merge the dict in args into the construction variables. If args
- is not a dict, it is converted into a dict using ParseFlags.
- If unique is not set, the flags are appended rather than merged.
+ Merge the dict in args into the construction variables of this
+ env, or the passed-in dict. If args is not a dict, it is
+ converted into a dict using ParseFlags. If unique is not set,
+ the flags are appended rather than merged.
"""
+ if dict is None:
+ dict = self
if not SCons.Util.is_Dict(args):
args = self.ParseFlags(args)
if not unique:
self[key] = t
return self
+# def MergeShellPaths(self, args, prepend=1):
+# """
+# Merge the dict in args into the shell environment in env['ENV'].
+# Shell path elements are appended or prepended according to prepend.
+
+# Uses Pre/AppendENVPath, so it always appends or prepends uniquely.
+
+# Example: env.MergeShellPaths({'LIBPATH': '/usr/local/lib'})
+# prepends /usr/local/lib to env['ENV']['LIBPATH'].
+# """
+
+# for pathname, pathval in args.items():
+# if not pathval:
+# continue
+# if prepend:
+# apply(self.PrependENVPath, (pathname, pathval))
+# else:
+# apply(self.AppendENVPath, (pathname, pathval))
+
+
# Used by the FindSourceFiles() method, below.
# Stuck here for support of pre-2.2 Python versions.
def build_source(ss, result):
orig[val] = None
self.scanner_map_delete(kw)
- def AppendENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep):
+ def AppendENVPath(self, name, newpath, envname = 'ENV',
+ sep = os.pathsep, delete_existing=1):
"""Append path elements to the path 'name' in the 'ENV'
dictionary for this environment. Will only add any particular
path once, and will normpath and normcase all paths to help
assure this. This can also handle the case where the env
variable is a list instead of a string.
+
+ If delete_existing is 0, a newpath which is already in the path
+ will not be moved to the end (it will be left where it is).
"""
orig = ''
if self._dict.has_key(envname) and self._dict[envname].has_key(name):
orig = self._dict[envname][name]
- nv = SCons.Util.AppendPath(orig, newpath, sep)
+ nv = SCons.Util.AppendPath(orig, newpath, sep, delete_existing)
if not self._dict.has_key(envname):
self._dict[envname] = {}
orig[val] = None
self.scanner_map_delete(kw)
- def PrependENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep):
+ def PrependENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep,
+ delete_existing=1):
"""Prepend path elements to the path 'name' in the 'ENV'
dictionary for this environment. Will only add any particular
path once, and will normpath and normcase all paths to help
assure this. This can also handle the case where the env
variable is a list instead of a string.
+
+ If delete_existing is 0, a newpath which is already in the path
+ will not be moved to the front (it will be left where it is).
"""
orig = ''
if self._dict.has_key(envname) and self._dict[envname].has_key(name):
orig = self._dict[envname][name]
- nv = SCons.Util.PrependPath(orig, newpath, sep)
+ nv = SCons.Util.PrependPath(orig, newpath, sep, delete_existing)
if not self._dict.has_key(envname):
self._dict[envname] = {}
assert env['A'] == ['aaa'], env['A']
assert env['B'] == ['bbb'], env['B']
+# def test_MergeShellPaths(self):
+# """Test the MergeShellPaths() method
+# """
+# env = Environment()
+# env.MergeShellPaths({})
+# assert not env['ENV'].has_key('INCLUDE'), env['INCLUDE']
+# env.MergeShellPaths({'INCLUDE': r'c:\Program Files\Stuff'})
+# assert env['ENV']['INCLUDE'] == r'c:\Program Files\Stuff', env['ENV']['INCLUDE']
+# env.MergeShellPaths({'INCLUDE': r'c:\Program Files\Stuff'})
+# assert env['ENV']['INCLUDE'] == r'c:\Program Files\Stuff', env['ENV']['INCLUDE']
+# env.MergeShellPaths({'INCLUDE': r'xyz'})
+# assert env['ENV']['INCLUDE'] == r'xyz%sc:\Program Files\Stuff'%os.pathsep, env['ENV']['INCLUDE']
+
+# env = Environment()
+# env['ENV']['INCLUDE'] = 'xyz'
+# env.MergeShellPaths({'INCLUDE':['c:/inc1', 'c:/inc2']} )
+# assert env['ENV']['INCLUDE'] == r'c:/inc1%sc:/inc2%sxyz'%(os.pathsep, os.pathsep), env['ENV']['INCLUDE']
+
+# # test prepend=0
+# env = Environment()
+# env.MergeShellPaths({'INCLUDE': r'c:\Program Files\Stuff'}, prepend=0)
+# assert env['ENV']['INCLUDE'] == r'c:\Program Files\Stuff', env['ENV']['INCLUDE']
+# env.MergeShellPaths({'INCLUDE': r'xyz'}, prepend=0)
+# assert env['ENV']['INCLUDE'] == r'c:\Program Files\Stuff%sxyz'%os.pathsep, env['ENV']['INCLUDE']
class BaseTestCase(unittest.TestCase,TestEnvironmentFixture):
env1.AppendENVPath('PATH',r'C:\dir\num\three', sep = ';')
env1.AppendENVPath('MYPATH',r'C:\mydir\num\three','MYENV', sep = ';')
env1.AppendENVPath('MYPATH',r'C:\mydir\num\one','MYENV', sep = ';')
+ # this should do nothing since delete_existing is 0
+ env1.AppendENVPath('MYPATH',r'C:\mydir\num\three','MYENV', sep = ';', delete_existing=0)
assert(env1['ENV']['PATH'] == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three')
assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one')
env1.PrependENVPath('PATH',r'C:\dir\num\three',sep = ';')
env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV',sep = ';')
env1.PrependENVPath('MYPATH',r'C:\mydir\num\one','MYENV',sep = ';')
+ # this should do nothing since delete_existing is 0
+ env1.PrependENVPath('MYPATH',r'C:\mydir\num\three','MYENV', sep = ';', delete_existing=0)
assert(env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one')
assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two')
continue
return None
-def PrependPath(oldpath, newpath, sep = os.pathsep):
+def PrependPath(oldpath, newpath, sep = os.pathsep, delete_existing=1):
"""This prepends newpath elements to the given oldpath. Will only
add any particular path once (leaving the first one it encounters
and ignoring the rest, to preserve path order), and will
Old Path: "/foo/bar:/foo"
New Path: "/biz/boom:/foo"
Result: "/biz/boom:/foo:/foo/bar"
+
+ If delete_existing is 0, then adding a path that exists will
+ not move it to the beginning; it will stay where it is in the
+ list.
"""
orig = oldpath
else:
newpaths = string.split(newpath, sep)
- newpaths = newpaths + paths # prepend new paths
+ if not delete_existing:
+ # First uniquify the old paths, making sure to
+ # preserve the first instance (in Unix/Linux,
+ # the first one wins), and remembering them in normpaths.
+ # Then insert the new paths at the head of the list
+ # if they're not already in the normpaths list.
+ result = []
+ normpaths = []
+ for path in paths:
+ if not path:
+ continue
+ normpath = os.path.normpath(os.path.normcase(path))
+ if normpath not in normpaths:
+ result.append(path)
+ normpaths.append(normpath)
+ newpaths.reverse() # since we're inserting at the head
+ for path in newpaths:
+ if not path:
+ continue
+ normpath = os.path.normpath(os.path.normcase(path))
+ if normpath not in normpaths:
+ result.insert(0, path)
+ normpaths.append(normpath)
+ paths = result
- normpaths = []
- paths = []
- # now we add them only if they are unique
- for path in newpaths:
- normpath = os.path.normpath(os.path.normcase(path))
- if path and not normpath in normpaths:
- paths.append(path)
- normpaths.append(normpath)
+ else:
+ newpaths = newpaths + paths # prepend new paths
+
+ normpaths = []
+ paths = []
+ # now we add them only if they are unique
+ for path in newpaths:
+ normpath = os.path.normpath(os.path.normcase(path))
+ if path and not normpath in normpaths:
+ paths.append(path)
+ normpaths.append(normpath)
if is_list:
return paths
else:
return string.join(paths, sep)
-def AppendPath(oldpath, newpath, sep = os.pathsep):
+def AppendPath(oldpath, newpath, sep = os.pathsep, delete_existing=1):
"""This appends new path elements to the given old path. Will
only add any particular path once (leaving the last one it
encounters and ignoring the rest, to preserve path order), and
Old Path: "/foo/bar:/foo"
New Path: "/biz/boom:/foo"
Result: "/foo/bar:/biz/boom:/foo"
+
+ If delete_existing is 0, then adding a path that exists
+ will not move it to the end; it will stay where it is in the list.
"""
orig = oldpath
else:
newpaths = string.split(newpath, sep)
- newpaths = paths + newpaths # append new paths
- newpaths.reverse()
-
- normpaths = []
- paths = []
- # now we add them only of they are unique
- for path in newpaths:
- normpath = os.path.normpath(os.path.normcase(path))
- if path and not normpath in normpaths:
- paths.append(path)
- normpaths.append(normpath)
-
- paths.reverse()
+ if not delete_existing:
+ # add old paths to result, then
+ # add new paths if not already present
+ # (I thought about using a dict for normpaths for speed,
+ # but it's not clear hashing the strings would be faster
+ # than linear searching these typically short lists.)
+ result = []
+ normpaths = []
+ for path in paths:
+ if not path:
+ continue
+ result.append(path)
+ normpaths.append(os.path.normpath(os.path.normcase(path)))
+ for path in newpaths:
+ if not path:
+ continue
+ normpath = os.path.normpath(os.path.normcase(path))
+ if normpath not in normpaths:
+ result.append(path)
+ normpaths.append(normpath)
+ paths = result
+ else:
+ # start w/ new paths, add old ones if not present,
+ # then reverse.
+ newpaths = paths + newpaths # append new paths
+ newpaths.reverse()
+
+ normpaths = []
+ paths = []
+ # now we add them only if they are unique
+ for path in newpaths:
+ normpath = os.path.normpath(os.path.normcase(path))
+ if path and not normpath in normpaths:
+ paths.append(path)
+ normpaths.append(normpath)
+ paths.reverse()
if is_list:
return paths
assert(p1 == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three')
assert(p2 == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one')
+ def test_PrependPathPreserveOld(self):
+ """Test prepending to a path while preserving old paths"""
+ p1 = r'C:\dir\num\one;C:\dir\num\two'
+ # have to include the pathsep here so that the test will work on UNIX too.
+ p1 = PrependPath(p1,r'C:\dir\num\two',sep = ';', delete_existing=0)
+ p1 = PrependPath(p1,r'C:\dir\num\three',sep = ';')
+ assert(p1 == r'C:\dir\num\three;C:\dir\num\one;C:\dir\num\two')
+
+ def test_AppendPathPreserveOld(self):
+ """Test appending to a path while preserving old paths"""
+ p1 = r'C:\dir\num\one;C:\dir\num\two'
+ # have to include the pathsep here so that the test will work on UNIX too.
+ p1 = AppendPath(p1,r'C:\dir\num\one',sep = ';', delete_existing=0)
+ p1 = AppendPath(p1,r'C:\dir\num\three',sep = ';')
+ assert(p1 == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three')
+
def test_NodeList(self):
"""Test NodeList class"""
class TestClass: