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

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

Powered by Google App Engine
This is Rietveld 408576698