Skip to content

Commit ba0934a

Browse files
authored
Merge branch 'master' into exception-convert
2 parents 3d47e1a + 37c7473 commit ba0934a

14 files changed

+181
-136
lines changed

CHANGES.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
6666
- Improved the conversion of a "foreign" exception from an action
6767
into BuildError by making sure our defaults get applied even in
6868
corner cases. Fixes #4530.
69+
- Restructured API docs build (Sphinx) so main module contents appear
70+
on a given page *before* the submodule docs, not after. Also
71+
tweaked the Util package doc build so it's structured more like the
72+
other packages (a missed part of the transition when it was split).
6973

7074

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

RELEASE.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ DOCUMENTATION
7272
- Updated Value Node docs.
7373
- Update manpage for Tools, and for the TOOL variable.
7474
- Update manpage and user guide for Variables usage.
75+
- Restructured API Docs build so main package contents are listed
76+
before contents of package submodules.
7577

7678

7779

SCons/Debug.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@
2323

2424
"""Code for debugging SCons internal things.
2525
26-
Shouldn't be needed by most users. Quick shortcuts:
26+
Shouldn't be needed by most users. Quick shortcuts::
2727
28-
from SCons.Debug import caller_trace
29-
caller_trace()
28+
from SCons.Debug import caller_trace
29+
caller_trace()
3030
"""
3131

3232
import atexit

SCons/PathList.py

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
"""Handle lists of directory paths.
2525
26-
These are the path lists that get set as CPPPATH, LIBPATH,
26+
These are the path lists that get set as ``CPPPATH``, ``LIBPATH``,
2727
etc.) with as much caching of data and efficiency as we can, while
2828
still keeping the evaluation delayed so that we Do the Right Thing
2929
(almost) regardless of how the variable is specified.
@@ -47,10 +47,10 @@ def node_conv(obj):
4747
"""
4848
This is the "string conversion" routine that we have our substitutions
4949
use to return Nodes, not strings. This relies on the fact that an
50-
EntryProxy object has a get() method that returns the underlying
51-
Node that it wraps, which is a bit of architectural dependence
52-
that we might need to break or modify in the future in response to
53-
additional requirements.
50+
:class:`~SCons.Node.FS.EntryProxy` object has a ``get()`` method that
51+
returns the underlying Node that it wraps, which is a bit of
52+
architectural dependence that we might need to break or modify in the
53+
future in response to additional requirements.
5454
"""
5555
try:
5656
get = obj.get
@@ -64,34 +64,35 @@ def node_conv(obj):
6464
return result
6565

6666
class _PathList:
67-
"""An actual PathList object."""
67+
"""An actual PathList object.
6868
69-
def __init__(self, pathlist, split=True) -> None:
70-
"""
71-
Initializes a PathList object, canonicalizing the input and
72-
pre-processing it for quicker substitution later.
69+
Initializes a :class:`PathList` object, canonicalizing the input and
70+
pre-processing it for quicker substitution later.
7371
74-
The stored representation of the PathList is a list of tuples
75-
containing (type, value), where the "type" is one of the TYPE_*
76-
variables defined above. We distinguish between:
72+
The stored representation of the :class:`PathList` is a list of tuples
73+
containing (type, value), where the "type" is one of the ``TYPE_*``
74+
variables defined above. We distinguish between:
7775
78-
strings that contain no '$' and therefore need no
79-
delayed-evaluation string substitution (we expect that there
80-
will be many of these and that we therefore get a pretty
81-
big win from avoiding string substitution)
76+
* Strings that contain no ``$`` and therefore need no
77+
delayed-evaluation string substitution (we expect that there
78+
will be many of these and that we therefore get a pretty
79+
big win from avoiding string substitution)
8280
83-
strings that contain '$' and therefore need substitution
84-
(the hard case is things like '${TARGET.dir}/include',
85-
which require re-evaluation for every target + source)
81+
* Strings that contain ``$`` and therefore need substitution
82+
(the hard case is things like ``${TARGET.dir}/include``,
83+
which require re-evaluation for every target + source)
8684
87-
other objects (which may be something like an EntryProxy
88-
that needs a method called to return a Node)
85+
* Other objects (which may be something like an
86+
:class:`~SCons.Node.FS.EntryProxy`
87+
that needs a method called to return a Node)
8988
90-
Pre-identifying the type of each element in the PathList up-front
91-
and storing the type in the list of tuples is intended to reduce
92-
the amount of calculation when we actually do the substitution
93-
over and over for each target.
94-
"""
89+
Pre-identifying the type of each element in the :class:`PathList`
90+
up-front and storing the type in the list of tuples is intended to
91+
reduce the amount of calculation when we actually do the substitution
92+
over and over for each target.
93+
"""
94+
95+
def __init__(self, pathlist, split=True) -> None:
9596
if SCons.Util.is_String(pathlist):
9697
if split:
9798
pathlist = pathlist.split(os.pathsep)
@@ -152,34 +153,33 @@ class PathListCache:
152153
use the same Memoizer pattern that we use elsewhere to count cache
153154
hits and misses, which is very valuable.
154155
155-
Lookup keys in the cache are computed by the _PathList_key() method.
156+
Lookup keys in the cache are computed by the :meth:`_PathList_key` method.
156157
Cache lookup should be quick, so we don't spend cycles canonicalizing
157-
all forms of the same lookup key. For example, 'x:y' and ['x',
158-
'y'] logically represent the same list, but we don't bother to
158+
all forms of the same lookup key. For example, ``x:y`` and ``['x', 'y']``
159+
logically represent the same list, but we don't bother to
159160
split string representations and treat those two equivalently.
160161
(Note, however, that we do, treat lists and tuples the same.)
161162
162163
The main type of duplication we're trying to catch will come from
163164
looking up the same path list from two different clones of the
164-
same construction environment. That is, given
165+
same construction environment. That is, given::
165166
166167
env2 = env1.Clone()
167168
168-
both env1 and env2 will have the same CPPPATH value, and we can
169-
cheaply avoid re-parsing both values of CPPPATH by using the
169+
both ``env1`` and ``env2`` will have the same ``CPPPATH`` value, and we can
170+
cheaply avoid re-parsing both values of ``CPPPATH`` by using the
170171
common value from this cache.
171172
"""
172173
def __init__(self) -> None:
173174
self._memo = {}
174175

