[PATCH 1 of 4 V3] import-checker: add utility to examine what module is imported easily

FUJIWARA Katsunori foozy at lares.dti.ne.jp
Sun May 17 18:12:02 UTC 2015


# HG changeset patch
# User FUJIWARA Katsunori <foozy at lares.dti.ne.jp>
# Date 1431885022 -32400
#      Mon May 18 02:50:22 2015 +0900
# Node ID 9a5603b2424cb01f4f5aa141d5d183ddf59efa03
# Parent  1ef96a3b8b89a896f2c9f3f977dbef8f45bb0e26
import-checker: add utility to examine what module is imported easily

`fromlocalfunc()` uses:

  - `modulename` (of the target source) to compose absolute module
    name imported relatively from it

    It is assumed that `modulename` is an `dotted_name_of_path()`-ed
    source file, which may have `.__init__` at the end of it.

    This assumption makes composing `prefix` of relative name easy.

  - `localmods` to examine whether there is a locally defined (=
    Mercurial specific) module matching against the specified name

    It is assumed that module names not existing in `localmods` are
    ones of Python standard library.

diff --git a/contrib/import-checker.py b/contrib/import-checker.py
--- a/contrib/import-checker.py
+++ b/contrib/import-checker.py
@@ -26,6 +26,72 @@ def dotted_name_of_path(path, trimpure=F
         return '.'.join(p for p in parts if p != 'pure')
     return '.'.join(parts)
 
+def fromlocalfunc(modulename, localmods):
+    """Get a function to examine which locally defined module the
+    target source imports via a specified name.
+
+    `modulename` is an `dotted_name_of_path()`-ed source file path,
+    which may have `.__init__` at the end of it, of the target source.
+
+    `localmods` is a dict (or set), of which key is an absolute
+    `dotted_name_of_path()`-ed source file path of locally defined (=
+    Mercurial specific) modules.
+
+    This function assumes that module names not existing in
+    `localmods` are ones of Python standard libarary.
+
+    This function returns the function, which takes `name` argument,
+    and returns `(absname, dottedpath, hassubmod)` tuple if `name`
+    matches against locally defined module. Otherwise, it returns
+    False.
+
+    It is assumed that `name` doesn't have `.__init__`.
+
+    `absname` is an absolute module name of specified `name`
+    (e.g. "hgext.convert"). This can be used to compose prefix for sub
+    modules or so.
+
+    `dottedpath` is a `dotted_name_of_path()`-ed source file path
+    (e.g. "hgext.convert.__init__") of `name`. This is used to look
+    module up in `localmods` again.
+
+    `hassubmod` is whether it may have sub modules under it (for
+    convenient, even though this is also equivalent to "absname !=
+    dottednpath")
+
+    >>> localmods = {'foo.__init__': True, 'foo.foo1': True,
+    ...              'foo.bar.__init__': True, 'foo.bar.bar1': True,
+    ...              'baz.__init__': True, 'baz.baz1': True }
+    >>> fromlocal = fromlocalfunc('foo.xxx', localmods)
+    >>> # relative
+    >>> fromlocal('foo1')
+    ('foo.foo1', 'foo.foo1', False)
+    >>> fromlocal('bar')
+    ('foo.bar', 'foo.bar.__init__', True)
+    >>> fromlocal('bar.bar1')
+    ('foo.bar.bar1', 'foo.bar.bar1', False)
+    >>> # absolute
+    >>> fromlocal('baz')
+    ('baz', 'baz.__init__', True)
+    >>> fromlocal('baz.baz1')
+    ('baz.baz1', 'baz.baz1', False)
+    >>> # unknown = maybe standard library
+    >>> fromlocal('os')
+    False
+    """
+    prefix = '.'.join(modulename.split('.')[:-1])
+    if prefix:
+        prefix += '.'
+    def fromlocal(name):
+        # check relative name at first
+        for n in prefix + name, name:
+            if n in localmods:
+                return (n, n, False)
+            dottedpath = n + '.__init__'
+            if dottedpath in localmods:
+                return (n, dottedpath, True)
+        return False
+    return fromlocal
 
 def list_stdlib_modules():
     """List the modules present in the stdlib.


More information about the Mercurial-devel mailing list