view mercurial/packagescan.py @ 2568:52ce0d6bc375

HTTPS: fix python2.3, persistent connections, don't explode if SSL is not available The urllib2 differences between python 2.3 and 2.4 are hidden by using keepalive.py, which also gives us support for persistent connections. Support for HTTPS is enabled only if there's a HTTPSHandler class in urllib2. It's not possible to have separate classes as handlers for HTTP and HTTPS: to support persistent HTTPS connections, we need a class that inherits from both keepalive.HTTPHandler and urllib2.HTTPSHandler. If we try to pass (an instance of) this class and (an instance of) the httphandler class to urllib2.build_opener, this function ends up getting confused, since both classes are subclasses of the HTTPHandler default handler, and raises an exception.
author Alexis S. L. Carvalho <alexis@cecm.usp.br>
date Thu, 06 Jul 2006 03:14:55 -0300
parents 976b6b2a1613
children c4325f0a9b91
line wrap: on
line source

# packagescan.py - Helper module for identifing used modules.
# Used for the py2exe distutil.
# This module must be the first mercurial module imported in setup.py
#
# Copyright 2005 Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
import glob
import os
import sys
import ihooks
import types
import string

# Install this module as fake demandload module
sys.modules['mercurial.demandload'] = sys.modules[__name__]

# Requiredmodules contains the modules imported by demandload.
# Please note that demandload can be invoked before the 
# mercurial.packagescan.scan method is invoked in case a mercurial
# module is imported.
requiredmodules = {} 
def demandload(scope, modules):
    """ fake demandload function that collects the required modules 
        foo            import foo
        foo bar        import foo, bar
        foo.bar        import foo.bar
        foo:bar        from foo import bar
        foo:bar,quux   from foo import bar, quux
        foo.bar:quux   from foo.bar import quux"""

    for m in modules.split():
        mod = None
        try:
            module, fromlist = m.split(':')
            fromlist = fromlist.split(',')
        except:
            module = m
            fromlist = []
        mod = __import__(module, scope, scope, fromlist)
        if fromlist == []:
            # mod is only the top package, but we need all packages
            comp = module.split('.')
            i = 1
            mn = comp[0]
            while True:
                # mn and mod.__name__ might not be the same
                scope[mn] = mod
                requiredmodules[mod.__name__] = 1
                if len(comp) == i: break
                mod = getattr(mod,comp[i]) 
                mn = string.join(comp[:i+1],'.')
                i += 1
        else:
            # mod is the last package in the component list
            requiredmodules[mod.__name__] = 1
            for f in fromlist:
                scope[f] = getattr(mod,f)
                if type(scope[f]) == types.ModuleType:
                    requiredmodules[scope[f].__name__] = 1

class SkipPackage(Exception):
    def __init__(self, reason):
        self.reason = reason

scan_in_progress = False

def scan(libpath,packagename):
    """ helper for finding all required modules of package <packagename> """
    global scan_in_progress
    scan_in_progress = True
    # Use the package in the build directory
    libpath = os.path.abspath(libpath)
    sys.path.insert(0,libpath)
    packdir = os.path.join(libpath,packagename.replace('.', '/'))
    # A normal import would not find the package in
    # the build directory. ihook is used to force the import.
    # After the package is imported the import scope for
    # the following imports is settled.
    p = importfrom(packdir)
    globals()[packagename] = p
    sys.modules[packagename] = p
    # Fetch the python modules in the package
    cwd = os.getcwd()
    os.chdir(packdir)
    pymodulefiles = glob.glob('*.py')
    extmodulefiles = glob.glob('*.pyd')
    os.chdir(cwd)
    # Import all python modules and by that run the fake demandload
    for m in pymodulefiles:
        if m == '__init__.py': continue
        tmp = {}
        mname,ext = os.path.splitext(m)
        fullname = packagename+'.'+mname
        try:
            __import__(fullname,tmp,tmp)
        except SkipPackage, inst:
            print >> sys.stderr, 'skipping %s: %s' % (fullname, inst.reason)
            continue
        requiredmodules[fullname] = 1
    # Import all extension modules and by that run the fake demandload
    for m in extmodulefiles:
        tmp = {}
        mname,ext = os.path.splitext(m)
        fullname = packagename+'.'+mname
        __import__(fullname,tmp,tmp)
        requiredmodules[fullname] = 1

def getmodules():
    return requiredmodules.keys()

def importfrom(filename):
    """
    import module/package from a named file and returns the module.
    It does not check on sys.modules or includes the module in the scope.
    """
    loader = ihooks.BasicModuleLoader()
    path, file = os.path.split(filename)
    name, ext  = os.path.splitext(file)
    m = loader.find_module_in_dir(name, path)
    if not m:
        raise ImportError, name
    m = loader.load_module(name, m)
    return m