27
27
28
28
import os .path
29
29
import sys
30
+ from contextlib import suppress
30
31
from functools import cmp_to_key
31
32
from typing import Callable , Sequence
32
33
@@ -58,22 +59,30 @@ class Variable:
58
59
__slots__ = ('key' , 'aliases' , 'help' , 'default' , 'validator' , 'converter' , 'do_subst' )
59
60
60
61
def __lt__ (self , other ):
61
- """Comparison fuction so Variable instances sort."""
62
+ """Comparison fuction so :class:` Variable` instances sort."""
62
63
return self .key < other .key
63
64
64
65
def __str__ (self ) -> str :
65
- """Provide a way to "print" a Variable object."""
66
+ """Provide a way to "print" a :class:` Variable` object."""
66
67
return (
67
- f"({ self .key !r} , { self .aliases } , { self .help !r} , { self .default !r} , "
68
+ f"({ self .key !r} , { self .aliases } , "
69
+ f"help={ self .help !r} , default={ self .default !r} , "
68
70
f"validator={ self .validator } , converter={ self .converter } )"
69
71
)
70
72
71
73
72
74
class Variables :
73
- """A container for multiple Build Variables.
75
+ """A container for Build Variables.
74
76
75
- Includes methods to updates the environment with the variables,
76
- and to render the help text.
77
+ Includes a method to populate the variables with values into a
78
+ construction envirionment, and methods to render the help text.
79
+
80
+ Note that the pubic API for creating a ``Variables`` object is
81
+ :func:`SCons.Script.Variables`, a kind of factory function, which
82
+ defaults to supplying the contents of :attr:`~SCons.Script.ARGUMENTS`
83
+ as the *args* parameter if it was not otherwise given. That is the
84
+ behavior documented in the manpage for ``Variables`` - and different
85
+ from the default if you instantiate this directly.
77
86
78
87
Arguments:
79
88
files: string or list of strings naming variable config scripts
@@ -83,11 +92,15 @@ class Variables:
83
92
instead of a fresh instance. Currently inoperable (default ``False``)
84
93
85
94
.. versionchanged:: 4.8.0
86
- The default for *is_global* changed to ``False`` (previously
87
- ``True`` but it had no effect due to an implementation error).
95
+ The default for *is_global* changed to ``False`` (the previous
96
+ default ``True`` had no effect due to an implementation error).
88
97
89
98
.. deprecated:: 4.8.0
90
99
*is_global* is deprecated.
100
+
101
+ .. versionadded:: NEXT_RELEASE
102
+ The :attr:`defaulted` attribute now lists those variables which
103
+ were filled in from default values.
91
104
"""
92
105
93
106
def __init__ (
@@ -102,15 +115,18 @@ def __init__(
102
115
files = [files ] if files else []
103
116
self .files : Sequence [str ] = files
104
117
self .unknown : dict [str , str ] = {}
118
+ self .defaulted : list [str ] = []
105
119
106
120
def __str__ (self ) -> str :
107
- """Provide a way to "print" a Variables object."""
108
- s = "Variables(\n options=[\n "
109
- for option in self .options :
110
- s += f" { str (option )} ,\n "
111
- s += " ],\n "
112
- s += f" args={ self .args } ,\n files={ self .files } ,\n unknown={ self .unknown } ,\n )"
113
- return s
121
+ """Provide a way to "print" a :class:`Variables` object."""
122
+ opts = ',\n ' .join ((f" { option !s} " for option in self .options ))
123
+ return (
124
+ f"Variables(\n options=[\n { opts } \n ],\n "
125
+ f" args={ self .args } ,\n "
126
+ f" files={ self .files } ,\n "
127
+ f" unknown={ self .unknown } ,\n "
128
+ f" defaulted={ self .defaulted } ,\n )"
129
+ )
114
130
115
131
# lint: W0622: Redefining built-in 'help'
116
132
def _do_add (
@@ -122,7 +138,7 @@ def _do_add(
122
138
converter : Callable | None = None ,
123
139
** kwargs ,
124
140
) -> None :
125
- """Create a Variable and add it to the list.
141
+ """Create a :class:` Variable` and add it to the list.
126
142
127
143
This is the internal implementation for :meth:`Add` and
128
144
:meth:`AddVariables`. Not part of the public API.
@@ -203,9 +219,9 @@ def Add(
203
219
return self ._do_add (key , * args , ** kwargs )
204
220
205
221
def AddVariables (self , * optlist ) -> None :
206
- """Add a list of Build Variables.
222
+ """Add Build Variables.
207
223
208
- Each list element is a tuple/list of arguments to be passed on
224
+ Each *optlist* element is a sequence of arguments to be passed on
209
225
to the underlying method for adding variables.
210
226
211
227
Example::
@@ -223,13 +239,22 @@ def AddVariables(self, *optlist) -> None:
223
239
def Update (self , env , args : dict | None = None ) -> None :
224
240
"""Update an environment with the Build Variables.
225
241
242
+ Collects variables from the input sources which do not match
243
+ a variable description in this object. These are ignored for
244
+ purposes of adding to *env*, but can be retrieved using the
245
+ :meth:`UnknownVariables` method. Also collects variables which
246
+ are set in *env* from the default in a variable description and
247
+ not from the input sources. These are available in the
248
+ :attr:`defaulted` attribute.
249
+
226
250
Args:
227
251
env: the environment to update.
228
252
args: a dictionary of keys and values to update in *env*.
229
253
If omitted, uses the saved :attr:`args`
230
254
"""
231
- # first pull in the defaults
255
+ # first pull in the defaults, except any which are None.
232
256
values = {opt .key : opt .default for opt in self .options if opt .default is not None }
257
+ self .defaulted = list (values )
233
258
234
259
# next set the values specified in any options script(s)
235
260
for filename in self .files :
@@ -256,6 +281,8 @@ def Update(self, env, args: dict | None = None) -> None:
256
281
for option in self .options :
257
282
if arg in option .aliases + [option .key ,]:
258
283
values [option .key ] = value
284
+ with suppress (ValueError ):
285
+ self .defaulted .remove (option .key )
259
286
added = True
260
287
if not added :
261
288
self .unknown [arg ] = value
@@ -269,6 +296,8 @@ def Update(self, env, args: dict | None = None) -> None:
269
296
for option in self .options :
270
297
if arg in option .aliases + [option .key ,]:
271
298
values [option .key ] = value
299
+ with suppress (ValueError ):
300
+ self .defaulted .remove (option .key )
272
301
added = True
273
302
if not added :
274
303
self .unknown [arg ] = value
0 commit comments