| OLD | NEW |
| 1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 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 functools | 5 import functools |
| 6 import json | 6 import json |
| 7 import os | 7 import os |
| 8 import tempfile | 8 import tempfile |
| 9 | 9 |
| 10 from slave import recipe_api | 10 from slave import recipe_api |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 try: | 48 try: |
| 49 result_data.output = json.loads(raw_data) | 49 result_data.output = json.loads(raw_data) |
| 50 stream.emit('step returned json data: """\n%s\n"""' % | 50 stream.emit('step returned json data: """\n%s\n"""' % |
| 51 (result_data.output,)) | 51 (result_data.output,)) |
| 52 except ValueError: | 52 except ValueError: |
| 53 stream.emit('step had invalid json data: """\n%s\n"""' % | 53 stream.emit('step had invalid json data: """\n%s\n"""' % |
| 54 raw_data) | 54 raw_data) |
| 55 os.unlink(self.output_file) | 55 os.unlink(self.output_file) |
| 56 | 56 |
| 57 | 57 |
| 58 class JsonInputPlaceholder(recipe_api.Placeholder): | |
| 59 """JsonInputPlaceholder is meant to be a non-singleton object which, when | |
| 60 added to a step's cmd list, will be replaced by annotated_run with a | |
| 61 /path/to/json file during the evaluation of your recipe generator. | |
| 62 | |
| 63 The file will have the json-string passed to __init__, and is guaranteed to | |
| 64 exist solely for the duration of the step. | |
| 65 | |
| 66 Multiple instances of thif placeholder can occur in a step's command, and | |
| 67 each will be serialized to a different input file. | |
| 68 """ | |
| 69 __slots__ = ['json_string'] | |
| 70 | |
| 71 def __init__(self, json_string): | |
| 72 assert isinstance(json_string, basestring) | |
| 73 self.json_string = json_string | |
| 74 self.input_file = None | |
| 75 super(JsonInputPlaceholder, self).__init__() | |
| 76 | |
| 77 def render(self, test_data): | |
| 78 if test_data is not None: | |
| 79 # cheat and pretend like we're going to pass the data on the | |
| 80 # cmdline for test expectation purposes. | |
| 81 return [self.json_string] | |
| 82 else: # pragma: no cover | |
| 83 json_input_fd, self.input_file = tempfile.mkstemp() | |
| 84 os.write(json_input_fd, self.json_string) | |
| 85 os.close(json_input_fd) | |
| 86 return [self.input_file] | |
| 87 | |
| 88 def step_finished(self, stream, step_result, test_data): | |
| 89 if test_data is None: # pragma: no cover | |
| 90 os.unlink(self.input_file) | |
| 91 | |
| 92 | |
| 93 class JsonApi(recipe_api.RecipeApi): | 58 class JsonApi(recipe_api.RecipeApi): |
| 94 def __init__(self, **kwargs): | 59 def __init__(self, **kwargs): |
| 95 super(JsonApi, self).__init__(**kwargs) | 60 super(JsonApi, self).__init__(**kwargs) |
| 96 self.loads = json.loads | 61 self.loads = json.loads |
| 97 @functools.wraps(json.dumps) | 62 @functools.wraps(json.dumps) |
| 98 def dumps(*args, **kwargs): | 63 def dumps(*args, **kwargs): |
| 99 kwargs['sort_keys'] = True | 64 kwargs['sort_keys'] = True |
| 100 return json.dumps(*args, **kwargs) | 65 return json.dumps(*args, **kwargs) |
| 101 self.dumps = dumps | 66 self.dumps = dumps |
| 102 | 67 |
| 103 def input(self, data): | 68 def input(self, data): |
| 104 """A placeholder which will expand to a file path containing <data>.""" | 69 """A placeholder which will expand to a file path containing <data>.""" |
| 105 return JsonInputPlaceholder(self.dumps(data)) | 70 return recipe_api.InputDataPlaceholder(self.dumps(data), '.json') |
| 106 | 71 |
| 107 @staticmethod | 72 @staticmethod |
| 108 def output(): | 73 def output(): |
| 109 """A placeholder which will expand to '--output-json /tmp/file'.""" | 74 """A placeholder which will expand to '--output-json /tmp/file'.""" |
| 110 return JsonOutputPlaceholder() | 75 return JsonOutputPlaceholder() |
| 111 | 76 |
| 112 def property_args(self): | 77 def property_args(self): |
| 113 """Return --build-properties and --factory-properties arguments. LEGACY! | 78 """Return --build-properties and --factory-properties arguments. LEGACY! |
| 114 | 79 |
| 115 Since properties is the merge of build_properties and factory_properties, | 80 Since properties is the merge of build_properties and factory_properties, |
| 116 pass the merged dict as both arguments. | 81 pass the merged dict as both arguments. |
| 117 | 82 |
| 118 It's vastly preferable to have your recipe only pass the bare minimum | 83 It's vastly preferable to have your recipe only pass the bare minimum |
| 119 of arguments to steps. Passing property objects obscures the data that | 84 of arguments to steps. Passing property objects obscures the data that |
| 120 the script actually consumes from the property object. | 85 the script actually consumes from the property object. |
| 121 """ | 86 """ |
| 122 prop_str = self.dumps(dict(self.m.properties)) | 87 prop_str = self.dumps(dict(self.m.properties)) |
| 123 return [ | 88 return [ |
| 124 '--factory-properties', prop_str, | 89 '--factory-properties', prop_str, |
| 125 '--build-properties', prop_str | 90 '--build-properties', prop_str |
| 126 ] | 91 ] |
| 127 | 92 |
| OLD | NEW |