Remove morph dependency

morph library is distributed under GPLv3 dependency which means that we
need to distribute under package as well under GPLv3 license or stop
using this library.

Since we do not use too much from morph, so let's just let's write a
simple replacement for what we actually need.

Change-Id: I00df4e66a2365cbaa948707289b14262dc016454
This commit is contained in:
Andrey Kurilin 2019-02-04 18:46:46 +02:00
parent 3625758dfe
commit 78f43cd992
7 changed files with 124 additions and 30 deletions

View File

@ -17,10 +17,7 @@ Changelog
.. Release notes for existing releases are MUTABLE! If there is something that
was missed or can be improved, feel free to change it!
usreleased
--------------------
[1.4.0] - 2019-01-29
[1.4.0] - 2019-02-04
--------------------
Changed
@ -29,10 +26,18 @@ Changed
* Add the --html-static option to commands ``rally task trends``, it could generate
trends report with embedded js/css.
* Fix an issue with calling `rally` command without arguments
* Removed dependency to ``morph`` library.
Fixed
~~~~~
* ``rally`` command crashes while calling without any arguments
* Fix the ssh error while passing an dss key in ssh utils.
`Launchpad-bug #1807870 <https://launchpad.net/bugs/1807870>`_
[1.3.0] - 2018-12-01
--------------------

View File

@ -23,6 +23,7 @@ from rally.common import validation
from rally import consts
from rally import exceptions
from rally.plugins.common.exporters.elastic import client
from rally.plugins.common.exporters.elastic import flatten
from rally.task import exporter
LOG = logging.getLogger(__name__)
@ -146,14 +147,6 @@ class ElasticSearchExporter(exporter.TaskExporter):
if self._remote:
self._client = client.ElasticSearchClient(self.output_destination)
@staticmethod
def _pack(obj):
import morph
return sorted(["%s=%s" % (k, v)
for k, v in morph.flatten(obj).items()])
def _add_index(self, index, body, doc_id=None, doc_type="data"):
"""Create a document for the specified index with specified id.
@ -349,11 +342,11 @@ class ElasticSearchExporter(exporter.TaskExporter):
"deployment_uuid": task["env_uuid"],
"deployment_name": task["env_name"],
"scenario_name": workload["name"],
"scenario_cfg": self._pack(workload["args"]),
"scenario_cfg": flatten.transform(workload["args"]),
"description": workload["description"],
"runner_name": workload["runner_type"],
"runner_cfg": self._pack(workload["runner"]),
"contexts": self._pack(workload["contexts"]),
"runner_cfg": flatten.transform(workload["runner"]),
"contexts": flatten.transform(workload["contexts"]),
"started_at": started_at,
"load_duration": workload["load_duration"],
"full_duration": workload["full_duration"],

View File

@ -0,0 +1,67 @@
# 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 six
def _join_keys(first, second):
if not second:
return first
elif second.startswith("["):
return "%s%s" % (first, second)
else:
return "%s.%s" % (first, second)
def _process(obj):
if isinstance(obj, (six.string_types, six.binary_type)):
yield "", obj
elif isinstance(obj, dict):
for first, tmp_value in obj.items():
for second, value in _process(tmp_value):
yield _join_keys(first, second), value
elif isinstance(obj, (list, tuple)):
for i, tmp_value in enumerate(obj):
for second, value in _process(tmp_value):
yield _join_keys("[%s]" % i, second), value
else:
try:
yield "", "%s" % obj
except Exception:
raise ValueError("Cannot transform obj of '%s' type to flatten "
"structure." % type(obj))
def transform(obj):
"""Transform object to a flatten structure.
Example:
IN:
{"foo": ["xxx", "yyy", {"bar": {"zzz": ["Hello", "World!"]}}]}
OUTPUT:
[
"foo[0]=xxx",
"foo[1]=yyy",
"foo[2].bar.zzz[0]=Hello",
"foo[2].bar.zzz[1]=World!"
]
"""
result = []
for key, value in _process(obj):
if key:
result.append("%s=%s" % (key, value))
else:
result.append(value)
return sorted(result)

View File

@ -7,7 +7,6 @@ alembic # MIT
decorator # new BSD License
Jinja2 # BSD
jsonschema<3.0.0 # MIT
morph # GPLv3+
netaddr # BSD
oslo.config!=4.3.0,!=4.4.0 # Apache Software License
# do not forget to remove `testresources` from test-requirements. it is a

View File

@ -157,18 +157,6 @@ class ElasticSearchExporterTestCase(test.TestCase):
self.assertFalse(exporter._remote)
self.assertIsNone(getattr(exporter, "_client", None))
def test__pack(self):
exporter = elastic.ElasticSearchExporter([], None)
self.assertEqual(
{"key1=value1", "key2=value2"},
set(exporter._pack({"key1": "value1", "key2": "value2"})))
self.assertEqual(
{"key1=value1", "key2.foo.bar=1", "key2.xxx=yyy"},
set(exporter._pack({"key1": "value1", "key2": {"foo": {"bar": 1},
"xxx": "yyy"}})))
@ddt.data(None, "/home/bar", "https://example.com")
def test__add_index(self, destination):

View File

@ -0,0 +1,43 @@
# 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.
from rally.plugins.common.exporters.elastic import flatten
from tests.unit import test
class FlattenTestCase(test.TestCase):
def test_transform(self):
self.assertEqual(
["key1=value1", "key2=value2"],
flatten.transform({"key1": "value1", "key2": "value2"}))
self.assertEqual(
["key1=value1", "key2.foo.bar=1", "key2.xxx=yyy"],
flatten.transform(
{"key1": "value1", "key2": {"foo": {"bar": 1}, "xxx": "yyy"}}))
self.assertEqual(
["foo[0]=xxx", "foo[1]=yyy", "foo[2].bar.zzz[0]=Hello",
"foo[2].bar.zzz[1]=World!"],
flatten.transform(
{"foo": ["xxx", "yyy", {"bar": {"zzz": ["Hello", "World!"]}}]})
)
def test__join_keys(self):
self.assertEqual("key", flatten._join_keys("key", ""))
self.assertEqual("key.value", flatten._join_keys("key", "value"))
self.assertEqual("[0].value", flatten._join_keys("[0]", "value"))
self.assertEqual("key[0]", flatten._join_keys("key", "[0]"))
self.assertEqual("[0][0]", flatten._join_keys("[0]", "[0]"))

View File

@ -22,7 +22,6 @@ linecache2==1.0.0
Mako==1.0.7
MarkupSafe==1.0
monotonic==1.4
morph==0.1.2
msgpack==0.5.4
netaddr==0.7.19
netifaces==0.10.6