summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Deegan <bill@baddogconsulting.com>2024-11-14 05:17:03 (GMT)
committerGitHub <noreply@github.com>2024-11-14 05:17:03 (GMT)
commitc1ddbc7fa5e34ae6aba45104e6dfb39ebb08d3eb (patch)
tree31076b6059df2117720836daf6984ff8a20046a1
parentb4d72c716aa98d3cefcf9fcb358429b08ac58114 (diff)
parentc8ebf8ee8393e3471083920ea07387a30aa6ced1 (diff)
downloadSCons-c1ddbc7fa5e34ae6aba45104e6dfb39ebb08d3eb.zip
SCons-c1ddbc7fa5e34ae6aba45104e6dfb39ebb08d3eb.tar.gz
SCons-c1ddbc7fa5e34ae6aba45104e6dfb39ebb08d3eb.tar.bz2
Merge pull request #4633 from mwichmann/feature/Dictionary-dict
Add as_dict flag to env.Dictionary
-rw-r--r--CHANGES.txt4
-rw-r--r--RELEASE.txt4
-rw-r--r--SCons/Environment.py58
-rw-r--r--SCons/Environment.xml71
-rw-r--r--SCons/EnvironmentTests.py20
5 files changed, 100 insertions, 57 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index b75f856..7d6ef00 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -134,6 +134,10 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
- Add a tag to each CacheDir to let systems ignore backing it up
(per https://bford.info/cachedir/). Update the way a CacheDir
is created, since it now has to create two files.
+ - The Dictionary method now has an as_dict flag. If true, Dictionary
+ always returns a dict. The default remains to return different
+ types depending on whether zero, one, or multiple construction
+ variable names are given.
RELEASE 4.8.1 - Tue, 03 Sep 2024 17:22:20 -0700
diff --git a/RELEASE.txt b/RELEASE.txt
index 2cb6638..e71f535 100644
--- a/RELEASE.txt
+++ b/RELEASE.txt
@@ -70,6 +70,10 @@ CHANGED/ENHANCED EXISTING FUNCTIONALITY
(per https://bford.info/cachedir/). Update the way a CacheDir
is created, since it now has to create two files.
+- The Dictionary method now has an as_dict flag. If true, Dictionary
+ always returns a dict. The default remains to return different
+ types depending on whether zero, one, or multiple construction
+
FIXES
-----
diff --git a/SCons/Environment.py b/SCons/Environment.py
index ad50456..0c14468 100644
--- a/SCons/Environment.py
+++ b/SCons/Environment.py
@@ -537,7 +537,7 @@ class SubstitutionEnvironment:
Special note: methods here and in actual child classes might be called
via proxy from an :class:`OverrideEnvironment`, which isn't in the
- Python inheritance chain. Take care that methods called with a *self*
+ class inheritance chain. Take care that methods called with a *self*
that's really an ``OverrideEnvironment`` don't make bad assumptions.
"""
@@ -1708,23 +1708,33 @@ class Base(SubstitutionEnvironment):
return None
- def Dictionary(self, *args: str):
+ def Dictionary(self, *args: str, as_dict: bool = False):
"""Return construction variables from an environment.
Args:
- args (optional): variable names to look up
+ args (optional): construction variable names to select.
+ If omitted, all variables are selected and returned
+ as a dict.
+ as_dict: if true, and *args* is supplied, return the
+ variables and their values in a dict. If false
+ (the default), return a single value as a scalar,
+ or multiple values in a list.
Returns:
- If *args* omitted, the dictionary of all construction variables.
- If one arg, the corresponding value is returned.
- If more than one arg, a list of values is returned.
+ A dictionary of construction variables, or a single value
+ or list of values.
Raises:
KeyError: if any of *args* is not in the construction environment.
+
+ .. versionchanged:: NEXT_RELEASE
+ Added the *as_dict* keyword arg to specify always returning a dict.
"""
if not args:
return self._dict
- dlist = [self._dict[x] for x in args]
+ if as_dict:
+ return {key: self._dict[key] for key in args}
+ dlist = [self._dict[key] for key in args]
if len(dlist) == 1:
return dlist[0]
return dlist
@@ -1754,13 +1764,10 @@ class Base(SubstitutionEnvironment):
If *key* is supplied, a formatted dictionary is generated like the
no-arg case - previously a single *key* displayed just the value.
"""
- if not key:
- cvars = self.Dictionary()
- elif len(key) == 1:
- dkey = key[0]
- cvars = {dkey: self[dkey]}
+ if len(key):
+ cvars = self.Dictionary(*key, as_dict=True)
else:
- cvars = dict(zip(key, self.Dictionary(*key)))
+ cvars = self.Dictionary()
fmt = format.lower()
@@ -2716,28 +2723,29 @@ class OverrideEnvironment(Base):
return False
return key in self.__dict__['__subject']
- def Dictionary(self, *args):
+ def Dictionary(self, *args, as_dict: bool = False):
"""Return construction variables from an environment.
- Returns all the visible variables, or just those in *args* if
- specified. Obtains a Dictionary view of the subject env, then layers
- the overrrides on top, after which any any deleted items are removed.
-
- Returns:
- Like :meth:`Base.Dictionary`, returns a dict if *args* is
- omitted; a single value if there is one arg; else a list of values.
+ Behavior is as described for :class:`SubstitutionEnvironment.Dictionary`
+ but understanda about the override.
Raises:
- KeyError: if any of *args* is not visible in the construction environment.
+ KeyError: if any of *args* is not in the construction environment.
+
+ .. versionchanged: NEXT_RELEASE
+ Added the *as_dict* keyword arg to always return a dict.
"""
- d = self.__dict__['__subject'].Dictionary().copy()
+ d = {}
+ d.update(self.__dict__['__subject'])
d.update(self.__dict__['overrides'])
d = {k: v for k, v in d.items() if k not in self.__dict__['__deleted']}
if not args:
return d
- dlist = [d[x] for x in args]
+ if as_dict:
+ return {key: d[key] for key in args}
+ dlist = [d[key] for key in args]
if len(dlist) == 1:
- dlist = dlist[0]
+ return dlist[0]
return dlist
def items(self):
diff --git a/SCons/Environment.xml b/SCons/Environment.xml
index 403d6b8..bc4c3b7 100644
--- a/SCons/Environment.xml
+++ b/SCons/Environment.xml
@@ -1624,16 +1624,22 @@ but will not include any such extension in the return value.
<scons_function name="Dictionary">
<arguments signature="env">
-([vars])
+([var, ...], [as_dict=])
</arguments>
<summary>
<para>
-Returns a dictionary object
-containing the &consvars; in the &consenv;.
-If there are any arguments specified,
-the values of the specified &consvars;
-are returned as a string (if one
-argument) or as a list of strings.
+Return an object containing &consvars; from
+<parameter>env</parameter>.
+If <parameter>var</parameter> is omitted,
+all the &consvars; with their values
+are returned in a <type>dict</type>.
+If <parameter>var</parameter> is specified,
+and <parameter>as_dict</parameter> is true,
+the specified &consvars; are returned in a <type>dict</type>;
+otherwise (the default, for backwards compatibility),
+values only are returned,
+as a scalar if one <parameter>var</parameter> is given,
+or as a list if multiples.
</para>
<para>
@@ -1648,8 +1654,8 @@ cc_values = env.Dictionary('CC', 'CCFLAGS', 'CCCOM')
<note><para>
The object returned by &f-link-env-Dictionary; should be treated
as a read-only view into the &consvars;.
-Some &consvars; have special internal handling,
-and making changes through the &f-env-Dictionary; object can bypass
+Some &consvars; require special internal handling,
+and modifying them through the &f-env-Dictionary; object can bypass
that handling and cause data inconsistencies.
The primary use of &f-env-Dictionary; is for diagnostic purposes -
it is used widely by test cases specifically because
@@ -1657,6 +1663,11 @@ it bypasses the special handling so that behavior
can be verified.
</para></note>
+<para>
+<emphasis>Changed in NEXT_RELEASE</emphasis>:
+<parameter>as_dict</parameter> added.
+</para>
+
</summary>
</scons_function>
@@ -1702,24 +1713,30 @@ for more information.
<scons_function name="Dump">
<arguments signature="env">
-([key, ...], [format=])
+([var, ...], [format=TYPE])
</arguments>
<summary>
<para>
-Serializes &consvars; from the current &consenv;
-to a string.
-The method supports the following formats specified by
-<parameter>format</parameter>,
-which must be used a a keyword argument:
+Serialize &consvars; from <parameter>env</parameter> to a string.
+If <varname>var</varname> is omitted,
+all the &consvars; are serialized.
+If one or more <varname>var</varname> values are supplied,
+only those variables and their values are serialized.
+</para>
+
+<para>
+The optional <parameter>format</parameter> string
+selects the serialization format:
</para>
<variablelist>
<varlistentry>
<term><literal>pretty</literal></term>
<listitem>
<para>
-Returns a pretty-printed representation of the variables
+Returns a pretty-printed representation
+of the &consvars; - the result will look like a
+&Python; <type>dict</type>
(this is the default).
-The variables will be presented in &Python; dict form.
</para>
</listitem>
</varlistentry>
@@ -1727,31 +1744,25 @@ The variables will be presented in &Python; dict form.
<term><literal>json</literal></term>
<listitem>
<para>
-Returns a JSON-formatted string representation of the variables.
+Returns a JSON-formatted representation of the variables.
The variables will be presented as a JSON object literal,
-the JSON equivalent of a &Python; dict.
+the JSON equivalent of a &Python; <type>dict</type>..
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
-If no <varname>key</varname> is supplied,
-all the &consvars; are serialized.
-If one or more keys are supplied,
-only those keys and their values are serialized.
-</para>
-
-<para>
<emphasis>Changed in NEXT_RELEASE</emphasis>:
More than one <parameter>key</parameter> can be specified.
-The returned string always looks like a dict (or JSON equivalent);
+The returned string always looks like a <type>dict</type>
+(or equivalent in other formats);
previously a single key serialized only the value,
not the key with the value.
</para>
<para>
-This SConstruct:
+Examples: this &SConstruct;
</para>
<example_commands>
@@ -1773,7 +1784,7 @@ will print something like:
</example_commands>
<para>
-While this SConstruct:
+While this &SConstruct;:
</para>
<example_commands>
@@ -2022,7 +2033,7 @@ FindSourceFiles('src')
</example_commands>
<para>
-As you can see build support files (SConstruct in the above example)
+As you can see build support files (&SConstruct; in the above example)
will also be returned by this function.
</para>
</summary>
diff --git a/SCons/EnvironmentTests.py b/SCons/EnvironmentTests.py
index 62238c7..22b9074 100644
--- a/SCons/EnvironmentTests.py
+++ b/SCons/EnvironmentTests.py
@@ -1832,8 +1832,10 @@ def exists(env):
assert env['CCC1'] == 'c1', env['CCC1']
assert env['CCC2'] == ['c2'], env['CCC2']
assert env['DDD1'] == ['a', 'b', 'c'], env['DDD1']
- assert env['LL1'] == [env.Literal('a literal'), \
- env.Literal('b literal')], env['LL1']
+ assert env['LL1'] == [
+ env.Literal('a literal'),
+ env.Literal('b literal'),
+ ], env['LL1']
assert env['LL2'] == [
env.Literal('c literal'),
env.Literal('b literal'),
@@ -2135,6 +2137,13 @@ def generate(env):
xxx, zzz = env.Dictionary('XXX', 'ZZZ')
assert xxx == 'x'
assert zzz == 'z'
+ # added in NEXT_RELEASE: as_dict flag
+ with self.subTest():
+ expect = {'XXX': 'x'}
+ self.assertEqual(env.Dictionary('XXX', as_dict=True), expect)
+ with self.subTest():
+ expect = {'XXX': 'x', 'YYY': 'y'}
+ self.assertEqual(env.Dictionary('XXX', 'YYY', as_dict=True), expect)
assert 'BUILDERS' in env.Dictionary()
assert 'CC' in env.Dictionary()
assert 'CCFLAGS' in env.Dictionary()
@@ -3927,6 +3936,13 @@ class OverrideEnvironmentTestCase(unittest.TestCase,TestEnvironmentFixture):
xxx, yyy = env2.Dictionary('XXX', 'YYY')
assert xxx == 'x2', xxx
assert yyy == 'y', yyy
+ # added in NEXT_VERSION: as_dict flag
+ with self.subTest():
+ expect = {'XXX': 'x3'}
+ self.assertEqual(env3.Dictionary('XXX', as_dict=True), expect)
+ with self.subTest():
+ expect = {'XXX': 'x2', 'YYY': 'y'}
+ self.assertEqual(env2.Dictionary('XXX', 'YYY', as_dict=True), expect)
# test deletion in top override
del env3['XXX']