Esempio n. 1
0
 def _populate_existing_modnames(self, names):
     # Populates any name that corresponds to a top-level module
     from xdoctest import static_analysis as static
     for n in names:
         if n not in self.known:
             if static.modname_to_modpath(n) is not None:
                 self.known[n] = 'import {}'.format(n)
Esempio n. 2
0
def _module_exists(modname):
    if modname not in _MODNAME_EXISTS_CACHE:
        from xdoctest import static_analysis as static
        modpath = static.modname_to_modpath(modname)
        exists_flag = modpath is not None
        _MODNAME_EXISTS_CACHE[modname] = exists_flag
    exists_flag = _MODNAME_EXISTS_CACHE[modname]
    return exists_flag
Esempio n. 3
0
def _rectify_to_modpath(modpath_or_name):
    """ if modpath_or_name is a name, statically converts it to a path """
    modpath = static.modname_to_modpath(modpath_or_name)
    if modpath is None:
        if exists(modpath_or_name):
            modpath = modpath_or_name
        else:
            raise ValueError('Cannot find module={}'.format(modpath_or_name))
    return modpath
Esempio n. 4
0
def _static_modname_to_modpath(modname, **kwargs):
    # Calls static.modname_to_modpath with checks
    had = modname in sys.modules
    try:
        modpath = static.modname_to_modpath(modname, **kwargs)
    except ValueError:
        modpath = None
    if not had:
        assert modname not in sys.modules, (
            '{} should not be imported'.format(modname))
    return modpath
Esempio n. 5
0
 def expand_module(path):
     # if True or filetype in {'py', 'pyx'}:
     # filetype = get_current_filetype()
     from xdoctest import static_analysis as static
     try:
         path = static.modname_to_modpath(path)
         # print('rectified module to path = {!r}'.format(path))
     except Exception as ex:
         # if True or filetype in {'py', 'pyx'}:
         return None
     return path
Esempio n. 6
0
def _static_parse_imports(modpath, imports=None, use_all=True):
    # from ubelt.meta import static_analysis as static
    # TODO: port some of this functionality over
    from xdoctest import static_analysis as static
    modname = static.modpath_to_modname(modpath)
    if imports is not None:
        import_paths = {
            m: static.modname_to_modpath(modname + '.' + m, hide_init=False)
            for m in imports
        }
    else:
        imports = []
        import_paths = {}
        for sub_modpath in static.package_modpaths(modpath,
                                                   with_pkg=True,
                                                   recursive=False):
            # print('sub_modpath = {!r}'.format(sub_modpath))
            sub_modname = static.modpath_to_modname(sub_modpath)
            rel_modname = sub_modname[len(modname) + 1:]
            if rel_modname.startswith('_'):
                continue
            if not rel_modname:
                continue
            import_paths[rel_modname] = sub_modpath
            imports.append(rel_modname)
        imports = sorted(imports)

    from_imports = []
    for rel_modname in imports:
        sub_modpath = import_paths[rel_modname]
        with open(sub_modpath, 'r') as file:
            source = file.read()
        valid_callnames = None
        if use_all:
            try:
                valid_callnames = static.parse_static_value('__all__', source)
            except NameError:
                pass
        if valid_callnames is None:
            # The __all__ variable is not specified or we dont care
            top_level = static.TopLevelVisitor.parse(source)
            attrnames = list(top_level.assignments) + list(
                top_level.calldefs.keys())
            # list of names we wont export by default
            invalid_callnames = dir(builtins)
            valid_callnames = []
            for attr in attrnames:
                if '.' in attr or attr.startswith('_'):
                    continue
                if attr in invalid_callnames:
                    continue
                valid_callnames.append(attr)
        from_imports.append((rel_modname, sorted(valid_callnames)))
    return modname, imports, from_imports
Esempio n. 7
0
def _rectify_to_modpath(modpath_or_name):
    """ if modpath_or_name is a name, statically converts it to a path """
    modpath = static_analysis.modname_to_modpath(modpath_or_name)
    if modpath is None:
        if six.PY2:
            if modpath_or_name.endswith('.pyc'):
                modpath_or_name = modpath_or_name[:-1]
        if exists(modpath_or_name):
            modpath = modpath_or_name
        else:
            raise ValueError('Cannot find module={}'.format(modpath_or_name))
    return modpath
