mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-02-22 04:49:00 +00:00
Types: Adds ParameterDict Type
Acts like a regular dictionary however will automatically url encode/decode the data along with relevant type information.
This commit is contained in:
parent
e884c3bcca
commit
85218a10d2
@ -32,6 +32,7 @@ import numbers
|
|||||||
import shlex
|
import shlex
|
||||||
import string
|
import string
|
||||||
from bisect import insort
|
from bisect import insort
|
||||||
|
from urllib import quote, unquote
|
||||||
from collections import defaultdict, MutableMapping
|
from collections import defaultdict, MutableMapping
|
||||||
from copy import copy
|
from copy import copy
|
||||||
|
|
||||||
@ -586,3 +587,118 @@ def enum(args, start=0, step=1):
|
|||||||
|
|
||||||
return Enum
|
return Enum
|
||||||
|
|
||||||
|
|
||||||
|
class ParameterDict(dict):
|
||||||
|
"""
|
||||||
|
A dict-like object that automatically encodes various types into a url safe string,
|
||||||
|
and enforces a single type for the contents in a list.
|
||||||
|
Each value is first prefixed with 2 letters to preserve type when encoding to a string.
|
||||||
|
The format used is "value_type, value_dimension" e.g a 'list of floats' would become 'fl'.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Function to determine the appropriate prefix based on the parameters type
|
||||||
|
@staticmethod
|
||||||
|
def _get_prefix(obj):
|
||||||
|
if isinstance(obj, basestring):
|
||||||
|
prefix = 's'
|
||||||
|
elif isinstance(obj, float):
|
||||||
|
prefix = 'f'
|
||||||
|
elif isinstance(obj, long):
|
||||||
|
prefix = 'd'
|
||||||
|
elif isinstance(obj, bool):
|
||||||
|
prefix = 'b'
|
||||||
|
elif isinstance(obj, int):
|
||||||
|
prefix = 'i'
|
||||||
|
elif obj is None:
|
||||||
|
prefix = 'n'
|
||||||
|
else:
|
||||||
|
raise ValueError('Unable to encode {} {}'.format(obj, type(obj)))
|
||||||
|
return prefix
|
||||||
|
|
||||||
|
# Function to add prefix and urlencode a provided parameter.
|
||||||
|
@staticmethod
|
||||||
|
def _encode(obj):
|
||||||
|
if isinstance(obj, list):
|
||||||
|
t = type(obj[0])
|
||||||
|
prefix = ParameterDict._get_prefix(obj[0]) + 'l'
|
||||||
|
for item in obj:
|
||||||
|
if not isinstance(item, t):
|
||||||
|
msg = 'Lists must only contain a single type, contains {} and {}'
|
||||||
|
raise ValueError(msg.format(t, type(item)))
|
||||||
|
obj = '0newelement0'.join(str(x) for x in obj)
|
||||||
|
else:
|
||||||
|
prefix = ParameterDict._get_prefix(obj) + 's'
|
||||||
|
return quote(prefix + str(obj))
|
||||||
|
|
||||||
|
# Function to decode a string and return a value of the original parameter type.
|
||||||
|
# pylint: disable=too-many-return-statements
|
||||||
|
@staticmethod
|
||||||
|
def _decode(string):
|
||||||
|
value_type = string[:1]
|
||||||
|
value_dimension = string[1:2]
|
||||||
|
value = unquote(string[2:])
|
||||||
|
if value_dimension == 's':
|
||||||
|
if value_type == 's':
|
||||||
|
return str(value)
|
||||||
|
elif value_type == 'b':
|
||||||
|
return boolean(value)
|
||||||
|
elif value_type == 'd':
|
||||||
|
return long(value)
|
||||||
|
elif value_type == 'f':
|
||||||
|
return float(value)
|
||||||
|
elif value_type == 'i':
|
||||||
|
return int(value)
|
||||||
|
elif value_type == 'n':
|
||||||
|
return None
|
||||||
|
elif value_dimension == 'l':
|
||||||
|
return [ParameterDict._decode(value_type + 's' + x)
|
||||||
|
for x in value.split('0newelement0')]
|
||||||
|
else:
|
||||||
|
raise ValueError('Unknown {} {}'.format(type(string), string))
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
for k, v in kwargs.iteritems():
|
||||||
|
self.__setitem__(k, v)
|
||||||
|
dict.__init__(self, *args)
|
||||||
|
|
||||||
|
def __setitem__(self, name, value):
|
||||||
|
dict.__setitem__(self, name, self._encode(value))
|
||||||
|
|
||||||
|
def __getitem__(self, name):
|
||||||
|
return self._decode(dict.__getitem__(self, name))
|
||||||
|
|
||||||
|
def __contains__(self, item):
|
||||||
|
return dict.__contains__(self, self._encode(item))
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return iter((k, self._decode(v)) for (k, v) in self.items())
|
||||||
|
|
||||||
|
def iteritems(self):
|
||||||
|
return self.__iter__()
|
||||||
|
|
||||||
|
def get(self, name):
|
||||||
|
return self._decode(dict.get(self, name))
|
||||||
|
|
||||||
|
def pop(self, key):
|
||||||
|
return self._decode(dict.pop(self, key))
|
||||||
|
|
||||||
|
def popitem(self):
|
||||||
|
key, value = dict.popitem(self)
|
||||||
|
return (key, self._decode(value))
|
||||||
|
|
||||||
|
def iter_encoded_items(self):
|
||||||
|
return dict.iteritems(self)
|
||||||
|
|
||||||
|
def get_encoded_value(self, name):
|
||||||
|
return dict.__getitem__(self, name)
|
||||||
|
|
||||||
|
def values(self):
|
||||||
|
return [self[k] for k in dict.keys(self)]
|
||||||
|
|
||||||
|
def update(self, *args, **kwargs):
|
||||||
|
for d in list(args) + [kwargs]:
|
||||||
|
if isinstance(d, ParameterDict):
|
||||||
|
dict.update(self, d)
|
||||||
|
else:
|
||||||
|
for k, v in d.iteritems():
|
||||||
|
self[k] = v
|
||||||
|
Loading…
x
Reference in New Issue
Block a user