~rbanffy/+junk/python3-seamicroclient

« back to all changes in this revision

Viewing changes to python-seamicroclient-0.2.1/seamicroclient/utils.py

  • Committer: Ricardo Bánffy
  • Date: 2015-12-15 21:36:41 UTC
  • Revision ID: rbanffy@gmail.com-20151215213641-l6rxowkaerz02467
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 
3
#    not use this file except in compliance with the License. You may obtain
 
4
#    a copy of the License at
 
5
#
 
6
#         http://www.apache.org/licenses/LICENSE-2.0
 
7
#
 
8
#    Unless required by applicable law or agreed to in writing, software
 
9
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
10
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
11
#    License for the specific language governing permissions and limitations
 
12
#    under the License.
 
13
 
 
14
import os
 
15
import pkg_resources
 
16
import sys
 
17
import uuid
 
18
 
 
19
import six
 
20
 
 
21
from seamicroclient import exceptions
 
22
from seamicroclient.openstack.common import strutils
 
23
 
 
24
 
 
25
def env(*args, **kwargs):
 
26
    """
 
27
    returns the first environment variable set
 
28
    if none are non-empty, defaults to '' or keyword arg default
 
29
    """
 
30
    for arg in args:
 
31
        value = os.environ.get(arg, None)
 
32
        if value:
 
33
            return value
 
34
    return kwargs.get('default', '')
 
35
 
 
36
 
 
37
def find_resource(manager, name_or_id, **find_args):
 
38
    """Helper for the _find_* methods."""
 
39
    # first try to get entity as integer id
 
40
    try:
 
41
        return manager.get(int(name_or_id))
 
42
    except (TypeError, ValueError, exceptions.NotFound):
 
43
        pass
 
44
 
 
45
    # now try to get entity as uuid
 
46
    try:
 
47
        tmp_id = strutils.safe_encode(name_or_id)
 
48
        if six.PY3:
 
49
            tmp_id = tmp_id.decode()
 
50
        uuid.UUID(tmp_id)
 
51
        return manager.get(tmp_id)
 
52
    except (TypeError, ValueError, exceptions.NotFound):
 
53
        pass
 
54
 
 
55
    # for str id which is not uuid (for Flavor search currently)
 
56
    if getattr(manager, 'is_alphanum_id_allowed', False):
 
57
        try:
 
58
            return manager.get(name_or_id)
 
59
        except exceptions.NotFound:
 
60
            pass
 
61
 
 
62
    try:
 
63
        try:
 
64
            return manager.find(human_id=name_or_id, **find_args)
 
65
        except exceptions.NotFound:
 
66
            pass
 
67
 
 
68
        # finally try to find entity by name
 
69
        try:
 
70
            resource = getattr(manager, 'resource_class', None)
 
71
            name_attr = resource.NAME_ATTR if resource else 'name'
 
72
            kwargs = {name_attr: name_or_id}
 
73
            kwargs.update(find_args)
 
74
            return manager.find(**kwargs)
 
75
        except exceptions.NotFound:
 
76
            msg = "No %s with a name or ID of '%s' exists." % \
 
77
                (manager.resource_class.__name__.lower(), name_or_id)
 
78
            raise exceptions.CommandError(msg)
 
79
    except exceptions.NoUniqueMatch:
 
80
        msg = ("Multiple %s matches found for '%s', use an ID to be more"
 
81
               " specific." % (manager.resource_class.__name__.lower(),
 
82
                               name_or_id))
 
83
        raise exceptions.CommandError(msg)
 
84
 
 
85
 
 
86
def _format_field_name(attr):
 
87
    """Format an object attribute in a human-friendly way."""
 
88
    # Split at ':' and leave the extension name as-is.
 
89
    parts = attr.rsplit(':', 1)
 
90
    name = parts[-1].replace('_', ' ')
 
91
    # Don't title() on mixed case
 
92
    if name.isupper() or name.islower():
 
93
        name = name.title()
 
94
    parts[-1] = name
 
95
    return ': '.join(parts)
 
96
 
 
97
 
 
98
def _make_field_formatter(attr, filters=None):
 
99
    """
 
100
    Given an object attribute, return a formatted field name and a
 
101
    formatter suitable for passing to print_list.
 
102
 
 
103
    Optionally pass a dict mapping attribute names to a function. The function
 
104
    will be passed the value of the attribute and should return the string to
 
105
    display.
 
106
    """
 
107
    filter_ = None
 
108
    if filters:
 
109
        filter_ = filters.get(attr)
 
110
 
 
111
    def get_field(obj):
 
112
        field = getattr(obj, attr, '')
 
113
        if field and filter_:
 
114
            field = filter_(field)
 
115
        return field
 
116
 
 
117
    name = _format_field_name(attr)
 
118
    formatter = get_field
 
119
    return name, formatter
 
120
 
 
121
 
 
122
class HookableMixin(object):
 
123
 
 
124
    """Mixin so classes can register and run hooks."""
 
125
    _hooks_map = {}
 
126
 
 
127
    @classmethod
 
128
    def add_hook(cls, hook_type, hook_func):
 
129
        if hook_type not in cls._hooks_map:
 
130
            cls._hooks_map[hook_type] = []
 
131
 
 
132
        cls._hooks_map[hook_type].append(hook_func)
 
133
 
 
134
    @classmethod
 
135
    def run_hooks(cls, hook_type, *args, **kwargs):
 
136
        hook_funcs = cls._hooks_map.get(hook_type) or []
 
137
        for hook_func in hook_funcs:
 
138
            hook_func(*args, **kwargs)
 
139
 
 
140
 
 
141
def safe_issubclass(*args):
 
142
    """Like issubclass, but will just return False if not a class."""
 
143
 
 
144
    try:
 
145
        if issubclass(*args):
 
146
            return True
 
147
    except TypeError:
 
148
        pass
 
149
 
 
150
    return False
 
151
 
 
152
 
 
153
def import_class(import_str):
 
154
    """Returns a class from a string including module and class."""
 
155
    mod_str, _sep, class_str = import_str.rpartition('.')
 
156
    __import__(mod_str)
 
157
    return getattr(sys.modules[mod_str], class_str)
 
158
 
 
159
 
 
160
def _load_entry_point(ep_name, name=None):
 
161
    """Try to load the entry point ep_name that matches name."""
 
162
    for ep in pkg_resources.iter_entry_points(ep_name, name=name):
 
163
        try:
 
164
            return ep.load()
 
165
        except (ImportError, pkg_resources.UnknownExtra, AttributeError):
 
166
            continue
 
167
 
 
168
 
 
169
def is_integer_like(val):
 
170
    """Returns validation of a value as an integer."""
 
171
    try:
 
172
        value = int(val)
 
173
        return True
 
174
    except (TypeError, ValueError, AttributeError):
 
175
        return False