#!/usr/bin/env python
#
# $Source: /home/blais/repos/cvsroot/pydeps/bin/pydeps-path,v $
# $Id: pydeps-path,v 1.1 2004/02/03 18:44:45 blais Exp $
#

"""pydeps-path [<options>] <file> [<file> ...]

Compute and print which PYTHONPATH component an import dependency for a module
comes from.
"""

__version__ = "$Revision: 1.1 $"
__author__ = "Martin Blais <blais@furius.ca>"


import sys, os, re
from os.path import *

import imp

from pprint import pprint




impre = re.compile('\s*import\s*([^;]*)\s*')
fromre = re.compile('\s*from\s*([^;]*)\s*import')
asre = re.compile('(\S+)\s+as\s+\S+')

def finddeps( fn ):

    """Opens a file and extracts the imported modules."""

    try:
        lines = map(lambda x: x.strip(), open(fn, 'r').readlines())
    except IOError, e:
        raise SystemExit("Error: reading file (%s)" % str(e))

    modules = {}
    for l in lines:
        mo = impre.match(l.strip())
        mods = None
        if mo:
            mods = mo.group(1)
        else:
            mo = fromre.match(l)
            if mo:
                mods = mo.group(1)
        if mods:
            for modname in mods.split(','):
                modname = modname.strip()
                mo = asre.match(modname)
                if mo:
                    modname = mo.group(1)
                modules[modname] = True
    
    return modules.keys()

def graph( pairs ):
    
    print """
digraph "source tree" {
    overlap=scale;
    size="8,10";
    ratio="fill";
    fontsize="16";
    fontname="Helvetica";
        clusterrank="local";
"""
    for p in pairs:
        print '"%s" -> "%s" ;' % p

    print "}"

def __import_final__(name):

    """Import that returns the final component module.  This is exactly from the
    Library Reference documentation in builtin-functions."""

    mod = __import__(name)
    components = name.split('.')
    for comp in components[1:]:
        mod = getattr(mod, comp)
    return mod


def main():
    import optparse
    parser = optparse.OptionParser(__doc__.strip(), version=__version__)
    parser.add_option('-p', '--restrict-path', action='append',
                      help="Restricts modules in the given path.")
    parser.add_option('-P', '--subpath', action='store_true',
                      help="Prints only first path component.")
    import optcomplete; optcomplete.autocomplete(parser)
    opts, args = parser.parse_args()

    # Create initial list of unresolve dependencies in the depends map.
    pathcomps = {}

    for fn in args:
        deps = finddeps(fn)

        adeps = []
        for dep in deps:
            try:
                impdep = __import_final__(dep)
            except ImportError:
                continue

            try:
                dfn = impdep.__file__
                for p in sys.path:
                    if dfn.startswith(p):
                        val = None

                        # Reject if not under path restriction.
                        if opts.restrict_path:
                            ok = False
                            for pfn in opts.restrict_path:
                                if dfn.startswith(pfn):
                                    ok = True
                                    break
                            if not ok:
                                continue
                            val = filter(None, dfn[len(pfn):].split(os.sep))[0]

                        pathcomps[p] = val
            except AttributeError:
                pass

    for p, v in pathcomps.iteritems():
        if opts.subpath:
            print v
        else:
            print p
    
if __name__ == '__main__':
    main()