Esempio n. 8
0
def modname_to_modpath(modname, hide_init=True, hide_main=True):  # nocover
    r"""
    Finds the path to a python module from its name.

    Determines the path to a python module without directly import it

    Converts the name of a module (__name__) to the path (__file__) where it is
    located without importing the module. Returns None if the module does not
    exist.

    Args:
        modname (str): module filepath
        hide_init (bool): if False, __init__.py will be returned for packages
        hide_main (bool): if False, and hide_init is True, __main__.py will be
            returned for packages, if it exists.

    Returns:
        str: modpath - path to the module, or None if it doesn't exist

    CommandLine:
        python -m ubelt.util_import modname_to_modpath

    Example:
        >>> from ubelt.util_import import *  # NOQA
        >>> import sys
        >>> modname = 'ubelt.progiter'
        >>> already_exists = modname in sys.modules
        >>> modpath = modname_to_modpath(modname)
        >>> print('modpath = %r' % (modpath,))
        >>> assert already_exists or modname not in sys.modules

    Example:
        >>> from ubelt.util_import import *  # NOQA
        >>> import sys
        >>> modname = 'ubelt.__main__'
        >>> modpath = modname_to_modpath(modname, hide_main=False)
        >>> print('modpath = %r' % (modpath,))
        >>> assert modpath.endswith('__main__.py')
        >>> modname = 'ubelt'
        >>> modpath = modname_to_modpath(modname, hide_init=False)
        >>> print('modpath = %r' % (modpath,))
        >>> assert modpath.endswith('__init__.py')
        >>> modname = 'ubelt'
        >>> modpath = modname_to_modpath(modname, hide_init=False, hide_main=False)
        >>> print('modpath = %r' % (modpath,))
        >>> assert modpath.endswith('__init__.py')
    """
    from xdoctest import static_analysis as static
    return static.modname_to_modpath(modname, hide_init, hide_main)
Esempio n. 9
0
def autogen_init(modpath_or_name,
                 imports=None,
                 attrs=True,
                 use_all=True,
                 dry=False):
    """
    Autogenerates imports for a package __init__.py file.

    Args:
        modpath_or_name (str): path to or name of a package module.
            The path should reference the dirname not the __init__.py file.
            If specified by name, must be findable from the PYTHONPATH.
        imports (list): if specified, then only these specific submodules are
            used in package generation. Otherwise, all non underscore prefixed
            modules are used.
        attrs (bool): if False, then module attributes will not be
            imported.
        use_all (bool): if False the `__all__` attribute is ignored.
        dry (bool): if True, the autogenerated string is not written

    Notes:
        This will partially override the __init__ file. By default everything
        up to the last comment / __future__ import is preserved, and everything
        after is overriden.  For more fine grained control, you can specify
        XML-like `# <AUTOGEN_INIT>` and `# </AUTOGEN_INIT>` comments around the
        volitle area. If specified only the area between these tags will be
        overwritten.

        To autogenerate a module on demand, its useful to keep a doctr comment
        in the __init__ file like this:
            python -c "import ubelt._internal as a; a.autogen_init('<your_module_path_or_name>')"
    """
    # from ubelt import util_import
    from xdoctest import static_analysis as static
    if exists(modpath_or_name):
        modpath = modpath_or_name
    else:
        modpath = static.modname_to_modpath(modpath_or_name)
        if modpath is None:
            raise ValueError('Invalid module {}'.format(modpath_or_name))

    if imports is None:
        # the __init__ file may have a variable describing the correct imports
        # should imports specify the name of this variable or should it always
        # be GLOBAL_MODULES?
        with open(join(modpath, '__init__.py'), 'r') as file:
            source = file.read()
        varname = 'GLOBAL_MODULES'
        try:
            imports = static.parse_static_value(varname, source)
        except NameError:
            pass

    modname, imports, from_imports = _static_parse_imports(modpath,
                                                           imports=imports,
                                                           use_all=use_all)
    if not attrs:
        from_imports = []
    initstr = _initstr(modname, imports, from_imports, withheader=False)
    if dry:
        print(initstr)
    else:
        _autogen_init_write(modpath, initstr)