Merge "Refactor share metadata tests"
This commit is contained in:
commit
1be8d2d09d
@ -23,6 +23,7 @@ from tempest.lib.common.utils import data_utils
|
|||||||
from tempest.lib import exceptions
|
from tempest.lib import exceptions
|
||||||
|
|
||||||
from manila_tempest_tests import share_exceptions
|
from manila_tempest_tests import share_exceptions
|
||||||
|
from manila_tempest_tests import utils
|
||||||
|
|
||||||
|
|
||||||
CONF = config.CONF
|
CONF = config.CONF
|
||||||
@ -42,6 +43,9 @@ class SharesClient(rest_client.RestClient):
|
|||||||
self.share_network_id = CONF.share.share_network_id
|
self.share_network_id = CONF.share.share_network_id
|
||||||
self.share_size = CONF.share.share_size
|
self.share_size = CONF.share.share_size
|
||||||
|
|
||||||
|
def _parse_resp(self, body, verify_top_key=None):
|
||||||
|
return utils._parse_resp(body, verify_top_key=verify_top_key)
|
||||||
|
|
||||||
def create_share(self, share_protocol=None, size=None,
|
def create_share(self, share_protocol=None, size=None,
|
||||||
name=None, snapshot_id=None, description=None,
|
name=None, snapshot_id=None, description=None,
|
||||||
metadata=None, share_network_id=None,
|
metadata=None, share_network_id=None,
|
||||||
@ -446,7 +450,7 @@ class SharesClient(rest_client.RestClient):
|
|||||||
def get_metadata_item(self, share_id, key):
|
def get_metadata_item(self, share_id, key):
|
||||||
resp, body = self.get("shares/%s/metadata/%s" % (share_id, key))
|
resp, body = self.get("shares/%s/metadata/%s" % (share_id, key))
|
||||||
self.expected_success(200, resp.status)
|
self.expected_success(200, resp.status)
|
||||||
return self._parse_resp(body)
|
return self._parse_resp(body, verify_top_key='meta')
|
||||||
|
|
||||||
###############
|
###############
|
||||||
|
|
||||||
|
@ -34,14 +34,15 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||||||
def _verify_share_metadata(self, share, md):
|
def _verify_share_metadata(self, share, md):
|
||||||
|
|
||||||
# get metadata of share
|
# get metadata of share
|
||||||
metadata = self.shares_client.get_metadata(share["id"])['metadata']
|
metadata = self.shares_v2_client.get_metadata(share["id"])['metadata']
|
||||||
|
|
||||||
# verify metadata
|
# verify metadata
|
||||||
self.assertEqual(md, metadata)
|
self.assertEqual(md, metadata)
|
||||||
|
|
||||||
# verify metadata items
|
# verify metadata items
|
||||||
for key in md:
|
for key in md:
|
||||||
get_value = self.shares_client.get_metadata_item(share["id"], key)
|
get_value = self.shares_v2_client.get_metadata_item(share["id"],
|
||||||
|
key)
|
||||||
self.assertEqual(md[key], get_value[key])
|
self.assertEqual(md[key], get_value[key])
|
||||||
|
|
||||||
@decorators.idempotent_id('9070249f-6e94-4a38-a036-08debee547c3')
|
@decorators.idempotent_id('9070249f-6e94-4a38-a036-08debee547c3')
|
||||||
@ -69,17 +70,18 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||||||
cleanup_in_class=False)
|
cleanup_in_class=False)
|
||||||
|
|
||||||
# set metadata
|
# set metadata
|
||||||
self.shares_client.set_metadata(share["id"], md)
|
self.shares_v2_client.set_metadata(share["id"], md)
|
||||||
|
|
||||||
# verify metadata
|
# verify metadata
|
||||||
self._verify_share_metadata(share, md)
|
self._verify_share_metadata(share, md)
|
||||||
|
|
||||||
# delete metadata
|
# delete metadata
|
||||||
for key in md.keys():
|
for key in md.keys():
|
||||||
self.shares_client.delete_metadata(share["id"], key)
|
self.shares_v2_client.delete_metadata(share["id"], key)
|
||||||
|
|
||||||
# verify deletion of metadata
|
# verify deletion of metadata
|
||||||
get_metadata = self.shares_client.get_metadata(share["id"])['metadata']
|
get_metadata = self.shares_v2_client.get_metadata(share["id"])[
|
||||||
|
'metadata']
|
||||||
self.assertEmpty(get_metadata)
|
self.assertEmpty(get_metadata)
|
||||||
|
|
||||||
@decorators.idempotent_id('4e5f8159-62b6-4d5c-f729-d8b1f029d7de')
|
@decorators.idempotent_id('4e5f8159-62b6-4d5c-f729-d8b1f029d7de')
|
||||||
@ -93,13 +95,13 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||||||
cleanup_in_class=False)
|
cleanup_in_class=False)
|
||||||
|
|
||||||
# set metadata
|
# set metadata
|
||||||
self.shares_client.set_metadata(share["id"], md1)
|
self.shares_v2_client.set_metadata(share["id"], md1)
|
||||||
|
|
||||||
# verify metadata
|
# verify metadata
|
||||||
self._verify_share_metadata(share, md1)
|
self._verify_share_metadata(share, md1)
|
||||||
|
|
||||||
# set metadata again
|
# set metadata again
|
||||||
self.shares_client.set_metadata(share["id"], md2)
|
self.shares_v2_client.set_metadata(share["id"], md2)
|
||||||
|
|
||||||
# verify metadata
|
# verify metadata
|
||||||
md1.update(md2)
|
md1.update(md2)
|
||||||
@ -110,10 +112,11 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||||||
|
|
||||||
# delete metadata
|
# delete metadata
|
||||||
for key in md.keys():
|
for key in md.keys():
|
||||||
self.shares_client.delete_metadata(share["id"], key)
|
self.shares_v2_client.delete_metadata(share["id"], key)
|
||||||
|
|
||||||
# verify deletion of metadata
|
# verify deletion of metadata
|
||||||
get_metadata = self.shares_client.get_metadata(share["id"])['metadata']
|
get_metadata = self.shares_v2_client.get_metadata(
|
||||||
|
share["id"])['metadata']
|
||||||
self.assertEmpty(get_metadata)
|
self.assertEmpty(get_metadata)
|
||||||
|
|
||||||
@decorators.idempotent_id('2ec70ba5-050b-3b17-c862-c149e53543c0')
|
@decorators.idempotent_id('2ec70ba5-050b-3b17-c862-c149e53543c0')
|
||||||
@ -127,13 +130,13 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||||||
cleanup_in_class=False)
|
cleanup_in_class=False)
|
||||||
|
|
||||||
# set metadata
|
# set metadata
|
||||||
self.shares_client.set_metadata(share["id"], md1)
|
self.shares_v2_client.set_metadata(share["id"], md1)
|
||||||
|
|
||||||
# verify metadata
|
# verify metadata
|
||||||
self._verify_share_metadata(share, md1)
|
self._verify_share_metadata(share, md1)
|
||||||
|
|
||||||
# set metadata again
|
# set metadata again
|
||||||
self.shares_client.set_metadata(share["id"], md2)
|
self.shares_v2_client.set_metadata(share["id"], md2)
|
||||||
|
|
||||||
# verify metadata
|
# verify metadata
|
||||||
md = {u"key9": u"value13", u"key10": u"value10",
|
md = {u"key9": u"value13", u"key10": u"value10",
|
||||||
@ -142,10 +145,11 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||||||
|
|
||||||
# delete metadata
|
# delete metadata
|
||||||
for key in md.keys():
|
for key in md.keys():
|
||||||
self.shares_client.delete_metadata(share["id"], key)
|
self.shares_v2_client.delete_metadata(share["id"], key)
|
||||||
|
|
||||||
# verify deletion of metadata
|
# verify deletion of metadata
|
||||||
get_metadata = self.shares_client.get_metadata(share["id"])['metadata']
|
get_metadata = self.shares_v2_client.get_metadata(
|
||||||
|
share["id"])['metadata']
|
||||||
self.assertEmpty(get_metadata)
|
self.assertEmpty(get_metadata)
|
||||||
|
|
||||||
@decorators.idempotent_id('c94851f4-2559-4712-9297-9912db1da7ff')
|
@decorators.idempotent_id('c94851f4-2559-4712-9297-9912db1da7ff')
|
||||||
@ -160,10 +164,10 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||||||
cleanup_in_class=False)
|
cleanup_in_class=False)
|
||||||
|
|
||||||
# set metadata
|
# set metadata
|
||||||
self.shares_client.set_metadata(share["id"], md1)
|
self.shares_v2_client.set_metadata(share["id"], md1)
|
||||||
|
|
||||||
# update metadata
|
# update metadata
|
||||||
self.shares_client.update_all_metadata(share["id"], md2)
|
self.shares_v2_client.update_all_metadata(share["id"], md2)
|
||||||
|
|
||||||
# verify metadata
|
# verify metadata
|
||||||
self._verify_share_metadata(share, md2)
|
self._verify_share_metadata(share, md2)
|
||||||
@ -173,9 +177,9 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||||||
def test_set_metadata_min_size_key(self):
|
def test_set_metadata_min_size_key(self):
|
||||||
data = {"k": "value"}
|
data = {"k": "value"}
|
||||||
|
|
||||||
self.shares_client.set_metadata(self.share["id"], data)
|
self.shares_v2_client.set_metadata(self.share["id"], data)
|
||||||
|
|
||||||
body_get = self.shares_client.get_metadata(
|
body_get = self.shares_v2_client.get_metadata(
|
||||||
self.share["id"])['metadata']
|
self.share["id"])['metadata']
|
||||||
self.assertEqual(data['k'], body_get.get('k'))
|
self.assertEqual(data['k'], body_get.get('k'))
|
||||||
|
|
||||||
@ -185,9 +189,9 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||||||
max_key = "k" * 255
|
max_key = "k" * 255
|
||||||
data = {max_key: "value"}
|
data = {max_key: "value"}
|
||||||
|
|
||||||
self.shares_client.set_metadata(self.share["id"], data)
|
self.shares_v2_client.set_metadata(self.share["id"], data)
|
||||||
|
|
||||||
body_get = self.shares_client.get_metadata(
|
body_get = self.shares_v2_client.get_metadata(
|
||||||
self.share["id"])['metadata']
|
self.share["id"])['metadata']
|
||||||
self.assertIn(max_key, body_get)
|
self.assertIn(max_key, body_get)
|
||||||
self.assertEqual(data[max_key], body_get.get(max_key))
|
self.assertEqual(data[max_key], body_get.get(max_key))
|
||||||
@ -197,9 +201,9 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||||||
def test_set_metadata_min_size_value(self):
|
def test_set_metadata_min_size_value(self):
|
||||||
data = {"key": "v"}
|
data = {"key": "v"}
|
||||||
|
|
||||||
self.shares_client.set_metadata(self.share["id"], data)
|
self.shares_v2_client.set_metadata(self.share["id"], data)
|
||||||
|
|
||||||
body_get = self.shares_client.get_metadata(
|
body_get = self.shares_v2_client.get_metadata(
|
||||||
self.share["id"])['metadata']
|
self.share["id"])['metadata']
|
||||||
self.assertEqual(data['key'], body_get['key'])
|
self.assertEqual(data['key'], body_get['key'])
|
||||||
|
|
||||||
@ -209,9 +213,9 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||||||
max_value = "v" * 1023
|
max_value = "v" * 1023
|
||||||
data = {"key": max_value}
|
data = {"key": max_value}
|
||||||
|
|
||||||
self.shares_client.set_metadata(self.share["id"], data)
|
self.shares_v2_client.set_metadata(self.share["id"], data)
|
||||||
|
|
||||||
body_get = self.shares_client.get_metadata(
|
body_get = self.shares_v2_client.get_metadata(
|
||||||
self.share["id"])['metadata']
|
self.share["id"])['metadata']
|
||||||
self.assertEqual(data['key'], body_get['key'])
|
self.assertEqual(data['key'], body_get['key'])
|
||||||
|
|
||||||
@ -220,9 +224,9 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||||||
def test_upd_metadata_min_size_key(self):
|
def test_upd_metadata_min_size_key(self):
|
||||||
data = {"k": "value"}
|
data = {"k": "value"}
|
||||||
|
|
||||||
self.shares_client.update_all_metadata(self.share["id"], data)
|
self.shares_v2_client.update_all_metadata(self.share["id"], data)
|
||||||
|
|
||||||
body_get = self.shares_client.get_metadata(
|
body_get = self.shares_v2_client.get_metadata(
|
||||||
self.share["id"])['metadata']
|
self.share["id"])['metadata']
|
||||||
self.assertEqual(data, body_get)
|
self.assertEqual(data, body_get)
|
||||||
|
|
||||||
@ -232,9 +236,9 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||||||
max_key = "k" * 255
|
max_key = "k" * 255
|
||||||
data = {max_key: "value"}
|
data = {max_key: "value"}
|
||||||
|
|
||||||
self.shares_client.update_all_metadata(self.share["id"], data)
|
self.shares_v2_client.update_all_metadata(self.share["id"], data)
|
||||||
|
|
||||||
body_get = self.shares_client.get_metadata(
|
body_get = self.shares_v2_client.get_metadata(
|
||||||
self.share["id"])['metadata']
|
self.share["id"])['metadata']
|
||||||
self.assertEqual(data, body_get)
|
self.assertEqual(data, body_get)
|
||||||
|
|
||||||
@ -243,9 +247,9 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||||||
def test_upd_metadata_min_size_value(self):
|
def test_upd_metadata_min_size_value(self):
|
||||||
data = {"key": "v"}
|
data = {"key": "v"}
|
||||||
|
|
||||||
self.shares_client.update_all_metadata(self.share["id"], data)
|
self.shares_v2_client.update_all_metadata(self.share["id"], data)
|
||||||
|
|
||||||
body_get = self.shares_client.get_metadata(
|
body_get = self.shares_v2_client.get_metadata(
|
||||||
self.share["id"])['metadata']
|
self.share["id"])['metadata']
|
||||||
self.assertEqual(data, body_get)
|
self.assertEqual(data, body_get)
|
||||||
|
|
||||||
@ -255,8 +259,8 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||||||
max_value = "v" * 1023
|
max_value = "v" * 1023
|
||||||
data = {"key": max_value}
|
data = {"key": max_value}
|
||||||
|
|
||||||
self.shares_client.update_all_metadata(self.share["id"], data)
|
self.shares_v2_client.update_all_metadata(self.share["id"], data)
|
||||||
|
|
||||||
body_get = self.shares_client.get_metadata(
|
body_get = self.shares_v2_client.get_metadata(
|
||||||
self.share["id"])['metadata']
|
self.share["id"])['metadata']
|
||||||
self.assertEqual(data, body_get)
|
self.assertEqual(data, body_get)
|
||||||
|
@ -61,14 +61,14 @@ class SharesMetadataNegativeTest(base.BaseSharesMixedTest):
|
|||||||
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
|
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
|
||||||
def test_try_set_metadata_with_empty_key(self):
|
def test_try_set_metadata_with_empty_key(self):
|
||||||
self.assertRaises(lib_exc.BadRequest,
|
self.assertRaises(lib_exc.BadRequest,
|
||||||
self.shares_client.set_metadata,
|
self.shares_v2_client.set_metadata,
|
||||||
self.share["id"], {"": "value"})
|
self.share["id"], {"": "value"})
|
||||||
|
|
||||||
@decorators.idempotent_id('759ca34d-1c87-43f3-8da2-8e1d373049ac')
|
@decorators.idempotent_id('759ca34d-1c87-43f3-8da2-8e1d373049ac')
|
||||||
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
|
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
|
||||||
def test_try_upd_metadata_with_empty_key(self):
|
def test_try_upd_metadata_with_empty_key(self):
|
||||||
self.assertRaises(lib_exc.BadRequest,
|
self.assertRaises(lib_exc.BadRequest,
|
||||||
self.shares_client.update_all_metadata,
|
self.shares_v2_client.update_all_metadata,
|
||||||
self.share["id"], {"": "value"})
|
self.share["id"], {"": "value"})
|
||||||
|
|
||||||
@decorators.idempotent_id('94c7ebb3-14c3-4ff1-9839-ae3acb318cd0')
|
@decorators.idempotent_id('94c7ebb3-14c3-4ff1-9839-ae3acb318cd0')
|
||||||
@ -77,7 +77,7 @@ class SharesMetadataNegativeTest(base.BaseSharesMixedTest):
|
|||||||
too_big_key = "x" * 256
|
too_big_key = "x" * 256
|
||||||
md = {too_big_key: "value"}
|
md = {too_big_key: "value"}
|
||||||
self.assertRaises(lib_exc.BadRequest,
|
self.assertRaises(lib_exc.BadRequest,
|
||||||
self.shares_client.set_metadata,
|
self.shares_v2_client.set_metadata,
|
||||||
self.share["id"], md)
|
self.share["id"], md)
|
||||||
|
|
||||||
@decorators.idempotent_id('33ef3047-6ca3-4547-a681-b52314382dcb')
|
@decorators.idempotent_id('33ef3047-6ca3-4547-a681-b52314382dcb')
|
||||||
@ -86,7 +86,7 @@ class SharesMetadataNegativeTest(base.BaseSharesMixedTest):
|
|||||||
too_big_key = "x" * 256
|
too_big_key = "x" * 256
|
||||||
md = {too_big_key: "value"}
|
md = {too_big_key: "value"}
|
||||||
self.assertRaises(lib_exc.BadRequest,
|
self.assertRaises(lib_exc.BadRequest,
|
||||||
self.shares_client.update_all_metadata,
|
self.shares_v2_client.update_all_metadata,
|
||||||
self.share["id"], md)
|
self.share["id"], md)
|
||||||
|
|
||||||
@decorators.idempotent_id('1114970a-1b45-4c56-b20a-e13e1764e3c4')
|
@decorators.idempotent_id('1114970a-1b45-4c56-b20a-e13e1764e3c4')
|
||||||
@ -95,7 +95,7 @@ class SharesMetadataNegativeTest(base.BaseSharesMixedTest):
|
|||||||
too_big_value = "x" * 1024
|
too_big_value = "x" * 1024
|
||||||
md = {"key": too_big_value}
|
md = {"key": too_big_value}
|
||||||
self.assertRaises(lib_exc.BadRequest,
|
self.assertRaises(lib_exc.BadRequest,
|
||||||
self.shares_client.set_metadata,
|
self.shares_v2_client.set_metadata,
|
||||||
self.share["id"], md)
|
self.share["id"], md)
|
||||||
|
|
||||||
@decorators.idempotent_id('c2eddcf0-cf81-4f9f-b06d-c9165ab8553e')
|
@decorators.idempotent_id('c2eddcf0-cf81-4f9f-b06d-c9165ab8553e')
|
||||||
@ -104,12 +104,12 @@ class SharesMetadataNegativeTest(base.BaseSharesMixedTest):
|
|||||||
too_big_value = "x" * 1024
|
too_big_value = "x" * 1024
|
||||||
md = {"key": too_big_value}
|
md = {"key": too_big_value}
|
||||||
self.assertRaises(lib_exc.BadRequest,
|
self.assertRaises(lib_exc.BadRequest,
|
||||||
self.shares_client.update_all_metadata,
|
self.shares_v2_client.update_all_metadata,
|
||||||
self.share["id"], md)
|
self.share["id"], md)
|
||||||
|
|
||||||
@decorators.idempotent_id('14df3262-5a2b-4de4-b335-422329b22b07')
|
@decorators.idempotent_id('14df3262-5a2b-4de4-b335-422329b22b07')
|
||||||
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
|
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
|
||||||
def test_try_delete_unexisting_metadata(self):
|
def test_try_delete_unexisting_metadata(self):
|
||||||
self.assertRaises(lib_exc.NotFound,
|
self.assertRaises(lib_exc.NotFound,
|
||||||
self.shares_client.delete_metadata,
|
self.shares_v2_client.delete_metadata,
|
||||||
self.share["id"], "wrong_key")
|
self.share["id"], "wrong_key")
|
||||||
|
@ -70,10 +70,10 @@ class SharesSchedulerHintsTest(base.BaseSharesMixedTest):
|
|||||||
self.assertEqual(backend_a, backend_b)
|
self.assertEqual(backend_a, backend_b)
|
||||||
|
|
||||||
# get metadata of share
|
# get metadata of share
|
||||||
metadata_a = self.shares_client.get_metadata(
|
metadata_a = self.shares_v2_client.get_metadata(
|
||||||
self.share_a["id"])['metadata']
|
self.share_a["id"])['metadata']
|
||||||
md_a = {"__affinity_same_host": "%s" % share_b["id"]}
|
md_a = {"__affinity_same_host": "%s" % share_b["id"]}
|
||||||
metadata_b = self.shares_client.get_metadata(
|
metadata_b = self.shares_v2_client.get_metadata(
|
||||||
share_b["id"])['metadata']
|
share_b["id"])['metadata']
|
||||||
md_b = {"__affinity_same_host": "%s" % self.share_a["id"]}
|
md_b = {"__affinity_same_host": "%s" % self.share_a["id"]}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
import json
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
|
|
||||||
@ -225,3 +226,43 @@ def get_extra_headers(request_version, graduation_version):
|
|||||||
headers = EXPERIMENTAL
|
headers = EXPERIMENTAL
|
||||||
extra_headers = True
|
extra_headers = True
|
||||||
return headers, extra_headers
|
return headers, extra_headers
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_resp(body, verify_top_key=None):
|
||||||
|
try:
|
||||||
|
body = json.loads(body)
|
||||||
|
except ValueError:
|
||||||
|
return body
|
||||||
|
|
||||||
|
# We assume, that if the first value of the deserialized body's
|
||||||
|
# item set is a dict or a list, that we just return the first value
|
||||||
|
# of deserialized body.
|
||||||
|
# Essentially "cutting out" the first placeholder element in a body
|
||||||
|
# that looks like this:
|
||||||
|
#
|
||||||
|
# {
|
||||||
|
# "users": [
|
||||||
|
# ...
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
try:
|
||||||
|
# Ensure there are not more than one top-level keys
|
||||||
|
# NOTE(freerunner): Ensure, that JSON is not nullable to
|
||||||
|
# to prevent StopIteration Exception
|
||||||
|
if not hasattr(body, "keys") or len(body.keys()) != 1:
|
||||||
|
return body
|
||||||
|
# Just return the "wrapped" element
|
||||||
|
first_key, first_item = tuple(body.items())[0]
|
||||||
|
if isinstance(first_item, (dict, list)):
|
||||||
|
if verify_top_key is not None:
|
||||||
|
assert_msg = (
|
||||||
|
"The expected top level key is '%(top_key)s' but we "
|
||||||
|
"found '%(actual_key)s'." % {
|
||||||
|
'top_key': verify_top_key,
|
||||||
|
'actual_key': first_key
|
||||||
|
})
|
||||||
|
assert verify_top_key == first_key, assert_msg
|
||||||
|
return first_item
|
||||||
|
except (ValueError, IndexError):
|
||||||
|
pass
|
||||||
|
return body
|
||||||
|
Loading…
Reference in New Issue
Block a user