|
21 | 21 | from optparse import OptionParser
|
22 | 22 | from re import compile as re
|
23 | 23 | import itertools
|
| 24 | +from collections import defaultdict |
24 | 25 |
|
25 | 26 | try: # Python 3.x
|
26 | 27 | from ConfigParser import RawConfigParser
|
@@ -131,7 +132,7 @@ def __str__(self):
|
131 | 132 | class Module(Definition):
|
132 | 133 |
|
133 | 134 | _fields = ('name', '_source', 'start', 'end', 'decorators', 'docstring',
|
134 |
| - 'children', 'parent', '_all', 'unicode_literals') |
| 135 | + 'children', 'parent', '_all', 'future_imports') |
135 | 136 | is_public = True
|
136 | 137 | _nest = staticmethod(lambda s: {'def': Function, 'class': Class}[s])
|
137 | 138 | module = property(lambda self: self)
|
@@ -197,7 +198,7 @@ class Decorator(Value):
|
197 | 198 |
|
198 | 199 | class TokenKind(int):
|
199 | 200 | def __repr__(self):
|
200 |
| - return "tk.{}".format(tk.tok_name[self]) |
| 201 | + return "tk.{0}".format(tk.tok_name[self]) |
201 | 202 |
|
202 | 203 |
|
203 | 204 | class Token(Value):
|
@@ -252,7 +253,7 @@ def __call__(self, filelike, filename):
|
252 | 253 | self.filename = filename
|
253 | 254 | self.all = None
|
254 | 255 | # TODO: what about Python 3.x?
|
255 |
| - self.unicode_literals = False |
| 256 | + self.future_imports = defaultdict(lambda: False) |
256 | 257 | self._accumulated_decorators = []
|
257 | 258 | return self.parse_module()
|
258 | 259 |
|
@@ -414,7 +415,7 @@ def parse_module(self):
|
414 | 415 | [], docstring, children, None, self.all)
|
415 | 416 | for child in module.children:
|
416 | 417 | child.parent = module
|
417 |
| - module.unicode_literals = self.unicode_literals |
| 418 | + module.future_imports = self.future_imports |
418 | 419 | log.debug("finished parsing module.")
|
419 | 420 | return module
|
420 | 421 |
|
@@ -479,9 +480,29 @@ def parse_from_import_statement(self):
|
479 | 480 | self.stream.move()
|
480 | 481 | assert self.current.value == 'import', self.current.value
|
481 | 482 | self.stream.move()
|
482 |
| - # TODO: lookout for parenthesis, comments, line breaks, etc. |
483 |
| - if self.current.value == 'unicode_literals': |
484 |
| - self.unicode_literals = True |
| 483 | + if self.current.value == '(': |
| 484 | + self.consume(tk.OP) |
| 485 | + expected_end_kind = tk.OP |
| 486 | + else: |
| 487 | + expected_end_kind = tk.NEWLINE |
| 488 | + while self.current.kind != expected_end_kind: |
| 489 | + if self.current.kind != tk.NAME: |
| 490 | + self.stream.move() |
| 491 | + continue |
| 492 | + log.debug("parsing import, token is %r (%s)", |
| 493 | + self.current.kind, self.current.value) |
| 494 | + log.debug('found future import: %s', self.current.value) |
| 495 | + self.future_imports[self.current.value] = True |
| 496 | + self.consume(tk.NAME) |
| 497 | + log.debug("parsing import, token is %r (%s)", |
| 498 | + self.current.kind, self.current.value) |
| 499 | + if self.current.kind == tk.NAME: |
| 500 | + self.consume(tk.NAME) # as |
| 501 | + self.consume(tk.NAME) # new name, irrelevant |
| 502 | + if self.current.value == ',': |
| 503 | + self.consume(tk.OP) |
| 504 | + log.debug("parsing import, token is %r (%s)", |
| 505 | + self.current.kind, self.current.value) |
485 | 506 |
|
486 | 507 |
|
487 | 508 | class Error(object):
|
@@ -1146,7 +1167,7 @@ def check_unicode_docstring(self, definition, docstring):
|
1146 | 1167 | For Unicode docstrings, use u"""Unicode triple-quoted strings""".
|
1147 | 1168 |
|
1148 | 1169 | '''
|
1149 |
| - if definition.module.unicode_literals: |
| 1170 | + if definition.module.future_imports['unicode_literals']: |
1150 | 1171 | return
|
1151 | 1172 |
|
1152 | 1173 | # Just check that docstring is unicode, check_triple_double_quotes
|
|
0 commit comments