Skip to content

Commit 04c86e1

Browse files
authored
Merge pull request SCons#4491 from mwichmann/maint/Value
WIP: Updates on Value nodes
2 parents f3bad91 + 9606606 commit 04c86e1

File tree

9 files changed

+108
-84
lines changed

9 files changed

+108
-84
lines changed

.appveyor.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ environment:
3636
matrix:
3737
# Test oldest and newest supported Pythons, and a subset in between.
3838
# Skipping 3.7 and 3.9 at this time
39-
- WINPYTHON: "Python311"
39+
- WINPYTHON: "Python312"
4040

4141
- WINPYTHON: "Python310"
4242

@@ -50,15 +50,15 @@ matrix:
5050
exclude:
5151
# test python 3.6 on Visual Studio 2017 image
5252
- image: Visual Studio 2017
53-
WINPYTHON: "Python311"
53+
WINPYTHON: "Python312"
5454
- image: Visual Studio 2017
5555
WINPYTHON: "Python310"
5656
- image: Visual Studio 2017
5757
WINPYTHON: "Python38"
5858

5959
# test python 3.8 on Visual Studio 2019 image
6060
- image: Visual Studio 2019
61-
WINPYTHON: "Python311"
61+
WINPYTHON: "Python312"
6262
- image: Visual Studio 2019
6363
WINPYTHON: "Python310"
6464
- image: Visual Studio 2019

CHANGES.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ NOTE: 4.3.0 now requires Python 3.6.0 and above. Python 3.5.x is no longer suppo
99

1010
RELEASE VERSION/DATE TO BE FILLED IN LATER
1111

12-
From John Doe:
12+
From Mats Wichmann:
1313

14-
- Whatever John Doe did.
14+
- Updated Value Node docs and tests.
1515

1616

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

RELEASE.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,13 @@ PACKAGING
4646

4747
- List changes in the way SCons is packaged and/or released
4848

49+
4950
DOCUMENTATION
5051
-------------
5152

52-
- List any significant changes to the documentation (not individual
53-
typo fixes, even if they're mentioned in src/CHANGES.txt to give
54-
the contributor credit)
53+
- Updated Value Node docs.
54+
55+
5556

5657
DEVELOPMENT
5758
-----------

SCons/Environment.xml

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3517,33 +3517,22 @@ gltool(env) # adds 'opengl' to the TOOLS variable
35173517
</arguments>
35183518
<summary>
35193519
<para>
3520-
Returns a Node object representing the specified &Python; value. Value
3521-
Nodes can be used as dependencies of targets. If the result of
3522-
calling
3523-
<function>str</function>(<parameter>value</parameter>)
3524-
changes between SCons runs, any targets depending on
3525-
<function>Value</function>(<parameter>value</parameter>)
3526-
will be rebuilt.
3527-
(This is true even when using timestamps to decide if
3528-
files are up-to-date.)
3529-
When using timestamp source signatures, Value Nodes'
3530-
timestamps are equal to the system time when the Node is created.
3520+
Returns a Node object representing the specified &Python;
3521+
<parameter>value</parameter>.
3522+
Value Nodes can be used as dependencies of targets.
3523+
If the string representation of the Value Node
3524+
changes between &SCons; runs, it is considered
3525+
out of date and any targets depending it will be rebuilt.
3526+
Since Value Nodes have no filesystem representation,
3527+
timestamps are not used; the timestamp deciders
3528+
perform the same content-based up to date check.
35313529
</para>
3532-
35333530
<para>
3534-
The returned Value Node object has a
3535-
<function>write</function>()
3536-
method that can be used to "build" a Value Node
3537-
by setting a new value.
35383531
The optional
35393532
<parameter>built_value</parameter>
35403533
argument can be specified
35413534
when the Value Node is created
3542-
to indicate the Node should already be considered
3543-
"built."
3544-
There is a corresponding
3545-
<function>read</function>()
3546-
method that will return the built value of the Node.
3535+
to indicate the Node should already be considered "built."
35473536
</para>
35483537

35493538
<para>
@@ -3553,6 +3542,16 @@ this is advised if the <parameter>value</parameter> parameter
35533542
cannot be converted to a string.
35543543
</para>
35553544

3545+
<para>
3546+
Value Nodes have a
3547+
<methodname>write</methodname>
3548+
method that can be used to "build" a Value Node
3549+
by setting a new value.
3550+
The corresponding
3551+
<methodname>read</methodname>
3552+
method returns the built value of the Node.
3553+
</para>
3554+
35563555
<para>
35573556
<emphasis>Changed in version 4.0:</emphasis>
35583557
the <parameter>name</parameter> parameter was added.
@@ -3562,36 +3561,39 @@ the <parameter>name</parameter> parameter was added.
35623561
Examples:
35633562
</para>
35643563

3564+
<!-- TODO fix second example or replace - still doesn't work -->
35653565
<example_commands>
35663566
env = Environment()
35673567

