From: Paul Molodowitch bookmarks: fixes invalidaterepo check if repo._bookmarks is a property also provides hglib.is_descriptor, which might be useful for other things diff -r 4d75e31662d4 tortoisehg/util/hglib.py --- a/tortoisehg/util/hglib.py Thu Dec 24 12:53:17 2009 -0600 +++ b/tortoisehg/util/hglib.py Thu Dec 24 12:27:59 2009 -0800 @@ -9,6 +9,7 @@ import sys import shlex import time +import inspect from mercurial import ui, util, extensions, match, bundlerepo, url from mercurial import dispatch, encoding, templatefilters, filemerge @@ -147,8 +148,7 @@ # from 1.4 to 1.5... for cachedAttr in ('_bookmarks', '_bookmarkcurrent'): # Check if it's a property or normal value... - classAttr = getattr(repo.__class__, cachedAttr, None) - if hasattr(classAttr, '__get__'): + if is_descriptor(repo, cachedAttr): # The very act of calling hasattr would # re-cache the property, so just assume it's # already cached, and catch the error if it wasn't. @@ -381,3 +381,18 @@ return False return rev == parents[0].node() + +def is_descriptor(obj, attr): + """ + Returns True if obj.attr is a descriptor - ie, accessing + the attribute will actually invoke the '__get__' method of + some object. + + Returns False if obj.attr exists, but is not a descriptor, + and None if obj.attr was not found at all. + """ + for cls in inspect.getmro(obj.__class__): + if attr in cls.__dict__: + return hasattr(cls.__dict__[attr], '__get__') + return None +