diff options
author | Armin Rigo <arigo@tunes.org> | 2005-09-25 11:45:45 (GMT) |
---|---|---|
committer | Armin Rigo <arigo@tunes.org> | 2005-09-25 11:45:45 (GMT) |
commit | dd5c023af56b9a424a3965364521c50b73308379 (patch) | |
tree | a5523abd7d1eb9bf44ca9722f4798d49b0497503 /Lib/inspect.py | |
parent | e9f8ec98d4cd4542b5d6c5870d56a1ce1ae5d03b (diff) | |
download | cpython-dd5c023af56b9a424a3965364521c50b73308379.zip cpython-dd5c023af56b9a424a3965364521c50b73308379.tar.gz cpython-dd5c023af56b9a424a3965364521c50b73308379.tar.bz2 |
some more fixes and tests for inspect.getsource(), triggered by crashes
from the PyPy project as well as the SF bug #1295909.
Diffstat (limited to 'Lib/inspect.py')
-rw-r--r-- | Lib/inspect.py | 47 |
1 files changed, 20 insertions, 27 deletions
diff --git a/Lib/inspect.py b/Lib/inspect.py index a801a29..57bf18c 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -485,19 +485,6 @@ def getcomments(object): comments[-1:] = [] return string.join(comments, '') -class ListReader: - """Provide a readline() method to return lines from a list of strings.""" - def __init__(self, lines): - self.lines = lines - self.index = 0 - - def readline(self): - i = self.index - if i < len(self.lines): - self.index = i + 1 - return self.lines[i] - else: return '' - class EndOfBlock(Exception): pass class BlockFinder: @@ -507,40 +494,46 @@ class BlockFinder: self.islambda = False self.started = False self.passline = False - self.last = 0 + self.last = 1 def tokeneater(self, type, token, (srow, scol), (erow, ecol), line): if not self.started: + # look for the first "def", "class" or "lambda" if token in ("def", "class", "lambda"): if token == "lambda": self.islambda = True self.started = True - self.passline = True + self.passline = True # skip to the end of the line elif type == tokenize.NEWLINE: - self.passline = False + self.passline = False # stop skipping when a NEWLINE is seen self.last = srow + if self.islambda: # lambdas always end at the first NEWLINE + raise EndOfBlock elif self.passline: pass - elif self.islambda: - raise EndOfBlock, self.last elif type == tokenize.INDENT: self.indent = self.indent + 1 self.passline = True elif type == tokenize.DEDENT: self.indent = self.indent - 1 - if self.indent == 0: - raise EndOfBlock, self.last - elif type == tokenize.NAME and scol == 0: - raise EndOfBlock, self.last + # the end of matching indent/dedent pairs end a block + # (note that this only works for "def"/"class" blocks, + # not e.g. for "if: else:" or "try: finally:" blocks) + if self.indent <= 0: + raise EndOfBlock + elif self.indent == 0 and type not in (tokenize.COMMENT, tokenize.NL): + # any other token on the same indentation level end the previous + # block as well, except the pseudo-tokens COMMENT and NL. + raise EndOfBlock def getblock(lines): """Extract the block of code at the top of the given list of lines.""" + blockfinder = BlockFinder() try: - tokenize.tokenize(ListReader(lines).readline, BlockFinder().tokeneater) - except EndOfBlock, eob: - return lines[:eob.args[0]] - # Fooling the indent/dedent logic implies a one-line definition - return lines[:1] + tokenize.tokenize(iter(lines).next, blockfinder.tokeneater) + except (EndOfBlock, IndentationError): + pass + return lines[:blockfinder.last] def getsourcelines(object): """Return a list of source lines and starting line number for an object. |