Autoloader (was Re: [Python-Dev] Adding Optik to 2.3 standard library) (original) (raw)

Barry A. Warsaw barry@zope.com
Mon, 15 Apr 2002 10:12:42 -0400


I've now uploaded a patch (really a tarball) to

http://sourceforge.net/tracker/index.php?func=detail&aid=544175&group_id=38019&atid=421099

Below is the init.py. I found that _copysyms() was necessary because if you just pulled in the exported symbols from say, getopt, getopt.getopt() wouldn't find the helper functions which are global to its namespace. Oh well. It does mean you have to watch out for name collisions when stitching stuff together like this.

You also have to play funny games with imports to get them to work right (you can't do intra-package imports through fully-qualified getopt.* imports).

-Barry

P.S. I think that ImportError probably ought to be an AttributeError

-------------------- snip snip --------------------

Copyright (c) 2002 Python Software Foundation

As of Python 2.3, we now have two command line option parsing systems, the

legacy getopt interface and Greg Ward's Optik. The code below provides a

lazy loading system so that only the option parsers requested are actually

loaded from this submodule.

Autoloader class, see

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65207

import sys

class _Autoloader: # legacy getopt module exports these symbols getopt_exports = ['getopt', 'GetoptError', 'error']

# Optik exports these symbols
optik_exports = ['OptionParser', 'SUPPRESS_HELP', 'SUPPRESS_USAGE',
                  'STD_HELP_OPTION', 'OptionValueError']

def __getattr__(self, name):
    if name in self.getopt_exports:
        import _getopt._getopt
        self._copysyms(_getopt._getopt)
    elif name in self.optik_exports:
        # Import the whole Optik world
        import _getopt.option
        self._copysyms(_getopt.option)
        import _getopt.option_parser
        self._copysyms(_getopt.option_parser)
        import _getopt.errors
        self._copysyms(_getopt.errors)
    else:
        raise ImportError, name
    return self.__dict__[name]

# If we don't copy all the globals from the module, we'll get exceptions
# when publically exported names try to access other globals in the same
# module.
def _copysyms(self, module):
    for name in dir(module):
        self.__dict__[name] = getattr(module, name)

So we can do sub-imports later

sys.modules['_getopt'] = sys.modules[name] sys.modules[name] = _Autoloader()