def parse_submodule_definition(modpath): """ Statically determine the submodules that should be auto-imported """ # the __init__ file may have a variable describing the correct imports # should imports specify the name of this variable or should it always # be __submodules__? imports = None init_fpath = join(modpath, '__init__.py') if exists(init_fpath): with open(init_fpath, 'r') as file: source = file.read() try: imports = static.parse_static_value('__submodules__', source) except NameError: try: imports = static.parse_static_value('__SUBMODULES__', source) except NameError: pass return imports
def parse_user_declarations(modpath): """ Statically determine special file-specific user options and declarations """ # the __init__ file may have a variable describing the correct imports # should imports specify the name of this variable or should it always be # __submodules__? user_decl = {} init_fpath = join(modpath, '__init__.py') if exists(init_fpath): with open(init_fpath, 'r') as file: source = file.read() try: # Include only these submodules user_decl['__submodules__'] = static.parse_static_value('__submodules__', source) except NameError: try: user_decl['__submodules__'] = static.parse_static_value('__SUBMODULES__', source) except NameError: pass else: warnings.warn( 'Use __submodules__, __SUBMODULES__ is depricated', DeprecationWarning) try: user_decl['__explicit__'] = static.parse_static_value('__extra_all__', source) except NameError: pass try: user_decl['__external__'] = static.parse_static_value('__external__', source) except NameError: pass try: # Add custom explicitly defined names to this, and they will be # automatically added to the __all__ variable. user_decl['__explicit__'] = static.parse_static_value('__explicit__', source) except NameError: pass try: # Procted items are exposed, but their attributes are not user_decl['__protected__'] = static.parse_static_value('__protected__', source) except NameError: pass try: # Private items and their attributes are not exposed user_decl['__private__'] = static.parse_static_value('__private__', source) except NameError: pass return user_decl
def _extract_attributes(modpath, respect_all=True): """ This is the function that basically simulates import * Example: >>> modpath = static.modname_to_modpath('mkinit', hide_init=False) >>> modpath = static.modname_to_modpath('ubelt.util_path', hide_init=False) >>> _extract_attributes(modpath) """ try: if six.PY2: with open(modpath, 'r') as file: source = file.read() else: with open(modpath, 'r', encoding='utf8') as file: source = file.read() except Exception as ex: # nocover raise IOError('Error reading {}, caused by {}'.format( modpath, repr(ex))) valid_attrs = None if respect_all: # pragma: nobranch try: valid_attrs = static.parse_static_value('__all__', source) except NameError: pass if valid_attrs is None: # The __all__ variable is not specified or we dont care try: top_level = TopLevelVisitor.parse(source) except SyntaxError as ex: msg = 'modpath={} has bad syntax: {}'.format(modpath, ex) raise SyntaxError(msg) attrnames = top_level.attrnames # list of names we wont export by default invalid_callnames = dir(builtins) valid_attrs = [] for attr in attrnames: if attr.startswith('_'): continue if attr in invalid_callnames: # nocover continue valid_attrs.append(attr) return valid_attrs
def _static_parse_imports(modpath, imports=None, use_all=True): """ Args: modpath (str): base path to a package (with an __init__) imports (list): list of submodules to look at in the base package CommandLine: python -m mkinit.static_autogen _static_parse_imports Example: >>> modpath = static.modname_to_modpath('mkinit') >>> tup = _static_parse_imports(modpath, None, True) >>> modname, imports, from_imports = tup >>> # assert 'autogen_init' in imports """ # FIXME: handle the case where the __init__.py file doesn't exist yet modname = static.modpath_to_modname(modpath, check=False) if imports is not None: if modname is None: raise AssertionError('modname is None') import_paths = { m: static.modname_to_modpath(modname + '.' + m, hide_init=False) for m in imports } else: import_paths = dict(_find_local_submodules(modpath)) imports = sorted(import_paths.keys()) from_imports = [] for rel_modname in imports: sub_modpath = import_paths[rel_modname] if sub_modpath is None: raise Exception('Failed to lookup {!r}'.format(rel_modname)) try: if six.PY2: with open(sub_modpath, 'r') as file: source = file.read() else: with open(sub_modpath, 'r', encoding='utf8') as file: source = file.read() except Exception as ex: # nocover raise IOError('Error reading {}, caused by {}'.format( sub_modpath, repr(ex))) valid_attrs = None if use_all: # pragma: nobranch try: valid_attrs = static.parse_static_value('__all__', source) except NameError: pass if valid_attrs is None: # The __all__ variable is not specified or we dont care top_level = TopLevelVisitor.parse(source) attrnames = top_level.attrnames # list of names we wont export by default invalid_callnames = dir(builtins) valid_attrs = [] for attr in attrnames: if attr.startswith('_'): continue if attr in invalid_callnames: # nocover continue valid_attrs.append(attr) from_imports.append((rel_modname, sorted(valid_attrs))) return modname, imports, from_imports