merge with crew.
--- 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'])
--- 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 <vadim.gelfer@gmail.com>.
+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)