1
0
mirror of https://github.com/ARM-software/workload-automation.git synced 2025-09-02 03:12:34 +01:00

WA Types: Added 'ParameterDict' type.

A new 'ParameterDict' has been added that automatically encodes and
decodes values when they are store in a dictionary. The dictionary uses 2 characters
prefixed to each value to store the original type information, e.g. 'fl' -> list of
floats, before being passed through a url encoder. The reverse process happens on retrieval.
To access the encoded values an `iterEncodedItems` and `getEncodedValue` methods have been added.

The appropriate unit tests have also been added.
This commit is contained in:
Marc Bonnici
2017-02-09 16:12:47 +00:00
parent 8f40e6aa40
commit 9ba30c27df
2 changed files with 243 additions and 2 deletions

View File

@@ -30,6 +30,7 @@ import re
import math
import shlex
from collections import defaultdict
from urllib import quote, unquote
from wlauto.utils.misc import isiterable, to_identifier
@@ -328,3 +329,119 @@ class range_dict(dict):
def __setitem__(self, i, v):
i = int(i)
super(range_dict, self).__setitem__(i, v)
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[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