def plugin_pinfo(self, runner, detail_level=0): """Generate info dict for a plugin from a plugin runner.""" plugin_class = getattr( runner.session.plugins, runner.plugin_name)._target display_fields = [ ("file", oinspect.find_file(plugin_class)), ("Plugin", "%s (%s)" % (plugin_class.__name__, plugin_class.name))] if getattr(plugin_class, "table_header", None): display_fields.append( ("", "This is a Typed Plugin.")) display_fields += [ ("Positional Args", self.format_parameters(plugin_class, True)), ("Keyword Args", self.format_parameters(plugin_class, False)), ("Docstring", oinspect.getdoc(plugin_class) or ""), ("Link", ( "http://www.rekall-forensic.com/epydocs/%s.%s-class.html" % ( plugin_class.__module__, plugin_class.__name__))), ] # Include the source if required. if detail_level > 0: info = self.info(plugin_class, detail_level=detail_level) display_fields.append(("source", self.format(info["source"]))) return self._format_fields(display_fields)
def plugin_pinfo(self, runner, detail_level=0): """Generate info dict for a plugin from a plugin runner.""" plugin_class = getattr(runner.session.plugins, runner.plugin_name)._target display_fields = [ ("file", oinspect.find_file(plugin_class)), ("Plugin", "%s (%s)" % (plugin_class.__name__, plugin_class.name)) ] if getattr(plugin_class, "table_header", None): display_fields.append(("", "This is a Typed Plugin.")) display_fields += [ ("Positional Args", self.format_parameters(plugin_class, True)), ("Keyword Args", self.format_parameters(plugin_class, False)), ("Docstring", oinspect.getdoc(plugin_class) or ""), ("Link", ("http://www.rekall-forensic.com/epydocs/%s.%s-class.html" % (plugin_class.__module__, plugin_class.__name__))), ] # Include the source if required. if detail_level > 0: info = self.info(plugin_class, detail_level=detail_level) display_fields.append(("source", self.format(info["source"]))) return self._format_fields(display_fields)
def plugin_info(self, runner, **kwargs): """Generate info dict for a plugin from a plugin runner.""" plugin_class = getattr( runner.session.plugins, runner.plugin_name)._target result = oinspect.Inspector.info(self, plugin_class, **kwargs) result["file"] = oinspect.find_file(plugin_class) result["type_name"] = "Rekall Plugin (%s)" % plugin_class.__name__ result["parameters"] = self.format_parameters(plugin_class) result["docstring"] = oinspect.getdoc(plugin_class) result["link"] = ( "http://www.rekall-forensic.com/epydocs/%s.%s-class.html" % ( plugin_class.__module__, plugin_class.__name__)) # Hide these two fields. result["init_definition"] = None result["string_form"] = None return result
def _find_edit_target(shell, args, opts, last_call): """Utility method used by magic_edit to find what to edit.""" def make_filename(arg): "Make a filename from the given args" try: filename = get_py_filename(arg) except IOError: # If it ends with .py but doesn't already exist, assume we want # a new file. if arg.endswith('.py'): filename = arg else: filename = None return filename # Set a few locals from the options for convenience: opts_prev = 'p' in opts opts_raw = 'r' in opts # custom exceptions class DataIsObject(Exception): pass # Default line number value lineno = opts.get('n', None) if opts_prev: args = '_%s' % last_call[0] if args not in shell.user_ns: args = last_call[1] # by default this is done with temp files, except when the given # arg is a filename use_temp = True data = '' # First, see if the arguments should be a filename. filename = make_filename(args) if filename: use_temp = False elif args: # Mode where user specifies ranges of lines, like in %macro. data = shell.extract_input_lines(args, opts_raw) if not data: try: # Load the parameter given as a variable. If not a string, # process it as an object instead (below) #print '*** args',args,'type',type(args) # dbg data = eval(args, shell.user_ns) if not isinstance(data, str): raise DataIsObject except (NameError, SyntaxError): # given argument is not a variable, try as a filename filename = make_filename(args) if filename is None: warn( "Argument given (%s) can't be found as a variable " "or as a filename." % args) return (None, None, None) use_temp = False except DataIsObject as e: # macros have a special edit function if isinstance(data, Macro): raise MacroToEdit(data) from e # For objects, try to edit the file where they are defined filename = find_file(data) if filename: if 'fakemodule' in filename.lower() and \ inspect.isclass(data): # class created by %edit? Try to find source # by looking for method definitions instead, the # __module__ in those classes is FakeModule. attrs = [ getattr(data, aname) for aname in dir(data) ] for attr in attrs: if not inspect.ismethod(attr): continue filename = find_file(attr) if filename and \ 'fakemodule' not in filename.lower(): # change the attribute to be the edit # target instead data = attr break m = ipython_input_pat.match(os.path.basename(filename)) if m: raise InteractivelyDefined(int( m.groups()[0])) from e datafile = 1 if filename is None: filename = make_filename(args) datafile = 1 if filename is not None: # only warn about this if we get a real name warn('Could not find file where `%s` is defined.\n' 'Opening a file named `%s`' % (args, filename)) # Now, make sure we can actually read the source (if it was # in a temp file it's gone by now). if datafile: if lineno is None: lineno = find_source_lines(data) if lineno is None: filename = make_filename(args) if filename is None: warn('The file where `%s` was defined ' 'cannot be read or found.' % data) return (None, None, None) use_temp = False if use_temp: filename = shell.mktempfile(data) print('IPython will make a temporary file named:', filename) # use last_call to remember the state of the previous call, but don't # let it be clobbered by successive '-p' calls. try: last_call[0] = shell.displayhook.prompt_count if not opts_prev: last_call[1] = args except: pass return filename, lineno, use_temp
def info(self, obj, oname='', formatter=None, info=None, detail_level=0): """Compute a dict with detailed information about an object. This overrides the superclass method for two main purposes: * avoid calling str() or repr() on the object * use our custom repr Args: obj: object to inspect. oname: (optional) string reference to this object formatter: (optional) custom docstring formatter info: (optional) previously computed information about obj detail_level: (optional) 0 or 1; 1 means "include more detail" Returns: A dict with information about obj. """ # We want to include the following list of keys for all objects: # * name # * found # * isclass # * string_form # * type_name # # For callables, we want to add a subset of: # * argspec # * call_docstring # * definition # * docstring # * file # * init_definition # * init_docstring # * source_end_line # * source_start_line # * source_definition # # For detail_level 1, we include: # * file # This can be expensive, as the stdlib mechanisms for looking up the file # containing obj may call repr(obj). # # NOTE: These keys should stay in sync with the corresponding list in our # frontend code. # # We want non-None values for: # * isalias # * ismagic # * namespace # # TODO(b/138128444): Handle class_docstring and call_def, or determine that # we're safe ignoring them. obj_type = type(obj) out = { 'name': oname, 'found': True, 'is_class': inspect.isclass(obj), 'string_form': None, # Fill in empty values. 'docstring': None, 'file': None, 'isalias': False, 'ismagic': info.ismagic if info else False, 'namespace': info.namespace if info else '', } if detail_level >= self.str_detail_level: out['string_form'] = _safe_repr(obj) if getattr(info, 'ismagic', False): out['type_name'] = 'Magic function' else: out['type_name'] = obj_type.__name__ # If the object is callable, we want to compute a docstring and related # information. We could exit early, but all the code below is in conditional # blocks, so there's no need. # # We can't simply call into the superclass method, as we need to avoid # (transitively) calling inspect.getfile(): this function will end up # calling repr() on our object. # We want to include a docstring if we don't have source, which happens # when: # * detail_level == 0, or # * detail_level == 1 but we can't find source # So we first try dealing with detail_level == 1, and then set # the docstring if no source is set. if detail_level == 1: # This should only ever happen if the user has asked for source (eg via # `obj??`), so we're OK with potentially calling repr for now. # TODO(b/138128444): Ensure we don't call str() or repr(). source = _getsource(obj) if source is None and hasattr(obj, '__class__'): source = _getsource(obj.__class__) if source is not None: out['source'] = source if 'source' not in out: formatter = formatter or (lambda x: x) docstring = formatter(_getdoc(obj) or '<no docstring>') if docstring: out['docstring'] = docstring if _iscallable(obj): filename = oinspect.find_file(obj) if filename and (filename.endswith( ('.py', '.py3', '.pyc')) or '<ipython-input' in filename): out['file'] = filename line = oinspect.find_source_lines(obj) out['source_start_line'] = line # inspect.getsourcelines exposes the length of the source as well, which # can be used to highlight the entire code block, but find_source_lines # currently does not expose this. For now just highlight the first line. out['source_end_line'] = line # The remaining attributes only apply to classes or callables. if inspect.isclass(obj): # For classes with an __init__, we set init_definition and init_docstring. init = getattr(obj, '__init__', None) if init: init_docstring = _getdoc(init) if init_docstring and init_docstring != _BASE_INIT_DOC: out['init_docstring'] = init_docstring init_def = self._getdef(init, oname) if init_def: out['init_definition'] = init_def src_def = _get_source_definition(init) if src_def: out['source_definition'] = src_def # For classes, the __init__ method is the method invoked on call, but # old-style classes may not have an __init__ method. if init: argspec = _getargspec_dict(init) if argspec: out['argspec'] = argspec elif callable(obj): definition = self._getdef(obj, oname) if definition: out['definition'] = definition src_def = _get_source_definition(obj) if src_def: out['source_definition'] = src_def if not oinspect.is_simple_callable(obj): call_docstring = _getdoc(obj.__call__) if call_docstring and call_docstring != _BASE_CALL_DOC: out['call_docstring'] = call_docstring out['argspec'] = _getargspec_dict(obj) return oinspect.object_info(**out)
def _find_edit_target(shell, args, opts, last_call): """Utility method used by magic_edit to find what to edit.""" def make_filename(arg): "Make a filename from the given args" arg = unquote_filename(arg) try: filename = get_py_filename(arg) except IOError: # If it ends with .py but doesn't already exist, assume we want # a new file. if arg.endswith(".py"): filename = arg else: filename = None return filename # Set a few locals from the options for convenience: opts_prev = "p" in opts opts_raw = "r" in opts # custom exceptions class DataIsObject(Exception): pass # Default line number value lineno = opts.get("n", None) if opts_prev: args = "_%s" % last_call[0] if args not in shell.user_ns: args = last_call[1] # by default this is done with temp files, except when the given # arg is a filename use_temp = True data = "" # First, see if the arguments should be a filename. filename = make_filename(args) if filename: use_temp = False elif args: # Mode where user specifies ranges of lines, like in %macro. data = shell.extract_input_lines(args, opts_raw) if not data: try: # Load the parameter given as a variable. If not a string, # process it as an object instead (below) # print '*** args',args,'type',type(args) # dbg data = eval(args, shell.user_ns) if not isinstance(data, string_types): raise DataIsObject except (NameError, SyntaxError): # given argument is not a variable, try as a filename filename = make_filename(args) if filename is None: warn("Argument given (%s) can't be found as a variable " "or as a filename." % args) return (None, None, None) use_temp = False except DataIsObject: # macros have a special edit function if isinstance(data, Macro): raise MacroToEdit(data) # For objects, try to edit the file where they are defined filename = find_file(data) if filename: if "fakemodule" in filename.lower() and inspect.isclass(data): # class created by %edit? Try to find source # by looking for method definitions instead, the # __module__ in those classes is FakeModule. attrs = [getattr(data, aname) for aname in dir(data)] for attr in attrs: if not inspect.ismethod(attr): continue filename = find_file(attr) if filename and "fakemodule" not in filename.lower(): # change the attribute to be the edit # target instead data = attr break m = ipython_input_pat.match(os.path.basename(filename)) if m: raise InteractivelyDefined(int(m.groups()[0])) datafile = 1 if filename is None: filename = make_filename(args) datafile = 1 if filename is not None: # only warn about this if we get a real name warn( "Could not find file where `%s` is defined.\n" "Opening a file named `%s`" % (args, filename) ) # Now, make sure we can actually read the source (if it was # in a temp file it's gone by now). if datafile: if lineno is None: lineno = find_source_lines(data) if lineno is None: filename = make_filename(args) if filename is None: warn("The file where `%s` was defined " "cannot be read or found." % data) return (None, None, None) use_temp = False if use_temp: filename = shell.mktempfile(data) print("IPython will make a temporary file named:", filename) # use last_call to remember the state of the previous call, but don't # let it be clobbered by successive '-p' calls. try: last_call[0] = shell.displayhook.prompt_count if not opts_prev: last_call[1] = args except: pass return filename, lineno, use_temp