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

Side by Side Diff: tools/json_schema_compiler/code.py

Issue 9491002: json_schema_compiler: any, additionalProperties, functions on types (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: remove whitespace Created 8 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 (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 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 class Code(object): 5 class Code(object):
6 """A convenience object for constructing code. 6 """A convenience object for constructing code.
7 7
8 Logically each object should be a block of code. All methods except |Render| 8 Logically each object should be a block of code. All methods except |Render|
9 and |IsEmpty| return self. 9 and |IsEmpty| return self.
10 """ 10 """
11 def __init__(self, indent_size=2, comment_length=80): 11 def __init__(self, indent_size=2, comment_length=80):
12 self._code = [] 12 self._code = []
13 self._substitute = []
13 self._indent_level = 0 14 self._indent_level = 0
14 self._indent_size = indent_size 15 self._indent_size = indent_size
15 self._comment_length = comment_length 16 self._comment_length = comment_length
16 17
17 def Append(self, line=''): 18 def Append(self, line='', substitute=True):
18 """Appends a line of code at the current indent level or just a newline if 19 """Appends a line of code at the current indent level or just a newline if
19 line is not specified. Trailing whitespace is stripped. 20 line is not specified. Trailing whitespace is stripped.
21
22 substitute: indicated whether this line should be affected by
23 code.Substitute().
20 """ 24 """
25 self._substitute.append(substitute)
21 self._code.append(((' ' * self._indent_level) + line).rstrip()) 26 self._code.append(((' ' * self._indent_level) + line).rstrip())
22 return self 27 return self
23 28
24 def IsEmpty(self): 29 def IsEmpty(self):
25 """Returns True if the Code object is empty. 30 """Returns True if the Code object is empty.
26 """ 31 """
27 return not bool(self._code) 32 return not bool(self._code)
28 33
29 def Concat(self, obj): 34 def Concat(self, obj):
30 """Concatenate another Code object onto this one. Trailing whitespace is 35 """Concatenate another Code object onto this one. Trailing whitespace is
31 stripped. 36 stripped.
32 37
33 Appends the code at the current indent level. Will fail if there are any 38 Appends the code at the current indent level. Will fail if there are any
34 un-interpolated format specifiers eg %s, %(something)s which helps 39 un-interpolated format specifiers eg %s, %(something)s which helps
35 isolate any strings that haven't been substituted. 40 isolate any strings that haven't been substituted.
36 """ 41 """
37 if not isinstance(obj, Code): 42 if not isinstance(obj, Code):
38 raise TypeError(type(obj)) 43 raise TypeError(type(obj))
39 assert self is not obj 44 assert self is not obj
40 for line in obj._code: 45 for substitute, line in zip(obj._substitute, obj._code):
Yoyo Zhou 2012/02/28 22:23:41 itertools.izip?
calamity 2012/03/01 04:47:09 Done.
41 try: 46 try:
42 # line % () will fail if any substitution tokens are left in line 47 # line % () will fail if any substitution tokens are left in line
43 self._code.append(((' ' * self._indent_level) + line % ()).rstrip()) 48 if substitute:
49 line %= ()
44 except TypeError: 50 except TypeError:
45 raise TypeError('Unsubstituted value when concatting\n' + line) 51 raise TypeError('Unsubstituted value when concatting\n' + line)
52 except ValueError:
53 raise ValueError('Stray % character when concatting\n' + line)
54 self.Append(line, substitute)
46 55
47 return self 56 return self
48 57
49 def Sblock(self, line=''): 58 def Sblock(self, line=''):
50 """Starts a code block. 59 """Starts a code block.
51 60
52 Appends a line of code and then increases the indent level. 61 Appends a line of code and then increases the indent level.
53 """ 62 """
54 self.Append(line) 63 self.Append(line)
55 self._indent_level += self._indent_size 64 self._indent_level += self._indent_size
56 return self 65 return self
57 66
58 def Eblock(self, line=''): 67 def Eblock(self, line=''):
59 """Ends a code block by decreasing and then appending a line (or a blank 68 """Ends a code block by decreasing and then appending a line (or a blank
60 line if not given). 69 line if not given).
61 """ 70 """
62 # TODO(calamity): Decide if type checking is necessary 71 # TODO(calamity): Decide if type checking is necessary
63 #if not isinstance(line, basestring): 72 #if not isinstance(line, basestring):
64 # raise TypeError 73 # raise TypeError
65 self._indent_level -= self._indent_size 74 self._indent_level -= self._indent_size
66 self.Append(line) 75 self.Append(line)
67 return self 76 return self
68 77
69 # TODO(calamity): Make comment its own class or something and Render at
70 # self.Render() time
71 def Comment(self, comment): 78 def Comment(self, comment):
72 """Adds the given string as a comment. 79 """Adds the given string as a comment.
73 80
74 Will split the comment if it's too long. Use mainly for variable length 81 Will split the comment if it's too long. Use mainly for variable length
75 comments. Otherwise just use code.Append('// ...') for comments. 82 comments. Otherwise just use code.Append('// ...') for comments.
83
84 Unaffected by code.Substitute().
Yoyo Zhou 2012/02/28 22:23:41 You could make substitute a parameter to this func
not at google - send to devlin 2012/02/28 22:41:17 Might a better solution be to just escape all % ch
calamity 2012/03/01 04:47:09 Escaping is a little more tricky that that. Since
calamity 2012/03/01 04:47:09 I think it's safer to disallow that. The problem h
not at google - send to devlin 2012/03/01 07:09:37 Ah, I see the problem. Cool. I think that parall
calamity 2012/03/01 23:58:48 Done.
76 """ 85 """
77 comment_symbol = '// ' 86 comment_symbol = '// '
78 max_len = self._comment_length - self._indent_level - len(comment_symbol) 87 max_len = self._comment_length - self._indent_level - len(comment_symbol)
79 while len(comment) >= max_len: 88 while len(comment) >= max_len:
80 line = comment[0:max_len] 89 line = comment[0:max_len]
81 last_space = line.rfind(' ') 90 last_space = line.rfind(' ')
82 if last_space != -1: 91 if last_space != -1:
83 line = line[0:last_space] 92 line = line[0:last_space]
84 comment = comment[last_space + 1:] 93 comment = comment[last_space + 1:]
85 else: 94 else:
86 comment = comment[max_len:] 95 comment = comment[max_len:]
87 self.Append(comment_symbol + line) 96 self.Append(comment_symbol + line, substitute=False)
88 self.Append(comment_symbol + comment) 97 self.Append(comment_symbol + comment, substitute=False)
89 return self 98 return self
90 99
91 def Substitute(self, d): 100 def Substitute(self, d):
92 """Goes through each line and interpolates using the given dict. 101 """Goes through each line and interpolates using the given dict.
93 102
94 Raises type error if passed something that isn't a dict 103 Raises type error if passed something that isn't a dict
95 104
96 Use for long pieces of code using interpolation with the same variables 105 Use for long pieces of code using interpolation with the same variables
97 repeatedly. This will reduce code and allow for named placeholders which 106 repeatedly. This will reduce code and allow for named placeholders which
98 are more clear. 107 are more clear.
99 """ 108 """
100 if not isinstance(d, dict): 109 if not isinstance(d, dict):
101 raise TypeError('Passed argument is not a dictionary: ' + d) 110 raise TypeError('Passed argument is not a dictionary: ' + d)
102 for i, line in enumerate(self._code): 111 for i, line in enumerate(self._code):
103 # Only need to check %s because arg is a dict and python will allow 112 if self._substitute[i]:
104 # '%s %(named)s' but just about nothing else 113 # Only need to check %s because arg is a dict and python will allow
105 if '%s' in self._code[i] or '%r' in self._code[i]: 114 # '%s %(named)s' but just about nothing else
106 raise TypeError('"%s" or "%r" found in substitution. ' 115 if '%s' in self._code[i] or '%r' in self._code[i]:
107 'Named arguments only. Use "%" to escape') 116 raise TypeError('"%s" or "%r" found in substitution. '
108 self._code[i] = line % d 117 'Named arguments only. Use "%" to escape')
118 self._code[i] = line % d
109 return self 119 return self
110 120
111 def Render(self): 121 def Render(self):
112 """Renders Code as a string. 122 """Renders Code as a string.
113 """ 123 """
114 return '\n'.join(self._code) 124 return '\n'.join(self._code)
115 125
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698