# HG changeset patch # User Vadim Gelfer # Date 1141407618 28800 # Node ID bf118f39afd74f8f97483fa4c9c9c871a9340cc9 # Parent 4ced57680ce72d516b30f8238f715169f63d2a19# Parent ca82f20b0c195ef6a1f169de131ef5143b3c0756 merge with crew. diff -r 4ced57680ce7 -r bf118f39afd7 hgext/patchbomb.py --- a/hgext/patchbomb.py Fri Mar 03 09:39:37 2006 -0800 +++ b/hgext/patchbomb.py Fri Mar 03 09:40:18 2006 -0800 @@ -49,20 +49,11 @@ # to = recipient1, recipient2, ... # cc = cc1, cc2, ... -from email.MIMEMultipart import MIMEMultipart -from email.MIMEText import MIMEText -from email.Utils import parseaddr -from mercurial import commands -from mercurial import hg -from mercurial import ui +from mercurial.demandload import * +demandload(globals(), '''email.MIMEMultipart email.MIMEText email.Utils + mercurial:commands,hg,ui + os popen2 smtplib socket sys tempfile time''') from mercurial.i18n import gettext as _ -import os -import popen2 -import smtplib -import socket -import sys -import tempfile -import time try: # readline gives raw_input editing capabilities, but is not @@ -149,7 +140,7 @@ if opts['diffstat']: body += cdiffstat('\n'.join(desc), patch) + '\n\n' body += '\n'.join(patch) - msg = MIMEText(body) + msg = email.MIMEText.MIMEText(body) subj = '[PATCH %d of %d] %s' % (idx, total, desc[0].strip()) if subj.endswith('.'): subj = subj[:-1] msg['Subject'] = subj @@ -194,7 +185,7 @@ sender = (opts['from'] or ui.config('patchbomb', 'from') or prompt('From', ui.username())) - msg = MIMEMultipart() + msg = email.MIMEMultipart.MIMEMultipart() msg['Subject'] = '[PATCH 0 of %d] %s' % ( len(patches), opts['subject'] or @@ -217,13 +208,13 @@ if l == '.': break body.append(l) - msg.attach(MIMEText('\n'.join(body) + '\n')) + msg.attach(email.MIMEText.MIMEText('\n'.join(body) + '\n')) ui.write('\n') if opts['diffstat']: d = cdiffstat(_('Final summary:\n'), jumbo) - if d: msg.attach(MIMEText(d)) + if d: msg.attach(email.MIMEText.MIMEText(d)) msgs.insert(0, msg) @@ -241,7 +232,7 @@ s.login(username, password) parent = None tz = time.strftime('%z') - sender_addr = parseaddr(sender)[1] + sender_addr = email.Utils.parseaddr(sender)[1] for m in msgs: try: m['Message-Id'] = genmsgid(m['X-Mercurial-Node']) diff -r 4ced57680ce7 -r bf118f39afd7 mercurial/demandload.py --- a/mercurial/demandload.py Fri Mar 03 09:39:37 2006 -0800 +++ b/mercurial/demandload.py Fri Mar 03 09:40:18 2006 -0800 @@ -1,15 +1,125 @@ -def demandload(scope, modules): - class d: - def __getattr__(self, name): - mod = self.__dict__["mod"] - scope = self.__dict__["scope"] - scope[mod] = __import__(mod, scope, scope, []) - return getattr(scope[mod], name) +'''Demand load modules when used, not when imported.''' + +__author__ = '''Copyright 2006 Vadim Gelfer . +This software may be used and distributed according to the terms +of the GNU General Public License, incorporated herein by reference.''' + +# this is based on matt's original demandload module. it is a +# complete rewrite. some time, we may need to support syntax of +# "import foo as bar". + +class _importer(object): + '''import a module. it is not imported until needed, and is + imported at most once per scope.''' + + def __init__(self, scope, modname, fromlist): + '''scope is context (globals() or locals()) in which import + should be made. modname is name of module to import. + fromlist is list of modules for "from foo import ..." + emulation.''' + + self.scope = scope + self.modname = modname + self.fromlist = fromlist + self.mod = None + + def module(self): + '''import the module if needed, and return.''' + if self.mod is None: + self.mod = __import__(self.modname, self.scope, self.scope, + self.fromlist) + del self.modname, self.fromlist + return self.mod + +class _replacer(object): + '''placeholder for a demand loaded module. demandload puts this in + a target scope. when an attribute of this object is looked up, + this object is replaced in the target scope with the actual + module. + + we use __getattribute__ to avoid namespace clashes between + placeholder object and real module.''' + + def __init__(self, importer, target): + self.importer = importer + self.target = target + # consider case where we do this: + # demandload(globals(), 'foo.bar foo.quux') + # foo will already exist in target scope when we get to + # foo.quux. so we remember that we will need to demandload + # quux into foo's scope when we really load it. + self.later = [] + + def module(self): + return object.__getattribute__(self, 'importer').module() + + def __getattribute__(self, key): + '''look up an attribute in a module and return it. replace the + name of the module in the caller\'s dict with the actual + module.''' - for m in modules.split(): - dl = d() - dl.mod = m - dl.scope = scope - scope[m] = dl + module = object.__getattribute__(self, 'module')() + target = object.__getattribute__(self, 'target') + importer = object.__getattribute__(self, 'importer') + later = object.__getattribute__(self, 'later') + + if later: + demandload(module.__dict__, ' '.join(later)) + + importer.scope[target] = module + + return getattr(module, key) + +class _replacer_from(_replacer): + '''placeholder for a demand loaded module. used for "from foo + import ..." emulation. semantics of this are different than + regular import, so different implementation needed.''' + + def module(self): + importer = object.__getattribute__(self, 'importer') + target = object.__getattribute__(self, 'target') + + return getattr(importer.module(), target) + +def demandload(scope, modules): + '''import modules into scope when each is first used. + + scope should be the value of globals() in the module calling this + function, or locals() in the calling function. + + modules is a string listing module names, separated by white + space. names are handled like this: + 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 mod in modules.split(): + col = mod.find(':') + if col >= 0: + fromlist = mod[col+1:].split(',') + mod = mod[:col] + else: + fromlist = [] + importer = _importer(scope, mod, fromlist) + if fromlist: + for name in fromlist: + scope[name] = _replacer_from(importer, name) + else: + dot = mod.find('.') + if dot >= 0: + basemod = mod[:dot] + val = scope.get(basemod) + # if base module has already been demandload()ed, + # remember to load this submodule into its namespace + # when needed. + if isinstance(val, _replacer): + later = object.__getattribute__(val, 'later') + later.append(mod[dot+1:]) + continue + else: + basemod = mod + scope[basemod] = _replacer(importer, basemod)