"""
thekraf.utils
=============
Miscellaneous utilities
"""
import argparse
from sqlalchemy.ext.mutable import Mutable
[docs]def get_subclasses(cls):
"""Get all subclasses of cls, recursively
If A is a subclass of cls and B is a subclass of A, both A and B will be
include
Note:
Does not include cls itself
Args:
cls(type):
Returns:
tuple[type]:
"""
children = cls.__subclasses__()
result = []
while children:
child = children.pop()
subclasses = child.__subclasses__()
result.append(child)
for subclass in subclasses:
children.append(subclass)
return tuple(result)
[docs]class MutableList(Mutable, list):
"""List type for SQLAlchemy with changed state for the session"""
@classmethod
[docs] def coerce(cls, key, value):
if not isinstance(value, MutableList):
if isinstance(value, list):
return MutableList(value)
value = Mutable.coerce(key, value)
return value
def __setitem__(self, key, value):
list.__setitem__(self, key, value)
self.changed()
def __getstate__(self):
return list(self)
def __setstate__(self, state):
self[:] = state
[docs]def recreate_field(unbound_field):
"""Make a copy of an unbound field that bumps the creation counter
WTForms determines the order of the fields of form with a creation counter
that is increment during the unbound field init. The issue is that the
fields of subclasses of a form are created after their super classes so the
subclass fields are always appended. That is, unless you override a field,
but that can be a lot of work.
If a subclass overrides a parent field by sending it through this function,
a copy of the unbound field will be created it an updated creation count
so the subclass can dictate the order of the fields.
Args:
unbound_field (wtforms.UnboundField): The field to copy
Returns:
wtforms.UnboundField: Copy of the field
"""
return unbound_field.field_class(*unbound_field.args,
**unbound_field.kwargs)