OLD | NEW |
1 # Copyright 2013-2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2013-2015 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import collections | 5 import collections |
6 import contextlib | 6 import contextlib |
7 import imp | 7 import imp |
8 import inspect | 8 import inspect |
9 import os | 9 import os |
10 import sys | 10 import sys |
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 self._instances = {} | 474 self._instances = {} |
475 | 475 |
476 def instantiate(self, mod): | 476 def instantiate(self, mod): |
477 if mod in self._instances: | 477 if mod in self._instances: |
478 return self._instances[mod] | 478 return self._instances[mod] |
479 deps_dict = { name: self.instantiate(dep) | 479 deps_dict = { name: self.instantiate(dep) |
480 for name, dep in mod.LOADED_DEPS.iteritems() } | 480 for name, dep in mod.LOADED_DEPS.iteritems() } |
481 self._instances[mod] = self._instantiator(mod, deps_dict) | 481 self._instances[mod] = self._instantiator(mod, deps_dict) |
482 return self._instances[mod] | 482 return self._instances[mod] |
483 | 483 |
| 484 |
484 def _invoke_with_properties(callable_obj, all_props, prop_defs, arg_names, | 485 def _invoke_with_properties(callable_obj, all_props, prop_defs, arg_names, |
485 **additional_args): | 486 **additional_args): |
486 """Internal version of invoke_with_properties. | 487 """Internal version of invoke_with_properties. |
487 | 488 |
488 The main difference is it gets passed the argument names as `arg_names`. | 489 The main difference is it gets passed the argument names as `arg_names`. |
489 This allows us to reuse this logic elsewhere, without defining a fake function | 490 This allows us to reuse this logic elsewhere, without defining a fake function |
490 which has arbitrary argument names. | 491 which has arbitrary argument names. |
491 """ | 492 """ |
492 for name, prop in prop_defs.items(): | 493 for name, prop in prop_defs.items(): |
493 if not isinstance(prop, BoundProperty): | 494 if not isinstance(prop, BoundProperty): |
494 raise ValueError( | 495 raise ValueError( |
495 "You tried to invoke {} with an unbound Property {} named {}".format( | 496 "You tried to invoke {} with an unbound Property {} named {}".format( |
496 callable, prop, name)) | 497 callable, prop, name)) |
497 | 498 |
| 499 # Maps parameter names to property names |
| 500 param_name_mapping = { |
| 501 prop.param_name: name for name, prop in prop_defs.iteritems()} |
| 502 |
498 props = [] | 503 props = [] |
499 for arg in arg_names: | 504 |
500 if arg in additional_args: | 505 for param_name in arg_names: |
501 props.append(additional_args.pop(arg)) | 506 if param_name in additional_args: |
| 507 props.append(additional_args.pop(param_name)) |
502 continue | 508 continue |
503 | 509 |
504 if arg not in prop_defs: | 510 if param_name not in param_name_mapping: |
505 raise UndefinedPropertyException( | 511 raise UndefinedPropertyException( |
506 "Missing property definition for '{}'.".format(arg)) | 512 "Missing property definition for parameter '{}'.".format(param_name)) |
507 | 513 |
508 prop = prop_defs[arg] | 514 prop_name = param_name_mapping[param_name] |
| 515 |
| 516 if prop_name not in prop_defs: |
| 517 raise UndefinedPropertyException( |
| 518 "Missing property value for '{}'.".format(prop_name)) |
| 519 |
| 520 prop = prop_defs[prop_name] |
509 props.append(prop.interpret(all_props.get( | 521 props.append(prop.interpret(all_props.get( |
510 prop.param_name, PROPERTY_SENTINEL))) | 522 prop_name, PROPERTY_SENTINEL))) |
511 | 523 |
512 return callable_obj(*props, **additional_args) | 524 return callable_obj(*props, **additional_args) |
513 | 525 |
| 526 |
514 def invoke_with_properties(callable_obj, all_props, prop_defs, | 527 def invoke_with_properties(callable_obj, all_props, prop_defs, |
515 **additional_args): | 528 **additional_args): |
516 """ | 529 """ |
517 Invokes callable with filtered, type-checked properties. | 530 Invokes callable with filtered, type-checked properties. |
518 | 531 |
519 Args: | 532 Args: |
520 callable_obj: The function to call, or class to instantiate. | 533 callable_obj: The function to call, or class to instantiate. |
521 This supports passing in either RunSteps, or a recipe module, | 534 This supports passing in either RunSteps, or a recipe module, |
522 which is a class. | 535 which is a class. |
523 all_props: A dictionary containing all the properties (instances of BoundPro
perty) | 536 all_props: A dictionary containing all the properties (strings) currently |
524 currently defined in the system. | 537 defined in the system. |
525 prop_defs: A dictionary of name to property definitions for this callable. | 538 prop_defs: A dictionary of property name to property definitions |
| 539 (BoundProperty) for this callable. |
526 additional_args: kwargs to pass through to the callable. | 540 additional_args: kwargs to pass through to the callable. |
527 Note that the names of the arguments can correspond to | 541 Note that the names of the arguments can correspond to |
528 positional arguments as well. | 542 positional arguments as well. |
529 | 543 |
530 Returns: | 544 Returns: |
531 The result of calling callable with the filtered properties | 545 The result of calling callable with the filtered properties |
532 and additional arguments. | 546 and additional arguments. |
533 """ | 547 """ |
534 # Check that we got passed BoundProperties, and not Properties | 548 # Check that we got passed BoundProperties, and not Properties |
535 | 549 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
580 modapi = (getattr(mod, 'TEST_API', None) or RecipeTestApi)(module=mod) | 594 modapi = (getattr(mod, 'TEST_API', None) or RecipeTestApi)(module=mod) |
581 for k,v in deps.iteritems(): | 595 for k,v in deps.iteritems(): |
582 setattr(modapi.m, k, v) | 596 setattr(modapi.m, k, v) |
583 return modapi | 597 return modapi |
584 | 598 |
585 mapper = DependencyMapper(instantiator) | 599 mapper = DependencyMapper(instantiator) |
586 api = RecipeTestApi(module=None) | 600 api = RecipeTestApi(module=None) |
587 for k,v in toplevel_deps.iteritems(): | 601 for k,v in toplevel_deps.iteritems(): |
588 setattr(api, k, mapper.instantiate(v)) | 602 setattr(api, k, mapper.instantiate(v)) |
589 return api | 603 return api |
OLD | NEW |