Merge "Add Python 3.4 as supported interpreters"
This commit is contained in:
commit
ec14f4ef08
@ -7,7 +7,7 @@
|
||||
#
|
||||
# NOTE: The script assumes that you have the following
|
||||
# programs already installed:
|
||||
# -> Python 2.6 or Python 2.7
|
||||
# -> Python 2.6, Python 2.7 or Python 3.4
|
||||
|
||||
set -e
|
||||
|
||||
|
@ -19,6 +19,7 @@ import itertools
|
||||
import random
|
||||
import time
|
||||
|
||||
from rally.common import costilius
|
||||
from rally.common import log as logging
|
||||
from rally.common import utils
|
||||
from rally import consts
|
||||
@ -58,7 +59,7 @@ class Scenario(object):
|
||||
self._admin_clients = admin_clients
|
||||
self._clients = clients
|
||||
self._idle_duration = 0
|
||||
self._atomic_actions = {}
|
||||
self._atomic_actions = costilius.OrderedDict()
|
||||
|
||||
# TODO(amaretskiy): consider about prefix part of benchmark uuid
|
||||
@classmethod
|
||||
|
@ -323,12 +323,12 @@ def _add_command_parsers(categories, subparsers):
|
||||
|
||||
def validate_deprecated_args(argv, fn):
|
||||
if (len(argv) > 3
|
||||
and (argv[2] == fn.func_name)
|
||||
and (argv[2] == fn.__name__)
|
||||
and getattr(fn, "deprecated_args", None)):
|
||||
for item in fn.deprecated_args:
|
||||
if item in argv[3:]:
|
||||
LOG.warning("Deprecated argument %s for %s." % (item,
|
||||
fn.func_name))
|
||||
fn.__name__))
|
||||
|
||||
|
||||
def run(argv, categories):
|
||||
@ -379,14 +379,15 @@ def run(argv, categories):
|
||||
return(0)
|
||||
|
||||
fn = CONF.category.action_fn
|
||||
fn_args = [arg.decode("utf-8") for arg in CONF.category.action_args]
|
||||
fn_args = [encodeutils.safe_decode(arg)
|
||||
for arg in CONF.category.action_args]
|
||||
fn_kwargs = {}
|
||||
for k in CONF.category.action_kwargs:
|
||||
v = getattr(CONF.category, "action_kwarg_" + k)
|
||||
if v is None:
|
||||
continue
|
||||
if isinstance(v, six.string_types):
|
||||
v = v.decode("utf-8")
|
||||
v = encodeutils.safe_decode(v)
|
||||
fn_kwargs[k] = v
|
||||
|
||||
# call the action with the remaining arguments
|
||||
|
@ -608,7 +608,8 @@ class TaskCommands(object):
|
||||
STATUS_FAIL = "FAIL"
|
||||
for result in results:
|
||||
key = result["key"]
|
||||
for sla in result["data"]["sla"]:
|
||||
for sla in sorted(result["data"]["sla"],
|
||||
key=lambda x: x["criterion"]):
|
||||
success = sla.pop("success")
|
||||
sla["status"] = success and STATUS_PASS or STATUS_FAIL
|
||||
sla["benchmark"] = key["name"]
|
||||
@ -616,7 +617,7 @@ class TaskCommands(object):
|
||||
failed_criteria += int(not success)
|
||||
data.append(sla if tojson else rutils.Struct(**sla))
|
||||
if tojson:
|
||||
print(json.dumps(data))
|
||||
print(json.dumps(data, sort_keys=False))
|
||||
else:
|
||||
cliutils.print_list(data, ("benchmark", "pos", "criterion",
|
||||
"status", "detail"))
|
||||
|
51
rally/common/costilius.py
Normal file
51
rally/common/costilius.py
Normal file
@ -0,0 +1,51 @@
|
||||
#
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""
|
||||
This module is a storage for different types of workarounds.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
try:
|
||||
from collections import OrderedDict # noqa
|
||||
except ImportError:
|
||||
# NOTE(andreykurilin): Python 2.6 issue. OrderedDict is not
|
||||
# present in `collections` library.
|
||||
from ordereddict import OrderedDict # noqa
|
||||
|
||||
|
||||
def is_py26():
|
||||
return sys.version_info[:2] == (2, 6)
|
||||
|
||||
|
||||
if is_py26():
|
||||
import simplejson as json
|
||||
else:
|
||||
import json
|
||||
|
||||
|
||||
def json_loads(*args, **kwargs):
|
||||
"""Deserialize a str or unicode instance to a Python object.
|
||||
|
||||
'simplejson' is used in Python 2.6 environment, because standard 'json'
|
||||
library not include several important features(for example
|
||||
'object_pairs_hook', which allows to deserialize input object to
|
||||
OrderedDict)
|
||||
"""
|
||||
|
||||
return json.loads(*args, **kwargs)
|
@ -19,6 +19,8 @@ from sqlalchemy.dialects import mysql as mysql_types
|
||||
from sqlalchemy.ext import mutable
|
||||
from sqlalchemy import types as sa_types
|
||||
|
||||
from rally.common import costilius
|
||||
|
||||
|
||||
class JSONEncodedDict(sa_types.TypeDecorator):
|
||||
"""Represents an immutable structure as a json-encoded string."""
|
||||
@ -27,12 +29,13 @@ class JSONEncodedDict(sa_types.TypeDecorator):
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
if value is not None:
|
||||
value = json.dumps(value)
|
||||
value = json.dumps(value, sort_keys=False)
|
||||
return value
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
if value is not None:
|
||||
value = json.loads(value)
|
||||
value = costilius.json_loads(
|
||||
value, object_pairs_hook=costilius.OrderedDict)
|
||||
return value
|
||||
|
||||
|
||||
|
@ -37,3 +37,7 @@ requests>=2.2.0,!=2.4.0
|
||||
SQLAlchemy>=0.9.7,<=0.9.99
|
||||
sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3
|
||||
six>=1.9.0
|
||||
|
||||
# Python 2.6 related packages(see rally.common.costilius for more details)
|
||||
ordereddict
|
||||
simplejson>=2.2.0
|
||||
|
@ -17,6 +17,8 @@ classifier =
|
||||
Programming Language :: Python :: 2
|
||||
Programming Language :: Python :: 2.6
|
||||
Programming Language :: Python :: 2.7
|
||||
Programming Language :: Python :: 3
|
||||
Programming Language :: Python :: 3.4
|
||||
|
||||
[files]
|
||||
packages =
|
||||
|
@ -535,11 +535,11 @@ class SLATestCase(unittest.TestCase):
|
||||
rally("task sla_check")
|
||||
expected = [
|
||||
{"benchmark": "KeystoneBasic.create_and_list_users",
|
||||
"criterion": "max_seconds_per_iteration",
|
||||
"criterion": "failure_rate",
|
||||
"detail": mock.ANY,
|
||||
"pos": 0, "status": "PASS"},
|
||||
{"benchmark": "KeystoneBasic.create_and_list_users",
|
||||
"criterion": "failure_rate",
|
||||
"criterion": "max_seconds_per_iteration",
|
||||
"detail": mock.ANY,
|
||||
"pos": 0, "status": "PASS"}
|
||||
]
|
||||
|
@ -13,6 +13,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_utils import encodeutils
|
||||
from six.moves import configparser
|
||||
|
||||
import inspect
|
||||
@ -37,7 +38,7 @@ class RallyCmdError(Exception):
|
||||
|
||||
def __init__(self, code, output):
|
||||
self.code = code
|
||||
self.output = output
|
||||
self.output = encodeutils.safe_decode(output)
|
||||
|
||||
def __str__(self):
|
||||
return "Code: %d Output: %s\n" % (self.code, self.output)
|
||||
@ -50,7 +51,7 @@ class TaskConfig(object):
|
||||
|
||||
def __init__(self, config):
|
||||
config_file = tempfile.NamedTemporaryFile(delete=False)
|
||||
config_file.write(json.dumps(config).encode("utf-8"))
|
||||
config_file.write(encodeutils.safe_encode(json.dumps(config)))
|
||||
config_file.close()
|
||||
self.filename = config_file.name
|
||||
|
||||
@ -159,7 +160,7 @@ class Rally(object):
|
||||
:param getjson: in cases, when rally prints JSON, you can catch output
|
||||
deserialized
|
||||
:param report_path: if present, rally command and its output will be
|
||||
wretten to file with passed file name
|
||||
written to file with passed file name
|
||||
:param raw: don't write command itself to report file. Only output
|
||||
will be written
|
||||
"""
|
||||
@ -167,8 +168,8 @@ class Rally(object):
|
||||
if not isinstance(cmd, list):
|
||||
cmd = cmd.split(" ")
|
||||
try:
|
||||
output = subprocess.check_output(self.args + cmd,
|
||||
stderr=subprocess.STDOUT)
|
||||
output = encodeutils.safe_decode(subprocess.check_output(
|
||||
self.args + cmd, stderr=subprocess.STDOUT))
|
||||
|
||||
if write_report:
|
||||
if not report_path:
|
||||
@ -181,6 +182,6 @@ class Rally(object):
|
||||
|
||||
if getjson:
|
||||
return json.loads(output)
|
||||
return output.decode("utf-8")
|
||||
return output
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise RallyCmdError(e.returncode, e.output)
|
||||
|
Loading…
Reference in New Issue
Block a user