Skip to content

Commit 78e5c31

Browse files
add further checking to Get() arguments to overcome ambiguity that led to test failure
1 parent 6047240 commit 78e5c31

File tree

5 files changed

+51
-11
lines changed

5 files changed

+51
-11
lines changed

src/python/pants/engine/rules.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -392,9 +392,12 @@ def __new__(cls,
392392
)
393393

394394
def __str__(self):
395-
return '({}, {!r}, {})'.format(type_or_constraint_repr(self.output_constraint),
396-
self.input_selectors,
397-
self.func.__name__)
395+
return ('({}, {!r}, {}, gets={}, opts={})'
396+
.format(type_or_constraint_repr(self.output_constraint),
397+
self.input_selectors,
398+
self.func.__name__,
399+
self.input_gets,
400+
self.dependency_optionables))
398401

399402

400403
class SingletonRule(datatype(['output_constraint', 'value']), Rule):

src/python/pants/engine/scheduler.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,6 @@ def run_console_rule(self, product, subject):
510510
"""
511511
:param product: product type for the request.
512512
:param subject: subject for the request.
513-
:param v2_ui: whether to render the v2 engine UI
514513
"""
515514
request = self.execution_request([product], [subject])
516515
returns, throws = self.execute(request)

src/python/pants/engine/selectors.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import ast
88

9-
from pants.util.objects import Exactly, datatype
9+
from pants.util.objects import Exactly, TypeConstraint, datatype
1010

1111

1212
def type_or_constraint_repr(constraint):
@@ -79,16 +79,29 @@ def create_statically_for_rule_graph(cls, product_type, subject_type):
7979
return cls(product_type, subject_type, None)
8080

8181
def __new__(cls, *args):
82-
# TODO(#7114): typecheck the args (as in, ensure they are types or constraints)! After #7114, we
83-
# can just check that they are types.
82+
# TODO(#7114): Use datatype type checking for these fields! We can wait until after #7114, when
83+
# we can just check that they are types.
8484
if len(args) == 2:
8585
product, subject = args
86+
87+
if isinstance(subject, (type, TypeConstraint)):
88+
raise TypeError("""\
89+
The two-argument form of Get does not accept a type as its second argument.
90+
91+
args were: Get({args!r})
92+
93+
Get.create_statically_for_rule_graph() should be used to generate a Get() for
94+
the `input_gets` field of a rule. If you are using a `yield Get(...)` in a rule
95+
and a type was intended, use the 3-argument version:
96+
Get({product!r}, {subject_type!r}, {subject!r})
97+
""".format(args=args, product=product, subject_type=type(subject), subject=subject))
98+
8699
subject_declared_type = type(subject)
87100
elif len(args) == 3:
88101
product, subject_declared_type, subject = args
89102
else:
90-
raise Exception('Expected either two or three arguments to {}; got {}.'.format(
91-
Get.__name__, args))
103+
raise ValueError('Expected either two or three arguments to {}; got {}.'
104+
.format(Get.__name__, args))
92105
return super(Get, cls).__new__(cls, product, subject_declared_type, subject)
93106

94107

src/python/pants/option/optionable.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def signature(cls):
4949
output_type=cls.optionable_cls,
5050
input_selectors=tuple(),
5151
func=partial_construct_optionable,
52-
input_gets=(Get(ScopedOptions, Scope),),
52+
input_gets=(Get.create_statically_for_rule_graph(ScopedOptions, Scope),),
5353
dependency_optionables=(cls.optionable_cls,),
5454
)
5555

tests/python/pants_test/engine/test_selectors.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ class AClass(object):
1616

1717

1818
class BClass(object):
19-
pass
19+
20+
def __eq__(self, other):
21+
return type(self) == type(other)
2022

2123

2224
class SubBClass(BClass):
@@ -33,6 +35,29 @@ def assert_repr(self, expected, selector):
3335

3436

3537
class GetTest(unittest.TestCase):
38+
def test_create(self):
39+
# Test the equivalence of the 2-arg and 3-arg versions.
40+
self.assertEqual(Get(AClass, BClass()),
41+
Get(AClass, BClass, BClass()))
42+
43+
with self.assertRaises(TypeError) as cm:
44+
Get(AClass, BClass)
45+
self.assertEqual("""\
46+
The two-argument form of Get does not accept a type as its second argument.
47+
48+
args were: Get(({a!r}, {b!r}))
49+
50+
Get.create_statically_for_rule_graph() should be used to generate a Get() for
51+
the `input_gets` field of a rule. If you are using a `yield Get(...)` in a rule
52+
and a type was intended, use the 3-argument version:
53+
Get({a!r}, {t!r}, {b!r})
54+
""".format(a=AClass, t=type(BClass), b=BClass), str(cm.exception))
55+
56+
with self.assertRaises(ValueError) as cm:
57+
Get(1)
58+
self.assertEqual("Expected either two or three arguments to Get; got (1,).",
59+
str(cm.exception))
60+
3661
def _get_call_node(self, input_string):
3762
return ast.parse(input_string).body[0].value
3863

0 commit comments

Comments
 (0)