aboutsummaryrefslogtreecommitdiff
path: root/wa/utils
diff options
context:
space:
mode:
authorSergei Trofimov <sergei.trofimov@arm.com>2018-05-30 13:58:49 +0100
committerMarc Bonnici <marc.bonnici@arm.com>2018-06-07 14:48:40 +0100
commitb3de85455a872cd269187fb36263a17390f14d9c (patch)
tree6f958313086eaebfe64c27699c2c7527fb5facaf /wa/utils
parentc3ddb31d4d8ce58251b4876882a757cd643c097f (diff)
Add support for Python 3
Add support for running under Python 3, while maintaining compatibility with Python 2. See http://python-future.org/compatible_idioms.html for more details behind these changes.
Diffstat (limited to 'wa/utils')
-rwxr-xr-xwa/utils/cpustates.py30
-rw-r--r--wa/utils/diff.py23
-rw-r--r--wa/utils/doc.py16
-rw-r--r--wa/utils/exec_control.py8
-rw-r--r--wa/utils/log.py4
-rw-r--r--wa/utils/misc.py45
-rw-r--r--wa/utils/revent.py10
-rw-r--r--wa/utils/serializer.py28
-rw-r--r--wa/utils/terminalsize.py2
-rw-r--r--wa/utils/trace_cmd.py8
-rw-r--r--wa/utils/types.py101
11 files changed, 150 insertions, 125 deletions
diff --git a/wa/utils/cpustates.py b/wa/utils/cpustates.py
index 494b747e..c2557cd4 100755
--- a/wa/utils/cpustates.py
+++ b/wa/utils/cpustates.py
@@ -13,16 +13,17 @@
# limitations under the License.
#
-from __future__ import division
+
import os
import sys
-import csv
import re
import logging
from ctypes import c_int32
from collections import defaultdict
import argparse
+from devlib.utils.csvutil import create_writer, csvwriter
+
from wa.utils.trace_cmd import TraceCmdParser, trace_has_marker, TRACE_MARKER_START, TRACE_MARKER_STOP
@@ -114,7 +115,7 @@ class SystemPowerState(object):
self.timestamp = None
self.cpus = []
idle_state = -1 if no_idle else None
- for _ in xrange(num_cores):
+ for _ in range(num_cores):
self.cpus.append(CpuPowerState(idle_state=idle_state))
def copy(self):
@@ -331,8 +332,7 @@ class PowerStateTransitions(object):
def __init__(self, output_directory):
self.filepath = os.path.join(output_directory, 'state-transitions-timeline.csv')
- self._wfh = open(self.filepath, 'w')
- self.writer = csv.writer(self._wfh)
+ self.writer, self._wfh = create_writer(self.filepath)
headers = ['timestamp', 'cpu_id', 'frequency', 'idle_state']
self.writer.writerow(headers)
@@ -360,8 +360,7 @@ class PowerStateTimeline(object):
def __init__(self, output_directory, cpus):
self.filepath = os.path.join(output_directory, 'power-state-timeline.csv')
self.idle_state_names = {cpu.id: [s.name for s in cpu.cpuidle.states] for cpu in cpus}
- self._wfh = open(self.filepath, 'w')
- self.writer = csv.writer(self._wfh)
+ self.writer, self._wfh = create_writer(self.filepath)
headers = ['ts'] + ['{} CPU{}'.format(cpu.name, cpu.id) for cpu in cpus]
self.writer.writerow(headers)
@@ -405,7 +404,7 @@ class ParallelStats(object):
clusters.append(cpu.cpufreq.related_cpus)
for i, clust in enumerate(clusters):
- self.clusters[i] = set(clust)
+ self.clusters[str(i)] = set(clust)
self.clusters['all'] = set([cpu.id for cpu in cpus])
self.first_timestamp = None
@@ -419,7 +418,7 @@ class ParallelStats(object):
delta = timestamp - self.last_timestamp
active_cores = [i for i, c in enumerate(self.previous_states)
if c and c[0] == -1]
- for cluster, cluster_cores in self.clusters.iteritems():
+ for cluster, cluster_cores in self.clusters.items():
clust_active_cores = len(cluster_cores.intersection(active_cores))
self.parallel_times[cluster][clust_active_cores] += delta
if clust_active_cores:
@@ -438,7 +437,7 @@ class ParallelStats(object):
total_time = self.last_timestamp - self.first_timestamp
for cluster in sorted(self.parallel_times):
running_time = self.running_times[cluster]
- for n in xrange(len(self.clusters[cluster]) + 1):
+ for n in range(len(self.clusters[cluster]) + 1):
time = self.parallel_times[cluster][n]
time_pc = time / total_time
if not self.use_ratios:
@@ -474,8 +473,7 @@ class ParallelReport(object):
self.values.append(value)
def write(self):
- with open(self.filepath, 'w') as wfh:
- writer = csv.writer(wfh)
+ with csvwriter(self.filepath) as writer:
writer.writerow(['cluster', 'number_of_cores', 'total_time', '%time', '%running_time'])
writer.writerows(self.values)
@@ -520,7 +518,7 @@ class PowerStateStats(object):
total_time = self.last_timestamp - self.first_timestamp
state_stats = defaultdict(lambda: [None] * len(self.core_names))
- for cpu, states in self.cpu_states.iteritems():
+ for cpu, states in self.cpu_states.items():
for state in states:
time = states[state]
time_pc = time / total_time
@@ -543,8 +541,7 @@ class PowerStateStatsReport(object):
self.precision = precision
def write(self):
- with open(self.filepath, 'w') as wfh:
- writer = csv.writer(wfh)
+ with csvwriter(self.filepath) as writer:
headers = ['state'] + ['{} CPU{}'.format(c, i)
for i, c in enumerate(self.core_names)]
writer.writerow(headers)
@@ -561,8 +558,7 @@ class CpuUtilizationTimeline(object):
def __init__(self, output_directory, cpus):
self.filepath = os.path.join(output_directory, 'utilization-timeline.csv')
- self._wfh = open(self.filepath, 'w')
- self.writer = csv.writer(self._wfh)
+ self.writer, self._wfh = create_writer(self.filepath)
headers = ['ts'] + ['{} CPU{}'.format(cpu.name, cpu.id) for cpu in cpus]
self.writer.writerow(headers)
diff --git a/wa/utils/diff.py b/wa/utils/diff.py
index 9318f15c..c1bf3e67 100644
--- a/wa/utils/diff.py
+++ b/wa/utils/diff.py
@@ -1,11 +1,18 @@
-from wa.utils.misc import write_table
+import os
+import re
+
+from future.moves.itertools import zip_longest
+
+from wa.utils.misc import as_relative, diff_tokens, write_table
+from wa.utils.misc import ensure_file_directory_exists as _f
+from wa.utils.misc import ensure_directory_exists as _d
def diff_interrupt_files(before, after, result): # pylint: disable=R0914
output_lines = []
with open(before) as bfh:
with open(after) as ofh:
- for bline, aline in izip(bfh, ofh):
+ for bline, aline in zip(bfh, ofh):
bchunks = bline.strip().split()
while True:
achunks = aline.strip().split()
@@ -20,7 +27,7 @@ def diff_interrupt_files(before, after, result): # pylint: disable=R0914
diffchunks = ['>'] + achunks
output_lines.append(diffchunks)
try:
- aline = ofh.next()
+ aline = next(ofh)
except StopIteration:
break
@@ -45,11 +52,9 @@ def diff_interrupt_files(before, after, result): # pylint: disable=R0914
def diff_sysfs_dirs(before, after, result): # pylint: disable=R0914
before_files = []
- os.path.walk(before,
- lambda arg, dirname, names: arg.extend([os.path.join(dirname, f) for f in names]),
- before_files
- )
- before_files = filter(os.path.isfile, before_files)
+ for root, dirs, files in os.walk(before):
+ before_files.extend([os.path.join(root, f) for f in files])
+ before_files = list(filter(os.path.isfile, before_files))
files = [os.path.relpath(f, before) for f in before_files]
after_files = [os.path.join(after, f) for f in files]
diff_files = [os.path.join(result, f) for f in files]
@@ -61,7 +66,7 @@ def diff_sysfs_dirs(before, after, result): # pylint: disable=R0914
with open(bfile) as bfh, open(afile) as afh: # pylint: disable=C0321
with open(_f(dfile), 'w') as dfh:
- for i, (bline, aline) in enumerate(izip_longest(bfh, afh), 1):
+ for i, (bline, aline) in enumerate(zip_longest(bfh, afh), 1):
if aline is None:
logger.debug('Lines missing from {}'.format(afile))
break
diff --git a/wa/utils/doc.py b/wa/utils/doc.py
index f20cf39d..c0589e66 100644
--- a/wa/utils/doc.py
+++ b/wa/utils/doc.py
@@ -164,16 +164,16 @@ def format_simple_table(rows, headers=None, align='>', show_borders=True, border
"""Formats a simple table."""
if not rows:
return ''
- rows = [map(str, r) for r in rows]
+ rows = [list(map(str, r)) for r in rows]
num_cols = len(rows[0])
# cycle specified alignments until we have num_cols of them. This is
# consitent with how such cases are handled in R, pandas, etc.
it = cycle(align)
- align = [it.next() for _ in xrange(num_cols)]
+ align = [next(it) for _ in range(num_cols)]
- cols = zip(*rows)
- col_widths = [max(map(len, c)) for c in cols]
+ cols = list(zip(*rows))
+ col_widths = [max(list(map(len, c))) for c in cols]
if headers:
col_widths = [max(len(h), cw) for h, cw in zip(headers, col_widths)]
row_format = ' '.join(['{:%s%s}' % (align[i], w) for i, w in enumerate(col_widths)])
@@ -259,12 +259,12 @@ def indent(text, spaces=4):
def format_literal(lit):
- if isinstance(lit, basestring):
+ if isinstance(lit, str):
return '``\'{}\'``'.format(lit)
elif hasattr(lit, 'pattern'): # regex
return '``r\'{}\'``'.format(lit.pattern)
elif isinstance(lit, dict):
- content = indent(',\n'.join("{}: {}".format(key,val) for (key,val) in lit.iteritems()))
+ content = indent(',\n'.join("{}: {}".format(key,val) for (key,val) in lit.items()))
return '::\n\n{}'.format(indent('{{\n{}\n}}'.format(content)))
else:
return '``{}``'.format(lit)
@@ -287,7 +287,7 @@ def get_params_rst(parameters):
text += indent('\nconstraint: ``{}``\n'.format(get_type_name(param.constraint)))
if param.default:
value = param.default
- if isinstance(value, basestring) and value.startswith(USER_HOME):
+ if isinstance(value, str) and value.startswith(USER_HOME):
value = value.replace(USER_HOME, '~')
text += indent('\ndefault: {}\n'.format(format_literal(value)))
text += '\n'
@@ -298,7 +298,7 @@ def get_aliases_rst(aliases):
text = ''
for alias in aliases:
param_str = ', '.join(['{}={}'.format(n, format_literal(v))
- for n, v in alias.params.iteritems()])
+ for n, v in alias.params.items()])
text += '{}\n{}\n\n'.format(alias.name, indent(param_str))
return text
diff --git a/wa/utils/exec_control.py b/wa/utils/exec_control.py
index b98e8a06..a23336a4 100644
--- a/wa/utils/exec_control.py
+++ b/wa/utils/exec_control.py
@@ -12,7 +12,7 @@ def activate_environment(name):
#pylint: disable=W0603
global __active_environment
- if name not in __environments.keys():
+ if name not in list(__environments.keys()):
init_environment(name)
__active_environment = name
@@ -24,7 +24,7 @@ def init_environment(name):
:raises: ``ValueError`` if an environment with name ``name``
already exists.
"""
- if name in __environments.keys():
+ if name in list(__environments.keys()):
msg = "Environment {} already exists".format(name)
raise ValueError(msg)
__environments[name] = []
@@ -39,7 +39,7 @@ def reset_environment(name=None):
"""
if name is not None:
- if name not in __environments.keys():
+ if name not in list(__environments.keys()):
msg = "Environment {} does not exist".format(name)
raise ValueError(msg)
__environments[name] = []
@@ -75,7 +75,7 @@ def once_per_class(method):
if __active_environment is None:
activate_environment('default')
- func_id = repr(method.func_name) + repr(args[0].__class__)
+ func_id = repr(method.__name__) + repr(args[0].__class__)
if func_id in __environments[__active_environment]:
return
diff --git a/wa/utils/log.py b/wa/utils/log.py
index a254374e..1012e7ab 100644
--- a/wa/utils/log.py
+++ b/wa/utils/log.py
@@ -128,13 +128,13 @@ def disable(logs):
def __enable_logger(logger):
- if isinstance(logger, basestring):
+ if isinstance(logger, str):
logger = logging.getLogger(logger)
logger.propagate = True
def __disable_logger(logger):
- if isinstance(logger, basestring):
+ if isinstance(logger, str):
logger = logging.getLogger(logger)
logger.propagate = False
diff --git a/wa/utils/misc.py b/wa/utils/misc.py
index 9caf7b3b..bb9ab546 100644
--- a/wa/utils/misc.py
+++ b/wa/utils/misc.py
@@ -18,7 +18,7 @@
Miscellaneous functions that don't fit anywhere else.
"""
-from __future__ import division
+
import os
import sys
import re
@@ -30,9 +30,13 @@ import traceback
import logging
import random
import hashlib
+import sys
from datetime import datetime, timedelta
from operator import mul
-from StringIO import StringIO
+if sys.version_info[0] == 3:
+ from io import StringIO
+else:
+ from io import BytesIO as StringIO
from itertools import chain, cycle
from distutils.spawn import find_executable
@@ -83,11 +87,11 @@ def diff_tokens(before_token, after_token):
def prepare_table_rows(rows):
"""Given a list of lists, make sure they are prepared to be formatted into a table
by making sure each row has the same number of columns and stringifying all values."""
- rows = [map(str, r) for r in rows]
- max_cols = max(map(len, rows))
+ rows = [list(map(str, r)) for r in rows]
+ max_cols = max(list(map(len, rows)))
for row in rows:
pad = max_cols - len(row)
- for _ in xrange(pad):
+ for _ in range(pad):
row.append('')
return rows
@@ -102,10 +106,10 @@ def write_table(rows, wfh, align='>', headers=None): # pylint: disable=R0914
# cycle specified alignments until we have max_cols of them. This is
# consitent with how such cases are handled in R, pandas, etc.
it = cycle(align)
- align = [it.next() for _ in xrange(num_cols)]
+ align = [next(it) for _ in range(num_cols)]
- cols = zip(*rows)
- col_widths = [max(map(len, c)) for c in cols]
+ cols = list(zip(*rows))
+ col_widths = [max(list(map(len, c))) for c in cols]
row_format = ' '.join(['{:%s%s}' % (align[i], w) for i, w in enumerate(col_widths)])
row_format += '\n'
@@ -144,7 +148,7 @@ def _check_remove_item(the_list, item):
"""Helper function for merge_lists that implements checking wether an items
should be removed from the list and doing so if needed. Returns ``True`` if
the item has been removed and ``False`` otherwise."""
- if not isinstance(item, basestring):
+ if not isinstance(item, str):
return False
if not item.startswith('~'):
return False
@@ -275,7 +279,7 @@ def get_article(word):
def get_random_string(length):
"""Returns a random ASCII string of the specified length)."""
- return ''.join(random.choice(string.ascii_letters + string.digits) for _ in xrange(length))
+ return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(length))
class LoadSyntaxError(Exception):
@@ -307,9 +311,9 @@ def load_struct_from_python(filepath=None, text=None):
while modname in sys.modules: # highly unlikely, but...
modname = get_random_string(RAND_MOD_NAME_LEN)
mod = imp.new_module(modname)
- exec text in mod.__dict__ # pylint: disable=exec-used
+ exec(text, mod.__dict__) # pylint: disable=exec-used
return dict((k, v)
- for k, v in mod.__dict__.iteritems()
+ for k, v in mod.__dict__.items()
if not k.startswith('_'))
except SyntaxError as e:
raise LoadSyntaxError(e.message, filepath, e.lineno)
@@ -404,7 +408,7 @@ def istextfile(fileobj, blocksize=512):
def categorize(v):
if hasattr(v, 'merge_with') and hasattr(v, 'merge_into'):
return 'o'
- elif hasattr(v, 'iteritems'):
+ elif hasattr(v, 'items'):
return 'm'
elif isiterable(v):
return 's'
@@ -515,13 +519,14 @@ def merge_sequencies(s1, s2):
return type(s2)(unique(chain(s1, s2)))
+
def merge_maps(m1, m2):
- return type(m2)(chain(m1.iteritems(), m2.iteritems()))
+ return type(m2)(chain(iter(m1.items()), iter(m2.items())))
def merge_dicts_simple(base, other):
result = base.copy()
- for key, value in (other or {}).iteritems():
+ for key, value in (other or {}).items():
result[key] = merge_config_values(result.get(key), value)
return result
@@ -534,11 +539,11 @@ def touch(path):
def get_object_name(obj):
if hasattr(obj, 'name'):
return obj.name
- elif hasattr(obj, 'im_func'):
- return '{}.{}'.format(get_object_name(obj.im_class),
- obj.im_func.func_name)
+ elif hasattr(obj, '__func__') and hasattr(obj, '__self__'):
+ return '{}.{}'.format(get_object_name(obj.__self__.__class__),
+ obj.__func__.__name__)
elif hasattr(obj, 'func_name'):
- return obj.func_name
+ return obj.__name__
elif hasattr(obj, '__name__'):
return obj.__name__
elif hasattr(obj, '__class__'):
@@ -557,7 +562,7 @@ def resolve_cpus(name, target):
- 'all' - returns all cpus
- '' - Empty name will also return all cpus
"""
- cpu_list = range(target.number_of_cpus)
+ cpu_list = list(range(target.number_of_cpus))
# Support for passing cpu no directly
if isinstance(name, int):
diff --git a/wa/utils/revent.py b/wa/utils/revent.py
index 22839b97..50552277 100644
--- a/wa/utils/revent.py
+++ b/wa/utils/revent.py
@@ -13,7 +13,7 @@
# limitations under the License.
#
-from __future__ import division
+
import os
import struct
import signal
@@ -88,7 +88,7 @@ class UinputDeviceInfo(object):
self.abs_bits = bytearray(parts[3])
self.num_absinfo = parts[4]
self.absinfo = [absinfo(*read_struct(fh, absinfo_struct))
- for _ in xrange(self.num_absinfo)]
+ for _ in range(self.num_absinfo)]
def __str__(self):
return 'UInputInfo({})'.format(self.__dict__)
@@ -145,7 +145,7 @@ class ReventRecording(object):
if self.stream:
events = self._iter_events()
try:
- first = last = events.next()
+ first = last = next(events)
except StopIteration:
self._duration = 0
for last in events:
@@ -230,7 +230,7 @@ class ReventRecording(object):
def _read_devices(self, fh):
num_devices, = read_struct(fh, u32_struct)
- for _ in xrange(num_devices):
+ for _ in range(num_devices):
self.device_paths.append(read_string(fh))
def _read_gamepad_info(self, fh):
@@ -243,7 +243,7 @@ class ReventRecording(object):
raise RuntimeError(msg)
self.fh.seek(self._events_start)
if self.version >= 2:
- for _ in xrange(self.num_events):
+ for _ in range(self.num_events):
yield ReventEvent(self.fh)
else:
file_size = os.path.getsize(self.filepath)
diff --git a/wa/utils/serializer.py b/wa/utils/serializer.py
index 514d757e..1b7c1a74 100644
--- a/wa/utils/serializer.py
+++ b/wa/utils/serializer.py
@@ -71,7 +71,7 @@ POD_TYPES = [
dict,
set,
str,
- unicode,
+ str,
int,
float,
bool,
@@ -104,7 +104,7 @@ class WAJSONDecoder(_json.JSONDecoder):
d = _json.JSONDecoder.decode(self, s, **kwargs)
def try_parse_object(v):
- if isinstance(v, basestring):
+ if isinstance(v, str):
if v.startswith('REGEX:'):
_, flags, pattern = v.split(':', 2)
return re.compile(pattern, int(flags or 0))
@@ -122,8 +122,8 @@ class WAJSONDecoder(_json.JSONDecoder):
def load_objects(d):
pairs = []
- for k, v in d.iteritems():
- if hasattr(v, 'iteritems'):
+ for k, v in d.items():
+ if hasattr(v, 'items'):
pairs.append((k, load_objects(v)))
elif isiterable(v):
pairs.append((k, [try_parse_object(i) for i in v]))
@@ -160,13 +160,13 @@ class json(object):
_mapping_tag = _yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG
-_regex_tag = u'tag:wa:regex'
-_level_tag = u'tag:wa:level'
-_cpu_mask_tag = u'tag:wa:cpu_mask'
+_regex_tag = 'tag:wa:regex'
+_level_tag = 'tag:wa:level'
+_cpu_mask_tag = 'tag:wa:cpu_mask'
def _wa_dict_representer(dumper, data):
- return dumper.represent_mapping(_mapping_tag, data.iteritems())
+ return dumper.represent_mapping(_mapping_tag, iter(data.items()))
def _wa_regex_representer(dumper, data):
@@ -248,17 +248,17 @@ class python(object):
def loads(s, *args, **kwargs):
pod = {}
try:
- exec s in pod # pylint: disable=exec-used
+ exec(s, pod) # pylint: disable=exec-used
except SyntaxError as e:
raise SerializerSyntaxError(e.message, e.lineno)
- for k in pod.keys():
+ for k in list(pod.keys()):
if k.startswith('__'):
del pod[k]
return pod
def read_pod(source, fmt=None):
- if isinstance(source, basestring):
+ if isinstance(source, str):
with open(source) as fh:
return _read_pod(fh, fmt)
elif hasattr(source, 'read') and (hasattr(source, 'name') or fmt):
@@ -269,7 +269,7 @@ def read_pod(source, fmt=None):
def write_pod(pod, dest, fmt=None):
- if isinstance(dest, basestring):
+ if isinstance(dest, str):
with open(dest, 'w') as wfh:
return _write_pod(pod, wfh, fmt)
elif hasattr(dest, 'write') and (hasattr(dest, 'name') or fmt):
@@ -323,8 +323,8 @@ def _write_pod(pod, wfh, fmt=None):
def is_pod(obj):
if type(obj) not in POD_TYPES:
return False
- if hasattr(obj, 'iteritems'):
- for k, v in obj.iteritems():
+ if hasattr(obj, 'items'):
+ for k, v in obj.items():
if not (is_pod(k) and is_pod(v)):
return False
elif isiterable(obj):
diff --git a/wa/utils/terminalsize.py b/wa/utils/terminalsize.py
index 828ca3e6..f211b795 100644
--- a/wa/utils/terminalsize.py
+++ b/wa/utils/terminalsize.py
@@ -89,5 +89,5 @@ def _get_terminal_size_linux():
if __name__ == "__main__":
sizex, sizey = get_terminal_size()
- print 'width =', sizex, 'height =', sizey
+ print('width =', sizex, 'height =', sizey)
diff --git a/wa/utils/trace_cmd.py b/wa/utils/trace_cmd.py
index 8eaf4d59..65900c79 100644
--- a/wa/utils/trace_cmd.py
+++ b/wa/utils/trace_cmd.py
@@ -114,7 +114,7 @@ class DroppedEventsEvent(object):
def try_convert_to_numeric(v):
try:
if isiterable(v):
- return map(numeric, v)
+ return list(map(numeric, v))
else:
return numeric(v)
except ValueError:
@@ -153,13 +153,13 @@ def regex_body_parser(regex, flags=0):
If regex is a pre-compiled object, flags will be ignored.
"""
- if isinstance(regex, basestring):
+ if isinstance(regex, str):
regex = re.compile(regex, flags)
def regex_parser_func(event, text):
match = regex.search(text)
if match:
- for k, v in match.groupdict().iteritems():
+ for k, v in match.groupdict().items():
try:
event.fields[k] = int(v)
except ValueError:
@@ -321,7 +321,7 @@ class TraceCmdParser(object):
continue
body_parser = EVENT_PARSER_MAP.get(event_name, default_body_parser)
- if isinstance(body_parser, basestring) or isinstance(body_parser, re._pattern_type): # pylint: disable=protected-access
+ if isinstance(body_parser, str) or isinstance(body_parser, re._pattern_type): # pylint: disable=protected-access
body_parser = regex_body_parser(body_parser)
yield TraceCmdEvent(parser=body_parser, **match.groupdict())
diff --git a/wa/utils/types.py b/wa/utils/types.py
index 29d8cf49..6256b9c9 100644
--- a/wa/utils/types.py
+++ b/wa/utils/types.py
@@ -29,10 +29,19 @@ import os
import re
import numbers
import shlex
+import sys
from bisect import insort
-from urllib import quote, unquote
+if sys.version_info[0] == 3:
+ from urllib.parse import quote, unquote
+ from past.builtins import basestring
+ long = int
+else:
+ from urllib import quote, unquote
from collections import defaultdict, MutableMapping
from copy import copy
+from functools import total_ordering
+
+from future.utils import with_metaclass
from devlib.utils.types import identifier, boolean, integer, numeric, caseless_string
@@ -47,7 +56,7 @@ def list_of_strs(value):
"""
if not isiterable(value):
raise ValueError(value)
- return map(str, value)
+ return list(map(str, value))
list_of_strings = list_of_strs
@@ -59,7 +68,7 @@ def list_of_ints(value):
"""
if not isiterable(value):
raise ValueError(value)
- return map(int, value)
+ return list(map(int, value))
list_of_integers = list_of_ints
@@ -72,7 +81,7 @@ def list_of_numbers(value):
"""
if not isiterable(value):
raise ValueError(value)
- return map(numeric, value)
+ return list(map(numeric, value))
def list_of_bools(value, interpret_strings=True):
@@ -88,9 +97,9 @@ def list_of_bools(value, interpret_strings=True):
if not isiterable(value):
raise ValueError(value)
if interpret_strings:
- return map(boolean, value)
+ return list(map(boolean, value))
else:
- return map(bool, value)
+ return list(map(bool, value))
def list_of(type_):
@@ -98,16 +107,16 @@ def list_of(type_):
attempts to convert all elements in the passed value to the specifed
``type_``, raising ``ValueError`` on error."""
def __init__(self, values):
- list.__init__(self, map(type_, values))
+ list.__init__(self, list(map(type_, values)))
def append(self, value):
list.append(self, type_(value))
def extend(self, other):
- list.extend(self, map(type_, other))
+ list.extend(self, list(map(type_, other)))
def from_pod(cls, pod):
- return cls(map(type_, pod))
+ return cls(list(map(type_, pod)))
def _to_pod(self):
return self
@@ -132,7 +141,7 @@ def list_or_string(value):
a one-element list with stringified value will be returned.
"""
- if isinstance(value, basestring):
+ if isinstance(value, str):
return [value]
else:
try:
@@ -147,11 +156,11 @@ def list_or_caseless_string(value):
not iterable a one-element list with stringified value will be returned.
"""
- if isinstance(value, basestring):
+ if isinstance(value, str):
return [caseless_string(value)]
else:
try:
- return map(caseless_string, value)
+ return list(map(caseless_string, value))
except ValueError:
return [caseless_string(value)]
@@ -229,8 +238,8 @@ class arguments(list):
def __init__(self, value=None):
if isiterable(value):
- super(arguments, self).__init__(map(str, value))
- elif isinstance(value, basestring):
+ super(arguments, self).__init__(list(map(str, value)))
+ elif isinstance(value, str):
posix = os.name != 'nt'
super(arguments, self).__init__(shlex.split(value, posix=posix))
elif value is None:
@@ -242,7 +251,7 @@ class arguments(list):
return super(arguments, self).append(str(value))
def extend(self, values):
- return super(arguments, self).extend(map(str, values))
+ return super(arguments, self).extend(list(map(str, values)))
def __str__(self):
return ' '.join(self)
@@ -288,7 +297,7 @@ class prioritylist(object):
self.__delitem__(index)
def _priority_index(self, element):
- for priority, elements in self.elements.iteritems():
+ for priority, elements in self.elements.items():
if element in elements:
return (priority, elements.index(element))
raise IndexError(element)
@@ -333,7 +342,7 @@ class prioritylist(object):
else:
index_range = [index]
elif isinstance(index, slice):
- index_range = range(index.start or 0, index.stop, index.step or 1)
+ index_range = list(range(index.start or 0, index.stop, index.step or 1))
else:
raise ValueError('Invalid index {}'.format(index))
current_global_offset = 0
@@ -391,7 +400,7 @@ class toggle_set(set):
def __init__(self, *args):
if args:
value = args[0]
- if isinstance(value, basestring):
+ if isinstance(value, str):
msg = 'invalid type for toggle_set: "{}"'
raise TypeError(msg.format(type(value)))
set.__init__(self, *args)
@@ -507,12 +516,15 @@ class obj_dict(MutableMapping):
raise AttributeError("No such attribute: " + name)
def __getattr__(self, name):
+ if 'dict' not in self.__dict__:
+ raise AttributeError("No such attribute: " + name)
if name in self.__dict__['dict']:
return self.__dict__['dict'][name]
else:
raise AttributeError("No such attribute: " + name)
+@total_ordering
class level(object):
"""
A level has a name and behaves like a string when printed, however it also
@@ -538,11 +550,8 @@ class level(object):
def __repr__(self):
return '{}({})'.format(self.name, self.value)
- def __cmp__(self, other):
- if isinstance(other, level):
- return cmp(self.value, other.value)
- else:
- return cmp(self.value, other)
+ def __hash__(self):
+ return hash(self.name)
def __eq__(self, other):
if isinstance(other, level):
@@ -552,13 +561,24 @@ class level(object):
else:
return self.value == other
- def __ne__(self, other):
+ def __lt__(self, other):
if isinstance(other, level):
- return self.value != other.value
+ return self.value < other.value
elif isinstance(other, basestring):
- return self.name != other
+ return self.name < other
else:
- return self.value != other
+ return self.value < other
+
+
+class _EnumMeta(type):
+
+ def __str__(cls):
+ return str(cls.levels)
+
+ def __getattr__(self, name):
+ name = name.lower()
+ if name in self.__dict__:
+ return self.__dict__[name]
def enum(args, start=0, step=1):
@@ -583,11 +603,7 @@ def enum(args, start=0, step=1):
"""
- class Enum(object):
-
- class __metaclass__(type):
- def __str__(cls):
- return str(cls.levels)
+ class Enum(with_metaclass(_EnumMeta, object)):
@classmethod
def from_pod(cls, pod):
@@ -642,14 +658,14 @@ class ParameterDict(dict):
# Function to determine the appropriate prefix based on the parameters type
@staticmethod
def _get_prefix(obj):
- if isinstance(obj, basestring):
+ if isinstance(obj, str):
prefix = 's'
elif isinstance(obj, float):
prefix = 'f'
- elif isinstance(obj, long):
- prefix = 'd'
elif isinstance(obj, bool):
prefix = 'b'
+ elif isinstance(obj, long):
+ prefix = 'i'
elif isinstance(obj, int):
prefix = 'i'
elif obj is None:
@@ -686,7 +702,7 @@ class ParameterDict(dict):
elif value_type == 'b':
return boolean(value)
elif value_type == 'd':
- return long(value)
+ return int(value)
elif value_type == 'f':
return float(value)
elif value_type == 'i':
@@ -700,7 +716,7 @@ class ParameterDict(dict):
raise ValueError('Unknown {} {}'.format(type(string), string))
def __init__(self, *args, **kwargs):
- for k, v in kwargs.iteritems():
+ for k, v in kwargs.items():
self.__setitem__(k, v)
dict.__init__(self, *args)
@@ -714,7 +730,7 @@ class ParameterDict(dict):
return dict.__contains__(self, self._encode(item))
def __iter__(self):
- return iter((k, self._decode(v)) for (k, v) in self.items())
+ return iter((k, self._decode(v)) for (k, v) in list(self.items()))
def iteritems(self):
return self.__iter__()
@@ -730,7 +746,10 @@ class ParameterDict(dict):
return (key, self._decode(value))
def iter_encoded_items(self):
- return dict.iteritems(self)
+ if sys.version_info[0] == 3:
+ return dict.items(self)
+ else:
+ return dict.iteritems(self)
def get_encoded_value(self, name):
return dict.__getitem__(self, name)
@@ -743,7 +762,7 @@ class ParameterDict(dict):
if isinstance(d, ParameterDict):
dict.update(self, d)
else:
- for k, v in d.iteritems():
+ for k, v in d.items():
self[k] = v
@@ -762,7 +781,7 @@ class cpu_mask(object):
self._mask = 0
if isinstance(cpus, int):
self._mask = cpus
- elif isinstance(cpus, basestring):
+ elif isinstance(cpus, str):
if cpus[:2] == '0x' or cpus[:2] == '0X':
self._mask = int(cpus, 16)
else: