Skip to content

Commit 9c97705

Browse files
authored
Merge branch 'master' into maint/py313-re
2 parents 43c6529 + 9beb493 commit 9c97705

File tree

4 files changed

+45
-27
lines changed

4 files changed

+45
-27
lines changed

CHANGES.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
1414
- Updated Value Node docs and tests.
1515
- Python 3.13 compat: re.sub deprecated count, flags as positional args,
1616
caused update-release-info test to fail.
17+
- Dump() with json format selected now recognizes additional compound types
18+
(UserDict and UserList), which improves the detail of the display.
19+
json output is also sorted, to match the default display.
1720

1821

1922
RELEASE 4.7.0 - Sun, 17 Mar 2024 17:22:20 -0700

RELEASE.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ DEPRECATED FUNCTIONALITY
2626
CHANGED/ENHANCED EXISTING FUNCTIONALITY
2727
---------------------------------------
2828

29-
- List modifications to existing features, where the previous behavior
30-
wouldn't actually be considered a bug
29+
- Dump() with json format selected now recognizes additional compound types
30+
(UserDict and UserList), which improves the detail of the display.
31+
json output is also sorted, to match the default display.
3132

3233
FIXES
3334
-----

SCons/Environment.py

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@
3535
import sys
3636
import re
3737
import shlex
38-
from collections import UserDict, deque
38+
from collections import UserDict, UserList, deque
3939
from subprocess import PIPE, DEVNULL
40-
from typing import Optional
40+
from typing import Optional, Sequence
4141

4242
import SCons.Action
4343
import SCons.Builder
@@ -1687,17 +1687,23 @@ def Dictionary(self, *args):
16871687
return dlist
16881688

16891689

1690-
def Dump(self, key=None, format: str='pretty'):
1691-
""" Return construction variables serialized to a string.
1690+
def Dump(self, key: Optional[str] = None, format: str = 'pretty') -> str:
1691+
""" Returns a dump of serialized construction variables.
1692+
1693+
The display formats are intended for humaan readers when
1694+
debugging - none of the supported formats produce a result that
1695+
SCons itself can directly make use of. Objects that cannot
1696+
directly be represented get a placeholder like
1697+
``<function foo at 0x123456>`` or ``<<non-serializable: function>>``.
16921698
16931699
Args:
1694-
key (optional): if None, format the whole dict of variables.
1695-
Else format the value of `key` (Default value = None)
1696-
format (str, optional): specify the format to serialize to.
1697-
`"pretty"` generates a pretty-printed string,
1698-
`"json"` a JSON-formatted string.
1699-
(Default value = `"pretty"`)
1700+
key: if ``None``, format the whole dict of variables,
1701+
else format just the value of *key*.
1702+
format: specify the format to serialize to. ``"pretty"`` generates
1703+
a pretty-printed string, ``"json"`` a JSON-formatted string.
17001704
1705+
Raises:
1706+
ValueError: *format* is not a recognized serialization format.
17011707
"""
17021708
if key:
17031709
cvars = self.Dictionary(key)
@@ -1707,9 +1713,9 @@ def Dump(self, key=None, format: str='pretty'):
17071713
fmt = format.lower()
17081714

17091715
if fmt == 'pretty':
1710-
import pprint
1711-
pp = pprint.PrettyPrinter(indent=2)
1716+
import pprint # pylint: disable=import-outside-toplevel
17121717

1718+
pp = pprint.PrettyPrinter(indent=2)
17131719
# TODO: pprint doesn't do a nice job on path-style values
17141720
# if the paths contain spaces (i.e. Windows), because the
17151721
# algorithm tries to break lines on spaces, while breaking
@@ -1718,26 +1724,33 @@ def Dump(self, key=None, format: str='pretty'):
17181724
return pp.pformat(cvars)
17191725

17201726
elif fmt == 'json':
1721-
import json
1722-
def non_serializable(obj):
1723-
return '<<non-serializable: %s>>' % type(obj).__qualname__
1724-
return json.dumps(cvars, indent=4, default=non_serializable)
1727+
import json # pylint: disable=import-outside-toplevel
1728+
1729+
class DumpEncoder(json.JSONEncoder):
1730+
"""SCons special json Dump formatter."""
1731+
def default(self, obj):
1732+
if isinstance(obj, (UserList, UserDict)):
1733+
return obj.data
1734+
return f'<<non-serializable: {type(obj).__qualname__}>>'
1735+
1736+
return json.dumps(cvars, indent=4, cls=DumpEncoder, sort_keys=True)
17251737
else:
17261738
raise ValueError("Unsupported serialization format: %s." % fmt)
17271739

17281740

1729-
def FindIxes(self, paths, prefix, suffix):
1730-
"""Search a list of paths for something that matches the prefix and suffix.
1741+
def FindIxes(self, paths: Sequence[str], prefix: str, suffix: str) -> Optional[str]:
1742+
"""Search *paths* for a path that has *prefix* and *suffix*.
17311743
1732-
Args:
1733-
paths: the list of paths or nodes.
1734-
prefix: construction variable for the prefix.
1735-
suffix: construction variable for the suffix.
1744+
Returns on first match.
17361745
1737-
Returns: the matched path or None
1746+
Arguments:
1747+
paths: the list of paths or nodes.
1748+
prefix: construction variable for the prefix.
1749+
suffix: construction variable for the suffix.
17381750
1751+
Returns:
1752+
The matched path or ``None``
17391753
"""
1740-
17411754
suffix = self.subst('$'+suffix)
17421755
prefix = self.subst('$'+prefix)
17431756

SCons/EnvironmentTests.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3182,7 +3182,8 @@ def test_Dump(self) -> None:
31823182
assert len(env.Dump()) > 200, env.Dump() # no args version
31833183

31843184
assert env.Dump('FOO', 'json') == '"foo"' # JSON key version
3185-
self.assertEqual(env.Dump('FOOFLAGS', 'json'), '"<<non-serializable: CLVar>>"')
3185+
expect = """[\n "--bar",\n "--baz"\n]"""
3186+
self.assertEqual(env.Dump('FOOFLAGS', 'json'), expect)
31863187
import json
31873188
env_dict = json.loads(env.Dump(format = 'json'))
31883189
assert env_dict['FOO'] == 'foo' # full JSON version

0 commit comments

Comments
 (0)