예제 #1
0
    def get_jedi_object(self, func_name, info, use_filename=True):
        """Call a desired function on a Jedi Script and return the result"""
        if not jedi:
            return
        if DEBUG_EDITOR:
            t0 = time.time()
        # override IPython qt_loaders ImportDenier behavior
        metas = sys.meta_path
        for meta in metas:
            if (meta.__class__.__name__ == 'ImportDenier'
                    and hasattr(meta, 'forbid')):
                sys.meta_path.remove(meta)

        if use_filename:
            filename = info['filename']
        else:
            filename = None

        try:
            script = jedi.Script(info['source_code'], info['line_num'],
                                 info['column'], filename)
            func = getattr(script, func_name)
            val = func()
        except Exception as e:
            val = None
            debug_print('Jedi error (%s)' % func_name)
            debug_print(str(e))
            if DEBUG_EDITOR:
                log_last_error(LOG_FILENAME, str(e))
        if DEBUG_EDITOR:
            log_dt(LOG_FILENAME, func_name, t0)
        if not val and filename:
            return self.get_jedi_object(func_name, info, False)
        else:
            return val
예제 #2
0
    def get_jedi_object(self, func_name, info, use_filename=True):
        """Call a desired function on a Jedi Script and return the result"""
        if not jedi:
            return
        if DEBUG_EDITOR:
            t0 = time.time()
        # override IPython qt_loaders ImportDenier behavior
        metas = sys.meta_path
        for meta in metas:
            if (meta.__class__.__name__ == 'ImportDenier'
                    and hasattr(meta, 'forbid')):
                sys.meta_path.remove(meta)

        if use_filename:
            filename = info['filename']
        else:
            filename = None

        try:
            script = jedi.Script(info['source_code'], info['line_num'],
                                 info['column'], filename)
            func = getattr(script, func_name)
            val = func()
        except Exception as e:
            val = None
            debug_print('Jedi error (%s)' % func_name)
            debug_print(str(e))
            if DEBUG_EDITOR:
                log_last_error(LOG_FILENAME, str(e))
        if DEBUG_EDITOR:
            log_dt(LOG_FILENAME, func_name, t0)
        if not val and filename:
            return self.get_jedi_object(func_name, info, False)
        else:
            return val
예제 #3
0
    def get_info(self, info):
        """Get a formatted calltip and docstring from Rope"""
        if self.project is None:
            return default_info_response()
        filename = info['filename']
        source_code = info['source_code']
        offset = info['position']

        # Set python path into rope project
        self.project.prefs.set('python_path', info['sys_path'])

        if filename is not None:
            if PY2:
                filename = filename.encode('utf-8')
            else:
                # TODO: test if this is working without any further change in
                # Python 3 with a user account containing unicode characters
                pass
        try:
            resource = rope.base.libutils.path_to_resource(
                self.project, filename)
        except Exception as _error:
            if DEBUG_EDITOR:
                log_last_error(LOG_FILENAME, "path_to_resource: %r" % filename)
            resource = None
        try:
            if DEBUG_EDITOR:
                t0 = time.time()
            cts = rope.contrib.codeassist.get_calltip(self.project,
                                                      source_code,
                                                      offset,
                                                      resource,
                                                      ignore_unknown=False,
                                                      remove_self=True,
                                                      maxfixes=3)
            if DEBUG_EDITOR:
                log_dt(LOG_FILENAME, "get_calltip", t0)
            if cts is not None:
                while '..' in cts:
                    cts = cts.replace('..', '.')
                if '(.)' in cts:
                    cts = cts.replace('(.)', '(...)')
            try:
                doc_text = rope.contrib.codeassist.get_doc(self.project,
                                                           source_code,
                                                           offset,
                                                           resource,
                                                           maxfixes=3)
                if DEBUG_EDITOR:
                    log_dt(LOG_FILENAME, "get_doc", t0)
            except Exception as _error:
                doc_text = ''
                if DEBUG_EDITOR:
                    log_last_error(LOG_FILENAME, "get_doc")
            return self.handle_info(cts, doc_text, source_code, offset)
        except Exception as _error:  #analysis:ignore
            if DEBUG_EDITOR:
                log_last_error(LOG_FILENAME, "get_calltip_text")
