File: utils.py

package info (click to toggle)
python-kgb 7.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 532 kB
  • sloc: python: 4,466; makefile: 3
file content (96 lines) | stat: -rw-r--r-- 2,644 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
"""Common utility functions used by kgb."""

from __future__ import unicode_literals

import inspect
from unittest.util import safe_repr

from kgb.pycompat import iteritems


def get_defined_attr_value(owner, name, ancestors_only=False):
    """Return a value as defined in a class, instance, or ancestor.

    This will look for the real definition, and not the definition returned
    when accessing the attribute or instantiating a class. This will bypass any
    descriptors and return the actual definition from the instance or class
    that defines it.

    Args:
        owner (type or object):
            The owner of the attribute.

        name (unicode):
            The name of the attribute.

        ancestors_only (bool, optional):
            Whether to only look in ancestors of ``owner``, and not in
            ``owner`` itself.

    Returns:
        object:
        The attribute value.

    Raises:
        AttributeError:
            The attribute could not be found.
    """
    if not ancestors_only:
        d = owner.__dict__

        if name in d:
            return d[name]

    if not inspect.isclass(owner):
        # NOTE: It's important we use __class__ and not type(). They are not
        #       synonymous. The latter will not return the class for an
        #       instance for old-style classes.
        return get_defined_attr_value(owner.__class__, name)

    for parent_cls in owner.__bases__:
        try:
            return get_defined_attr_value(parent_cls, name)
        except AttributeError:
            pass

    raise AttributeError


def is_attr_defined_on_ancestor(cls, name):
    """Return whether an attribute is defined on an ancestor of a class.

    Args:
        name (unicode):
            The name of the attribute.

    Returns:
        bool:
        ``True`` if an ancestor defined the attribute. ``False`` if it did not.
    """
    try:
        get_defined_attr_value(cls, name, ancestors_only=True)
        return True
    except AttributeError:
        return False


def format_spy_kwargs(kwargs):
    """Format keyword arguments.

    This will convert all keys to native strings, to help with showing
    more reasonable output that's consistent. The keys will also be
    provided in sorted order.

    Args:
        kwargs (dict):
            The dictionary of keyword arguments.

    Returns:
        unicode:
        The formatted string representation.
    """
    return '{%s}' % ', '.join(
        '%s: %s' % (safe_repr(str(key)), safe_repr(value))
        for key, value in sorted(iteritems(kwargs),
                                 key=lambda pair: pair[0])
    )