From 693b6f94e49f6efee1f65b124102a843abd439a1 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 10 Jan 2022 12:30:14 -0700 Subject: Update manpage bits about env['ENV'] [skip appveyor] Signed-off-by: Mats Wichmann --- SCons/Environment.py | 24 ++++---- SCons/Environment.xml | 153 +++++++++++++++++++++++++++----------------------- 2 files changed, 95 insertions(+), 82 deletions(-) diff --git a/SCons/Environment.py b/SCons/Environment.py index c8cddf7..d0a4baf 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -1279,15 +1279,15 @@ class Base(SubstitutionEnvironment): path = str(self.fs.Dir(path)) return path - def AppendENVPath(self, name, newpath, envname = 'ENV', - sep = os.pathsep, delete_existing=0): - """Append path elements to the path 'name' in the 'ENV' + def AppendENVPath(self, name, newpath, envname='ENV', + sep=os.pathsep, delete_existing=False): + """Append path elements to the path *name* in the *envname* 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 + If *delete_existing* is False, a *newpath* element already in the path will not be moved to the end (it will be left where it is). """ @@ -1302,10 +1302,10 @@ class Base(SubstitutionEnvironment): self._dict[envname][name] = nv - def AppendUnique(self, delete_existing=0, **kw): + def AppendUnique(self, delete_existing=False, **kw): """Append values to existing construction variables in an Environment, if they're not already there. - If delete_existing is 1, removes existing values first, so + If delete_existing is True, removes existing values first, so values move to end. """ kw = copy_non_reserved_keywords(kw) @@ -1756,15 +1756,15 @@ class Base(SubstitutionEnvironment): self.scanner_map_delete(kw) - def PrependENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep, - delete_existing=1): - """Prepend path elements to the path 'name' in the 'ENV' + def PrependENVPath(self, name, newpath, envname='ENV', + sep=os.pathsep, delete_existing=True): + """Prepend path elements to the path *name* in the *envname* 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 + If *delete_existing* is False, a *newpath* component already in the path will not be moved to the front (it will be left where it is). """ @@ -1780,10 +1780,10 @@ class Base(SubstitutionEnvironment): self._dict[envname][name] = nv - def PrependUnique(self, delete_existing=0, **kw): + def PrependUnique(self, delete_existing=False, **kw): """Prepend values to existing construction variables in an Environment, if they're not already there. - If delete_existing is 1, removes existing values first, so + If delete_existing is True, removes existing values first, so values move to front. """ kw = copy_non_reserved_keywords(kw) diff --git a/SCons/Environment.xml b/SCons/Environment.xml index 43e3b25..630d77b 100644 --- a/SCons/Environment.xml +++ b/SCons/Environment.xml @@ -78,49 +78,41 @@ env['BUILDERS']['NewBuilder'] = bld -A dictionary of environment variables -to use when invoking commands. When -&cv-ENV; is used in a command all list -values will be joined using the path separator and any other non-string -values will simply be coerced to a string. -Note that, by default, -&scons; +The execution environment - +a dictionary of environment variables +used when &SCons; invokes external commands +to build targets defined in this &consenv;. +When &cv-ENV; is passed to a command, +all list values are assumed to be path lists and +are joined using the search path separator. +Any other non-string values are coerced to a string. + + + +Note that by default +&SCons; does not -propagate the environment in effect when you -execute -&scons; -to the commands used to build target files. +propagate the environment in effect when you execute +&scons; (the "shell environment") +to the execution environment. This is so that builds will be guaranteed repeatable regardless of the environment variables set at the time &scons; is invoked. - - - -If you want to propagate your -environment variables +If you want to propagate a +shell environment variable to the commands executed to build target files, -you must do so explicitly: - - - -import os -env = Environment(ENV=os.environ.copy()) - - - -Note that you can choose only to propagate -certain environment variables. +you must do so explicitly. A common example is the system PATH environment variable, so that &scons; -uses the same utilities +will find utilities the same way as the invoking shell (or other process): @@ -128,6 +120,18 @@ as the invoking shell (or other process): import os env = Environment(ENV={'PATH': os.environ['PATH']}) + + +Although it is usually not recommended, +you can propagate the entire shell environment +in one go: + + + +import os +env = Environment(ENV=os.environ.copy()) + + @@ -645,26 +649,26 @@ See also &f-link-env-AppendUnique;, -Append new path elements to the given path in the -specified external environment (&cv-link-ENV; by default). -This will only add -any particular path once (leaving the last one it encounters and -ignoring the rest, to preserve path order), -and to help assure this, -will normalize all paths (using -os.path.normpath +Append path elements specified by newpath +to the given search path string or list name +in mapping envname in the &consenv;. +Supplying envname is optional: +the default is the execution environment &cv-link-ENV;. +Optional sep is used as the search path separator, +the default is the platform's separator (os.pathsep). +A path element will only appear once. +Any duplicates in newpath are dropped, +keeping the last appearing (to preserve path order). +If delete_existing +is False (the default) +any addition duplicating an existing path element is ignored; +if delete_existing +is True the existing value will +be dropped and the path element will be added at the end. +To help maintain uniqueness all paths are normalized (using +os.path.normpath and -os.path.normcase). -This can also handle the -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 -delete_existing -is False, then adding a path that already exists -will not move it to the end; it will stay where it is in the list. +os.path.normcase). @@ -683,6 +687,11 @@ print('after:', env['ENV']['INCLUDE']) before: /foo:/biz after: /biz:/foo/bar:/foo + + +See also &f-link-env-PrependENVPath;. + + @@ -1437,10 +1446,11 @@ Find an executable from one or more choices: progs may be a string or a list of strings. Returns the first value from progs that was found, or None. -Executable is searched by checking the paths specified -by env['ENV']['PATH']. +Executable is searched by checking the paths in the execution enviroment +(env['ENV']['PATH']). On Windows systems, additionally applies the filename suffixes found in -env['ENV']['PATHEXT'] +the execution environment +(env['ENV']['PATHEXT']) but will not include any such extension in the return value. &f-env-Detect; is a wrapper around &f-link-env-WhereIs;. @@ -2614,32 +2624,30 @@ and &f-link-env-PrependUnique;. -(name, newpath, [envname, sep, delete_existing]) +(name, newpath, [envname, sep, delete_existing=True]) -Prepend new path elements to the given path in the -specified external environment (&cv-link-ENV; by default). -This will only add -any particular path once (leaving the first one it encounters and -ignoring the rest, to preserve path order), -and to help assure this, -will normalize all paths (using +Prepend path elements specified by newpath +to the given search path string or list name +in mapping envname in the &consenv;. +Supplying envname is optional: +the default is the execution environment &cv-link-ENV;. +Optional sep is used as the search path separator, +the default is the platform's separator (os.pathsep). +A path element will only appear once. +Any duplicates in newpath are dropped, +keeping the first appearing (to preserve path order). +If delete_existing +is False +any addition duplicating an existing path element is ignored; +if delete_existing +is True (the default) the existing value will +be dropped and the path element will be inserted at the beginning. +To help maintain uniqueness all paths are normalized (using os.path.normpath and os.path.normcase). -This can also handle the -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 -delete_existing -is False, -then adding a path that already exists -will not move it to the beginning; -it will stay where it is in the list. @@ -2659,6 +2667,11 @@ print('after:', env['ENV']['INCLUDE']) before: /biz:/foo after: /foo/bar:/foo:/biz + + +See also &f-link-env-AppendENVPath;. + + -- cgit v0.12 From 7915580a6a6b52a5cbc26c2e85d93b96b2a0052c Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 10 Jan 2022 16:15:42 -0700 Subject: sider: typo fix [skip appveyor] Signed-off-by: Mats Wichmann --- SCons/Environment.xml | 2 +- SCons/Tool/tex.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SCons/Environment.xml b/SCons/Environment.xml index 630d77b..e10aef3 100644 --- a/SCons/Environment.xml +++ b/SCons/Environment.xml @@ -1446,7 +1446,7 @@ Find an executable from one or more choices: progs may be a string or a list of strings. Returns the first value from progs that was found, or None. -Executable is searched by checking the paths in the execution enviroment +Executable is searched by checking the paths in the execution environment (env['ENV']['PATH']). On Windows systems, additionally applies the filename suffixes found in the execution environment diff --git a/SCons/Tool/tex.py b/SCons/Tool/tex.py index 3a133b8..d8b694e 100644 --- a/SCons/Tool/tex.py +++ b/SCons/Tool/tex.py @@ -472,7 +472,7 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None shutil.move(resultfilename,str(target[0])) # Original comment (when TEXPICTS was not restored): - # The TEXPICTS enviroment variable is needed by a dvi -> pdf step + # The TEXPICTS environment variable is needed by a dvi -> pdf step # later on Mac OSX so leave it # # It is also used when searching for pictures (implicit dependencies). -- cgit v0.12 From e7a14480894842c3e6474569683da43ec452aac7 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 12 Jan 2022 07:27:12 -0700 Subject: Try pinning rst2pdf to let package build Signed-off-by: Mats Wichmann --- requirements.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index da3daca..9a7d638 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,9 +4,10 @@ # Can be used with twinecheck # See: https://github.com/pypa/readme_renderer readme-renderer -# 3.5.0 is bad. Hold at 3.4.3 for now until 3.5.1 is available -sphinx<3.5.0 +sphinx sphinx_rtd_theme +# recent release causes problems, pin older: +rst2pdf==0.98 lxml==4.6.5 rst2pdf ninja -- cgit v0.12 From 7214b3d0a99f7a1e0072a4a8e94e2816e26d2cbe Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 12 Jan 2022 11:35:50 -0700 Subject: Add unittests for unclear Path append operations Verifies what happens if added paths include duplicates Signed-off-by: Mats Wichmann --- SCons/EnvironmentTests.py | 70 +++++++++++++++++++++++++++++------------------ SCons/UtilTests.py | 24 ++++++++++++---- 2 files changed, 62 insertions(+), 32 deletions(-) diff --git a/SCons/EnvironmentTests.py b/SCons/EnvironmentTests.py index cd36fd2..c505422 100644 --- a/SCons/EnvironmentTests.py +++ b/SCons/EnvironmentTests.py @@ -1696,23 +1696,32 @@ def exists(env): def test_AppendENVPath(self): """Test appending to an ENV path.""" - env1 = self.TestEnvironment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'}, - MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'}) + env1 = self.TestEnvironment( + ENV={'PATH': r'C:\dir\num\one;C:\dir\num\two'}, + MYENV={'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'}, + ) # have to include the pathsep here so that the test will work on UNIX too. - env1.AppendENVPath('PATH',r'C:\dir\num\two', sep = ';') - 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 = ';', delete_existing=1) + env1.AppendENVPath('PATH', r'C:\dir\num\two', sep=';') + env1.AppendENVPath('PATH', r'C:\dir\num\three', sep=';') + env1.AppendENVPath('MYPATH', r'C:\mydir\num\three', 'MYENV', sep=';') + assert ( + env1['ENV']['PATH'] == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three' + ), env1['ENV']['PATH'] + + env1.AppendENVPath('MYPATH', r'C:\mydir\num\three', 'MYENV', sep=';') + env1.AppendENVPath( + 'MYPATH', r'C:\mydir\num\one', 'MYENV', sep=';', delete_existing=1 + ) # this should do nothing since delete_existing is 0 - env1.AppendENVPath('MYPATH',r'C:\mydir\num\three','MYENV', sep = ';') - 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') + assert ( + env1['MYENV']['MYPATH'] == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one' + ), env1['MYENV']['MYPATH'] - test = TestCmd.TestCmd(workdir = '') + test = TestCmd.TestCmd(workdir='') test.subdir('sub1', 'sub2') - p=env1['ENV']['PATH'] - env1.AppendENVPath('PATH','#sub1', sep = ';') - env1.AppendENVPath('PATH',env1.fs.Dir('sub2'), sep = ';') + p = env1['ENV']['PATH'] + env1.AppendENVPath('PATH', '#sub1', sep=';') + env1.AppendENVPath('PATH', env1.fs.Dir('sub2'), sep=';') assert env1['ENV']['PATH'] == p + ';sub1;sub2', env1['ENV']['PATH'] def test_AppendUnique(self): @@ -2357,23 +2366,32 @@ f5: \ def test_PrependENVPath(self): """Test prepending to an ENV path.""" - env1 = self.TestEnvironment(ENV = {'PATH': r'C:\dir\num\one;C:\dir\num\two'}, - MYENV = {'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'}) + env1 = self.TestEnvironment( + ENV={'PATH': r'C:\dir\num\one;C:\dir\num\two'}, + MYENV={'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'}, + ) # have to include the pathsep here so that the test will work on UNIX too. - env1.PrependENVPath('PATH',r'C:\dir\num\two',sep = ';') - 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 = ';') + env1.PrependENVPath('PATH', r'C:\dir\num\two', sep=';') + env1.PrependENVPath('PATH', r'C:\dir\num\three', sep=';') + assert ( + env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one' + ), env1['ENV']['PATH'] + + 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') + env1.PrependENVPath( + 'MYPATH', r'C:\mydir\num\three', 'MYENV', sep=';', delete_existing=0 + ) + assert ( + env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two' + ), env1['MYENV']['MYPATH'] - test = TestCmd.TestCmd(workdir = '') + test = TestCmd.TestCmd(workdir='') test.subdir('sub1', 'sub2') - p=env1['ENV']['PATH'] - env1.PrependENVPath('PATH','#sub1', sep = ';') - env1.PrependENVPath('PATH',env1.fs.Dir('sub2'), sep = ';') + p = env1['ENV']['PATH'] + env1.PrependENVPath('PATH', '#sub1', sep=';') + env1.PrependENVPath('PATH', env1.fs.Dir('sub2'), sep=';') assert env1['ENV']['PATH'] == 'sub2;sub1;' + p, env1['ENV']['PATH'] def test_PrependUnique(self): diff --git a/SCons/UtilTests.py b/SCons/UtilTests.py index 8001d2e..5ed31cb 100644 --- a/SCons/UtilTests.py +++ b/SCons/UtilTests.py @@ -534,10 +534,16 @@ class UtilTestCase(unittest.TestCase): # have to include the pathsep here so that the test will work on UNIX too. p1 = PrependPath(p1, r'C:\dir\num\two', sep=';') p1 = PrependPath(p1, r'C:\dir\num\three', sep=';') + assert p1 == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one', p1 + p2 = PrependPath(p2, r'C:\mydir\num\three', sep=';') p2 = PrependPath(p2, r'C:\mydir\num\one', sep=';') - assert (p1 == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one') - assert (p2 == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two') + assert p2 == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two', p2 + + # check (only) first one is kept if there are dupes in new + p3 = r'C:\dir\num\one' + p3 = PrependPath(p3, r'C:\dir\num\two;C:\dir\num\three;C:\dir\num\two', sep=';') + assert p3 == r'C:\dir\num\two;C:\dir\num\three;C:\dir\num\one', p3 def test_AppendPath(self): """Test appending to a path.""" @@ -546,10 +552,16 @@ class UtilTestCase(unittest.TestCase): # have to include the pathsep here so that the test will work on UNIX too. p1 = AppendPath(p1, r'C:\dir\num\two', sep=';') p1 = AppendPath(p1, r'C:\dir\num\three', sep=';') + assert p1 == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three', p1 + p2 = AppendPath(p2, r'C:\mydir\num\three', sep=';') p2 = AppendPath(p2, r'C:\mydir\num\one', sep=';') - 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') + assert p2 == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one', p2 + + # check (only) last one is kept if there are dupes in new + p3 = r'C:\dir\num\one' + p3 = AppendPath(p3, r'C:\dir\num\two;C:\dir\num\three;C:\dir\num\two', sep=';') + assert p3 == r'C:\dir\num\one;C:\dir\num\three;C:\dir\num\two', p3 def test_PrependPathPreserveOld(self): """Test prepending to a path while preserving old paths""" @@ -557,7 +569,7 @@ class UtilTestCase(unittest.TestCase): # 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') + assert p1 == r'C:\dir\num\three;C:\dir\num\one;C:\dir\num\two', p1 def test_AppendPathPreserveOld(self): """Test appending to a path while preserving old paths""" @@ -565,7 +577,7 @@ class UtilTestCase(unittest.TestCase): # 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') + assert p1 == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three', p1 def test_addPathIfNotExists(self): """Test the AddPathIfNotExists() function""" -- cgit v0.12 From db3b1a5a40b1bc56abbba8970efcd75f7f1f50f9 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 16 Jan 2022 09:12:21 -0700 Subject: Fix rst2pdf/Sphinx problem a better way Our Sphinx config specifies the use of rst2pdf: extensions = [ ... 'rst2pdf.pdfbuilder', ... As of 0.99 we apparently need to declare a pdf stylesheet, even though we don't knowingly use that style. With that change, unpin rst2pdf again. Also upgrade lxml, leaving it pinned to a version with a comment why. Signed-off-by: Mats Wichmann --- doc/sphinx/conf.py | 4 ++++ requirements.txt | 7 ++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/doc/sphinx/conf.py b/doc/sphinx/conf.py index d6d0778..9db9095 100644 --- a/doc/sphinx/conf.py +++ b/doc/sphinx/conf.py @@ -59,6 +59,10 @@ napoleon_include_private_with_doc = True # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] +# Since 0.99, rst2pdf says: "twoColumn isn't part of the default styles +# in 0.99. You need to add the twocolumn style file." +pdf_stylesheets = ['twocolumn'] + # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # diff --git a/requirements.txt b/requirements.txt index 9a7d638..1be070c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,9 +6,10 @@ readme-renderer sphinx sphinx_rtd_theme -# recent release causes problems, pin older: -rst2pdf==0.98 -lxml==4.6.5 +rst2pdf +# for now keep pinning "known working" lxml, +# it's been a troublesome component in the past. +lxml==4.7.1 rst2pdf ninja -- cgit v0.12