Skip to content

Instantly share code, notes, and snippets.

@specialunderwear
Last active July 12, 2019 09:08
Show Gist options
  • Save specialunderwear/88a0a877943abf2f799d9cf1780e6928 to your computer and use it in GitHub Desktop.
Save specialunderwear/88a0a877943abf2f799d9cf1780e6928 to your computer and use it in GitHub Desktop.
Have a Meta inner class like in django, that will turn into a _meta attribute.
from django.utils.functional import cached_property
class MetaClass(object):
def __init__(self, attrs, endpointname):
self.__dict__.update(attrs)
self.endpointname = endpointname
@cached_property
def endpoint(self):
from .api import exactapi
return exactapi.endpoint(self.endpointname)
def class_variables(cls):
return {
key: value for (key, value) in vars(cls).items() if not key.startswith("__")
}
class classproperty(object):
def __init__(self, f):
self.f = f
def __get__(self, obj, owner):
return self.f(owner)
class MetaInnerClassMetaClass(type):
"""
Have a _meta object just like django
>>> class Henk(dict, metaclass=MetaInnerClassMetaClass):
... class Meta:
... zult = True
... gaar = [1,2,3]
>>>
>>> class Klaas(Henk):
... class Meta:
... braatworst = "lekker"
... zult = False
>>>
>>> a = Henk()
>>> a._meta.zult
True
>>> a._meta.gaar
[1, 2, 3]
>>> b = Klaas()
>>> b._meta.zult
False
>>> b._meta.gaar
[1, 2, 3]
>>> b._meta.braatworst
'lekker'
"""
def __new__(cls, name, bases, attrs):
Meta = attrs.pop("Meta", None)
_meta = {}
for base in reversed(bases):
if hasattr(base, "_meta"):
_meta.update(class_variables(base._meta))
if Meta is not None:
_meta.update(class_variables(Meta))
classname = name.lower()
endpointname = _meta.pop("endpoint", classname) or classname
attrs["_meta"] = MetaClass(_meta, endpointname)
return super(MetaInnerClassMetaClass, cls).__new__(cls, name, bases, attrs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment