OLD | NEW |
1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 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 """Helper functions useful when writing scripts that integrate with GN. | 5 """Helper functions useful when writing scripts that integrate with GN. |
6 | 6 |
7 The main functions are ToGNString and FromGNString which convert between | 7 The main functions are ToGNString and FromGNString which convert between |
8 serialized GN veriables and Python variables. | 8 serialized GN veriables and Python variables. |
9 | 9 |
10 To use in a random python file in the build: | 10 To use in a random python file in the build: |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 raise GNException("Dictionary key is not a string.") | 56 raise GNException("Dictionary key is not a string.") |
57 result += "%s = %s\n" % (key, ToGNString(value[key], False)) | 57 result += "%s = %s\n" % (key, ToGNString(value[key], False)) |
58 return result | 58 return result |
59 | 59 |
60 if isinstance(value, int): | 60 if isinstance(value, int): |
61 return str(value) | 61 return str(value) |
62 | 62 |
63 raise GNException("Unsupported type when printing to GN.") | 63 raise GNException("Unsupported type when printing to GN.") |
64 | 64 |
65 | 65 |
66 def FromGNString(input): | 66 def FromGNString(input_string): |
67 """Converts the input string from a GN serialized value to Python values. | 67 """Converts the input string from a GN serialized value to Python values. |
68 | 68 |
69 For details on supported types see GNValueParser.Parse() below. | 69 For details on supported types see GNValueParser.Parse() below. |
70 | 70 |
71 If your GN script did: | 71 If your GN script did: |
72 something = [ "file1", "file2" ] | 72 something = [ "file1", "file2" ] |
73 args = [ "--values=$something" ] | 73 args = [ "--values=$something" ] |
74 The command line would look something like: | 74 The command line would look something like: |
75 --values="[ \"file1\", \"file2\" ]" | 75 --values="[ \"file1\", \"file2\" ]" |
76 Which when interpreted as a command line gives the value: | 76 Which when interpreted as a command line gives the value: |
(...skipping 15 matching lines...) Expand all Loading... |
92 Will yield the command line: | 92 Will yield the command line: |
93 asdf --value=asdf | 93 asdf --value=asdf |
94 The unquoted asdf string will not be valid input to this function, which | 94 The unquoted asdf string will not be valid input to this function, which |
95 accepts only quoted strings like GN scripts. In such cases, you can just use | 95 accepts only quoted strings like GN scripts. In such cases, you can just use |
96 the Python string literal directly. | 96 the Python string literal directly. |
97 | 97 |
98 The main use cases for this is for other types, in particular lists. When | 98 The main use cases for this is for other types, in particular lists. When |
99 using string interpolation on a list (as in the top example) the embedded | 99 using string interpolation on a list (as in the top example) the embedded |
100 strings will be quoted and escaped according to GN rules so the list can be | 100 strings will be quoted and escaped according to GN rules so the list can be |
101 re-parsed to get the same result.""" | 101 re-parsed to get the same result.""" |
102 parser = GNValueParser(input) | 102 parser = GNValueParser(input_string) |
103 return parser.Parse() | 103 return parser.Parse() |
104 | 104 |
105 | 105 |
106 def FromGNArgs(input): | 106 def FromGNArgs(input_string): |
107 """Converts a string with a bunch of gn arg assignments into a Python dict. | 107 """Converts a string with a bunch of gn arg assignments into a Python dict. |
108 | 108 |
109 Given a whitespace-separated list of | 109 Given a whitespace-separated list of |
110 | 110 |
111 <ident> = (integer | string | boolean | <list of the former>) | 111 <ident> = (integer | string | boolean | <list of the former>) |
112 | 112 |
113 gn assignments, this returns a Python dict, i.e.: | 113 gn assignments, this returns a Python dict, i.e.: |
114 | 114 |
115 FromGNArgs("foo=true\nbar=1\n") -> { 'foo': True, 'bar': 1 }. | 115 FromGNArgs("foo=true\nbar=1\n") -> { 'foo': True, 'bar': 1 }. |
116 | 116 |
117 Only simple types and lists supported; variables, structs, calls | 117 Only simple types and lists supported; variables, structs, calls |
118 and other, more complicated things are not. | 118 and other, more complicated things are not. |
119 | 119 |
120 This routine is meant to handle only the simple sorts of values that | 120 This routine is meant to handle only the simple sorts of values that |
121 arise in parsing --args. | 121 arise in parsing --args. |
122 """ | 122 """ |
123 parser = GNValueParser(input) | 123 parser = GNValueParser(input_string) |
124 return parser.ParseArgs() | 124 return parser.ParseArgs() |
125 | 125 |
126 | 126 |
127 def UnescapeGNString(value): | 127 def UnescapeGNString(value): |
128 """Given a string with GN escaping, returns the unescaped string. | 128 """Given a string with GN escaping, returns the unescaped string. |
129 | 129 |
130 Be careful not to feed with input from a Python parsing function like | 130 Be careful not to feed with input from a Python parsing function like |
131 'ast' because it will do Python unescaping, which will be incorrect when | 131 'ast' because it will do Python unescaping, which will be incorrect when |
132 fed into the GN unescaper.""" | 132 fed into the GN unescaper.""" |
133 result = '' | 133 result = '' |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 elif next_char == '"': | 230 elif next_char == '"': |
231 return self.ParseString() | 231 return self.ParseString() |
232 elif self._ConstantFollows('true'): | 232 elif self._ConstantFollows('true'): |
233 return True | 233 return True |
234 elif self._ConstantFollows('false'): | 234 elif self._ConstantFollows('false'): |
235 return False | 235 return False |
236 else: | 236 else: |
237 raise GNException("Unexpected token: " + self.input[self.cur:]) | 237 raise GNException("Unexpected token: " + self.input[self.cur:]) |
238 | 238 |
239 def _ParseIdent(self): | 239 def _ParseIdent(self): |
240 id = '' | 240 ident = '' |
241 | 241 |
242 next_char = self.input[self.cur] | 242 next_char = self.input[self.cur] |
243 if not next_char.isalpha() and not next_char=='_': | 243 if not next_char.isalpha() and not next_char=='_': |
244 raise GNException("Expected an identifier: " + self.input[self.cur:]) | 244 raise GNException("Expected an identifier: " + self.input[self.cur:]) |
245 | 245 |
246 id += next_char | 246 ident += next_char |
247 self.cur += 1 | 247 self.cur += 1 |
248 | 248 |
249 next_char = self.input[self.cur] | 249 next_char = self.input[self.cur] |
250 while next_char.isalpha() or next_char.isdigit() or next_char=='_': | 250 while next_char.isalpha() or next_char.isdigit() or next_char=='_': |
251 id += next_char | 251 ident += next_char |
252 self.cur += 1 | 252 self.cur += 1 |
253 next_char = self.input[self.cur] | 253 next_char = self.input[self.cur] |
254 | 254 |
255 return id | 255 return ident |
256 | 256 |
257 def ParseNumber(self): | 257 def ParseNumber(self): |
258 self.ConsumeWhitespace() | 258 self.ConsumeWhitespace() |
259 if self.IsDone(): | 259 if self.IsDone(): |
260 raise GNException('Expected number but got nothing.') | 260 raise GNException('Expected number but got nothing.') |
261 | 261 |
262 begin = self.cur | 262 begin = self.cur |
263 | 263 |
264 # The first character can include a negative sign. | 264 # The first character can include a negative sign. |
265 if not self.IsDone() and _IsDigitOrMinus(self.input[self.cur]): | 265 if not self.IsDone() and _IsDigitOrMinus(self.input[self.cur]): |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 location in the input. If it does, the text is consumed and the function | 342 location in the input. If it does, the text is consumed and the function |
343 returns true. Otherwise, returns false and the current position is | 343 returns true. Otherwise, returns false and the current position is |
344 unchanged.""" | 344 unchanged.""" |
345 end = self.cur + len(constant) | 345 end = self.cur + len(constant) |
346 if end > len(self.input): | 346 if end > len(self.input): |
347 return False # Not enough room. | 347 return False # Not enough room. |
348 if self.input[self.cur:end] == constant: | 348 if self.input[self.cur:end] == constant: |
349 self.cur = end | 349 self.cur = end |
350 return True | 350 return True |
351 return False | 351 return False |
OLD | NEW |