예제 #4
0
    def get_info(self, info):
        """Get a formatted calltip and docstring from Rope"""
        if self.project is None:
            return default_info_response()
        filename = info['filename']
        source_code = info['source_code']
        offset = info['position']

        # Set python path into rope project
        self.project.prefs.set('python_path', info['sys_path'])

        if filename is not None:
            if PY2:
                filename = filename.encode('utf-8')
            else:
                # TODO: test if this is working without any further change in
                # Python 3 with a user account containing unicode characters
                pass
        try:
            resource = rope.base.libutils.path_to_resource(self.project,
                                                           filename)
        except Exception as _error:
            if DEBUG_EDITOR:
                log_last_error(LOG_FILENAME, "path_to_resource: %r" % filename)
            resource = None
        try:
            if DEBUG_EDITOR:
                t0 = time.time()
            cts = rope.contrib.codeassist.get_calltip(
                            self.project, source_code, offset, resource,
                            ignore_unknown=False, remove_self=True, maxfixes=3)
            if DEBUG_EDITOR:
                log_dt(LOG_FILENAME, "get_calltip", t0)
            if cts is not None:
                while '..' in cts:
                    cts = cts.replace('..', '.')
                if '(.)' in cts:
                    cts = cts.replace('(.)', '(...)')
            try:
                doc_text = rope.contrib.codeassist.get_doc(self.project,
                                     source_code, offset, resource, maxfixes=3)
                if DEBUG_EDITOR:
                    log_dt(LOG_FILENAME, "get_doc", t0)
            except Exception as _error:
                doc_text = ''
                if DEBUG_EDITOR:
                    log_last_error(LOG_FILENAME, "get_doc")
            return self.handle_info(cts, doc_text, source_code, offset)
        except Exception as _error:  #analysis:ignore
            if DEBUG_EDITOR:
                log_last_error(LOG_FILENAME, "get_calltip_text")
예제 #5
0
    def get_completions(self, info):
        """Get a list of (completion, type) tuples using Rope"""
        if self.project is None:
            return []
        filename = info['filename']
        source_code = info['source_code']
        offset = info['position']

        # Set python path into rope project
        self.project.prefs.set('python_path', info['sys_path'])

        # Prevent Rope from returning import completions because
        # it can't handle them. Only Jedi can do it!
        lines = sourcecode.split_source(source_code[:offset])
        last_line = lines[-1].lstrip()
        if (last_line.startswith('import ') or last_line.startswith('from ')) \
          and not ';' in last_line:
            return []

        if filename is not None:
            if PY2:
                filename = filename.encode('utf-8')
            else:
                # TODO: test if this is working without any further change in
                # Python 3 with a user account containing unicode characters
                pass
        try:
            resource = rope.base.libutils.path_to_resource(
                self.project, filename)
        except Exception as _error:
            if DEBUG_EDITOR:
                log_last_error(LOG_FILENAME, "path_to_resource: %r" % filename)
            resource = None
        try:
            if DEBUG_EDITOR:
                t0 = time.time()
            proposals = rope.contrib.codeassist.code_assist(self.project,
                                                            source_code,
                                                            offset,
                                                            resource,
                                                            maxfixes=3)
            proposals = rope.contrib.codeassist.sorted_proposals(proposals)
            if DEBUG_EDITOR:
                log_dt(LOG_FILENAME, "code_assist/sorted_proposals", t0)
            return [(proposal.name, proposal.type) for proposal in proposals]
        except Exception as _error:  #analysis:ignore
            if DEBUG_EDITOR:
                log_last_error(LOG_FILENAME, "get_completion_list")
        return []
예제 #6
0
def get_definition_with_regex(source, token, start_line=-1):
    """
    Find the definition of an object within a source closest to a given line
    """
    if not token:
        return None
    if DEBUG_EDITOR:
        t0 = time.time()
    patterns = [  # python / cython keyword definitions
        r'^c?import.*\W{0}{1}',
        r'from.*\W{0}\W.*c?import ',
        r'from .* c?import.*\W{0}{1}',
        r'class\s*{0}{1}',
        r'c?p?def[^=]*\W{0}{1}',
        r'cdef.*\[.*\].*\W{0}{1}',
        # enaml keyword definitions
        r'enamldef.*\W{0}{1}',
        r'attr.*\W{0}{1}',
        r'event.*\W{0}{1}',
        r'id\s*:.*\W{0}{1}'
    ]

    matches = get_matches(patterns, source, token, start_line)

    if not matches:
        patterns = [
            r'.*\Wself.{0}{1}[^=!<>]*=[^=]', r'.*\W{0}{1}[^=!<>]*=[^=]',
            r'self.{0}{1}[^=!<>]*=[^=]', r'{0}{1}[^=!<>]*=[^=]'
        ]
        matches = get_matches(patterns, source, token, start_line)
    # find the one closest to the start line (prefer before the start line)
    if matches:
        min_dist = len(source.splitlines())
        best_ind = 0
        for match in matches:
            dist = abs(start_line - match)
            if match <= start_line or not best_ind:
                if dist < min_dist:
                    min_dist = dist
                    best_ind = match
    if matches:
        if DEBUG_EDITOR:
            log_dt(LOG_FILENAME, 'regex definition match', t0)
        return best_ind
    else:
        if DEBUG_EDITOR:
            log_dt(LOG_FILENAME, 'regex definition failed match', t0)
        return None
예제 #7
0
def get_definition_with_regex(source, token, start_line=-1):
    """
    Find the definition of an object within a source closest to a given line
    """
    if not token:
        return None
    if DEBUG_EDITOR:
        t0 = time.time()
    patterns = [  # python / cython keyword definitions
                r'^c?import.*\W{0}{1}',
                r'from.*\W{0}\W.*c?import ',
                r'from .* c?import.*\W{0}{1}',
                r'class\s*{0}{1}',
                r'c?p?def[^=]*\W{0}{1}',
                r'cdef.*\[.*\].*\W{0}{1}',
                # enaml keyword definitions
                r'enamldef.*\W{0}{1}',
                r'attr.*\W{0}{1}',
                r'event.*\W{0}{1}',
                r'id\s*:.*\W{0}{1}']

    matches = get_matches(patterns, source, token, start_line)

    if not matches:
        patterns = [r'.*\Wself.{0}{1}[^=!<>]*=[^=]',
                    r'.*\W{0}{1}[^=!<>]*=[^=]',
                    r'self.{0}{1}[^=!<>]*=[^=]',
                    r'{0}{1}[^=!<>]*=[^=]']
        matches = get_matches(patterns, source, token, start_line)
    # find the one closest to the start line (prefer before the start line)
    if matches:
        min_dist = len(source.splitlines())
        best_ind = 0
        for match in matches:
            dist = abs(start_line - match)
            if match <= start_line or not best_ind:
                if dist < min_dist:
                    min_dist = dist
                    best_ind = match
    if matches:
        if DEBUG_EDITOR:
            log_dt(LOG_FILENAME, 'regex definition match', t0)
        return best_ind
    else:
        if DEBUG_EDITOR:
            log_dt(LOG_FILENAME, 'regex definition failed match', t0)
        return None
