Coverage for .tox/testcoverage/lib/python2.7/site-packages/_pytest/_code/source : 40%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
except ImportError: _AST_FLAG = 0 _ast = None
""" a immutable object holding a source code fragment, possibly deindenting it. """ if not part: partlines = [] if isinstance(part, Source): partlines = part.lines elif isinstance(part, (tuple, list)): partlines = [x.rstrip("\n") for x in part] elif isinstance(part, py.builtin._basestring): partlines = part.split('\n') if rstrip: while partlines: if partlines[-1].strip(): break partlines.pop() else: partlines = getsource(part, deindent=de).lines if de: partlines = deindent(partlines) lines.extend(partlines)
try: return self.lines == other.lines except AttributeError: if isinstance(other, str): return str(self) == other return False
if isinstance(key, int): return self.lines[key] else: if key.step not in (None, 1): raise IndexError("cannot slice a Source with a step") return self.__getslice__(key.start, key.stop)
""" return new source object with trailing and leading blank lines removed. """ start, end = 0, len(self) while start < end and not self.lines[start].strip(): start += 1 while end > start and not self.lines[end-1].strip(): end -= 1 source = Source() source.lines[:] = self.lines[start:end] return source
""" return a copy of the source object with 'before' and 'after' wrapped around it. """ before = Source(before) after = Source(after) newsource = Source() lines = [ (indent + line) for line in self.lines] newsource.lines = before.lines + lines + after.lines return newsource
""" return a copy of the source object with all lines indented by the given indent-string. """ newsource = Source() newsource.lines = [(indent+line) for line in self.lines] return newsource
""" return Source statement which contains the given linenumber (counted from 0). """
""" return (start, end) tuple which spans the minimal statement region which containing the given lineno. """ raise IndexError("lineno out of range")
""" return a new source object deindented by offset. If offset is None then guess an indentation offset from the first non-blank line. Subsequent lines which have a lower indentation offset will be copied verbatim as they are assumed to be part of multilines. """ # XXX maybe use the tokenizer to properly handle multiline # strings etc.pp?
""" return True if source is parseable, heuristically deindenting it by default. """ try: import parser except ImportError: syntax_checker = lambda x: compile(x, 'asd', 'exec') else: syntax_checker = parser.suite
if deindent: source = str(self.deindent()) else: source = str(self) try: #compile(source+'\n', "x", "exec") syntax_checker(source+'\n') except KeyboardInterrupt: raise except Exception: return False else: return True
flag=generators.compiler_flag, dont_inherit=0, _genframe=None): """ return compiled code object. if filename is None invent an artificial filename which displays the source/line position of the caller frame. """ if not filename or py.path.local(filename).check(file=0): if _genframe is None: _genframe = sys._getframe(1) # the caller fn,lineno = _genframe.f_code.co_filename, _genframe.f_lineno base = "<%d-codegen " % self._compilecounter self.__class__._compilecounter += 1 if not filename: filename = base + '%s:%d>' % (fn, lineno) else: filename = base + '%r %s:%d>' % (filename, fn, lineno) source = "\n".join(self.lines) + '\n' try: co = cpy_compile(source, filename, mode, flag) except SyntaxError: ex = sys.exc_info()[1] # re-represent syntax errors from parsing python strings msglines = self.lines[:ex.lineno] if ex.offset: msglines.append(" "*ex.offset + '^') msglines.append("(code was compiled probably from here: %s)" % filename) newex = SyntaxError('\n'.join(msglines)) newex.offset = ex.offset newex.lineno = ex.lineno newex.text = ex.text raise newex else: if flag & _AST_FLAG: return co lines = [(x + "\n") for x in self.lines] if sys.version_info[0] >= 3: # XXX py3's inspect.getsourcefile() checks for a module # and a pep302 __loader__ ... we don't have a module # at code compile-time so we need to fake it here m = ModuleType("_pycodecompile_pseudo_module") py.std.inspect.modulesbyfile[filename] = None py.std.sys.modules[None] = m m.__loader__ = 1 py.std.linecache.cache[filename] = (1, None, lines, filename) return co
# # public API shortcut functions #
generators.compiler_flag, dont_inherit=0): """ compile the given source to a raw code object, and maintain an internal cache which allows later retrieval of the source code for the code object and any recursively created code objects. """ if _ast is not None and isinstance(source, _ast.AST): # XXX should Source support having AST? return cpy_compile(source, filename, mode, flags, dont_inherit) _genframe = sys._getframe(1) # the caller s = Source(source) co = s.compile(filename, mode, flags, _genframe=_genframe) return co
""" Return source location (path, lineno) for the given object. If the source cannot be determined return ("", -1) """ py.std.inspect.getfile(obj)) except TypeError: return "", -1
except IOError: pass else:
# # helper functions #
except py.builtin._sysex: raise except: return None, -1
import _pytest._code obj = _pytest._code.getrawcode(obj) try: strsrc = inspect.getsource(obj) except IndentationError: strsrc = "\"Buggy python version consider upgrading, cannot get source\"" assert isinstance(strsrc, str) return Source(strsrc, **kwargs)
else: offset = 0 return list(lines)
# Don't deindent continuing lines of # multiline tokens (i.e. multiline strings) newlines.append(lines[i]) except (IndentationError, tokenize.TokenError): pass # Add any lines we didn't see. E.g. if an exception was raised.
# flatten all statements and except handlers into one lineno-list # AST's line numbers start indexing at 1 # treat the finally/orelse part as its own statement end = None else:
content += "\n" except ValueError: start, end = getstatementrange_old(lineno, source, assertion) return None, start, end # we need to correct the end: # - ast-parsing strips comments # - there might be empty lines # - we might have lesser indented code blocks at the end end = len(source.lines)
# make sure we don't span differently indented code blocks # by using the BlockFinder helper used which inspect.getsource() uses itself block_finder = inspect.BlockFinder() # if we start with an indented line, put blockfinder to "started" mode block_finder.started = source.lines[start][0].isspace() it = ((x + "\n") for x in source.lines[start:end]) try: for tok in tokenize.generate_tokens(lambda: next(it)): block_finder.tokeneater(*tok) except (inspect.EndOfBlock, IndentationError): end = block_finder.last + start except Exception: pass
# the end might still point to a comment or empty line, correct it end -= 1 else:
""" return (start, end) tuple which spans the minimal statement region which containing the given lineno. raise an IndexError if no such statementrange can be found. """ # XXX this logic is only used on python2.4 and below # 1. find the start of the statement from codeop import compile_command for start in range(lineno, -1, -1): if assertion: line = source.lines[start] # the following lines are not fully tested, change with care if 'super' in line and 'self' in line and '__init__' in line: raise IndexError("likely a subclass") if "assert" not in line and "raise" not in line: continue trylines = source.lines[start:lineno+1] # quick hack to prepare parsing an indented line with # compile_command() (which errors on "return" outside defs) trylines.insert(0, 'def xxx():') trysource = '\n '.join(trylines) # ^ space here try: compile_command(trysource) except (SyntaxError, OverflowError, ValueError): continue
# 2. find the end of the statement for end in range(lineno+1, len(source)+1): trysource = source[start:end] if trysource.isparseable(): return start, end raise SyntaxError("no valid source range around line %d " % (lineno,))
|