35683568
def create(target, source, env):
3569-
# A function that will write a 'prefix=$SOURCE'
3570-
# string into the file name specified as the
3571-
# $TARGET.
3569+
"""Action function to create a file from a Value.
3570+
3571+
Writes 'prefix=$SOURCE' into the file name given as $TARGET.
3572+
"""
35723573
with open(str(target[0]), 'wb') as f:
3573-
f.write('prefix=' + source[0].get_contents())
3574+
f.write(b'prefix=' + source[0].get_contents() + b'\n')
35743575

3575-
# Fetch the prefix= argument, if any, from the command
3576-
# line, and use /usr/local as the default.
3576+
# Fetch the prefix= argument, if any, from the command line.
3577+
# Use /usr/local as the default.
35773578
prefix = ARGUMENTS.get('prefix', '/usr/local')
35783579

3579-
# Attach a .Config() builder for the above function action
3580-
# to the construction environment.
3580+
# Attach builder named Config to the construction environment
3581+
# using the 'create' action function above.
35813582
env['BUILDERS']['Config'] = Builder(action=create)
35823583
env.Config(target='package-config', source=Value(prefix))
35833584

35843585
def build_value(target, source, env):
3585-
# A function that "builds" a Python Value by updating
3586-
# the Python value with the contents of the file
3587-
# specified as the source of the Builder call ($SOURCE).
3586+
"""Action function to "build" a Value.
3587+
3588+
Writes contents of $SOURCE into $TARGET, thus updating if it existed.
3589+
"""
35883590
target[0].write(source[0].get_contents())
35893591

35903592
output = env.Value('before')
35913593
input = env.Value('after')
35923594

3593-
# Attach a .UpdateValue() builder for the above function
3594-
# action to the construction environment.
3595+
# Attach a builder named UpdateValue to the construction environment
3596+
# using the 'build_value' action function above.
35953597
env['BUILDERS']['UpdateValue'] = Builder(action=build_value)
35963598
env.UpdateValue(target=Value(output), source=Value(input))
35973599
</example_commands>
@@ -3606,7 +3608,7 @@ env.UpdateValue(target=Value(output), source=Value(input))
36063608
<para>
36073609
Sets up a mapping to define a variant build directory in
36083610
<parameter>variant_dir</parameter>.
3609-
<parameter>src_dir</parameter> may not be underneath
3611+
<parameter>src_dir</parameter> must not be underneath
36103612
<parameter>variant_dir</parameter>.
36113613
A &f-VariantDir; mapping is global, even if called using the
36123614
&f-env-VariantDir; form.

SCons/Node/PythonTests.py

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@
2525

2626
import SCons.Errors
2727
import SCons.Node.Python
28+
from SCons.Script import Depends
2829

2930

3031
class ValueTestCase(unittest.TestCase):
3132
def test_Value(self) -> None:
32-
"""Test creating a Value() object
33-
"""
33+
"""Test creating a Value() object."""
3434
v1 = SCons.Node.Python.Value('a')
3535
assert v1.value == 'a', v1.value
3636

@@ -39,45 +39,50 @@ def test_Value(self) -> None:
3939
assert v2.value == value2, v2.value
4040
assert v2.value is value2, v2.value
4141

42+
# the two nodes are not the same though they have same attributes
4243
assert v1 is not v2
4344
assert v1.value == v2.value
45+
assert v1.name == v2.name
4446

47+
# node takes the built_value if one is supplied.
4548
v3 = SCons.Node.Python.Value('c', 'cb')
4649
assert v3.built_value == 'cb'
4750

4851
def test_build(self) -> None:
49-
"""Test "building" a Value Node
50-
"""
52+
"""Test "building" a Value Node."""
5153
class fake_executor:
5254
def __call__(self, node) -> None:
5355
node.write('faked')
5456

55-
v1 = SCons.Node.Python.Value('b', 'built')
57+
# *built_value* arg means already built, executor will not be called
58+
v1 = SCons.Node.Python.Value('b', built_value='built')
5659
v1.executor = fake_executor()
5760
v1.build()
5861
assert v1.built_value == 'built', v1.built_value
5962

63+
# not built, executor will build it
6064
v2 = SCons.Node.Python.Value('b')
6165
v2.executor = fake_executor()
6266
v2.build()
6367
assert v2.built_value == 'faked', v2.built_value
6468

69+
# test the *name* parameter to refer to the node
6570
v3 = SCons.Node.Python.Value(b'\x00\x0F', name='name')
6671
v3.executor = fake_executor()
6772
v3.build()
68-
assert v3.name == 'name', v3.name
6973
assert v3.built_value == 'faked', v3.built_value
74+
# building the node does not change the name
75+
assert v3.name == 'name', v3.name
7076

