def list(): """ Enumerate all top-level packages/modules. @rtype: C{tuple} of L{ModuleHandle}s """ import pkgutil # Get the list of top-level packages/modules using pkgutil. # We exclude "." from sys.path while doing so. Python includes "." in # sys.path by default, but this is undesirable for autoimporting. If # we autoimported random python scripts in the current directory, we # could accidentally execute code with side effects. If the current # working directory is /tmp, trying to enumerate modules there also # causes problems, because there are typically directories there not # readable by the current user. with ExcludeImplicitCwdFromPathCtx(): modlist = pkgutil.iter_modules(None) module_names = [t[1] for t in modlist] # pkgutil includes all *.py even if the name isn't a legal python # module name, e.g. if a directory in $PYTHONPATH has files named # "try.py" or "123.py", pkgutil will return entries named "try" or # "123". Filter those out. module_names = [m for m in module_names if is_identifier(m)] # Canonicalize. return tuple(ModuleHandle(m) for m in sorted(set(module_names)))
def test_is_identifier_unicode(): assert is_identifier('א') assert not is_identifier('א.') assert not is_identifier('א.א') assert not is_identifier('א.', prefix=True) assert is_identifier('א.', dotted=True, prefix=True) assert is_identifier('א.א', dotted=True)
def _from_args(cls, args, ignore_nonimports=False, ignore_shadowed=False): """ @type args: C{tuple} or C{list} of L{ImportStatement}s, L{PythonStatement}s, L{PythonBlock}s, L{FileText}, and/or L{Filename}s @param ignore_nonimports: If C{False}, complain about non-imports. If C{True}, ignore non-imports. @param ignore_shadowed: See L{ImportSet.__new__}. @rtype: L{ImportSet} """ if not isinstance(args, (tuple, list)): args = [args] # Filter empty arguments to allow the subsequent optimizations to work # more often. args = [a for a in args if a] if not args: return cls._EMPTY # If we only got one C{ImportSet}, just return it. if len(args) == 1 and type(args[0]) is cls and not ignore_shadowed: return args[0] # Collect all L{Import}s from arguments. imports = [] for arg in args: if isinstance(arg, Import): imports.append(arg) elif isinstance(arg, ImportSet): imports.extend(arg.imports) elif isinstance(arg, ImportStatement): imports.extend(arg.imports) elif isinstance(arg, str) and is_identifier(arg, dotted=True): imports.append(Import(arg)) else: # PythonBlock, PythonStatement, Filename, FileText, str block = PythonBlock(arg) for statement in block.statements: # Ignore comments/blanks. if statement.is_comment_or_blank: pass elif statement.is_import: imports.extend(ImportStatement(statement).imports) elif ignore_nonimports: pass else: raise NonImportStatementError( "Got non-import statement %r" % (statement, )) return cls._from_imports(imports, ignore_shadowed=ignore_shadowed)
def _from_args(cls, args, ignore_nonimports=False, ignore_shadowed=False): """ :type args: ``tuple`` or ``list`` of `ImportStatement` s, `PythonStatement` s, `PythonBlock` s, `FileText`, and/or `Filename` s :param ignore_nonimports: If ``False``, complain about non-imports. If ``True``, ignore non-imports. :param ignore_shadowed: See `ImportSet.__new__`. :rtype: `ImportSet` """ if not isinstance(args, (tuple, list)): args = [args] # Filter empty arguments to allow the subsequent optimizations to work # more often. args = [a for a in args if a] if not args: return cls._EMPTY # If we only got one ``ImportSet``, just return it. if len(args) == 1 and type(args[0]) is cls and not ignore_shadowed: return args[0] # Collect all `Import` s from arguments. imports = [] for arg in args: if isinstance(arg, Import): imports.append(arg) elif isinstance(arg, ImportSet): imports.extend(arg.imports) elif isinstance(arg, ImportStatement): imports.extend(arg.imports) elif isinstance(arg, str) and is_identifier(arg, dotted=True): imports.append(Import(arg)) else: # PythonBlock, PythonStatement, Filename, FileText, str block = PythonBlock(arg) for statement in block.statements: # Ignore comments/blanks. if statement.is_comment_or_blank: pass elif statement.is_import: imports.extend(ImportStatement(statement).imports) elif ignore_nonimports: pass else: raise NonImportStatementError( "Got non-import statement %r" % (statement,)) return cls._from_imports(imports, ignore_shadowed=ignore_shadowed)
def _from_identifier_or_statement(cls, arg): """ Parse either a raw identifier or a statement. >>> Import._from_identifier_or_statement('foo.bar.baz') Import('from foo.bar import baz') >>> Import._from_identifier_or_statement('import foo.bar.baz') Import('import foo.bar.baz') @rtype: L{Import} """ if is_identifier(arg, dotted=True): return cls.from_parts(arg, arg.split('.')[-1]) else: return cls._from_statement(arg)
def test_is_identifier_empty_1(): assert not is_identifier("", ) assert not is_identifier("", dotted=True) assert is_identifier("", prefix=True) assert is_identifier("", dotted=True, prefix=True)
def test_is_identifier_prefix_keyword_1(): assert not is_identifier("foo.or", dotted=True) assert is_identifier("foo.or", dotted=True, prefix=True)
def test_is_identifier_prefix_trailing_dot_1(): assert not is_identifier("foo.bar.", dotted=True) assert is_identifier("foo.bar.", dotted=True, prefix=True)
def test_is_identifier_dotted_print_1(): assert is_identifier("foo.print.bar", dotted=True)
def test_is_identifier_dotted_keyword_1(): assert not is_identifier("foo.from", dotted=True)
def test_is_identifier_bad_dotted_1(): assert not is_identifier("foo..bar", dotted=True)
def test_is_identifier_unwanted_dot_1(): assert not is_identifier("foo.bar")
def test_is_identifier_print_1(): assert is_identifier("print")
def test_is_identifier_keyword_1(): assert not is_identifier("from")
def test_is_identifier_bad_char_1(): assert not is_identifier("foo+bar")
def test_is_identifier_basic_1(): assert is_identifier("foo")