-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
EnforceOverrides doesn't work for magic methods #36
Comments
Backwards incompatibility here is a real puzzle. I have to enumerate all the magic methods to be certain that this does not break anything. |
It might be easier to just add it as a new class. As an aside, I had to make a few more tweaks to get it to work with properties (since properties aren't callable). This is the version I have now; changed lines marked: class EnforceOverridesAllMeta(ABCMeta):
def __new__(mcls, name, bases, namespace, **kwargs):
cls = super().__new__(mcls, name, bases, namespace, **kwargs)
for name, value in namespace.items():
# Actually checking the direct parent should be enough,
# otherwise the error would have emerged during the parent class checking
value = mcls.handle_special_value(value) # NOTE: this line moved above the if
if not callable(value): # NOTE: this line is different
continue
is_override = getattr(value, '__override__', False)
for base in bases:
base_class_method = getattr(base, name, False)
base_class_method = mcls.handle_special_value(base_class_method) # NOTE: this line added
if not base_class_method or not callable(base_class_method):
continue
assert is_override, \
'Method %s overrides but does not have @overrides decorator' % (name)
# `__finalized__` is added by `@final` decorator
assert not getattr(base_class_method, '__finalized__', False), \
'Method %s is finalized in %s, it cannot be overridden' % (base_class_method, base)
return cls
@staticmethod
def handle_special_value(value):
if isinstance(value, classmethod):
value = value.__get__(None, dict)
elif isinstance(value, property):
value = value.fget
return value |
I'd love to have the improved version... would like to mark So will this be included officially in some form? |
@apirogov I try to find time to do this :) |
Another issue is that |
@apirogov could you make another issue for the case you explained? |
Fixed this issue in #105 |
I tried marking an
__enter__
method as final, but this doesn't work:The
EnforceOverridesMeta
class explicitly excludes names that start with double underscores (seeenforce.py
lines 10-11). I suspect the intention of this is to exclude names like__module__
or__qualname__
. However, those could be more appropriately filtered by checkingcallable(value)
instead.The updated code would be:
Relevant scenarios:
__enter__
to ensure a behavior / safety by marking it final.__init__
is part of the interface (e.g. for factory functions operating on types), marking it as final.@overrides
markers on magic functions to make it explicit when such functions are being overriden.Note that the change as proposed above is not backwards compatible. To maintain backwards compatibility the existing class could be maintained and an additional class could be added with the new behavior (e.g.
EnforceOverridesAll
).The text was updated successfully, but these errors were encountered: