snakeoil.klass.util module

snakeoil.klass.util.combine_classes(kls: type, *extra: type) type[source]

Given a set of classes, combine this as if one had wrote the class by hand

This is primarily for composing metaclasses on the fly; this:

class foo(metaclass=combine_metaclasses(kls1, kls2, kls3)): pass

is the same as if you did this:

class mkls(kls1, kls2, kls3): pass class foo(metaclass=mkls): pass

snakeoil.klass.util.copy_class_docs(source_class)[source]

Copy the docs and annotations of a target class for methods that intersect with the target.

This does not check that the prototype signatures are the same, and it exempts __init__ since that makes no sense to copy

snakeoil.klass.util.copy_docs(target)[source]

Copy the docs and annotations off of the given target

This is used for implementations that look like something (the target), but do not actually invoke the the target.

If you’re just wrapping something- a true decorator- use functools.wraps

snakeoil.klass.util.get_attrs_of(obj: ~typing.Any, weakref=False, suppressions: ~typing.Iterable[str] = (), _sentinel=<object object>) Iterable[tuple[str, Any]][source]

yield the attributes of a given instance.

This handles both slotted and non slotted classes- slotted classes do not have __dict__. It also handles mixed derivations, a non slotted class that inherited from a slotted class.

For an ordered __dict__ class, the ordering is not honored in what this yields.

Parameters:
  • weakref – by default, suppress that __weakref__ exists since it’s python internal bookkeeping. The only reason to enable this is for introspection tools; even state saving tools shouldn’t care about __weakref__

  • suppressions – attributes to suppress from the return. Use this as a way to avoid having to write a filter in the consumer- this already has to do filtering after all.

snakeoil.klass.util.get_slots_of(kls: type) Iterable[tuple[type, None | tuple[str, ...]]][source]

Visit a class MRO collecting all slotting

This cannot collect slotting of C objects- python builtins like object, or literal python C extensions, not unless they expose __slots__.