Patchwork [1,of,4,V2] import-checker: add utility to examine what module is imported easily

login
register
mail settings
Submitter Katsunori FUJIWARA
Date May 15, 2015, 2:13 p.m.
Message ID <d7a3d39a03eccc94a164.1431699225@juju>
Download mbox | patch
Permalink /patch/9094/
State Accepted
Commit cccff2f636951ef29cc6917ef48a69ba51645b48
Delegated to: Augie Fackler
Headers show

Comments

Katsunori FUJIWARA - May 15, 2015, 2:13 p.m.
# HG changeset patch
# User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
# Date 1431699038 -32400
#      Fri May 15 23:10:38 2015 +0900
# Node ID d7a3d39a03eccc94a164ba44704452d7233c71d5
# Parent  d1bd0fd07ee6adf4ab3be2b0a0a7c0df54d55abf
import-checker: add utility to examine what module is imported easily
Augie Fackler - May 15, 2015, 9:31 p.m.
> On May 15, 2015, at 10:13, FUJIWARA Katsunori <foozy@lares.dti.ne.jp> wrote:
> 
> # HG changeset patch
> # User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
> # Date 1431699038 -32400
> #      Fri May 15 23:10:38 2015 +0900
> # Node ID d7a3d39a03eccc94a164ba44704452d7233c71d5
> # Parent  d1bd0fd07ee6adf4ab3be2b0a0a7c0df54d55abf
> import-checker: add utility to examine what module is imported easily

So, I've tried to make sense of this patch a couple of times, and I'm at a loss.

I *think* what this does is that given a module name and a list of "localmods" (but I'm not sure what I'd put in localmods), it returns the canonicalized full-dotted-path of a module?

I think this needs a description in the docstring of `fromlocalfunc` as to what `localmods` should be, and perhaps some wordsmithing around the "what" in the docstring (and probably the commit message too).


> 
> 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,58 @@ 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 whether specified name causes
> +    importing locally defined one
> +
> +    Returned function takes `name` argument, and returns `(absname,
> +    dottedpath, hassubmod)` tuple if `name` matches against locally
> +    defined module. Otherwise, it returns False.
> +
> +    `absname` is absolute module name of `name`. This can be used to
> +    compose prefix for sub items or so.
> +
> +    `dottedpath` is `dotted_name_of_path()`-ed source file path. This
> +    may have `.__init__` at tne end of it. This is used to follow
> +    import chain.
> +
> +    `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.
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel

Patch

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,58 @@  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 whether specified name causes
+    importing locally defined one
+
+    Returned function takes `name` argument, and returns `(absname,
+    dottedpath, hassubmod)` tuple if `name` matches against locally
+    defined module. Otherwise, it returns False.
+
+    `absname` is absolute module name of `name`. This can be used to
+    compose prefix for sub items or so.
+
+    `dottedpath` is `dotted_name_of_path()`-ed source file path. This
+    may have `.__init__` at tne end of it. This is used to follow
+    import chain.
+
+    `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.