예제 #8
0
    def get_completions(self, info):
        """Get a list of (completion, type) tuples using Rope"""
        if self.project is None:
            return []
        filename = info['filename']
        source_code = info['source_code']
        offset = info['position']

        # Set python path into rope project
        self.project.prefs.set('python_path', info['sys_path'])

        # Prevent Rope from returning import completions because
        # it can't handle them. Only Jedi can do it!
        lines = sourcecode.split_source(source_code[:offset])
        last_line = lines[-1].lstrip()
        if (last_line.startswith('import ') or last_line.startswith('from ')) \
          and not ';' in last_line:
            return []

        if filename is not None:
            if PY2:
                filename = filename.encode('utf-8')
            else:
                # TODO: test if this is working without any further change in
                # Python 3 with a user account containing unicode characters
                pass
        try:
            resource = rope.base.libutils.path_to_resource(self.project,
                                                           filename)
        except Exception as _error:
            if DEBUG_EDITOR:
                log_last_error(LOG_FILENAME, "path_to_resource: %r" % filename)
            resource = None
        try:
            if DEBUG_EDITOR:
                t0 = time.time()
            proposals = rope.contrib.codeassist.code_assist(self.project,
                                    source_code, offset, resource, maxfixes=3)
            proposals = rope.contrib.codeassist.sorted_proposals(proposals)
            if DEBUG_EDITOR:
                log_dt(LOG_FILENAME, "code_assist/sorted_proposals", t0)
            return [(proposal.name, proposal.type) for proposal in proposals]
        except Exception as _error:  #analysis:ignore
            if DEBUG_EDITOR:
                log_last_error(LOG_FILENAME, "get_completion_list")
        return []
예제 #9
0
    def get_definition(self, info):
        """Find a definition location using Rope"""
        if self.project is None:
            return

        filename = info['filename']
        source_code = info['source_code']
        offset = info['position']

        # Set python path into rope project
        self.project.prefs.set('python_path', info['sys_path'])
        if filename is not None:
            if PY2:
                filename = filename.encode('utf-8')
            else:
                # TODO: test if this is working without any further change in
                # Python 3 with a user account containing unicode characters
                pass
        try:
            resource = rope.base.libutils.path_to_resource(
                self.project, filename)
        except Exception as _error:
            if DEBUG_EDITOR:
                log_last_error(LOG_FILENAME, "path_to_resource: %r" % filename)
            resource = None
        try:
            if DEBUG_EDITOR:
                t0 = time.time()
            resource, lineno = rope.contrib.codeassist.get_definition_location(
                self.project, source_code, offset, resource, maxfixes=3)
            if DEBUG_EDITOR:
                log_dt(LOG_FILENAME, "get_definition_location", t0)
            if resource is not None:
                filename = resource.real_path
            if filename and lineno:
                return filename, lineno
        except Exception as _error:  #analysis:ignore
            if DEBUG_EDITOR:
                log_last_error(LOG_FILENAME, "get_definition_location")
예제 #10
0
    def get_definition(self, info):
        """Find a definition location using Rope"""
        if self.project is None:
            return

        filename = info['filename']
        source_code = info['source_code']
        offset = info['position']

        # Set python path into rope project
        self.project.prefs.set('python_path', info['sys_path'])
        if filename is not None:
            if PY2:
                filename = filename.encode('utf-8')
            else:
                # TODO: test if this is working without any further change in
                # Python 3 with a user account containing unicode characters
                pass
        try:
            resource = rope.base.libutils.path_to_resource(self.project,
                                                           filename)
        except Exception as _error:
            if DEBUG_EDITOR:
                log_last_error(LOG_FILENAME, "path_to_resource: %r" % filename)
            resource = None
        try:
            if DEBUG_EDITOR:
                t0 = time.time()
            resource, lineno = rope.contrib.codeassist.get_definition_location(
                    self.project, source_code, offset, resource, maxfixes=3)
            if DEBUG_EDITOR:
                log_dt(LOG_FILENAME, "get_definition_location", t0)
            if resource is not None:
                filename = resource.real_path
            if filename and lineno:
                return filename, lineno
        except Exception as _error:  #analysis:ignore
            if DEBUG_EDITOR:
                log_last_error(LOG_FILENAME, "get_definition_location")