175176
def _PathList_key(self, pathlist):
176-
"""
177-
Returns the key for memoization of PathLists.
177+
"""Returns the key for memoization of PathLists.
178178
179179
Note that we want this to be pretty quick, so we don't completely
180180
canonicalize all forms of the same list. For example,
181-
'dir1:$ROOT/dir2' and ['$ROOT/dir1', 'dir'] may logically
182-
represent the same list if you're executing from $ROOT, but
181+
``dir1:$ROOT/dir2`` and ``['$ROOT/dir1', 'dir']`` may logically
182+
represent the same list if you're executing from ``$ROOT``, but
183183
we're not going to bother splitting strings into path elements,
184184
or massaging strings into Nodes, to identify that equivalence.
185185
We just want to eliminate obvious redundancy from the normal
@@ -191,9 +191,10 @@ def _PathList_key(self, pathlist):
191191

192192
@SCons.Memoize.CountDictCall(_PathList_key)
193193
def PathList(self, pathlist, split=True):
194-
"""
195-
Returns the cached _PathList object for the specified pathlist,
196-
creating and caching a new object as necessary.
194+
"""Entry point for getting PathLists.
195+
196+
Returns the cached :class:`_PathList` object for the specified
197+
pathlist, creating and caching a new object as necessary.
197198
"""
198199
pathlist = self._PathList_key(pathlist)
199200
try:
@@ -215,7 +216,8 @@ def PathList(self, pathlist, split=True):
215216

216217
PathList = PathListCache().PathList
217218

218-
219+
# TODO: removing the class object here means Sphinx doesn't pick up its
220+
# docstrings: they're fine for reading here, but are not in API Docs.
219221
del PathListCache
220222

221223
# Local Variables:

SCons/Variables/ListVariable.py

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2222
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2323

24-
"""Variable type for list Variables.
24+
"""Variable type for List Variables.
2525
26-
A 'list' option may either be 'all', 'none' or a list of names
27-
separated by comma. After the option has been processed, the option
26+
A list variable may given as 'all', 'none' or a list of names
27+
separated by comma. After the variable has been processed, the variable
2828
value holds either the named list elements, all list elements or no
2929
list elements at all.
3030
@@ -41,7 +41,7 @@
4141
elems=list_of_libs,
4242
)
4343
)
44-
...
44+
env = Environment(variables=opts)
4545
for lib in list_of_libs:
4646
if lib in env['shared']:
4747
env.SharedObject(...)
@@ -53,14 +53,21 @@
5353
# since elements can occur twice.
5454

5555
import collections
56-
from typing import Tuple, Callable
56+
from typing import Callable, List, Optional, Tuple, Union
5757

5858
import SCons.Util
5959

6060
__all__ = ['ListVariable',]
6161

6262

6363
class _ListVariable(collections.UserList):
64+
"""Internal class holding the data for a List Variable.
65+
66+
The initializer accepts two arguments, the list of actual values
67+
given, and the list of allowable values. Not normally instantiated
68+
by hand, but rather by the ListVariable converter function.
69+
"""
70+
6471
def __init__(self, initlist=None, allowedElems=None) -> None:
6572
if initlist is None:
6673
initlist = []
@@ -88,19 +95,18 @@ def __lt__(self, other):
8895
return NotImplemented
8996

9097
def __str__(self) -> str:
91-
if not len(self):
98+
if not self.data:
9299
return 'none'
93100
self.data.sort()
94101
if self.data == self.allowedElems:
95102
return 'all'
96-
else:
97-
return ','.join(self)
103+
return ','.join(self)
98104

99105
def prepare_to_store(self):
100-
return self.__str__()
106+
return str(self)
101107

102108
def _converter(val, allowedElems, mapdict) -> _ListVariable:
103-
""" """
109+
"""Convert list variables."""
104110
if val == 'none':
105111
val = []
106112
elif val == 'all':
@@ -111,39 +117,57 @@ def _converter(val, allowedElems, mapdict) -> _ListVariable:
111117
notAllowed = [v for v in val if v not in allowedElems]
112118
if notAllowed:
113119
raise ValueError(
114-
"Invalid value(s) for option: %s" % ','.join(notAllowed)
120+
f"Invalid value(s) for option: {','.join(notAllowed)}"
115121
)
116122
return _ListVariable(val, allowedElems)
117123

118124

119125
# def _validator(key, val, env) -> None:
120126
# """ """
121-
# # TODO: write validator for pgk list
127+
# # TODO: write validator for list variable
122128
# pass
123129

124130

125-
def ListVariable(key, help, default, names, map={}) -> Tuple[str, str, str, None, Callable]:
126-
"""Return a tuple describing a list SCons Variable.
127-
128-
The input parameters describe a 'list' option. Returns
129-
a tuple including the correct converter and validator.
130-
The result is usable for input to :meth:`Add`.
131-
132-
*help* will have text appended indicating the legal values
133-
(not including any extra names from *map*).
134-
135-
*map* can be used to map alternative names to the ones in *names* -
136-
that is, a form of alias.
137-
138-
A 'list' option may either be 'all', 'none' or a list of
139-
names (separated by commas).
131+
# lint: W0622: Redefining built-in 'help' (redefined-builtin)
132+
# lint: W0622: Redefining built-in 'map' (redefined-builtin)
133+
def ListVariable(
134+
key,
135+
help: str,
136+
default: Union[str, List[str]],
137+
names: List[str],
138+
map: Optional[dict] = None,
139+
) -> Tuple[str, str, str, None, Callable]:
140+
"""Return a tuple describing a list variable.
141+
142+
The input parameters describe a list variable, where the values
143+
can be one or more from *names* plus the special values ``all``
144+
and ``none``.
145+
146+
Arguments:
147+
key: the name of the list variable.
148+
help: the basic help message. Will have text appended indicating
149+
the allowable values (not including any extra names from *map*).
150+
default: the default value(s) for the list variable. Can be
151+
given as string (possibly comma-separated), or as a list of strings.
152+
``all`` or ``none`` are allowed as *default*.
153+
names: the allowable values. Must be a list of strings.
154+
map: optional dictionary to map alternative names to the ones in
155+
*names*, providing a form of alias. The converter will make
156+
the replacement, names from *map* are not stored and will
157+
not appear in the help message.
158+
159+
Returns:
160+
A tuple including the correct converter and validator. The
161+
result is usable as input to :meth:`~SCons.Variables.Variables.Add`.
140162
"""
141-
names_str = 'allowed names: %s' % ' '.join(names)
163+
if map is None:
164+
map = {}
165+
names_str = f"allowed names: {' '.join(names)}"
142166
if SCons.Util.is_List(default):
143167
default = ','.join(default)
144168
help = '\n '.join(
145169
(help, '(all|none|comma-separated list of names)', names_str))
146-
return (key, help, default, None, lambda val: _converter(val, names, map))
170+
return key, help, default, None, lambda val: _converter(val, names, map)
147171

148172
# Local Variables:
149173
# tab-width:4

SCons/Variables/ListVariableTests.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,8 @@ def test_converter(self) -> None:
101101
x = o.converter('three,ONE,TWO')
102102
assert str(x) == 'all', x
103103

104-
caught = None
105-
try:
104+
with self.assertRaises(ValueError):
106105
x = o.converter('no_match')
107-
except ValueError:
108-
caught = 1
109-
assert caught, "did not catch expected ValueError"
110106

111107
def test_copy(self) -> None:
112108
"""Test copying a ListVariable like an Environment would"""

doc/sphinx/SCons.Node.rst

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
SCons.Node package
22
==================
33

4+
Module contents
5+
---------------
6+
7+
.. automodule:: SCons.Node
8+
:members:
9+
:undoc-members:
10+
:show-inheritance:
11+
12+
413
Submodules
514
----------
615

@@ -27,12 +36,3 @@ SCons.Node.Python module
2736
:members:
2837
:undoc-members:
2938
:show-inheritance:
30-
31-
32-
Module contents
33-
---------------
34-
35-
.. automodule:: SCons.Node
36-
:members:
37-
:undoc-members:
38-
:show-inheritance:

0 commit comments

Comments
 (0)