Remove costilius module

Rally droped to maintain python2.6 thus we don't need to
maintain it anymore.

Change-Id: I60031646247cc94ca3e8506888d2cbc82cac4bdb
This commit is contained in:
Roman Vasilets 2016-06-07 17:53:27 +03:00
parent 670c2c6566
commit 3beac49204
7 changed files with 23 additions and 264 deletions

View File

@ -1,118 +0,0 @@
#
# 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.
"""
from distutils import spawn
import os
import subprocess
import sys
from rally.common.i18n import _LE
from rally import exceptions
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)
def sp_check_output(*popenargs, **kwargs):
"""Run command with arguments and return its output as a byte string.
If the exit code was non-zero it raises a CalledProcessError. The
CalledProcessError object will have the return code in the returncode
attribute and output in the output attribute.
The arguments are the same as for the Popen constructor.
"""
if is_py26():
# NOTE(andreykurilin): as I said before, support python 26 env is hard
# task. Subprocess supports check_output function from Python 2.7, so
# let's copy-paste code of this function from it.
if "stdout" in kwargs:
raise ValueError("stdout argument not allowed, "
"it will be overridden.")
process = subprocess.Popen(stdout=subprocess.PIPE,
*popenargs, **kwargs)
output, unused_err = process.communicate()
retcode = process.poll()
if retcode:
cmd = kwargs.get("args")
if cmd is None:
cmd = popenargs[0]
raise subprocess.CalledProcessError(retcode, cmd, output=output)
return output
return subprocess.check_output(*popenargs, **kwargs)
def get_interpreter(python_version):
"""Discovers PATH to find proper python interpreter
:param python_version: (major, minor) version numbers
:type python_version: tuple
"""
if not isinstance(python_version, tuple):
msg = (_LE("given format of python version `%s` is invalid") %
python_version)
raise exceptions.InvalidArgumentsException(msg)
interpreter_name = "python%s.%s" % python_version
interpreter = spawn.find_executable(interpreter_name)
if interpreter:
return interpreter
else:
interpreters = filter(
os.path.isfile, [os.path.join(p, interpreter_name)
for p in os.environ.get("PATH", "").split(":")])
cmd = "%s -c 'import sys; print(sys.version_info[:2])'"
for interpreter in interpreters:
try:
out = sp_check_output(cmd % interpreter, shell=True)
except subprocess.CalledProcessError:
pass
else:
if out.strip() == str(python_version):
return interpreter

View File

@ -13,14 +13,13 @@
# License for the specific language governing permissions and limitations
# under the License.
import collections
import json
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."""
@ -34,8 +33,8 @@ class JSONEncodedDict(sa_types.TypeDecorator):
def process_result_value(self, value, dialect):
if value is not None:
value = costilius.json_loads(
value, object_pairs_hook=costilius.OrderedDict)
value = json.loads(
value, object_pairs_hook=collections.OrderedDict)
return value

View File

@ -13,16 +13,16 @@
# License for the specific language governing permissions and limitations
# under the License.
import collections
import functools
from rally.common import costilius
from rally.common import utils
class ActionTimerMixin(object):
def __init__(self):
self._atomic_actions = costilius.OrderedDict()
self._atomic_actions = collections.OrderedDict()
def atomic_actions(self):
"""Returns the content of each atomic action."""

View File