7177
def test_read(self) -> None:
72-
"""Test the Value.read() method
73-
"""
78+
"""Test the Value.read() method."""
7479
v1 = SCons.Node.Python.Value('a')
7580
x = v1.read()
7681
assert x == 'a', x
7782

7883
def test_write(self) -> None:
79-
"""Test the Value.write() method
80-
"""
84+
"""Test the Value.write() method."""
85+
# creating the node without built_value does not set it
8186
v1 = SCons.Node.Python.Value('a')
8287
assert v1.value == 'a', v1.value
8388
assert not hasattr(v1, 'built_value')
@@ -87,8 +92,7 @@ def test_write(self) -> None:
8792
assert v1.built_value == 'new', v1.built_value
8893

8994
def test_get_csig(self) -> None:
90-
"""Test calculating the content signature of a Value() object
91-
"""
95+
"""Test calculating the content signature of a Value() object."""
9296
v1 = SCons.Node.Python.Value('aaa')
9397
csig = v1.get_csig(None)
9498
assert csig == 'aaa', csig
@@ -101,8 +105,17 @@ def test_get_csig(self) -> None:
101105
csig = v3.get_csig(None)
102106
assert csig == 'None', csig
103107

104-
105-
108+
# Dependencies: a tree of Value nodes comes back as a single string.
109+
# This may change someday, bot for now:
110+
v1 = SCons.Node.Python.Value('node1')
111+
v2 = SCons.Node.Python.Value('node2')
112+
v3 = SCons.Node.Python.Value('node3')
113+
v4 = SCons.Node.Python.Value('node4')
114+
Depends(v1, [v2, v3])
115+
Depends(v3, v4)
116+
assert v1.read() == 'node1', v1.read
117+
csig = v1.get_csig()
118+
assert csig == 'node1node2node3node4', csig
106119

107120

108121
class ValueNodeInfoTestCase(unittest.TestCase):

SCons/Taskmaster/Job.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,8 @@ def __init__(self, num, stack_size, interrupted) -> None:
278278

279279
try:
280280
prev_size = threading.stack_size(stack_size * 1024)
281-
except AttributeError as e:
282-
# Only print a warning if the stack size has been
283-
# explicitly set.
281+
except RuntimeError as e:
282+
# Only print a warning if the stack size has been explicitly set.
284283
if explicit_stack_size is not None:
285284
msg = "Setting stack size is unsupported by this version of Python:\n " + \
286285
e.args[0]

test/Actions/function.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,6 @@
3939
test.write('SConstruct', r"""
4040
import re
4141
42-
import SCons.Action
43-
import SCons.Builder
44-
4542
options = Variables()
4643
options.AddVariables(
4744
('header', 'Header string (default cell argument)', 'Head:'),
@@ -91,8 +88,8 @@ def foo(b=b):
9188
9289
exec(withClosure % optEnv)
9390
94-
genHeaderBld = SCons.Builder.Builder(
95-
action=SCons.Action.Action(toto(), 'Generating $TARGET', varlist=['ENVDEPS']),
91+
genHeaderBld = Builder(
92+
action=Action(toto(), 'Generating $TARGET', varlist=['ENVDEPS']),
9693
suffix='.gen.h',
9794
)
9895

test/Value/GetContent.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#!/usr/bin/env python
22
#
3-
# __COPYRIGHT__
3+
# SPDX-License-Identifier: MIT
4+
#
5+
# Copyright The SCons Foundation
46
#
57
# Permission is hereby granted, free of charge, to any person obtaining
68
# a copy of this software and associated documentation files (the
@@ -20,9 +22,6 @@
2022
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2123
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2224
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23-
#
24-
25-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
2625

2726
"""
2827
Test the Value node as a build target
@@ -33,18 +32,25 @@
3332
test = TestSCons.TestSCons()
3433

3534
test.write('SConstruct', """
36-
import SCons.Script
35+
import SCons.Node
36+
3737
def null_build(target, source, env):
3838
pass
39+
3940
env = DefaultEnvironment()
40-
env['BUILDERS']['ValueBuilder'] = SCons.Builder.Builder(
41-
action=SCons.Action.Action(null_build),
42-
target_factory=SCons.Node.Python.Value,
43-
)
44-
v = env.ValueBuilder("myvalue",env.Dir("#"))
45-
v[0].get_text_contents()
41+
env['BUILDERS']['ValueBuilder'] = Builder(
42+
action=Action(null_build),
43+
target_factory=SCons.Node.Python.Value,
44+
)
45+
v = env.ValueBuilder("myvalue", env.Dir("#"))
46+
_ = v[0].get_text_contents() # only care it doesn't take exception
4647
""")
4748

4849
test.run()
4950
test.pass_test()
5051

52+
# Local Variables:
53+
# tab-width:4
54+
# indent-tabs-mode:nil
55+
# End:
56+
# vim: set expandtab tabstop=4 shiftwidth=4:

0 commit comments

Comments
 (0)