forked from openstack/rally
-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.py
124 lines (104 loc) · 4.28 KB
/
utils.py
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# Copyright 2013 IBM Corp.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import jsonschema
from rally import consts
class ActionBuilder(object):
"""Builder class for mapping and creating action objects.
An action list is an array of single key/value dicts which takes
the form:
[{"action": times}, {"action": times}...]
Here 'action' is a string which indicates a action to perform and
'times' is a non-zero positive integer which specifies how many
times to run the action in sequence.
This utility builder class will build and return methods which
wrapper the action call the given amount of times.
"""
SCHEMA_TEMPLATE = {
"type": "array",
"$schema": consts.JSON_SCHEMA,
"items": {
"type": "object",
"properties": {},
"additionalProperties": False,
"minItems": 0
}
}
ITEM_TEMPLATE = {
"type": "integer",
"minimum": 0,
"exclusiveMinimum": True,
"optional": True
}
def __init__(self, action_keywords):
"""Create a new instance of the builder for the given action keywords.
:param action_keywords: A list of strings which are the keywords this
instance of the builder supports.
"""
self._bindings = {}
self.schema = dict(ActionBuilder.SCHEMA_TEMPLATE)
for kw in action_keywords:
self.schema["items"]["properties"][kw] = (
ActionBuilder.ITEM_TEMPLATE)
def bind_action(self, action_key, action, *args, **kwargs):
"""Bind an action to an action key.
Static args/kwargs can be optionally binded.
:param action_key: The action keyword to bind the action to.
:param action: A method/function to call for the action.
:param args: (optional) Static positional args to prepend
to all invocations of the action.
:param kwargs: (optional) Static kwargs to prepend to all
invocations of the action.
"""
self.validate([{action_key: 1}])
self._bindings[action_key] = {
"action": action,
"args": args or (),
"kwargs": kwargs or {}
}
def validate(self, actions):
"""Validate the list of action objects against the builder schema.
:param actions: The list of action objects to validate.
"""
jsonschema.validate(actions, self.schema)
def _build(self, func, times, *args, **kwargs):
"""Build the wrapper action call."""
def _f():
for i in range(times):
func(*args, **kwargs)
return _f
def build_actions(self, actions, *args, **kwargs):
"""Build a list of callable actions.
A list of callable actions based on the given action object list and
the actions bound to this builder.
:param actions: A list of action objects to build callable
action for.
:param args: (optional) Positional args to pass into each
built action. These will be appended to any args set for the
action via its binding.
:param kwargs: (optional) Keyword args to pass into each built
action. These will be appended to any kwards set for the action
via its binding.
"""
self.validate(actions)
bound_actions = []
for action in actions:
action_key = list(action)[0]
times = action.get(action_key)
binding = self._bindings.get(action_key)
dft_kwargs = dict(binding["kwargs"])
dft_kwargs.update(kwargs or {})
bound_actions.append(self._build(
binding["action"], times,
*(binding["args"] + args), **dft_kwargs))
return bound_actions