1

How can I know which members module/package defines? By defining I mean:

somemodule.py

import os # <-- Not defined in this module
from os.path import sep # <-- Not defined in this module

I_AM_ATTRIBUTE = None # <-- Is defined in this module

class SomeClass(object): # <-- Is defined also...
    pass

So I need a some sort of function that when called would yield only I_AM_ATTRIBUTE and SomeClass.

Now I have been trying to do using dir(somemodule), but how can I know which ones are defined in somemodule? Checking against __module__ does not work, since that is not defined in modules and attributes (such as os package, or sep attribute).

Apparently wild import (from somemodule import *) also fails to filter those, so is it even possible?

Best I can get is:

import somemodule

for name in dir(somemodule):
    try:
        value = getattr(somemodule, name)
    except:
        pass
    else:
        if hasattr(value, "__module__"):
            if value.__module__ != somemodule.__name__:
                continue
        if hasattr(value, "__name__"):
            if not value.__name__.startswith(__name__):
                continue
        print "somemodule defines:", name

Takes os out, but leaves sep.

Ciantic
  • 6,064
  • 4
  • 54
  • 49
  • 1
    What's wrong with reading the source? You can trivially figure this out by reading? Why not simply read? – S.Lott Jan 13 '10 at 11:07

2 Answers2

1

There is no way to do this. This is because simple attributes (like I_AM_ATTRIBUTE in your example) are simply values stored in the module's dictionary. When they are copied to another module, they are placed in that module's dictionary as well, and there is no way to tell which was the original location. You can only tell with objects that provide a __module__ attribute such as classes and functions.

Regarding wild import, running from somemodule import * on your example will import all attributes, including os and sep. If a package provides an __all__ variable, wild import will import the names contained there. Otherwise, it will import all names not beginning with an underscore, regardless of which module they are originally from.

interjay
  • 107,303
  • 21
  • 270
  • 254
1

What does "define" mean? For me, defined means that some symbol is part of the module's public interface. This matches up with how it seems you're trying to use the term, including in your example, but if you have some purpose which doesn't align with this definition, you'll have to clarify the question on what you're really trying to do. This makes it a documentation issue.

So you can't know what a module defines, and some things which are imported might still be "defined in that module" or "defined to be part of that module's public interface". This happens often when importing from a private module, including C extension modules.

For your own modules, use __all__ (can do that easily) or the informal underscore prefix for non-public (e.g. _private_var = 42). Both conventions are recognized by help() and should be used by other documentation generators.

Community
  • 1
  • 1
  • Heh, I bet you read my earlier question... Since I'm trying to do documentation generator (in fact improving Sphinx) to do automatic package documentation, and pondering the exact fact that if the module does not have `__all__`, what stuff should we document? I'm probably ending to use the above code *if* `__all__` is not defined... It at least drops the "os" and such imports off. – Ciantic Jan 13 '10 at 13:04
  • No, actually I hadn't read it, but I took a stab at what you *really* wanted to do rather than try and fix your attempted solution. :) –  Jan 13 '10 at 13:09
  • If there is no \_\_all\_\_, document everything that does not begin with an underscore, and require the author to add \_\_all\_\_ if that's not what's desired. If you want to add notices like "(this is possibly an implementation detail)" for things which you can detect, such as imported modules, that's also reasonable, but it's hard to tell if those are part of the interface. (For example, os.path is part of the interface, but is a separate module.) –  Jan 13 '10 at 13:12
  • To allow fixes to a module which does not define its own \_\_all\_\_ without modifying that module directly, you might allow configuration which specifies \_\_all\_\_ externally, but be very careful of that getting out of sync. –  Jan 13 '10 at 13:13