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

Side by Side Diff: recipe_modules/json/api.py

Issue 1773273003: Make output placeholders like json.output index-able by name. (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/recipes-py@master
Patch Set: Rebase uppon https://codereview.chromium.org/1785543004/ Created 4 years, 9 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 unified diff | Download patch
OLDNEW
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 collections 6 import collections
7 import contextlib 7 import contextlib
8 import json 8 import json
9 9
10 from recipe_engine import recipe_api 10 from recipe_engine import recipe_api
11 from recipe_engine import util as recipe_util 11 from recipe_engine import util as recipe_util
12 from recipe_engine import config_types 12 from recipe_engine import config_types
13 13
14 14
15 class JsonOutputPlaceholder(recipe_util.OutputPlaceholder): 15 class JsonOutputPlaceholder(recipe_util.OutputPlaceholder):
16 """JsonOutputPlaceholder is meant to be a placeholder object which, when added 16 """JsonOutputPlaceholder is meant to be a placeholder object which, when added
17 to a step's cmd list, will be replaced by annotated_run with the path to a 17 to a step's cmd list, will be replaced by annotated_run with the path to a
18 temporary file (e.g. /tmp/tmp4lp1qM) which will exist only for the duration of 18 temporary file (e.g. /tmp/tmp4lp1qM) which will exist only for the duration of
19 the step. If the script requires a flag (e.g. --output-json /path/to/file), 19 the step. If the script requires a flag (e.g. --output-json /path/to/file),
20 you must supply that flag yourself in the cmd list. 20 you must supply that flag yourself in the cmd list.
21 21
22 This placeholder can be optionally added when you use the Steps.step() 22 This placeholder can be optionally added when you use the Steps.step()
23 method in this module. 23 method in this module.
24 24
25 FIXME 25 FIXME
26 After the termination of the step, this file is expected to contain a valid 26 After the termination of the step, this file is expected to contain a valid
27 JSON document, which will be set as the json.output for that step in the 27 JSON document, which will be set as the json.output for that step in the
28 step_history OrderedDict passed to your recipe generator. 28 step_history OrderedDict passed to your recipe generator.
29 """ 29 """
30 def __init__(self, api, add_json_log): 30 def __init__(self, api, add_json_log, name=None):
31 self.raw = api.m.raw_io.output('.json') 31 self.raw = api.m.raw_io.output('.json')
32 self.add_json_log = add_json_log 32 self.add_json_log = add_json_log
33 super(JsonOutputPlaceholder, self).__init__() 33 super(JsonOutputPlaceholder, self).__init__(name=name)
34 34
35 @property 35 @property
36 def backing_file(self): 36 def backing_file(self):
37 return self.raw.backing_file 37 return self.raw.backing_file
38 38
39 def render(self, test): 39 def render(self, test):
40 return self.raw.render(test) 40 return self.raw.render(test)
41 41
42 def result(self, presentation, test): 42 def result(self, presentation, test):
43 raw_data = self.raw.result(presentation, test) 43 raw_data = self.raw.result(presentation, test)
44 44
45 valid = False 45 valid = False
46 ret = None 46 ret = None
47 try: 47 try:
48 ret = JsonApi.loads( 48 ret = JsonApi.loads(
49 raw_data, object_pairs_hook=collections.OrderedDict) 49 raw_data, object_pairs_hook=collections.OrderedDict)
50 valid = True 50 valid = True
51 # TypeError is raised when raw_data is None, which can happen if the json 51 # TypeError is raised when raw_data is None, which can happen if the json
52 # file was not created. We then correctly handle this as invalid result. 52 # file was not created. We then correctly handle this as invalid result.
53 except (ValueError, TypeError): # pragma: no cover 53 except (ValueError, TypeError): # pragma: no cover
54 pass 54 pass
55 55
56 if self.add_json_log: 56 if self.add_json_log:
57 key = self.name + ('' if valid else ' (invalid)') 57 key = self.full_name + ('' if valid else ' (invalid)')
58 with contextlib.closing(recipe_util.StringListIO()) as listio: 58 with contextlib.closing(recipe_util.StringListIO()) as listio:
59 json.dump(ret, listio, indent=2, sort_keys=True) 59 json.dump(ret, listio, indent=2, sort_keys=True)
60 presentation.logs[key] = listio.lines 60 presentation.logs[key] = listio.lines
61 61
62 return ret 62 return ret
63 63
64 64
65 class JsonApi(recipe_api.RecipeApi): 65 class JsonApi(recipe_api.RecipeApi):
66 def __init__(self, **kwargs): 66 def __init__(self, **kwargs):
67 super(JsonApi, self).__init__(**kwargs) 67 super(JsonApi, self).__init__(**kwargs)
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 return True 100 return True
101 except Exception: 101 except Exception:
102 return False 102 return False
103 103
104 @recipe_util.returns_placeholder 104 @recipe_util.returns_placeholder
105 def input(self, data): 105 def input(self, data):
106 """A placeholder which will expand to a file path containing <data>.""" 106 """A placeholder which will expand to a file path containing <data>."""
107 return self.m.raw_io.input(self.dumps(data), '.json') 107 return self.m.raw_io.input(self.dumps(data), '.json')
108 108
109 @recipe_util.returns_placeholder 109 @recipe_util.returns_placeholder
110 def output(self, add_json_log=True): 110 def output(self, add_json_log=True, name=None):
111 """A placeholder which will expand to '/tmp/file'.""" 111 """A placeholder which will expand to '/tmp/file'."""
112 return JsonOutputPlaceholder(self, add_json_log) 112 return JsonOutputPlaceholder(self, add_json_log, name=name)
113 113
114 # TODO(you): This method should be in the `file` recipe_module 114 # TODO(you): This method should be in the `file` recipe_module
115 def read(self, name, path, add_json_log=True, **kwargs): 115 def read(self, name, path, add_json_log=True,
116 json_output_name=None, **kwargs):
116 """Returns a step that reads a JSON file.""" 117 """Returns a step that reads a JSON file."""
117 return self.m.python.inline( 118 return self.m.python.inline(
118 name, 119 name,
119 """ 120 """
120 import shutil 121 import shutil
121 import sys 122 import sys
122 shutil.copy(sys.argv[1], sys.argv[2]) 123 shutil.copy(sys.argv[1], sys.argv[2])
123 """, 124 """,
124 args=[path, self.output(add_json_log=add_json_log)], 125 args=[path,
126 self.output(add_json_log=add_json_log, name=json_output_name)],
125 add_python_log=False, 127 add_python_log=False,
126 **kwargs 128 **kwargs
127 ) 129 )
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698