@ -22,7 +22,6 @@ import tempfile
from oslo_utils import encodeutils
from rally.common import costilius
from rally.common.i18n import _
from rally.common.io import subunit_v2
from rally.common import logging
@ -43,7 +42,7 @@ class TempestSetupFailure(exceptions.RallyException):
def check_output(*args, **kwargs):
kwargs["stderr"] = subprocess.STDOUT
try:
output = costilius.sp_check_output(*args, **kwargs)
output = subprocess.check_output(*args, **kwargs)
except subprocess.CalledProcessError as e:
LOG.error("Failed cmd: '%s'" % e.cmd)
LOG.error("Error output: '%s'" % encodeutils.safe_decode(e.output))
@ -182,23 +181,8 @@ class Tempest(object):
LOG.debug("No virtual environment for Tempest found.")
LOG.info(_("Installing the virtual environment for Tempest."))
LOG.debug("Virtual environment directory: %s" % path_to_venv)
required_vers = (2, 7)
if sys.version_info[:2] != required_vers:
# NOTE(andreykurilin): let's try to find a suitable python
# interpreter for Tempest
python_interpreter = costilius.get_interpreter(required_vers)
if not python_interpreter:
raise exceptions.IncompatiblePythonVersion(
version=sys.version, required_version=required_vers)
LOG.info(
_("Tempest requires Python %(required)s, '%(found)s' was "
"found in your system and it will be used for installing"
" virtual environment.") % {"required": required_vers,
"found": python_interpreter})
else:
python_interpreter = sys.executable
try:
check_output(["virtualenv", "-p", python_interpreter, ".venv"],
check_output(["virtualenv", "-p", sys.executable, ".venv"],
cwd=self.path())
# NOTE(kun): Using develop mode installation is for run
# multiple tempest instance. However, dependency

View File

@ -1,102 +0,0 @@
#
# 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.
#
import mock
from rally.common import costilius
from rally import exceptions
from tests.unit import test
PATH = "rally.common.costilius"
class SPCheckCallTestCase(test.TestCase):
@mock.patch("%s.subprocess" % PATH)
@mock.patch("%s.is_py26" % PATH, return_value=True)
def test_simulation_of_py26_env(self, mock_is_py26, mock_subprocess):
output = "output"
process = mock.MagicMock()
process.communicate.return_value = (output, "unused_err")
process.poll.return_value = None
mock_subprocess.Popen.return_value = process
some_args = (1, 2)
some_kwargs = {"a": 2}
self.assertEqual(output, costilius.sp_check_output(*some_args,
**some_kwargs))
mock_subprocess.Popen.assert_called_once_with(
stdout=mock_subprocess.PIPE, *some_args, **some_kwargs)
self.assertFalse(mock_subprocess.check_output.called)
@mock.patch("%s.subprocess" % PATH)
@mock.patch("%s.is_py26" % PATH, return_value=False)
def test_simulation_of_any_not_py26_env(self, mock_is_py26,
mock_subprocess):
output = "output"
mock_subprocess.check_output.return_value = output
some_args = (1, 2)
some_kwargs = {"a": 2}
self.assertEqual(output, costilius.sp_check_output(*some_args,
**some_kwargs))
mock_subprocess.check_output.assert_called_once_with(
*some_args, **some_kwargs)
self.assertFalse(mock_subprocess.Popen.called)
class GetInterpreterTestCase(test.TestCase):
def test_wrong_format(self):
self.assertRaises(exceptions.InvalidArgumentsException,
costilius.get_interpreter, "something_bad")
@mock.patch("%s.spawn" % PATH)
@mock.patch("%s.sp_check_output" % PATH)
@mock.patch("%s.os.path.isfile" % PATH)
@mock.patch("%s.os.environ" % PATH)
def test_found_correct_python_interpreter_with_distutils(
self, mock_environ, mock_isfile, mock_sp_check_output, mock_spawn):
vers = (2, 7)
interpreter = "something"
mock_spawn.find_executable.return_value = interpreter
self.assertEqual(interpreter, costilius.get_interpreter(vers))
self.assertFalse(mock_environ.called)
self.assertFalse(mock_isfile.called)
self.assertFalse(mock_sp_check_output.called)
@mock.patch("%s.spawn" % PATH)
@mock.patch("%s.sp_check_output" % PATH)
@mock.patch("%s.os.path.isfile" % PATH, return_value=True)
@mock.patch("%s.os.environ" % PATH)
def test_found_correct_python_interpreter_without_distutils(
self, mock_environ, mock_isfile, mock_sp_check_output, mock_spawn):
vers = (2, 7)
paths = ["one_path", "second_path"]
mock_environ.get.return_value = ":".join(paths)
mock_sp_check_output.return_value = "%s\n" % str(vers)
mock_spawn.find_executable.return_value = None
found_interpreter = costilius.get_interpreter(vers)
self.assertEqual(1, mock_sp_check_output.call_count)
self.assertIn(
found_interpreter, ["%s/%s" % (f, "python2.7") for f in paths])

View File

@ -13,9 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
import collections
import mock
from rally.common import costilius
from rally.task import atomic
from tests.unit import test
@ -39,7 +40,7 @@ class AtomicActionTestCase(test.TestCase):
pass
expected = [("test", 20), ("test (2)", 12), ("some", 4)]
self.assertEqual(costilius.OrderedDict(expected),
self.assertEqual(collections.OrderedDict(expected),
inst.atomic_actions())
@mock.patch("time.time", side_effect=[1, 3])
@ -56,7 +57,7 @@ class AtomicActionTestCase(test.TestCase):
pass
expected = [("test", 2)]
self.assertEqual(costilius.OrderedDict(expected),
self.assertEqual(collections.OrderedDict(expected),
inst.atomic_actions())
@mock.patch("time.time", side_effect=[1, 3])
@ -70,7 +71,7 @@ class AtomicActionTestCase(test.TestCase):
inst = Some()
self.assertEqual(5, inst.some_func(2, 3))
self.assertEqual(costilius.OrderedDict({"some": 2}),
self.assertEqual(collections.OrderedDict({"some": 2}),
inst.atomic_actions())
@mock.patch("time.time", side_effect=[1, 3])
@ -87,7 +88,7 @@ class AtomicActionTestCase(test.TestCase):
inst = TestTimer()
self.assertRaises(TestException, inst.some_func)
self.assertEqual(costilius.OrderedDict({"test": 2}),
self.assertEqual(collections.OrderedDict({"test": 2}),
inst.atomic_actions())
@mock.patch("time.time", side_effect=[1, 3, 1, 3])
@ -106,20 +107,20 @@ class AtomicActionTestCase(test.TestCase):
inst = TestAtomicTimer()
self.assertEqual(5, inst.some_func(2, 3))
self.assertEqual(costilius.OrderedDict({"some": 2}),
self.assertEqual(collections.OrderedDict({"some": 2}),
inst.atomic_actions())
inst = TestAtomicTimer()
self.assertEqual(5, inst.some_func(2, 3, atomic_action=False))
self.assertEqual(costilius.OrderedDict(),
self.assertEqual(collections.OrderedDict(),
inst.atomic_actions())
inst = TestAtomicTimer()
self.assertEqual(5, inst.other_func(2, 3))
self.assertEqual(costilius.OrderedDict(),
self.assertEqual(collections.OrderedDict(),
inst.atomic_actions())
inst = TestAtomicTimer()
self.assertEqual(5, inst.other_func(2, 3, foo=True))
self.assertEqual(costilius.OrderedDict({"some": 2}),
self.assertEqual(collections.OrderedDict({"some": 2}),
inst.atomic_actions())

View File

@ -94,22 +94,18 @@ class TempestUtilsTestCase(BaseTestCase):
self.assertFalse(mock_check_output.called)
@mock.patch("%s.tempest.sys" % TEMPEST_PATH)
@mock.patch("%s.tempest.costilius.get_interpreter" % TEMPEST_PATH,
return_value="python")
@mock.patch("os.path.isdir", return_value=False)
@mock.patch("%s.tempest.check_output" % TEMPEST_PATH,
return_value="some_output")
def test__venv_install_when_venv_not_exist(self, mock_check_output,
mock_isdir,
mock_get_interpreter, mock_sys):
mock_isdir, mock_sys):
mock_sys.version_info = "not_py27_env"
self.verifier._install_venv()
mock_isdir.assert_called_once_with(self.verifier.path(".venv"))
mock_check_output.assert_has_calls([
mock.call(["virtualenv", "-p", mock_get_interpreter.return_value,
".venv"], cwd="/tmp"),
mock.call(["virtualenv", "-p", mock_sys.executable, ".venv"],
cwd="/tmp"),
mock.call(["/tmp/tools/with_venv.sh", "pip", "install", "-r",
"requirements.txt", "-r", "test-requirements.txt"],
cwd="/tmp"),
@ -118,14 +114,13 @@ class TempestUtilsTestCase(BaseTestCase):
])
@mock.patch("%s.tempest.sys" % TEMPEST_PATH)
@mock.patch("%s.tempest.costilius.get_interpreter" % TEMPEST_PATH,
return_value=None)
@mock.patch("os.path.isdir", return_value=False)
def test__venv_install_fails__when_py27_is_not_present(
self, mock_isdir, mock_get_interpreter, mock_sys):
self, mock_isdir, mock_sys):
mock_sys.version_info = "not_py27_env"
mock_sys.executable = "fake_path"
self.assertRaises(exceptions.IncompatiblePythonVersion,
self.assertRaises(tempest.TempestSetupFailure,
self.verifier._install_venv)
mock_isdir.assert_called_once_with(self.verifier.path(".venv"))