Index: tools/json_schema_compiler/code.py |
diff --git a/tools/json_schema_compiler/code.py b/tools/json_schema_compiler/code.py |
index c19029a1ef0a2b3ba5135cbfc57dd9b12b0d08cb..e9ade79a6ff6ff9b9072301939fd45a7d77f0caf 100644 |
--- a/tools/json_schema_compiler/code.py |
+++ b/tools/json_schema_compiler/code.py |
@@ -2,6 +2,8 @@ |
# Use of this source code is governed by a BSD-style license that can be |
# found in the LICENSE file. |
+import itertools |
+ |
class Code(object): |
"""A convenience object for constructing code. |
@@ -10,14 +12,19 @@ class Code(object): |
""" |
def __init__(self, indent_size=2, comment_length=80): |
self._code = [] |
+ self._substitute = [] |
self._indent_level = 0 |
self._indent_size = indent_size |
self._comment_length = comment_length |
- def Append(self, line=''): |
+ def Append(self, line='', substitute=True): |
"""Appends a line of code at the current indent level or just a newline if |
line is not specified. Trailing whitespace is stripped. |
+ |
+ substitute: indicated whether this line should be affected by |
+ code.Substitute(). |
""" |
+ self._substitute.append(substitute) |
self._code.append(((' ' * self._indent_level) + line).rstrip()) |
return self |
@@ -37,12 +44,16 @@ class Code(object): |
if not isinstance(obj, Code): |
raise TypeError(type(obj)) |
assert self is not obj |
- for line in obj._code: |
+ for substitute, line in itertools.izip(obj._substitute, obj._code): |
try: |
# line % () will fail if any substitution tokens are left in line |
- self._code.append(((' ' * self._indent_level) + line % ()).rstrip()) |
+ if substitute: |
+ line %= () |
except TypeError: |
raise TypeError('Unsubstituted value when concatting\n' + line) |
+ except ValueError: |
+ raise ValueError('Stray % character when concatting\n' + line) |
+ self.Append(line, substitute) |
return self |
@@ -66,13 +77,13 @@ class Code(object): |
self.Append(line) |
return self |
- # TODO(calamity): Make comment its own class or something and Render at |
- # self.Render() time |
def Comment(self, comment): |
"""Adds the given string as a comment. |
Will split the comment if it's too long. Use mainly for variable length |
comments. Otherwise just use code.Append('// ...') for comments. |
+ |
+ Unaffected by code.Substitute(). |
""" |
comment_symbol = '// ' |
max_len = self._comment_length - self._indent_level - len(comment_symbol) |
@@ -84,8 +95,8 @@ class Code(object): |
comment = comment[last_space + 1:] |
else: |
comment = comment[max_len:] |
- self.Append(comment_symbol + line) |
- self.Append(comment_symbol + comment) |
+ self.Append(comment_symbol + line, substitute=False) |
+ self.Append(comment_symbol + comment, substitute=False) |
return self |
def Substitute(self, d): |
@@ -100,12 +111,13 @@ class Code(object): |
if not isinstance(d, dict): |
raise TypeError('Passed argument is not a dictionary: ' + d) |
for i, line in enumerate(self._code): |
- # Only need to check %s because arg is a dict and python will allow |
- # '%s %(named)s' but just about nothing else |
- if '%s' in self._code[i] or '%r' in self._code[i]: |
- raise TypeError('"%s" or "%r" found in substitution. ' |
- 'Named arguments only. Use "%" to escape') |
- self._code[i] = line % d |
+ if self._substitute[i]: |
+ # Only need to check %s because arg is a dict and python will allow |
+ # '%s %(named)s' but just about nothing else |
+ if '%s' in self._code[i] or '%r' in self._code[i]: |
+ raise TypeError('"%s" or "%r" found in substitution. ' |
+ 'Named arguments only. Use "%" to escape') |
+ self._code[i] = line % d |
return self |
def Render(self): |