Made typeclass loading a little more forgiving, adding a multitude of try-levels to fall back to in case of errors. Default is now to fallback to first settings-set default, then to the library default and only as a last resort fall back to the model. Every fallback step is logged. This should make the missing-hook error of #698 go away and report missing typeclasses in a better way.
This commit is contained in:
parent
c9ed8b5ec5
commit
d752106906
5 changed files with 71 additions and 6 deletions
|
|
@ -89,8 +89,23 @@ class TypeclassBase(SharedMemoryModelBase):
|
|||
"""
|
||||
|
||||
# storage of stats
|
||||
attrs["typename"] = name#cls.__name__
|
||||
attrs["typename"] = name
|
||||
attrs["path"] = "%s.%s" % (attrs["__module__"], name)
|
||||
#defaultpath = attrs["__defaultclasspath__"]
|
||||
#attrs["__defaultclass__"] = class_from_module(attrs["__defaultclasspath__"])
|
||||
#try:
|
||||
# defaultpath = attrs["__defaultclasspath__"]
|
||||
# attrs["__defaultclass__"] = class_from_module(attrs["__defaultclasspath__"])
|
||||
#except Exception:
|
||||
# log_trace("Typeclass error for %s: Default typeclass '%s' could not load. "
|
||||
# "Falling back to library base." % (name, defaultpath))
|
||||
# try:
|
||||
# # two levels down from TypedObject will always be the default base class.
|
||||
# attrs["__defaultclass__"] = cls.__mro__[cls.__mro__.index(TypedObject)-2]
|
||||
# except Exception:
|
||||
# log_trace("Critical error for %s: Neither typeclass, "
|
||||
# "default fallback nor base class could load." % name)
|
||||
# attrs["__defaultclass__"] = cls
|
||||
|
||||
# typeclass proxy setup
|
||||
if not "Meta" in attrs:
|
||||
|
|
@ -172,9 +187,33 @@ class TypedObject(SharedMemoryModel):
|
|||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
This is the main function of the typeclass system -
|
||||
to dynamically re-apply a class based on the
|
||||
db_typeclass_path rather than use the one in the model.
|
||||
The `__init__` method of typeclasses is the core operational
|
||||
code of the typeclass system, where it dynamically re-applies
|
||||
a class based on the db_typeclass_path database field rather
|
||||
than use the one in the model.
|
||||
|
||||
Args:
|
||||
Passed through to parent.
|
||||
|
||||
Kwargs:
|
||||
Passed through to parent.
|
||||
|
||||
Notes:
|
||||
The loading mechanism will attempt the following steps:
|
||||
|
||||
1. Attempt to load typeclass given on command line
|
||||
1. Attempt to load typeclass stored in db_typeclass_path
|
||||
1. Attempt to load `__settingsclasspath__`, which is by the
|
||||
default classes defined to be the respective user-set
|
||||
base typeclass settings, like `BASE_OBJECT_TYPECLASS`.
|
||||
1. Attempt to load `__defaultclasspath__`, which is the
|
||||
base classes in the library, like DefaultObject etc.
|
||||
1. If everything else fails, use the database model.
|
||||
|
||||
Normal operation is to load successfully at either step 1
|
||||
or 2 depending on how the class was called. Tracebacks
|
||||
will be logged for every step the loader must take beyond
|
||||
2.
|
||||
|
||||
"""
|
||||
typeclass_path = kwargs.pop("typeclass", None)
|
||||
|
|
@ -182,15 +221,29 @@ class TypedObject(SharedMemoryModel):
|
|||
if typeclass_path:
|
||||
try:
|
||||
self.__class__ = class_from_module(typeclass_path)
|
||||
except ImportError:
|
||||
except Exception:
|
||||
log_trace()
|
||||
try:
|
||||
self.__class__ = class_from_module(self.__settingsclasspath__)
|
||||
except Exception:
|
||||
log_trace()
|
||||
try:
|
||||
self.__class__ = class_from_module(self.__defaultclasspath__)
|
||||
except Exception:
|
||||
log_trace()
|
||||
self.__class__ = self._meta.proxy_for_model or self.__class__
|
||||
finally:
|
||||
self.db_typclass_path = typeclass_path
|
||||
elif self.db_typeclass_path:
|
||||
try:
|
||||
self.__class__ = class_from_module(self.db_typeclass_path)
|
||||
except ImportError:
|
||||
except Exception:
|
||||
log_trace()
|
||||
try:
|
||||
self.__class__ = class_from_module(self.__defaultclasspath__)
|
||||
except Exception:
|
||||
log_trace()
|
||||
self.__dbclass__ = self._meta.proxy_for_model or self.__class__
|
||||
else:
|
||||
self.db_typeclass_path = "%s.%s" % (self.__module__, self.__class__.__name__)
|
||||
# important to put this at the end since _meta is based on the set __class__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue