Example #1
0
def test_eqne_1():
    m1a = ModuleHandle("foo.bar")
    m1b = ModuleHandle("foo.bar")
    m2  = ModuleHandle("foo.baz")
    assert     (m1a == m1b)
    assert not (m1a != m1b)
    assert not (m1a == m2)
    assert     (m1a != m2)
Example #2
0
def describe_xref(identifier, container):
    module = ModuleHandle(str(container.defining_module.canonical_name))
    assert module.filename == Filename(container.defining_module.filename)
    linenos = get_string_linenos(
        module,
        "(L{|<)%s" % (identifier,),
        container.docstring)
    return (module, linenos, str(container.canonical_name), identifier)
Example #3
0
    def check_xref(self, identifier, container):
        """
        Check that ``identifier`` cross-references a proper symbol.

        Look in modules that we weren't explicitly asked to look in, if
        needed.
        """
        if identifier in builtins.__dict__:
            return True
        def check_container():
            if self.expanded_docindex.find(identifier, container) is not None:
                return True
            if isinstance(container, RoutineDoc):
                tcontainer = self.expanded_docindex.get_vardoc(
                    container.canonical_name)
                doc = self.expanded_docindex.find(identifier, tcontainer)
                while (doc is not None and tcontainer not in (None, UNKNOWN)
                       and tcontainer.overrides not in (None, UNKNOWN)):
                    tcontainer = tcontainer.overrides
                    doc = self.expanded_docindex.find(identifier, tcontainer)
                return doc is not None
            return False
        def check_defining_module(x):
            if x is None:
                return False
            defining_module_name = remove_epydoc_sym_suffix(str(
                x.defining_module.canonical_name))
            if defining_module_name in ASSUME_MODULES_OK:
                return True
            if self.expanded_docindex.add_module(defining_module_name):
                if check_container():
                    return True
            return False
        if check_container():
            return True
        if (isinstance(container, RoutineDoc) and
            identifier in container.all_args()):
            return True
        if check_defining_module(container):
            return True
        # If the user has imported foo.bar.baz as baz and now uses
        # ``baz.quux``, we need to add the module foo.bar.baz.
        for prefix in reversed(list(prefixes(
                    DottedIdentifier(remove_epydoc_sym_suffix(identifier))))):
            if check_defining_module(
                self.docindex.find(str(prefix), container)):
                return True
        try:
            module = ModuleHandle.containing(identifier)
        except ImportError:
            pass
        else:
            if str(module.name) in ASSUME_MODULES_OK:
                return True
            if self.expanded_docindex.add_module(module):
                if check_container():
                    return True
        return False
Example #4
0
def get_string_linenos(module, searchstring, within_string):
    """
    Return the line numbers (1-indexed) within C{filename} that contain
    C{searchstring}.  Only consider string literals (i.e. not comments).
    First look for exact matches of C{within_string} (modulo indenting) and
    then search within that.  Only if the C{within_string} is not found,
    search the entire file.

    [If there's a comment on the same line as a string that also contains the
    searchstring, we'll get confused.]
    """
    module = ModuleHandle(module)
    regexp = re.compile(searchstring)
    map = map_strings_to_line_numbers(module)
    results = []

    def scan_within_string(results, start_lineno, orig_full_string):
        for i, line in enumerate(orig_full_string.splitlines()):
            if regexp.search(line):
                results.append(start_lineno + i)

    try:
        lineno, orig_full_string = map[within_string.strip()]
    except KeyError:
        pass
    else:
        # We found the larger string exactly within the ast.
        scan_within_string(results, lineno, orig_full_string)
        if results:
            return tuple(results)
        # We could continue down if this ever happened.
        raise Exception(
            "Found superstring in %r but not substring %r within superstring" %
            (module.filename, searchstring))
    # Try a full text search.
    for lineno, orig_full_string in map.values():
        scan_within_string(results, lineno, orig_full_string)
    if results:
        return tuple(sorted(results))
    raise Exception("Could not find %r anywhere in %r" %
                    (searchstring, module.filename))
Example #5
0
    def add_module(self, module):
        """
        Adds ``module`` and recreates the DocIndex with the updated set of
        modules.

        :return:
          Whether anything was added.
        """
        module = ModuleHandle(module)
        for prefix in module.ancestors:
            if prefix in self.modules:
                # The module, or a prefix of it, was already added.
                return False

        for existing_module in sorted(self.modules):
            if existing_module.startswith(module):
                # This supersedes an existing module.
                assert existing_module != module
                self.modules.remove(existing_module)

        logger.debug("Expanding docindex to include %r", module)
        self.modules.add(module)
        del self.docindex
        return True
Example #6
0
def replace_star_imports(codeblock, params=None):
    r"""
    Replace lines such as::
      from foo.bar import *
    with
      from foo.bar import f1, f2, f3

    Note that this requires involves actually importing C{foo.bar}, which may
    have side effects.  (TODO: rewrite to avoid this?)

    The result includes all imports from the C{email} module.  The result
    excludes shadowed imports.  In this example:
      1. The original C{MIMEAudio} import is shadowed, so it is removed.
      2. The C{MIMEImage} import in the C{email} module is shadowed by a
         subsequent import, so it is omitted.

      >>> codeblock = PythonBlock('from keyword import *', filename="/tmp/x.py")

      >>> print replace_star_imports(codeblock)
      [PYFLYBY] /tmp/x.py: replaced 'from keyword import *' with 2 imports
      from keyword import iskeyword, kwlist
      <BLANKLINE>

    Usually you'll want to remove unused imports after replacing star imports.

    @type codeblock:
      L{PythonBlock} or convertible (C{str})
    @rtype:
      L{PythonBlock}
    """
    from pyflyby._modules import ModuleHandle
    params = ImportFormatParams(params)
    codeblock = PythonBlock(codeblock)
    filename = codeblock.filename
    transformer = SourceToSourceFileImportsTransformation(codeblock)
    for block in transformer.import_blocks:
        # Iterate over the import statements in C{block.input}.  We do this
        # instead of using C{block.importset} because the latter doesn't
        # preserve the order of inputs.  The order is important for
        # determining what's shadowed.
        imports = [
            imp for s in block.input.statements
            for imp in ImportStatement(s).imports
        ]
        # Process "from ... import *" statements.
        new_imports = []
        for imp in imports:
            if imp.split.member_name != "*":
                new_imports.append(imp)
            elif imp.split.module_name.startswith("."):
                # The source contains e.g. "from .foo import *".  Right now we
                # don't have a good way to figure out the absolute module
                # name, so we can't get at foo.  That said, there's a decent
                # chance that this is inside an __init__ anyway, which is one
                # of the few justifiable use cases for star imports in library
                # code.
                logger.warning(
                    "%s: can't replace star imports in relative import: %s",
                    filename,
                    imp.pretty_print().strip())
                new_imports.append(imp)
            else:
                module = ModuleHandle(imp.split.module_name)
                try:
                    with ImportPathForRelativeImportsCtx(codeblock):
                        exports = module.exports
                except Exception as e:
                    logger.warning(
                        "%s: couldn't import '%s' to enumerate exports, "
                        "leaving unchanged: '%s'.  %s: %s", filename,
                        module.name, imp,
                        type(e).__name__, e)
                    new_imports.append(imp)
                    continue
                if not exports:
                    # We found nothing in the target module.  This probably
                    # means that module itself is just importing things from
                    # other modules.  Currently we intentionally exclude those
                    # imports since usually we don't want them.  TODO: do
                    # something better here.
                    logger.warning("%s: found nothing to import from %s, ",
                                   "leaving unchanged: '%s'", filename, module,
                                   imp)
                    new_imports.append(imp)
                else:
                    new_imports.extend(exports)
                    logger.info("%s: replaced %r with %d imports", filename,
                                imp.pretty_print().strip(), len(exports))
        block.importset = ImportSet(new_imports, ignore_shadowed=True)
    return transformer.output(params=params)
Example #7
0
 def __init__(self, modules):
     self.modules = set([ModuleHandle(m) for m in modules])
Example #8
0
def test_find_bad_doc_cross_references_1():
    result = find_bad_doc_cross_references([xrefs])
    expected = (
        (ModuleHandle('tests.xrefs'), (3, ), 'tests.xrefs',
         u'undefined_xref_from_module'),
        (ModuleHandle('tests.xrefs'), (18, ), 'tests.xrefs.FooClass',
         u'undefined_xref_from_class'),
        # TODO: undefined_xref_from_class_attribute
        (ModuleHandle('tests.xrefs'), (30, ),
         'tests.xrefs.FooClass.foo_method', u'undefined_xref_from_method'),
        (ModuleHandle('tests.xrefs'), (37, ),
         'tests.xrefs.FooClass.foo_wrapped_method',
         u'undefined_xref_from_wrapped_method'),
        (ModuleHandle('tests.xrefs'), (40, ),
         'tests.xrefs.FooClass.foo_wrapped_method',
         u'undefined_xref_from_param'),
        (ModuleHandle('tests.xrefs'), (42, ),
         'tests.xrefs.FooClass.foo_wrapped_method',
         u'undefined_xref_from_type'),
        (ModuleHandle('tests.xrefs'), (44, ),
         'tests.xrefs.FooClass.foo_wrapped_method',
         u'undefined_xref_from_args_param'),
        (ModuleHandle('tests.xrefs'), (46, ),
         'tests.xrefs.FooClass.foo_wrapped_method',
         u'undefined_xref_from_args_type'),
        (ModuleHandle('tests.xrefs'), (48, ),
         'tests.xrefs.FooClass.foo_wrapped_method',
         u'undefined_xref_from_kwargs_param'),
        (ModuleHandle('tests.xrefs'), (50, ),
         'tests.xrefs.FooClass.foo_wrapped_method',
         u'undefined_xref_from_kwargs_type'),
        (ModuleHandle('tests.xrefs'), (52, ),
         'tests.xrefs.FooClass.foo_wrapped_method',
         u'undefined_xref_from_rtype'),
        (ModuleHandle('tests.xrefs'), (60, 63),
         'tests.xrefs.FooClass.foo_property', u'undefined_xref_from_property'),
        (ModuleHandle('tests.xrefs'), (63, ), '??.foo_property',
         u'undefined_xref_from_property_rtype'),
        (ModuleHandle('tests.xrefs'), (70, ),
         'tests.xrefs.FooClass.__foo_private_method',
         u'undefined_xref_from_private_method'),
        (ModuleHandle('tests.xrefs'), (76, ),
         'tests.xrefs.foo_global_function',
         u'undefined_xref_from_global_function'),
    )
    assert result == expected
