Mercurial > hg-stable
changeset 14979:a5046880eca3
merge with crew
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Thu, 28 Jul 2011 14:20:06 -0500 |
parents | d78b92353f26 (current diff) 5a0fdc715769 (diff) |
children | 6312171468f7 |
files | |
diffstat | 50 files changed, 125 insertions(+), 123 deletions(-) [+] |
line wrap: on
line diff
--- a/contrib/check-code.py Tue Jul 26 21:30:12 2011 +0200 +++ b/contrib/check-code.py Thu Jul 28 14:20:06 2011 -0500 @@ -148,7 +148,7 @@ (r'(?<!def)\s+(any|all|format)\(', "any/all/format not available in Python 2.4"), (r'(?<!def)\s+(callable)\(', - "callable not available in Python 3, use hasattr(f, '__call__')"), + "callable not available in Python 3, use getattr(f, '__call__', None)"), (r'if\s.*\selse', "if ... else form not available in Python 2.4"), (r'^\s*(%s)\s\s' % '|'.join(keyword.kwlist), "gratuitous whitespace after Python keyword"), @@ -168,6 +168,8 @@ "comparison with singleton, use 'is' or 'is not' instead"), (r'^\s*(while|if) [01]:', "use True/False for constant Boolean expression"), + (r'(?<!def)\s+hasattr', + 'hasattr(foo, bar) is broken, use util.safehasattr(foo, bar) instead'), (r'opener\([^)]*\).read\(', "use opener.read() instead"), (r'opener\([^)]*\).write\(',
--- a/contrib/setup3k.py Tue Jul 26 21:30:12 2011 +0200 +++ b/contrib/setup3k.py Thu Jul 28 14:20:06 2011 -0500 @@ -8,7 +8,7 @@ from lib2to3.refactor import get_fixers_from_package as getfixers import sys -if not hasattr(sys, 'version_info') or sys.version_info < (2, 4, 0, 'final'): +if getattr(sys, 'version_info', (0, 0, 0)) < (2, 4, 0, 'final'): raise SystemExit("Mercurial requires Python 2.4 or later.") if sys.version_info[0] >= 3: @@ -236,7 +236,7 @@ try: build_ext.build_extension(self, ext) except CCompilerError: - if not hasattr(ext, 'optional') or not ext.optional: + if getattr(ext, 'optional', False): raise log.warn("Failed to build optional extension '%s' (skipping)", ext.name)
--- a/contrib/win32/hgwebdir_wsgi.py Tue Jul 26 21:30:12 2011 +0200 +++ b/contrib/win32/hgwebdir_wsgi.py Thu Jul 28 14:20:06 2011 -0500 @@ -50,7 +50,7 @@ #sys.path.insert(0, r'c:\path\to\python\lib') # Enable tracing. Run 'python -m win32traceutil' to debug -if hasattr(sys, 'isapidllhandle'): +if getattr(sys, 'isapidllhandle', None) is not None: import win32traceutil # To serve pages in local charset instead of UTF-8, remove the two lines below
--- a/doc/gendoc.py Tue Jul 26 21:30:12 2011 +0200 +++ b/doc/gendoc.py Thu Jul 28 14:20:06 2011 -0500 @@ -9,6 +9,7 @@ from mercurial.i18n import _ from mercurial.help import helptable from mercurial import extensions +from mercurial import util def get_desc(docstr): if not docstr: @@ -95,7 +96,7 @@ ui.write(".. _%s:\n" % name) ui.write("\n") section(ui, sec) - if hasattr(doc, '__call__'): + if util.safehasattr(doc, '__call__'): doc = doc() ui.write(doc) ui.write("\n")
--- a/hgext/convert/cvsps.py Tue Jul 26 21:30:12 2011 +0200 +++ b/hgext/convert/cvsps.py Thu Jul 28 14:20:06 2011 -0500 @@ -11,6 +11,7 @@ from mercurial import util from mercurial.i18n import _ from mercurial import hook +from mercurial import util class logentry(object): '''Class logentry has the following attributes: @@ -513,8 +514,8 @@ e.comment == c.comment and e.author == c.author and e.branch == c.branch and - (not hasattr(e, 'branchpoints') or - not hasattr (c, 'branchpoints') or + (not util.safehasattr(e, 'branchpoints') or + not util.safehasattr (c, 'branchpoints') or e.branchpoints == c.branchpoints) and ((c.date[0] + c.date[1]) <= (e.date[0] + e.date[1]) <=
--- a/hgext/convert/git.py Tue Jul 26 21:30:12 2011 +0200 +++ b/hgext/convert/git.py Thu Jul 28 14:20:06 2011 -0500 @@ -16,7 +16,7 @@ # Windows does not support GIT_DIR= construct while other systems # cannot remove environment variable. Just assume none have # both issues. - if hasattr(os, 'unsetenv'): + if util.safehasattr(os, 'unsetenv'): def gitopen(self, s, noerr=False): prevgitdir = os.environ.get('GIT_DIR') os.environ['GIT_DIR'] = self.path
--- a/hgext/convert/transport.py Tue Jul 26 21:30:12 2011 +0200 +++ b/hgext/convert/transport.py Thu Jul 28 14:20:06 2011 -0500 @@ -54,7 +54,7 @@ if p: providers.append(p) else: - if hasattr(svn.client, 'get_windows_simple_provider'): + if util.safehasattr(svn.client, 'get_windows_simple_provider'): providers.append(svn.client.get_windows_simple_provider(pool)) return svn.core.svn_auth_open(providers, pool) @@ -73,7 +73,7 @@ self.password = '' # Only Subversion 1.4 has reparent() - if ra is None or not hasattr(svn.ra, 'reparent'): + if ra is None or not util.safehasattr(svn.ra, 'reparent'): self.client = svn.client.create_context(self.pool) ab = _create_auth_baton(self.pool) if False:
--- a/hgext/inotify/__init__.py Tue Jul 26 21:30:12 2011 +0200 +++ b/hgext/inotify/__init__.py Thu Jul 28 14:20:06 2011 -0500 @@ -11,6 +11,7 @@ # todo: socket permissions from mercurial.i18n import _ +from mercurial import util import server from client import client, QueryFailed @@ -31,7 +32,7 @@ ui.write((' %s/\n') % path) def reposetup(ui, repo): - if not hasattr(repo, 'dirstate'): + if not util.safehasattr(repo, 'dirstate'): return class inotifydirstate(repo.dirstate.__class__):
--- a/hgext/mq.py Tue Jul 26 21:30:12 2011 +0200 +++ b/hgext/mq.py Thu Jul 28 14:20:06 2011 -0500 @@ -938,7 +938,7 @@ p.write("# User " + user + "\n") if date: p.write("# Date %s %s\n\n" % date) - if hasattr(msg, '__call__'): + if util.safehasattr(msg, '__call__'): msg = msg() commitmsg = msg and msg or ("[mq]: %s" % patchfn) n = repo.commit(commitmsg, user, date, match=match, force=True)
--- a/hgext/pager.py Tue Jul 26 21:30:12 2011 +0200 +++ b/hgext/pager.py Thu Jul 28 14:20:06 2011 -0500 @@ -58,7 +58,7 @@ from mercurial.i18n import _ def _runpager(p): - if not hasattr(os, 'fork'): + if not util.safehasattr(os, 'fork'): sys.stdout = util.popen(p, 'wb') if util.isatty(sys.stderr): sys.stderr = sys.stdout
--- a/hgext/relink.py Tue Jul 26 21:30:12 2011 +0200 +++ b/hgext/relink.py Thu Jul 28 14:20:06 2011 -0500 @@ -36,7 +36,8 @@ command is running. (Both repositories will be locked against writes.) """ - if not hasattr(util, 'samefile') or not hasattr(util, 'samedevice'): + if (not util.safehasattr(util, 'samefile') or + not util.safehasattr(util, 'samedevice')): raise util.Abort(_('hardlinks are not supported on this system')) src = hg.repository(ui, ui.expandpath(origin or 'default-relink', origin or 'default'))
--- a/mercurial/bookmarks.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/bookmarks.py Thu Jul 28 14:20:06 2011 -0500 @@ -151,11 +151,10 @@ def listbookmarks(repo): # We may try to list bookmarks on a repo type that does not # support it (e.g., statichttprepository). - if not hasattr(repo, '_bookmarks'): - return {} + marks = getattr(repo, '_bookmarks', {}) d = {} - for k, v in repo._bookmarks.iteritems(): + for k, v in marks.iteritems(): d[k] = hex(v) return d
--- a/mercurial/byterange.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/byterange.py Thu Jul 28 14:20:06 2011 -0500 @@ -103,9 +103,7 @@ """This effectively allows us to wrap at the instance level. Any attribute not found in _this_ object will be searched for in self.fo. This includes methods.""" - if hasattr(self.fo, name): - return getattr(self.fo, name) - raise AttributeError(name) + return getattr(self.fo, name) def tell(self): """Return the position within the range. @@ -170,10 +168,8 @@ offset is relative to the current position (self.realpos). """ assert offset >= 0 - if not hasattr(self.fo, 'seek'): - self._poor_mans_seek(offset) - else: - self.fo.seek(self.realpos + offset) + seek = getattr(self.fo, 'seek', self._poor_mans_seek) + seek(self.realpos + offset) self.realpos += offset def _poor_mans_seek(self, offset):
--- a/mercurial/cmdutil.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/cmdutil.py Thu Jul 28 14:20:06 2011 -0500 @@ -161,7 +161,7 @@ if not pat or pat == '-': fp = writable and repo.ui.fout or repo.ui.fin - if hasattr(fp, 'fileno'): + if util.safehasattr(fp, 'fileno'): return os.fdopen(os.dup(fp.fileno()), mode) else: # if this fp can't be duped properly, return @@ -177,9 +177,9 @@ return getattr(self.f, attr) return wrappedfileobj(fp) - if hasattr(pat, 'write') and writable: + if util.safehasattr(pat, 'write') and writable: return pat - if hasattr(pat, 'read') and 'r' in mode: + if util.safehasattr(pat, 'read') and 'r' in mode: return pat return open(makefilename(repo, pat, node, total, seqno, revwidth, pathname), @@ -520,7 +520,7 @@ revwidth=revwidth, mode='ab') if fp != template: shouldclose = True - if fp != sys.stdout and hasattr(fp, 'name'): + if fp != sys.stdout and util.safehasattr(fp, 'name'): repo.ui.note("%s\n" % fp.name) fp.write("# HG changeset patch\n")
--- a/mercurial/commands.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/commands.py Thu Jul 28 14:20:06 2011 -0500 @@ -1659,8 +1659,9 @@ def debugignore(ui, repo, *values, **opts): """display the combined ignore pattern""" ignore = repo.dirstate._ignore - if hasattr(ignore, 'includepat'): - ui.write("%s\n" % ignore.includepat) + includepat = getattr(ignore, 'includepat', None) + if includepat is not None: + ui.write("%s\n" % includepat) else: raise util.Abort(_("no ignore patterns found")) @@ -2647,7 +2648,7 @@ doc = gettext(entry[0].__doc__) if not doc: doc = _("(no help text available)") - if hasattr(entry[0], 'definition'): # aliased command + if util.safehasattr(entry[0], 'definition'): # aliased command if entry[0].definition.startswith('!'): # shell alias doc = _('shell alias for::\n\n %s') % entry[0].definition[1:] else: @@ -2732,7 +2733,7 @@ # description if not doc: doc = _("(no help text available)") - if hasattr(doc, '__call__'): + if util.safehasattr(doc, '__call__'): doc = doc() ui.write("%s\n\n" % header)
--- a/mercurial/demandimport.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/demandimport.py Thu Jul 28 14:20:06 2011 -0500 @@ -27,6 +27,8 @@ import __builtin__ _origimport = __import__ +nothing = object() + class _demandmod(object): """module demand-loader and proxy""" def __init__(self, name, globals, locals): @@ -50,7 +52,7 @@ h, t = p, None if '.' in p: h, t = p.split('.', 1) - if not hasattr(mod, h): + if getattr(mod, h, nothing) is nothing: setattr(mod, h, _demandmod(p, mod.__dict__, mod.__dict__)) elif t: subload(getattr(mod, h), t) @@ -109,12 +111,12 @@ mod = _origimport(name, globals, locals) # recurse down the module chain for comp in name.split('.')[1:]: - if not hasattr(mod, comp): + if getattr(mod, comp, nothing) is nothing: setattr(mod, comp, _demandmod(comp, mod.__dict__, mod.__dict__)) mod = getattr(mod, comp) for x in fromlist: # set requested submodules for demand load - if not hasattr(mod, x): + if getattr(mod, x, nothing) is nothing: setattr(mod, x, _demandmod(x, mod.__dict__, locals)) return mod @@ -137,6 +139,8 @@ # raise ImportError if x not defined '__main__', '_ssl', # conditional imports in the stdlib, issue1964 + 'rfc822', + 'mimetools', ] def enable(): @@ -146,4 +150,3 @@ def disable(): "disable global demand-loading of modules" __builtin__.__import__ = _origimport -
--- a/mercurial/dispatch.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/dispatch.py Thu Jul 28 14:20:06 2011 -0500 @@ -159,16 +159,16 @@ elif m in "zlib".split(): ui.warn(_("(is your Python install correct?)\n")) except IOError, inst: - if hasattr(inst, "code"): + if util.safehasattr(inst, "code"): ui.warn(_("abort: %s\n") % inst) - elif hasattr(inst, "reason"): + elif util.safehasattr(inst, "reason"): try: # usually it is in the form (errno, strerror) reason = inst.reason.args[1] except (AttributeError, IndexError): # it might be anything, for example a string reason = inst.reason ui.warn(_("abort: error: %s\n") % reason) - elif hasattr(inst, "args") and inst.args[0] == errno.EPIPE: + elif util.safehasattr(inst, "args") and inst.args[0] == errno.EPIPE: if ui.debugflag: ui.warn(_("broken pipe\n")) elif getattr(inst, "strerror", None): @@ -338,7 +338,7 @@ ui.debug("alias '%s' shadows command '%s'\n" % (self.name, self.cmdname)) - if hasattr(self, 'shell'): + if util.safehasattr(self, 'shell'): return self.fn(ui, *args, **opts) else: try: @@ -506,7 +506,7 @@ cmd = aliases[0] fn = entry[0] - if cmd and hasattr(fn, 'shell'): + if cmd and util.safehasattr(fn, 'shell'): d = lambda: fn(ui, *args[1:]) return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d, [], {})
--- a/mercurial/encoding.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/encoding.py Thu Jul 28 14:20:06 2011 -0500 @@ -140,12 +140,12 @@ def colwidth(s): "Find the column width of a UTF-8 string for display" d = s.decode(encoding, 'replace') - if hasattr(unicodedata, 'east_asian_width'): + eaw = getattr(unicodedata, 'east_asian_width', None) + if eaw is not None: wide = "WF" if ambiguous == "wide": wide = "WFA" - w = unicodedata.east_asian_width - return sum([w(c) in wide and 2 or 1 for c in d]) + return sum([eaw(c) in wide and 2 or 1 for c in d]) return len(d) def lower(s):
--- a/mercurial/extensions.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/extensions.py Thu Jul 28 14:20:06 2011 -0500 @@ -124,7 +124,7 @@ where orig is the original (wrapped) function, and *args, **kwargs are the arguments passed to it. ''' - assert hasattr(wrapper, '__call__') + assert util.safehasattr(wrapper, '__call__') aliases, entry = cmdutil.findcmd(command, table) for alias, e in table.iteritems(): if e is entry: @@ -177,12 +177,12 @@ your end users, you should play nicely with others by using the subclass trick. ''' - assert hasattr(wrapper, '__call__') + assert util.safehasattr(wrapper, '__call__') def wrap(*args, **kwargs): return wrapper(origfn, *args, **kwargs) origfn = getattr(container, funcname) - assert hasattr(origfn, '__call__') + assert util.safehasattr(origfn, '__call__') setattr(container, funcname, wrap) return origfn
--- a/mercurial/fancyopts.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/fancyopts.py Thu Jul 28 14:20:06 2011 -0500 @@ -75,7 +75,7 @@ # copy defaults to state if isinstance(default, list): state[name] = default[:] - elif hasattr(default, '__call__'): + elif getattr(default, '__call__', False): state[name] = None else: state[name] = default
--- a/mercurial/help.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/help.py Thu Jul 28 14:20:06 2011 -0500 @@ -31,7 +31,7 @@ """Return a delayed loader for help/topic.txt.""" def loader(): - if hasattr(sys, 'frozen'): + if util.mainfrozen(): module = sys.executable else: module = __file__
--- a/mercurial/hg.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/hg.py Thu Jul 28 14:20:06 2011 -0500 @@ -537,7 +537,7 @@ def remoteui(src, opts): 'build a remote ui from ui or repo and opts' - if hasattr(src, 'baseui'): # looks like a repository + if util.safehasattr(src, 'baseui'): # looks like a repository dst = src.baseui.copy() # drop repo-specific config src = src.ui # copy target options from repo else: # assume it's a global ui object
--- a/mercurial/hgweb/hgweb_mod.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/hgweb/hgweb_mod.py Thu Jul 28 14:20:06 2011 -0500 @@ -7,7 +7,7 @@ # GNU General Public License version 2 or any later version. import os -from mercurial import ui, hg, hook, error, encoding, templater +from mercurial import ui, hg, hook, error, encoding, templater, util from common import get_stat, ErrorResponse, permhooks, caching from common import HTTP_OK, HTTP_NOT_MODIFIED, HTTP_BAD_REQUEST from common import HTTP_NOT_FOUND, HTTP_SERVER_ERROR @@ -147,7 +147,7 @@ cmd = cmd[style + 1:] # avoid accepting e.g. style parameter as command - if hasattr(webcommands, cmd): + if util.safehasattr(webcommands, cmd): req.form['cmd'] = [cmd] else: cmd = ''
--- a/mercurial/hgweb/request.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/hgweb/request.py Thu Jul 28 14:20:06 2011 -0500 @@ -101,7 +101,7 @@ self.headers = [] def write(self, thing): - if hasattr(thing, "__iter__"): + if util.safehasattr(thing, "__iter__"): for part in thing: self.write(part) else:
--- a/mercurial/hgweb/server.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/hgweb/server.py Thu Jul 28 14:20:06 2011 -0500 @@ -248,7 +248,7 @@ from threading import activeCount _mixin = SocketServer.ThreadingMixIn except ImportError: - if hasattr(os, "fork"): + if util.safehasattr(os, "fork"): _mixin = SocketServer.ForkingMixIn else: class _mixin(object):
--- a/mercurial/hgweb/webutil.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/hgweb/webutil.py Thu Jul 28 14:20:06 2011 -0500 @@ -72,7 +72,7 @@ d['date'] = s.date() d['description'] = s.description() d['branch'] = s.branch() - if hasattr(s, 'path'): + if util.safehasattr(s, 'path'): d['file'] = s.path() yield d
--- a/mercurial/hgweb/wsgicgi.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/hgweb/wsgicgi.py Thu Jul 28 14:20:06 2011 -0500 @@ -78,5 +78,4 @@ for chunk in content: write(chunk) finally: - if hasattr(content, 'close'): - content.close() + getattr(content, 'close', lambda : None)()
--- a/mercurial/hook.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/hook.py Thu Jul 28 14:20:06 2011 -0500 @@ -21,14 +21,14 @@ ui.note(_("calling hook %s: %s\n") % (hname, funcname)) obj = funcname - if not hasattr(obj, '__call__'): + if not util.safehasattr(obj, '__call__'): d = funcname.rfind('.') if d == -1: raise util.Abort(_('%s hook is invalid ("%s" not in ' 'a module)') % (hname, funcname)) modname = funcname[:d] oldpaths = sys.path - if hasattr(sys, "frozen"): + if util.mainfrozen(): # binary installs require sys.path manipulation modpath, modfile = os.path.split(modname) if modpath and modfile: @@ -60,7 +60,7 @@ raise util.Abort(_('%s hook is invalid ' '("%s" is not defined)') % (hname, funcname)) - if not hasattr(obj, '__call__'): + if not util.safehasattr(obj, '__call__'): raise util.Abort(_('%s hook is invalid ' '("%s" is not callable)') % (hname, funcname)) @@ -99,7 +99,7 @@ env = {} for k, v in args.iteritems(): - if hasattr(v, '__call__'): + if util.safehasattr(v, '__call__'): v = v() if isinstance(v, dict): # make the dictionary element order stable across Python @@ -145,7 +145,7 @@ for hname, cmd in ui.configitems('hooks'): if hname.split('.')[0] != name or not cmd: continue - if hasattr(cmd, '__call__'): + if util.safehasattr(cmd, '__call__'): r = _pythonhook(ui, repo, name, hname, cmd, args, throw) or r elif cmd.startswith('python:'): if cmd.count(':') >= 2:
--- a/mercurial/httprepo.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/httprepo.py Thu Jul 28 14:20:06 2011 -0500 @@ -44,8 +44,7 @@ def __del__(self): for h in self.urlopener.handlers: h.close() - if hasattr(h, "close_all"): - h.close_all() + getattr(h, "close_all", lambda : None)() def url(self): return self.path
--- a/mercurial/i18n.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/i18n.py Thu Jul 28 14:20:06 2011 -0500 @@ -9,7 +9,7 @@ import gettext, sys, os # modelled after templater.templatepath: -if hasattr(sys, 'frozen'): +if getattr(sys, 'frozen', None) is not None: module = sys.executable else: module = __file__ @@ -61,4 +61,3 @@ _ = lambda message: message else: _ = gettext -
--- a/mercurial/keepalive.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/keepalive.py Thu Jul 28 14:20:06 2011 -0500 @@ -547,13 +547,14 @@ print "send:", repr(str) try: blocksize = 8192 - if hasattr(str,'read') : + read = getattr(str, 'read', None) + if read is not None: if self.debuglevel > 0: print "sendIng a read()able" - data = str.read(blocksize) + data = read(blocksize) while data: self.sock.sendall(data) - data = str.read(blocksize) + data = read(blocksize) else: self.sock.sendall(str) except socket.error, v:
--- a/mercurial/lsprof.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/lsprof.py Thu Jul 28 14:20:06 2011 -0500 @@ -86,9 +86,7 @@ for k, v in list(sys.modules.iteritems()): if v is None: continue - if not hasattr(v, '__file__'): - continue - if not isinstance(v.__file__, str): + if not isinstance(getattr(v, '__file__', None), str): continue if v.__file__.startswith(code.co_filename): mname = _fn2mod[code.co_filename] = k
--- a/mercurial/mail.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/mail.py Thu Jul 28 14:20:06 2011 -0500 @@ -37,7 +37,7 @@ # backward compatible: when tls = true, we use starttls. starttls = tls == 'starttls' or util.parsebool(tls) smtps = tls == 'smtps' - if (starttls or smtps) and not hasattr(socket, 'ssl'): + if (starttls or smtps) and not util.safehasattr(socket, 'ssl'): raise util.Abort(_("can't use TLS: Python SSL support not installed")) if smtps: ui.note(_('(using smtps)\n'))
--- a/mercurial/patch.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/patch.py Thu Jul 28 14:20:06 2011 -0500 @@ -126,7 +126,7 @@ mimeheaders = ['content-type'] - if not hasattr(stream, 'next'): + if not util.safehasattr(stream, 'next'): # http responses, for example, have readline but not next stream = fiter(stream)
--- a/mercurial/revlog.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/revlog.py Thu Jul 28 14:20:06 2011 -0500 @@ -226,9 +226,10 @@ self._nodepos = None v = REVLOG_DEFAULT_VERSION - if hasattr(opener, 'options'): - if 'revlogv1' in opener.options: - if 'generaldelta' in opener.options: + opts = getattr(opener, 'options', None) + if opts is not None: + if 'revlogv1' in opts: + if 'generaldelta' in opts: v |= REVLOGGENERALDELTA else: v = 0
--- a/mercurial/scmutil.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/scmutil.py Thu Jul 28 14:20:06 2011 -0500 @@ -324,10 +324,10 @@ def errhandler(err): if err.filename == path: raise err - if followsym and hasattr(os.path, 'samestat'): + samestat = getattr(os.path, 'samestat', None) + if followsym and samestat is not None: def adddir(dirlst, dirname): match = False - samestat = os.path.samestat dirstat = os.stat(dirname) for lstdirstat in dirlst: if samestat(dirstat, lstdirstat):
--- a/mercurial/statichttprepo.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/statichttprepo.py Thu Jul 28 14:20:06 2011 -0500 @@ -31,15 +31,11 @@ try: f = self.opener.open(req) data = f.read() - if hasattr(f, 'getcode'): - # python 2.6+ - code = f.getcode() - elif hasattr(f, 'code'): - # undocumented attribute, seems to be set in 2.4 and 2.5 - code = f.code - else: - # Don't know how to check, hope for the best. - code = 206 + # Python 2.6+ defines a getcode() function, and 2.4 and + # 2.5 appear to always have an undocumented code attribute + # set. If we can't read either of those, fall back to 206 + # and hope for the best. + code = getattr(f, 'getcode', lambda : getattr(f, 'code', 206))() except urllib2.HTTPError, inst: num = inst.code == 404 and errno.ENOENT or None raise IOError(num, inst)
--- a/mercurial/subrepo.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/subrepo.py Thu Jul 28 14:20:06 2011 -0500 @@ -181,22 +181,22 @@ def reporelpath(repo): """return path to this (sub)repo as seen from outermost repo""" parent = repo - while hasattr(parent, '_subparent'): + while util.safehasattr(parent, '_subparent'): parent = parent._subparent return repo.root[len(parent.root)+1:] def subrelpath(sub): """return path to this subrepo as seen from outermost repo""" - if hasattr(sub, '_relpath'): + if util.safehasattr(sub, '_relpath'): return sub._relpath - if not hasattr(sub, '_repo'): + if not util.safehasattr(sub, '_repo'): return sub._path return reporelpath(sub._repo) def _abssource(repo, push=False, abort=True): """return pull/push path of repo - either based on parent repo .hgsub info or on the top repo config. Abort or return None if no source found.""" - if hasattr(repo, '_subparent'): + if util.safehasattr(repo, '_subparent'): source = util.url(repo._subsource) if source.isabs(): return str(source) @@ -208,7 +208,7 @@ parent.path = posixpath.normpath(parent.path) return str(parent) else: # recursion reached top repo - if hasattr(repo, '_subtoppath'): + if util.safehasattr(repo, '_subtoppath'): return repo._subtoppath if push and repo.ui.config('paths', 'default-push'): return repo.ui.config('paths', 'default-push')
--- a/mercurial/templatefilters.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/templatefilters.py Thu Jul 28 14:20:06 2011 -0500 @@ -188,13 +188,13 @@ return '"%s"' % jsonescape(u) elif isinstance(obj, unicode): return '"%s"' % jsonescape(obj) - elif hasattr(obj, 'keys'): + elif util.safehasattr(obj, 'keys'): out = [] for k, v in obj.iteritems(): s = '%s: %s' % (json(k), json(v)) out.append(s) return '{' + ', '.join(out) + '}' - elif hasattr(obj, '__iter__'): + elif util.safehasattr(obj, '__iter__'): out = [] for i in obj: out.append(json(i)) @@ -279,7 +279,7 @@ """:stringify: Any type. Turns the value into text by converting values into text and concatenating them. """ - if hasattr(thing, '__iter__') and not isinstance(thing, str): + if util.safehasattr(thing, '__iter__') and not isinstance(thing, str): return "".join([stringify(t) for t in thing if t is not None]) return str(thing)
--- a/mercurial/templater.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/templater.py Thu Jul 28 14:20:06 2011 -0500 @@ -135,7 +135,7 @@ v = mapping.get(key) if v is None: v = context._defaults.get(key, '') - if hasattr(v, '__call__'): + if util.safehasattr(v, '__call__'): return v(**mapping) return v @@ -203,14 +203,14 @@ '''yield a single stream from a possibly nested set of iterators''' if isinstance(thing, str): yield thing - elif not hasattr(thing, '__iter__'): + elif not util.safehasattr(thing, '__iter__'): if thing is not None: yield str(thing) else: for i in thing: if isinstance(i, str): yield i - elif not hasattr(i, '__iter__'): + elif not util.safehasattr(i, '__iter__'): if i is not None: yield str(i) elif i is not None: @@ -341,7 +341,7 @@ normpaths = [] # executable version (py2exe) doesn't support __file__ - if hasattr(sys, 'frozen'): + if util.mainfrozen(): module = sys.executable else: module = __file__
--- a/mercurial/url.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/url.py Thu Jul 28 14:20:06 2011 -0500 @@ -129,7 +129,7 @@ orgsend(self, data) return _sendfile -has_https = hasattr(urllib2, 'HTTPSHandler') +has_https = util.safehasattr(urllib2, 'HTTPSHandler') if has_https: try: _create_connection = socket.create_connection @@ -186,8 +186,8 @@ # general transaction handler to support different ways to handle # HTTPS proxying before and after Python 2.6.3. def _generic_start_transaction(handler, h, req): - if hasattr(req, '_tunnel_host') and req._tunnel_host: - tunnel_host = req._tunnel_host + tunnel_host = getattr(req, '_tunnel_host', None) + if tunnel_host: if tunnel_host[:7] not in ['http://', 'https:/']: tunnel_host = 'https://' + tunnel_host new_tunnel = True
--- a/mercurial/util.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/util.py Thu Jul 28 14:20:06 2011 -0500 @@ -75,6 +75,10 @@ def sha1(s): return _fastsha1(s) +_notset = object() +def safehasattr(thing, attr): + return getattr(thing, attr, _notset) is not _notset + def _fastsha1(s): # This function will import sha1 from hashlib or sha (whichever is # available) and overwrite itself with it on the first call. @@ -354,8 +358,8 @@ The code supports py2exe (most common, Windows only) and tools/freeze (portable, not much used). """ - return (hasattr(sys, "frozen") or # new py2exe - hasattr(sys, "importers") or # old py2exe + return (safehasattr(sys, "frozen") or # new py2exe + safehasattr(sys, "importers") or # old py2exe imp.is_frozen("__main__")) # tools/freeze def hgexecutable(): @@ -779,7 +783,7 @@ self._fp.close() def __del__(self): - if hasattr(self, '_fp'): # constructor actually did something + if safehasattr(self, '_fp'): # constructor actually did something self.close() def makedirs(name, mode=None): @@ -1250,8 +1254,9 @@ def handler(signum, frame): terminated.add(os.wait()) prevhandler = None - if hasattr(signal, 'SIGCHLD'): - prevhandler = signal.signal(signal.SIGCHLD, handler) + SIGCHLD = getattr(signal, 'SIGCHLD', None) + if SIGCHLD is not None: + prevhandler = signal.signal(SIGCHLD, handler) try: pid = spawndetached(args) while not condfn():
--- a/mercurial/windows.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/windows.py Thu Jul 28 14:20:06 2011 -0500 @@ -99,8 +99,9 @@ def setbinary(fd): # When run without console, pipes may expose invalid # fileno(), usually set to -1. - if hasattr(fd, 'fileno') and fd.fileno() >= 0: - msvcrt.setmode(fd.fileno(), os.O_BINARY) + fno = getattr(fd, 'fileno', None) + if fno is not None and fno() >= 0: + msvcrt.setmode(fno(), os.O_BINARY) def pconvert(path): return '/'.join(path.split(os.sep))
--- a/mercurial/wireproto.py Tue Jul 26 21:30:12 2011 +0200 +++ b/mercurial/wireproto.py Thu Jul 28 14:20:06 2011 -0500 @@ -17,7 +17,7 @@ class future(object): '''placeholder for a value to be set later''' def set(self, value): - if hasattr(self, 'value'): + if util.safehasattr(self, 'value'): raise error.RepoError("future is already set") self.value = value @@ -58,8 +58,9 @@ req, rsp = [], [] for name, args, opts, resref in self.calls: mtd = getattr(self.remote, name) - if hasattr(mtd, 'batchable'): - batchable = getattr(mtd, 'batchable')(mtd.im_self, *args, **opts) + batchablefn = getattr(mtd, 'batchable', None) + if batchablefn is not None: + batchable = batchablefn(mtd.im_self, *args, **opts) encargsorres, encresref = batchable.next() if encresref: req.append((name, encargsorres,))
--- a/setup.py Tue Jul 26 21:30:12 2011 +0200 +++ b/setup.py Thu Jul 28 14:20:06 2011 -0500 @@ -5,7 +5,7 @@ # 'python setup.py --help' for more options import sys, platform -if not hasattr(sys, 'version_info') or sys.version_info < (2, 4, 0, 'final'): +if getattr(sys, 'version_info', (0, 0, 0)) < (2, 4, 0, 'final'): raise SystemExit("Mercurial requires Python 2.4 or later.") if sys.version_info[0] >= 3:
--- a/tests/run-tests.py Tue Jul 26 21:30:12 2011 +0200 +++ b/tests/run-tests.py Thu Jul 28 14:20:06 2011 -0500 @@ -340,10 +340,7 @@ """Terminate subprocess (with fallback for Python versions < 2.6)""" vlog('# Terminating process %d' % proc.pid) try: - if hasattr(proc, 'terminate'): - proc.terminate() - else: - os.kill(proc.pid, signal.SIGTERM) + getattr(proc, 'terminate', lambda : os.kill(proc.pid, signal.SIGTERM))() except OSError: pass
--- a/tests/sitecustomize.py Tue Jul 26 21:30:12 2011 +0200 +++ b/tests/sitecustomize.py Thu Jul 28 14:20:06 2011 -0500 @@ -1,6 +1,5 @@ try: import coverage - if hasattr(coverage, 'process_startup'): - coverage.process_startup() + getattr(coverage, 'process_startup', lambda: None)() except ImportError: pass
--- a/tests/test-symlink-os-yes-fs-no.py Tue Jul 26 21:30:12 2011 +0200 +++ b/tests/test-symlink-os-yes-fs-no.py Thu Jul 28 14:20:06 2011 -0500 @@ -5,7 +5,7 @@ BUNDLEPATH = os.path.join(TESTDIR, 'bundles', 'test-no-symlinks.hg') # only makes sense to test on os which supports symlinks -if not hasattr(os, "symlink"): +if not getattr(os, "symlink", False): sys.exit(80) # SKIPPED_STATUS defined in run-tests.py # clone with symlink support
--- a/tests/test-walkrepo.py Tue Jul 26 21:30:12 2011 +0200 +++ b/tests/test-walkrepo.py Thu Jul 28 14:20:06 2011 -0500 @@ -5,7 +5,7 @@ from os.path import join as pjoin u = ui.ui() -sym = hasattr(os, 'symlink') and hasattr(os.path, 'samestat') +sym = getattr(os, 'symlink', False) and getattr(os.path, 'samestat', False) hg.repository(u, 'top1', create=1) mkdir('subdir')
--- a/tests/tinyproxy.py Tue Jul 26 21:30:12 2011 +0200 +++ b/tests/tinyproxy.py Thu Jul 28 14:20:06 2011 -0500 @@ -23,7 +23,8 @@ def handle(self): (ip, port) = self.client_address - if hasattr(self, 'allowed_clients') and ip not in self.allowed_clients: + allowed = getattr(self, 'allowed_clients', None) + if allowed is not None and ip not in allowed: self.raw_requestline = self.rfile.readline() if self.parse_request(): self.send_error(403)