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

Side by Side Diff: recipe_engine/util.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: Address comments. 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-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 contextlib 5 import contextlib
6 import functools 6 import functools
7 import os 7 import os
8 import sys 8 import sys
9 import traceback 9 import traceback
10 import urllib 10 import urllib
(...skipping 17 matching lines...) Expand all
28 raise ModuleInjectionError( 28 raise ModuleInjectionError(
29 "RecipeApi has no dependency %r. (Add it to DEPS?)" % (key,)) 29 "RecipeApi has no dependency %r. (Add it to DEPS?)" % (key,))
30 else: 30 else:
31 raise ModuleInjectionError( 31 raise ModuleInjectionError(
32 "Recipe Module %r has no dependency %r. (Add it to __init__.py:DEPS?)" 32 "Recipe Module %r has no dependency %r. (Add it to __init__.py:DEPS?)"
33 % (self.owner_module.name, key)) 33 % (self.owner_module.name, key))
34 34
35 35
36 class Placeholder(object): 36 class Placeholder(object):
37 """Base class for command line argument placeholders. Do not use directly.""" 37 """Base class for command line argument placeholders. Do not use directly."""
38 def __init__(self): 38 def __init__(self, name=None):
39 self.name_pieces = None 39 if name is not None:
40 assert isinstance(name, basestring)
41 self.name = name
42 self.namespaces = None
40 43
41 @property 44 @property
42 def backing_file(self): # pragma: no cover 45 def backing_file(self): # pragma: no cover
43 """Return path to a temp file that holds or receives the data. 46 """Return path to a temp file that holds or receives the data.
44 47
45 Valid only after 'render' has been called. 48 Valid only after 'render' has been called.
46 """ 49 """
47 raise NotImplementedError 50 raise NotImplementedError
48 51
49 def render(self, test): # pragma: no cover 52 def render(self, test): # pragma: no cover
50 """Return [cmd items]*""" 53 """Return [cmd items]*"""
51 raise NotImplementedError 54 raise NotImplementedError
52 55
53 def result(self, presentation, test): 56 def result(self, presentation, test):
54 """Called after step completion. 57 """Called after step completion.
55 58
56 Args: 59 Args:
57 presentation (StepPresentation) - for the current step. 60 presentation (StepPresentation) - for the current step.
58 test (PlaceholderTestData) - test data for this placeholder. 61 test (PlaceholderTestData) - test data for this placeholder.
59 62
60 May optionally modify presentation as a side-effect. 63 May optionally modify presentation as a side-effect.
61 """ 64 """
62 pass 65 pass
63 66
64 @property 67 @property
65 def name(self): 68 def label(self):
66 assert self.name_pieces 69 if self.name is None:
67 return "%s.%s" % self.name_pieces 70 return "%s.%s" % self.namespaces
iannucci 2016/03/22 22:54:24 %s.%s[DEFAULT] maybe?
stgao 2016/03/22 23:40:25 Maybe not, this will change the current behavior i
71 else:
72 return "%s.%s[%s]" % (self.namespaces[0], self.namespaces[1], self.name)
68 73
69 74
70 class InputPlaceholder(Placeholder): 75 class InputPlaceholder(Placeholder):
76 """Base class for json/raw_io input placeholders. Do not use directly."""
77 def result(self, presentation, test):
78 """Returned value will be discarded."""
79 pass
80 result.__doc__ = Placeholder.result.__doc__
81
82
83 class OutputPlaceholder(Placeholder):
84 """Base class for json/raw_io output placeholders. Do not use directly."""
85
86 def result(self, presentation, test):
87 """Returned value will be added to the step result."""
88 pass
89 result.__doc__ = Placeholder.result.__doc__
90
91
92 class InputPlaceholder(Placeholder):
71 """Base class for json/raw_io input placeholders. Do not use directly.""" 93 """Base class for json/raw_io input placeholders. Do not use directly."""
72 def result(self, presentation, test): 94 def result(self, presentation, test):
73 """Returned value will be discarded.""" 95 """Returned value will be discarded."""
74 pass 96 pass
75 result.__doc__ = Placeholder.result.__doc__ 97 result.__doc__ = Placeholder.result.__doc__
76 98
77 99
78 class OutputPlaceholder(Placeholder): 100 class OutputPlaceholder(Placeholder):
79 """Base class for json/raw_io output placeholders. Do not use directly.""" 101 """Base class for json/raw_io output placeholders. Do not use directly."""
80 def result(self, presentation, test): 102 def result(self, presentation, test):
(...skipping 25 matching lines...) Expand all
106 return func.__get__(obj).__name__ 128 return func.__get__(obj).__name__
107 else: 129 else:
108 return func.__name__ 130 return func.__name__
109 131
110 132
111 def returns_placeholder(func): 133 def returns_placeholder(func):
112 @static_wraps(func) 134 @static_wraps(func)
113 def inner(self, *args, **kwargs): 135 def inner(self, *args, **kwargs):
114 ret = static_call(self, func, *args, **kwargs) 136 ret = static_call(self, func, *args, **kwargs)
115 assert isinstance(ret, Placeholder) 137 assert isinstance(ret, Placeholder)
116 ret.name_pieces = (self.name, static_name(self, func)) 138 ret.namespaces = (self.name, static_name(self, func))
117 return ret 139 return ret
118 # prevent this placeholder-returning function from becoming a composite_step. 140 # prevent this placeholder-returning function from becoming a composite_step.
119 inner._non_step = True # pylint: disable=protected-access 141 inner._non_step = True # pylint: disable=protected-access
120 return inner 142 return inner
121 143
122 144
123 def scan_directory(path, predicate): 145 def scan_directory(path, predicate):
124 """Recursively scans a directory and yields paths that match predicate.""" 146 """Recursively scans a directory and yields paths that match predicate."""
125 for root, _dirs, files in os.walk(path): 147 for root, _dirs, files in os.walk(path):
126 for file_name in (f for f in files if predicate(f)): 148 for file_name in (f for f in files if predicate(f)):
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 self.lines[-1].write(s) 200 self.lines[-1].write(s)
179 break 201 break
180 self.lines[-1].write(s[:i]) 202 self.lines[-1].write(s[:i])
181 self.lines[-1] = self.lines[-1].getvalue() 203 self.lines[-1] = self.lines[-1].getvalue()
182 self.lines.append(StringIO()) 204 self.lines.append(StringIO())
183 s = s[i+1:] 205 s = s[i+1:]
184 206
185 def close(self): 207 def close(self):
186 if not isinstance(self.lines[-1], basestring): 208 if not isinstance(self.lines[-1], basestring):
187 self.lines[-1] = self.lines[-1].getvalue() 209 self.lines[-1] = self.lines[-1].getvalue()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698