Example #9
0
def test_module_1():
    m = ModuleHandle("logging")
    assert m.module is logging
Example #10
0
def test_filename_init_1():
    fn = logging.__file__
    fn = Filename(re.sub("[.]pyc$", ".py", fn)).real
    m = ModuleHandle("logging")
    assert m.filename.real == fn
    assert m.filename.base == "__init__.py"
Example #11
0
def test_ModuleHandle_from_module_1():
    m = ModuleHandle(logging.handlers)
    assert m == ModuleHandle("logging.handlers")
    assert m.name == DottedIdentifier("logging.handlers")
Example #12
0
def test_ModuleHandle_dotted_1():
    m = ModuleHandle("logging.handlers")
    assert m.name == DottedIdentifier("logging.handlers")
Example #13
0
def test_ModuleHandle_1():
    m = ModuleHandle("sys")
    assert m.name == DottedIdentifier("sys")
Example #14
0
def test_find_bad_doc_cross_references_1():
    from pyflyby._docxref import find_bad_doc_cross_references
    from pyflyby._modules import ModuleHandle

    result = find_bad_doc_cross_references([xrefs])
    expected = (
        (ModuleHandle('tests.xrefs'), (3, ), 'tests.xrefs',
         u'undefined_xref_from_module'),
        (ModuleHandle('tests.xrefs'), (19, ), 'tests.xrefs.FooClass',
         u'undefined_xref_from_class'),
        # TODO: undefined_xref_from_class_attribute
        (ModuleHandle('tests.xrefs'), (31, ),
         'tests.xrefs.FooClass.foo_method', u'undefined_xref_from_method'),
        (ModuleHandle('tests.xrefs'), (38, ),
         'tests.xrefs.FooClass.foo_wrapped_method',
         u'undefined_xref_from_wrapped_method'),
        (ModuleHandle('tests.xrefs'), (41, ),
         'tests.xrefs.FooClass.foo_wrapped_method',
         u'undefined_xref_from_param'),
        (ModuleHandle('tests.xrefs'), (43, ),
         'tests.xrefs.FooClass.foo_wrapped_method',
         u'undefined_xref_from_type'),
        (ModuleHandle('tests.xrefs'), (45, ),
         'tests.xrefs.FooClass.foo_wrapped_method',
         u'undefined_xref_from_args_param'),
        (ModuleHandle('tests.xrefs'), (47, ),
         'tests.xrefs.FooClass.foo_wrapped_method',
         u'undefined_xref_from_args_type'),
        (ModuleHandle('tests.xrefs'), (49, ),
         'tests.xrefs.FooClass.foo_wrapped_method',
         u'undefined_xref_from_kwargs_param'),
        (ModuleHandle('tests.xrefs'), (51, ),
         'tests.xrefs.FooClass.foo_wrapped_method',
         u'undefined_xref_from_kwargs_type'),
        (ModuleHandle('tests.xrefs'), (53, ),
         'tests.xrefs.FooClass.foo_wrapped_method',
         u'undefined_xref_from_rtype'),
        (ModuleHandle('tests.xrefs'), (61, 64),
         'tests.xrefs.FooClass.foo_property', u'undefined_xref_from_property'),
        (ModuleHandle('tests.xrefs'), (64, ), '??.foo_property',
         u'undefined_xref_from_property_rtype'),
        (ModuleHandle('tests.xrefs'), (71, ),
         'tests.xrefs.FooClass.__foo_private_method',
         u'undefined_xref_from_private_method'),
        (ModuleHandle('tests.xrefs'), (77, ),
         'tests.xrefs.foo_global_function',
         u'undefined_xref_from_global_function'),
    )
    assert result == expected