[Python-Dev] Can we improve support for abstract base classes with desciptors
Nick Coghlan
ncoghlan at gmail.com
Wed Jun 8 17:55:28 CEST 2011
On Thu, Jun 9, 2011 at 1:01 AM, Darren Dale <dsdale24 at gmail.com> wrote:
[snip excellent analysis of the problem]
I have some suggestions regarding a few details of your current code,
but your basic proposal looks sound to me.
I would tweak __new__ along the following lines though:
def __new__(mcls, name, bases, namespace):
cls = super().__new__(mcls, name, bases, namespace)
# Compute set of abstract method names
# CHANGE 1: refactor descriptor and abstract method scan to
happen in a single pass
def is_descriptor(value):
return (hasattr(value, '__get__') or hasattr(value, '__set__')
or hasattr(value, '__delete__'))
def is_abstract(value):
return getattr(value, "__isabstractmethod__", False)
def get_abstract_names_for_item(item):
name, value = item
if is_abstract(value):
return [name]
elif is_descriptor(value):
# CHANGE 2: Deliberately ignore descriptors on the
descriptor objects
# CHANGE 3: Use new-style string formatting
return ['{}.{}'.format(name, attr) for attr in
dir(value) if is_abstract(getattr(value, attr))]
return []
def get_abstract_names(ns):
names = []
for item in ns.items():
names.extend(get_abstract_names_for_item(item))
return names
abstract_names = get_abstract_names(namespace.items())
for base in bases:
for name in getattr(base, "__abstractmethods__", ()):
# CHANGE 4: Using rpartition better tolerates weird
naming in the metaclass
# (weird naming in descriptors will still blow up in
the earlier search for abstract names)
descr_name, is_descr, attr = name.rpartition('.')
if is_descr:
# base class identified a descriptor abstract method:
descr = getattr(cls, descr_name, None)
val = getattr(descr, attr, None)
else:
val = getattr(cls, name, None)
if val is None or is_abstract(val):
abstract_names.append(name)
cls.__abstractmethods__ = frozenset(abstract_names)
Cheers,
Nick.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
More information about the Python-Dev
mailing list