Mercurial > cgi-bin > hgweb.cgi > tincan
changeset 19:5d9a1b82251a draft before-template-changes
Return the "deepest" subclass; this allows subclassing tincan.Page and
making a standard base page class for a webapp.
author | David Barts <n5jrn@me.com> |
---|---|
date | Mon, 20 May 2019 17:42:18 -0700 |
parents | e88ab99914cf |
children | 6bf9a41a09f2 |
files | tincan.py |
diffstat | 1 files changed, 31 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/tincan.py Mon May 20 08:40:56 2019 -0700 +++ b/tincan.py Mon May 20 17:42:18 2019 -0700 @@ -489,16 +489,43 @@ spec.loader.exec_module(mod) except Exception as e: raise TinCanError("{0}: error importing: {1!s}".format(pycpath, e)) from e - # Locate a suitable class + # Locate a suitable class. We look for the "deepest" class object + # we can find in the inheritance tree. self._class = None + score = -1 + ambig = False for i in dir(mod): v = getattr(mod, i) - if isclass(v) and issubclass(v, klass) and v is not klass: - if self._class is not None: - raise TinCanError("{0}: contains multiple {1} classes".format(pypath, klass.__name__)) + if not isclass(v): + continue + d = self._cldepth(klass, v) + if d > score: self._class = v + score = d + ambig = False + elif d == score: + ambig = True if self._class is None: raise TinCanError("{0}: contains no {1} classes".format(pypath, klass.__name__)) + if ambig: + raise TinCanError("{0}: contains ambiguous {1} classes".format(pypath, klass.__name__)) + + # This might fail for complex inheritance schemes from the classes of + # interest (so don't use them!). + def _cldepth(self, base, klass, count=0): + if klass is object: + # not found + return -1 + elif klass is base: + # just found + return count + else: + # must recurse + for c in klass.__bases__: + result = self._cldepth(base, c, count=count+1) + if result > 0: + return result + return -1 def _redirect(self): try: