src/eric7/Utilities/ClassBrowsers/__init__.py

Sun, 11 Dec 2022 15:49:39 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sun, 11 Dec 2022 15:49:39 +0100
branch
eric7
changeset 9609
c2f9c10c47cc
parent 9497
8beca4047c53
child 9612
93b496cc3c88
permissions
-rw-r--r--

Added a few TODO markers.

# -*- coding: utf-8 -*-

# Copyright (c) 2005 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Package implementing class browsers for various languages.

Currently it offers class browser support for the following
programming languages.

<ul>
<li>CORBA IDL</li>
<li>JavaScript</li>
<li>ProtoBuf</li>
<li>Python 3</li>
<li>Ruby</li>
</ul>
"""

# TODO: move the IDL and Protobuf class browsers to the plugins.

import importlib
import os

from eric7 import Preferences

PY_SOURCE = 1
PTL_SOURCE = 128
RB_SOURCE = 129
IDL_SOURCE = 130
JS_SOURCE = 131
PROTO_SOURCE = 132
UNKNOWN_SOURCE = 255

SUPPORTED_TYPES = [
    PY_SOURCE,
    PTL_SOURCE,
    RB_SOURCE,
    IDL_SOURCE,
    JS_SOURCE,
    PROTO_SOURCE,
]

__extensions = {
    "IDL": [".idl"],
    "Python": [".py", ".pyw", ".ptl"],  # currently not used
    "Ruby": [".rb"],
    "JavaScript": [".js"],
    "ProtoBuf": [".proto"],
}


def getClassBrowserModule(moduleType):
    """
    Function to import a class browser module.

    @param moduleType type of class browser to load
    @type str
    @return reference to the imported class browser module
    @rtype module
    """
    typeMapping = {
        "idl": ".idlclbr",
        "javascript": ".jsclbr",
        "protobuf": ".protoclbr",
        "python": ".pyclbr",
        "ruby": ".rbclbr",
    }

    if moduleType in typeMapping:
        mod = importlib.import_module(typeMapping[moduleType], __package__)
        return mod

    return None


def readmodule(module, path=None, isPyFile=False):
    """
    Function to read a source file and return a dictionary of classes, functions,
    modules, etc. .

    The real work of parsing the source file is delegated to the individual
    file parsers.

    @param module name of the source file
    @type str
    @param path list of paths the file should be searched in
    @type list of str
    @param isPyFile flag indicating a Python file
    @type bool
    @return the resulting dictionary
    @rtype dict
    """
    ext = os.path.splitext(module)[1].lower()
    path = [] if path is None else path[:]

    if ext in __extensions["IDL"]:
        moduleType = "idl"
    elif ext in __extensions["ProtoBuf"]:
        moduleType = "protobuf"
    elif ext in __extensions["Ruby"]:
        moduleType = "ruby"
    elif ext in __extensions["JavaScript"]:
        moduleType = "javascript"
    elif ext in Preferences.getPython("Python3Extensions") or isPyFile:
        moduleType = "python"
    else:
        # try Python if it is without extension
        moduleType = "python"

    classBrowserModule = getClassBrowserModule(moduleType)
    if classBrowserModule:
        dictionary = classBrowserModule.readmodule_ex(module, path, isTypeFile=isPyFile)
        classBrowserModule.clearModulesCache()
    else:
        dictionary = {}

    return dictionary


def find_module(name, path, isPyFile=False):
    """
    Function to extend the Python module finding mechanism.

    This function searches for files in the given list of paths. If the
    file name doesn't have an extension or an extension of .py, the normal
    Python search implemented in the imp module is used. For all other
    supported files only the paths list is searched.

    @param name file name or module name to search for
    @type str
    @param path search paths
    @type list of str
    @param isPyFile flag indicating a Python file
    @type bool
    @return tuple of the open file, pathname and description. Description
        is a tuple of file suffix, file mode and file type)
    @rtype tuple
    @exception ImportError The file or module wasn't found.
    """
    ext = os.path.splitext(name)[1].lower()

    if ext in __extensions["Ruby"]:
        sourceType = RB_SOURCE
    elif ext in __extensions["IDL"]:
        sourceType = IDL_SOURCE
    elif ext in __extensions["ProtoBuf"]:
        sourceType = PROTO_SOURCE
    elif ext in __extensions["JavaScript"]:
        sourceType = JS_SOURCE
    elif ext == ".ptl":
        sourceType = PTL_SOURCE
    elif (
        name.lower().endswith(tuple(Preferences.getPython("Python3Extensions")))
        or isPyFile
    ):
        sourceType = PY_SOURCE
    else:
        sourceType = UNKNOWN_SOURCE

    if sourceType != UNKNOWN_SOURCE:
        for p in path:  # search in path
            pathname = os.path.join(p, name)
            if os.path.exists(pathname):
                return (open(pathname), pathname, (ext, "r", sourceType))
                # __IGNORE_WARNING_Y115__
        raise ImportError
    else:
        # standard Python module file
        if name.lower().endswith(".py"):
            name = name[:-3]

        spec = importlib.machinery.PathFinder.find_spec(name, path)
        if spec is None:
            raise ImportError
        if isinstance(spec.loader, importlib.machinery.SourceFileLoader):
            ext = os.path.splitext(spec.origin)[-1]
            return (open(spec.origin), spec.origin, (ext, "r", PY_SOURCE))
            # __IGNORE_WARNING_Y115__

    raise ImportError

eric ide

mercurial