xoutil.objects - Functions for dealing with objects

Several utilities for objects in general.

xoutil.objects.validate_attrs(source, target, force_equals=(), force_differents=())[source]

Makes a ‘comparison’ of source and target by its attributes (or keys).

This function returns True if and only if both of these tests pass:

  • All attributes in force_equals are equal in source and target
  • All attributes in force_differents are different in source and target

For instance:

>>> class Person(object):
...    def __init__(self, **kwargs):
...        for which in kwargs:
...            setattr(self, which, kwargs[which])

>>> source = Person(name='Manuel', age=33, sex='male')
>>> target = {'name': 'Manuel', 'age': 4, 'sex': 'male'}

>>> validate_attrs(source, target, force_equals=('sex',),
...                force_differents=('age',))
True

>>> validate_attrs(source, target, force_equals=('age',))
False

If both force_equals and force_differents are empty it will return True:

>>> validate_attrs(source, target)
True
xoutil.objects.iterate_over(source, *keys)[source]

Yields pairs of (key, value) for of all keys in source.

If any key is missing from source is ignored (not yielded).

If source is a collection, iterate over each of the items searching for any of keys. This is not recursive.

If no keys are provided, return an “empty” iterator – i.e will raise StopIteration upon calling next.

New in version 1.5.2.

xoutil.objects.smart_getter(obj, strict=False)[source]

Returns a smart getter for obj.

If obj is a mapping, it returns the .get() method bound to the object obj, otherwise it returns a partial of getattr on obj.

Parameters:strict – Set this to True so that the returned getter checks that keys/attrs exists. If strict is True the getter may raise a KeyError or an AttributeError.

Changed in version 1.5.3: Added the parameter strict.

xoutil.objects.smart_getter_and_deleter(obj)[source]

Returns a function that get and deletes either a key or an attribute of obj depending on the type of obj.

If obj is a collections.Mapping it must be a collections.MutableMapping.

xoutil.objects.popattr(obj, name, default=None)[source]

Looks for an attribute in the obj and returns its value and removes the attribute. If the attribute is not found, default is returned instead.

Examples:

>>> class Foo(object):
...   a = 1
>>> foo = Foo()
>>> foo.a = 2
>>> popattr(foo, 'a')
2
>>> popattr(foo, 'a')
1
>>> popattr(foo, 'a') is None
True
xoutil.objects.setdefaultattr(obj, name, value)[source]

Sets the attribute name to value if it is not set:

>>> class Someclass(object): pass
>>> inst = Someclass()
>>> setdefaultattr(inst, 'foo', 'bar')
'bar'

>>> inst.foo
'bar'

>>> inst.spam = 'egg'
>>> setdefaultattr(inst, 'spam', 'with ham')
'egg'

(New in version 1.2.1). If you want the value to be lazily evaluated you may provide a lazy-lambda:

>>> inst = Someclass()
>>> inst.a = 1
>>> def setting_a():
...    print('Evaluating!')
...    return 'a'

>>> setdefaultattr(inst, 'a', lazy(setting_a))
1

>>> setdefaultattr(inst, 'ab', lazy(setting_a))
Evaluating!
'a'
xoutil.objects.copy_class(cls, meta=None, ignores=None, new_attrs=None, new_name=None)[source]

Copies a class definition to a new class.

The returned class will have the same name, bases and module of cls.

Parameters:
  • meta – If None, the type(cls) of the class is used to build the new class, otherwise this must be a proper metaclass.
  • ignores

    A sequence of attributes names that should not be copied to the new class.

    An item may be callable accepting a single argument attr that must return a non-null value if the the attr should be ignored.

  • new_attrs (dict) – New attributes the class must have. These will take precedence over the attributes in the original class.
  • new_name – The name for the copy. If not provided the name will copied.

New in version 1.4.0.

Changed in version 1.7.1: The ignores argument must an iterable of strings or callables. Removed the glob-pattern and regular expressions as possible values. They are all possible via the callable variant.

New in version 1.7.1: The new_name argument.

xoutil.objects.fulldir(obj)[source]

Return a set with all attribute names defined in obj

class xoutil.objects.classproperty(fget)[source]

