Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(346)

Unified Diff: recipes.py

Issue 2237593002: Add support for operational arguments protobuf. (Closed) Base URL: https://github.com/luci/recipes-py@proto3-release
Patch Set: Comment for oneof map. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « recipe_engine/arguments_pb2.py ('k') | unittests/recipes_py_test.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: recipes.py
diff --git a/recipes.py b/recipes.py
index d78d4abf9bb7d119c6bccdadce671b049b6d95a1..a278e1000c231e87daf68d2e2664f2a8870cb928 100755
--- a/recipes.py
+++ b/recipes.py
@@ -20,6 +20,8 @@ ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, ROOT_DIR)
from recipe_engine import env
+from recipe_engine import arguments_pb2
+from google.protobuf import json_format as jsonpb
def get_package_config(args):
from recipe_engine import package
@@ -84,7 +86,7 @@ def handle_recipe_return(recipe_result, result_filename, stream_engine):
return 0
-def run(package_deps, args):
+def run(package_deps, args, op_args):
from recipe_engine import run as recipe_run
from recipe_engine import loader
from recipe_engine import step_runner
@@ -108,14 +110,24 @@ def run(package_deps, args):
def get_properties_from_json(props):
return json.loads(props)
+ def get_properties_from_operational_args(op_args):
+ if not op_args.properties.property:
+ return None
+ return _op_properties_to_dict(op_args.properties.property)
+
+
arg_properties = get_properties_from_args(args.props)
+ op_properties = get_properties_from_operational_args(op_args)
assert len(filter(bool,
- [arg_properties, args.properties_file, args.properties])) <= 1, (
+ (arg_properties, args.properties_file, args.properties,
+ op_properties))) <= 1, (
'Only one source of properties is allowed')
if args.properties:
properties = get_properties_from_json(args.properties)
elif args.properties_file:
properties = get_properties_from_file(args.properties_file)
+ elif op_properties is not None:
+ properties = op_properties
else:
properties = arg_properties
@@ -139,7 +151,9 @@ def run(package_deps, args):
os.chdir(workdir)
stream_engine = stream.ProductStreamEngine(
stream.StreamEngineInvariants(),
- stream.AnnotatorStreamEngine(sys.stdout, emit_timestamps=args.timestamps))
+ stream.AnnotatorStreamEngine(
+ sys.stdout, emit_timestamps=(args.timestamps or
+ op_args.annotation_flags.emit_timestamp)))
with stream_engine:
try:
ret = recipe_run.run_steps(
@@ -228,6 +242,47 @@ def info(args):
print package_spec.recipes_path
+# Map of arguments_pb2.Property "value" oneof conversion functions.
+#
+# The fields here should be kept in sync with the "value" oneof field names in
+# the arguments_pb2.Arguments.Property protobuf message.
+_OP_PROPERTY_CONV = {
+ 's': lambda prop: prop.s,
+ 'int': lambda prop: prop.int,
+ 'uint': lambda prop: prop.uint,
+ 'd': lambda prop: prop.d,
+ 'b': lambda prop: prop.b,
+ 'data': lambda prop: prop.data,
+ 'map': lambda prop: _op_properties_to_dict(prop.map.property),
+ 'list': lambda prop: [_op_property_value(v) for v in prop.list.property],
+}
+
+def _op_property_value(prop):
+ """Returns the Python-converted value of an arguments_pb2.Property.
+
+ Args:
+ prop (arguments_pb2.Property): property to convert.
+ Returns: The converted value.
+ Raises:
+ ValueError: If "prop" is incomplete or invalid.
+ """
+ typ = prop.WhichOneof('value')
+ conv = _OP_PROPERTY_CONV.get(typ)
+ if not conv:
+ raise ValueError('Unknown property field [%s]' % (typ,))
+ return conv(prop)
+
+
+def _op_properties_to_dict(pmap):
+ """Creates a properties dictionary from an arguments_pb2.PropertyMap entry.
+
+ Args:
+ pmap (arguments_pb2.PropertyMap): Map to convert to dictionary form.
+ Returns (dict): A dictionary derived from the properties in "pmap".
+ """
+ return dict((k, _op_property_value(pmap[k])) for k in pmap)
+
+
def main():
from recipe_engine import package
@@ -266,6 +321,11 @@ def main():
'--use-bootstrap', action='store_true',
help='Use bootstrap/bootstrap.py to create a isolated python virtualenv'
' with required python dependencies.')
+ parser.add_argument(
+ '--operational-args-path', action='store',
+ help='The path to an operational Arguments file. If provided, this file '
+ 'must contain a JSONPB-encoded Arguments protobuf message, and will '
+ 'be integrated into the runtime parameters.')
subp = parser.add_subparsers()
@@ -407,6 +467,13 @@ def main():
args = parser.parse_args()
+ # Load/parse operational arguments.
+ op_args = arguments_pb2.Arguments()
+ if args.operational_args_path is not None:
+ with open(args.operational_args_path) as fd:
+ data = fd.read()
+ jsonpb.Parse(data, op_args)
+
if args.use_bootstrap and not os.environ.pop('RECIPES_RUN_BOOTSTRAP', None):
subprocess.check_call(
[sys.executable, 'bootstrap/bootstrap.py', '--deps-file',
@@ -455,7 +522,7 @@ def main():
elif args.command == 'lint':
return lint(package_deps, args)
elif args.command == 'run':
- return run(package_deps, args)
+ return run(package_deps, args, op_args)
elif args.command == 'autoroll':
return autoroll(args)
elif args.command == 'depgraph':
« no previous file with comments | « recipe_engine/arguments_pb2.py ('k') | unittests/recipes_py_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698