From df7422a008be9236cf7ded05d99704a6b7ce7459 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 23 May 2020 12:07:39 -0600 Subject: Set Tasks class as abstract needs_execut method set as an abstract method, meaning you can't instantiate Task itself, and derived classes must implement the methid. The former warning framework for this (deprecated) is disabled, and some unit tests that were not implementing needs_execute were fixed - by deriving from the AlwaysTask class. Signed-off-by: Mats Wichmann --- CHANGES.txt | 3 ++ SCons/Taskmaster.py | 23 ++++--------- SCons/TaskmasterTests.py | 9 ++--- test/Deprecated/TaskmasterNeedsExecute.py | 53 ------------------------------ test/Removed/BuildDir/README.md | 2 +- test/Removed/CacheDir/README.md | 2 +- test/Removed/Copy-Method/README.md | 2 +- test/Removed/Old/TaskmasterNeedsExecute.py | 53 ++++++++++++++++++++++++++++++ test/Removed/Old/sconstest.skip | 0 test/Removed/README.md | 13 ++++++++ test/Removed/SourceCode/README.md | 2 +- test/Removed/SourceSignatures/README.md | 2 +- test/Removed/TargetSignatures/README.md | 2 +- 13 files changed, 87 insertions(+), 79 deletions(-) delete mode 100644 test/Deprecated/TaskmasterNeedsExecute.py create mode 100644 test/Removed/Old/TaskmasterNeedsExecute.py create mode 100644 test/Removed/Old/sconstest.skip create mode 100644 test/Removed/README.md diff --git a/CHANGES.txt b/CHANGES.txt index ecf3255..f2f3179 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -150,6 +150,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - ParseFlags should not modify the user's passed in dict in case it's a compound data structure (e.g. values are lists) (issue #3665) - In Py3 classes no longer need to be listed as deriving from object. + - Remove deprecated check for Task subclasses needing a needs_execute + method - this is now enforced via an abstract base class, so the + check and test is no longer needed. diff --git a/SCons/Taskmaster.py b/SCons/Taskmaster.py index 147cbcd..bfb7dc1 100644 --- a/SCons/Taskmaster.py +++ b/SCons/Taskmaster.py @@ -54,10 +54,11 @@ __doc__ = """ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -from itertools import chain import operator import sys import traceback +from abc import ABC, abstractmethod +from itertools import chain import SCons.Errors import SCons.Node @@ -115,10 +116,8 @@ def dump_stats(): print((fmt % n.attributes.stats.__dict__) + str(n)) - -class Task: - """ - Default SCons build engine task. +class Task(ABC): + """ SCons build engine abstract task class. This controls the interaction of the actual building of node and the rest of the engine. @@ -210,17 +209,9 @@ class Task: """ return self.node + @abstractmethod def needs_execute(self): - # TODO(deprecate): "return True" is the old default behavior; - # change it to NotImplementedError (after running through the - # Deprecation Cycle) so the desired behavior is explicitly - # determined by which concrete subclass is used. - #raise NotImplementedError - msg = ('Taskmaster.Task is an abstract base class; instead of\n' - '\tusing it directly, ' - 'derive from it and override the abstract methods.') - SCons.Warnings.warn(SCons.Warnings.TaskmasterNeedsExecuteWarning, msg) - return True + return def execute(self): """ @@ -577,7 +568,7 @@ class AlwaysTask(Task): dependencies) can use this as follows: class MyTaskSubclass(SCons.Taskmaster.Task): - needs_execute = SCons.Taskmaster.Task.execute_always + needs_execute = SCons.Taskmaster.AlwaysTask.needs_execute """ return True diff --git a/SCons/TaskmasterTests.py b/SCons/TaskmasterTests.py index 961910a..43a5047 100644 --- a/SCons/TaskmasterTests.py +++ b/SCons/TaskmasterTests.py @@ -291,7 +291,7 @@ class TaskmasterTestCase(unittest.TestCase): built_text = "up to date: " top_node = n3 - class MyTask(SCons.Taskmaster.Task): + class MyTask(SCons.Taskmaster.AlwaysTask): def execute(self): global built_text if self.targets[0].get_state() == SCons.Node.up_to_date: @@ -542,10 +542,11 @@ class TaskmasterTestCase(unittest.TestCase): """ ood = [] def TaskGen(tm, targets, top, node, ood=ood): - class MyTask(SCons.Taskmaster.Task): + class MyTask(SCons.Taskmaster.AlwaysTask): def make_ready(self): SCons.Taskmaster.Task.make_ready(self) self.ood.extend(self.out_of_date) + t = MyTask(tm, targets, top, node) t.ood = ood return t @@ -585,7 +586,7 @@ class TaskmasterTestCase(unittest.TestCase): def test_make_ready_exception(self): """Test handling exceptions from Task.make_ready() """ - class MyTask(SCons.Taskmaster.Task): + class MyTask(SCons.Taskmaster.AlwaysTask): def make_ready(self): raise MyException("from make_ready()") @@ -599,7 +600,7 @@ class TaskmasterTestCase(unittest.TestCase): def test_make_ready_all(self): """Test the make_ready_all() method""" - class MyTask(SCons.Taskmaster.Task): + class MyTask(SCons.Taskmaster.AlwaysTask): make_ready = SCons.Taskmaster.Task.make_ready_all n1 = Node("n1") diff --git a/test/Deprecated/TaskmasterNeedsExecute.py b/test/Deprecated/TaskmasterNeedsExecute.py deleted file mode 100644 index 9f7ade1..0000000 --- a/test/Deprecated/TaskmasterNeedsExecute.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python -# -# __COPYRIGHT__ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -""" -Verify the message about the deprecated Taskmaster.needs_task() -method, and the ability to suppress it. -""" - -import TestSCons - -test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) - -test.write('SConscript', """ -import SCons.Taskmaster -tm = SCons.Taskmaster.Taskmaster() -task = SCons.Taskmaster.Task(tm, [], True, None) -task.needs_execute() -""") - -msg ="""Taskmaster.Task is an abstract base class; instead of -\tusing it directly, derive from it and override the abstract methods.""" -test.deprecated_warning('taskmaster-needs-execute', msg) - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/BuildDir/README.md b/test/Removed/BuildDir/README.md index c4fd879..131e67b 100644 --- a/test/Removed/BuildDir/README.md +++ b/test/Removed/BuildDir/README.md @@ -1,6 +1,6 @@ BuildDir/Old contains old tests which used the now removed BuildDir function, env.BuildDir method, and build_dir argument to SConscript, -preserved here for reference; the presence of an scontest.skip file +preserved here for reference; the presence of an sconstest.skip file means they are never executed. The "new" tests verify failure using these symbols. diff --git a/test/Removed/CacheDir/README.md b/test/Removed/CacheDir/README.md index c5b75bf..46fcbc0 100644 --- a/test/Removed/CacheDir/README.md +++ b/test/Removed/CacheDir/README.md @@ -1,4 +1,4 @@ CacheDir/Old contains old tests of CacheDir which used the now removed SourceSignatures and TargetSignatures methods, preserved here for -reference; the presence of an scontest.skip file means they are never +reference; the presence of an sconstest.skip file means they are never executed. diff --git a/test/Removed/Copy-Method/README.md b/test/Removed/Copy-Method/README.md index 609c6e4..6352522 100644 --- a/test/Removed/Copy-Method/README.md +++ b/test/Removed/Copy-Method/README.md @@ -2,5 +2,5 @@ Copy-Method.py is the "new" test for env.Copy, making sure we get an AttributeError. The Old directory is the former tests from the deprecated state, -preserved here for reference; the presence of an scontest.skip file +preserved here for reference; the presence of an sconstest.skip file means they are never executed. diff --git a/test/Removed/Old/TaskmasterNeedsExecute.py b/test/Removed/Old/TaskmasterNeedsExecute.py new file mode 100644 index 0000000..9f7ade1 --- /dev/null +++ b/test/Removed/Old/TaskmasterNeedsExecute.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify the message about the deprecated Taskmaster.needs_task() +method, and the ability to suppress it. +""" + +import TestSCons + +test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) + +test.write('SConscript', """ +import SCons.Taskmaster +tm = SCons.Taskmaster.Taskmaster() +task = SCons.Taskmaster.Task(tm, [], True, None) +task.needs_execute() +""") + +msg ="""Taskmaster.Task is an abstract base class; instead of +\tusing it directly, derive from it and override the abstract methods.""" +test.deprecated_warning('taskmaster-needs-execute', msg) + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/Old/sconstest.skip b/test/Removed/Old/sconstest.skip new file mode 100644 index 0000000..e69de29 diff --git a/test/Removed/README.md b/test/Removed/README.md new file mode 100644 index 0000000..be3f9b9 --- /dev/null +++ b/test/Removed/README.md @@ -0,0 +1,13 @@ +This tree contains tests for formerly deprecated behaviors +that have since been removed. + +If there is a runnable test (i.e. a test that verifies a +particular old behavior actually fails if called), it is +here or in a subdirectory and is left selectable by the +test framework. + +If there is a test that cannot be run, it will be in a +subdirectory named Old, which will contain a sconstest.skip +file, ensuring those test files are never loaded by the +test framework. + diff --git a/test/Removed/SourceCode/README.md b/test/Removed/SourceCode/README.md index c584dc9..61feaad 100644 --- a/test/Removed/SourceCode/README.md +++ b/test/Removed/SourceCode/README.md @@ -2,5 +2,5 @@ SourceCode.py is the "new" test for SourceCode making sure we get a NameError. The Old directory is the former tests from the deprecated state, -preserved here for reference; the presence of an scontest.skip file +preserved here for reference; the presence of an sconstest.skip file means they are never executed. diff --git a/test/Removed/SourceSignatures/README.md b/test/Removed/SourceSignatures/README.md index 05d8d05..4714a68 100644 --- a/test/Removed/SourceSignatures/README.md +++ b/test/Removed/SourceSignatures/README.md @@ -2,5 +2,5 @@ SourceSignatures.py is the "new" test, only makes sure scons actually fails in the presence of the method or setoption call. The Old directory is the former tests from the deprecated state, -preserved here for reference; the presence of an scontest.skip file +preserved here for reference; the presence of an sconstest.skip file means they are never executed. diff --git a/test/Removed/TargetSignatures/README.md b/test/Removed/TargetSignatures/README.md index 00a8b6b..db00b8c 100644 --- a/test/Removed/TargetSignatures/README.md +++ b/test/Removed/TargetSignatures/README.md @@ -2,5 +2,5 @@ TargetSignatures.py is the "new" test, only makes sure scons actually fails in the presence of the method or setoption call. The Old directory is the former tests from the deprecated state, -preserved here for reference; the presence of an scontest.skip file +preserved here for reference; the presence of an sconstest.skip file means they are never executed. -- cgit v0.12