A descriptor that behaves like property for instances but for classes.

Example of its use:

class Foobar(object):
    @classproperty
    def getx(cls):
        return cls._x

Class properties are always read-only, if attribute values must be set or deleted, a metaclass must be defined.

xoutil.objects.get_first_of(sources, *keys, default=None, pred=None)[source]

Return the value of the first occurrence of any of the specified keys in source that matches pred (if given).

Both source and keys has the same meaning as in iterate_over().

Parameters:
  • default – A value to be returned if no key is found in source.
  • pred – A function that should receive a single value and return False if the value is not acceptable, and thus get_first_of should look for another.

Changed in version 1.5.2: Added the pred option.

xoutil.objects.xdir(obj, filter=None, attr_filter=None, value_filter=None, getattr=None)[source]

Return all (attr, value) pairs from obj that attr_filter(attr) and value_filter(value) are both True.

Parameters:
  • obj – The object to be instrospected.
  • filter

    optional A filter that will be passed both the attribute name and it’s value as two positional arguments. It should return True for attrs that should be yielded.

    Note

    If passed, both attr_filter and value_filter will be ignored.

  • attr_filteroptional A filter for attribute names. Deprecated since 1.4.1
  • value_filteroptional A filter for attribute values. Deprecated since 1.4.1
  • getteroptional A function with the same signature that getattr to be used to get the values from obj.

Deprecated since version 1.4.1: The use of params attr_filter and value_filter.

xoutil.objects.fdir(obj, filter=None, attr_filter=None, value_filter=None, getattr=None)[source]

Similar to xdir() but yields only the attributes names.

xoutil.objects.smart_copy(*sources, target, *, defaults=False)[source]

Copies the first apparition of attributes (or keys) from sources to target.

Parameters:
  • sources – The objects from which to extract keys or attributes.
  • target – The object to fill.
  • defaults (Either a bool, a dictionary, an iterable or a callable.) – Default values for the attributes to be copied as explained below. Defaults to False.

Every sources and target are always positional arguments. There should be at least one source. target will always be the last positional argument.

If defaults is a dictionary or an iterable then only the names provided by itering over defaults will be copied. If defaults is a dictionary, and one of its key is not found in any of the sources, then the value of the key in the dictionary is copied to target unless:

In these cases a KeyError is raised if the key is not found in the sources.

If default is an iterable and a key is not found in any of the sources, None is copied to target.

If defaults is a callable then it should receive one positional arguments for the current attribute name and several keyword arguments (we pass source) and return either True or False if the attribute should be copied.

If defaults is False (or None) only the attributes that do not start with a “_” are copied, if it’s True all attributes are copied.

When target is not a mapping only valid Python identifiers will be copied.

Each source is considered a mapping if it’s an instance of collections.Mapping or a MappingProxyType.

The target is considered a mapping if it’s an instance of collections.MutableMapping.

Returns:target.

Changed in version 1.7.0: defaults is now keyword only.

xoutil.objects.extract_attrs(obj, *names, default=Unset)[source]

Extracts all names from an object.

If obj is a Mapping, the names will be search in the keys of the obj; otherwise the names are considered regular attribute names.

If default is Unset and any name is not found, an AttributeError is raised, otherwise the default is used instead.

Returns a tuple if there are more that one name, otherwise returns a single value.

New in version 1.4.0.

Changed in version 1.5.3: Each name may be a path like in get_traverser(), but only ”.” is allowed as separator.

xoutil.objects.traverse(obj, path, default=Unset, sep='.', getter=None)[source]

Traverses an object’s hierarchy by performing an attribute get at each level.

This helps getting an attribute that is buried down several levels deep. For example:

traverse(request, 'session.somevalue')

If default is not provided (i.e is Unset) and any component in the path is not found an AttributeError exceptions is raised.

You may provide sep to change the default separator.

You may provide a custom getter. By default, does an smart_getter() over the objects. If provided getter should have the signature of getattr().

See get_traverser() if you need to apply the same path(s) to several objects. Actually this is equivalent to:

get_traverser(path, default=default, sep=sep, getter=getter)(obj)
xoutil.objects.get_traverser(*paths, default=Unset, sep='.', getter=None)[source]

Combines the power of traverse() with the expectations from both operator.itergetter() and operator.attrgetter().

Parameters:paths – Several paths to extract.

Keyword arguments has the same meaning as in traverse().

Returns:A function the when invoked with an object traverse the object finding each path.

New in version 1.5.3.

xoutil.objects.dict_merge(*dicts, **other)[source]

Merges several dicts into a single one.

Merging is similar to updating a dict, but if values are non-scalars they are also merged is this way:

  • Any two sequences or sets are joined together.
  • Any two mappings are recursively merged.
  • Other types are just replaced like in update().

If for a single key two values of incompatible types are found, raise a TypeError. If the values for a single key are compatible but different (i.e a list an a tuple) the resultant type will be the type of the first apparition of the key, unless for mappings which are always cast to dicts.

No matter the types of dicts the result is always a dict.

Without arguments, return the empty dict.

xoutil.objects.smart_getattr(name, *sources, **kwargs)[source]

Gets an attr by name for the first source that has it.

This is roughly that same as:

get_first_of(sources, name, default=Unset, **kwargs)

Warning

Deprecated since 1.5.1

xoutil.objects.pop_first_of(source, *keys, default=None)[source]

Similar to get_first_of() using as source either an object or a mapping and deleting the first attribute or key.

Examples:

>>> somedict = dict(bar='bar-dict', eggs='eggs-dict')

>>> class Foo(object): pass
>>> foo = Foo()
>>> foo.bar = 'bar-obj'
>>> foo.eggs = 'eggs-obj'

>>> pop_first_of((somedict, foo), 'eggs')
'eggs-dict'

>>> pop_first_of((somedict, foo), 'eggs')
'eggs-obj'

>>> pop_first_of((somedict, foo), 'eggs') is None
True

>>> pop_first_of((foo, somedict), 'bar')
'bar-obj'

>>> pop_first_of((foo, somedict), 'bar')
'bar-dict'

>>> pop_first_of((foo, somedict), 'bar') is None
True
xoutil.objects.get_and_del_attr(obj, name, default=None)

Deprecated alias for popattr().

xoutil.objects.get_and_del_first_of(source, *keys, default=None)

Deprecated alias for pop_first_of().

class xoutil.objects.metaclass(meta, **kwargs)[source]

Deprecated alias of xoutil.eight.meta.metaclass.

New in version 1.4.1.

Changed in version 1.7.0: Deprecated in favor of xoutil.eight.meta.metaclass().

xoutil.objects.fix_method_documentation(cls, method_name, ignore=None, min_length=10, deep=1, default=None)[source]

Fix the documentation for the given class using its super-classes.

This function may be useful for shells or Python Command Line Interfaces (CLI).

If cls has an invalid documentation, super-classes are recursed in MRO until a documentation definition was made at any level.

Parameters:
  • ignore – could be used to specify which classes to ignore by specifying its name in this list.
  • min_length – specify that documentations with less that a number of characters, also are ignored.
xoutil.objects.multi_getter(source, *ids)[source]

Get values from source of all given ids.

Parameters:
  • source – Any object but dealing with differences between mappings and other object types.
  • ids

    Identifiers to get values from source.

    An ID item could be:

    • a string: is considered a key, if source is a mapping, or an attribute name if source is an instance of any other type.
    • a collection of strings: find the first valid value in source evaluating each item in this collection using the above logic.

Example:

>>> d = {'x': 1, 'y': 2, 'z': 3}
>>> list(multi_getter(d, 'a', ('y', 'x'), ('x', 'y'), ('a', 'z', 'x')))
[None, 2, 1, 3]

>>> next(multi_getter(d, ('y', 'x'), ('x', 'y')), '---')
2

>>> next(multi_getter(d, 'a', ('b', 'c'), ('e', 'f')), '---') is None
True

New in version 1.7.1.

xoutil.objects.get_branch_subclasses(cls)[source]

Similar to type.__subclasses__() but recursive.

Only return sub-classes in branches (those with no sub-classes). Instead of returning a list, yield each valid value.

New in version 1.7.0.