Rename minixpath_select to get_from_path

This commit is contained in:
Justin Santa Barbara
2011-02-23 14:07:08 -08:00
parent 890acb4c17
commit 2d51a6048b
2 changed files with 12 additions and 189 deletions

View File

@@ -1,177 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011 Justin Santa Barbara
#
# 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 nova import test
from nova import utils
from nova import exception
class MiniXPathTestCase(test.TestCase):
def test_tolerates_nones(self):
xp = utils.minixpath_select
input = []
self.assertEquals([], xp(input, "a"))
self.assertEquals([], xp(input, "a/b"))
self.assertEquals([], xp(input, "a/b/c"))
input = [None]
self.assertEquals([], xp(input, "a"))
self.assertEquals([], xp(input, "a/b"))
self.assertEquals([], xp(input, "a/b/c"))
input = [{'a': None}]
self.assertEquals([], xp(input, "a"))
self.assertEquals([], xp(input, "a/b"))
self.assertEquals([], xp(input, "a/b/c"))
input = [{'a': {'b': None}}]
self.assertEquals([{'b': None}], xp(input, "a"))
self.assertEquals([], xp(input, "a/b"))
self.assertEquals([], xp(input, "a/b/c"))
input = [{'a': {'b': {'c': None}}}]
self.assertEquals([{'b': {'c': None}}], xp(input, "a"))
self.assertEquals([{'c': None}], xp(input, "a/b"))
self.assertEquals([], xp(input, "a/b/c"))
input = [{'a': {'b': {'c': None}}}, {'a': None}]
self.assertEquals([{'b': {'c': None}}], xp(input, "a"))
self.assertEquals([{'c': None}], xp(input, "a/b"))
self.assertEquals([], xp(input, "a/b/c"))
input = [{'a': {'b': {'c': None}}}, {'a': {'b': None}}]
self.assertEquals([{'b': {'c': None}}, {'b': None}], xp(input, "a"))
self.assertEquals([{'c': None}], xp(input, "a/b"))
self.assertEquals([], xp(input, "a/b/c"))
def test_does_select(self):
xp = utils.minixpath_select
input = [{'a': 'a_1'}]
self.assertEquals(['a_1'], xp(input, "a"))
self.assertEquals([], xp(input, "a/b"))
self.assertEquals([], xp(input, "a/b/c"))
input = [{'a': {'b': 'b_1'}}]
self.assertEquals([{'b': 'b_1'}], xp(input, "a"))
self.assertEquals(['b_1'], xp(input, "a/b"))
self.assertEquals([], xp(input, "a/b/c"))
input = [{'a': {'b': {'c': 'c_1'}}}]
self.assertEquals([{'b': {'c': 'c_1'}}], xp(input, "a"))
self.assertEquals([{'c': 'c_1'}], xp(input, "a/b"))
self.assertEquals(['c_1'], xp(input, "a/b/c"))
input = [{'a': {'b': {'c': 'c_1'}}}, {'a': None}]
self.assertEquals([{'b': {'c': 'c_1'}}],
xp(input, "a"))
self.assertEquals([{'c': 'c_1'}], xp(input, "a/b"))
self.assertEquals(['c_1'], xp(input, "a/b/c"))
input = [{'a': {'b': {'c': 'c_1'}}},
{'a': {'b': None}}]
self.assertEquals([{'b': {'c': 'c_1'}}, {'b': None}],
xp(input, "a"))
self.assertEquals([{'c': 'c_1'}], xp(input, "a/b"))
self.assertEquals(['c_1'], xp(input, "a/b/c"))
input = [{'a': {'b': {'c': 'c_1'}}},
{'a': {'b': {'c': 'c_2'}}}]
self.assertEquals([{'b': {'c': 'c_1'}}, {'b': {'c': 'c_2'}}],
xp(input, "a"))
self.assertEquals([{'c': 'c_1'}, {'c': 'c_2'}],
xp(input, "a/b"))
self.assertEquals(['c_1', 'c_2'], xp(input, "a/b/c"))
self.assertEquals([], xp(input, "a/b/c/d"))
self.assertEquals([], xp(input, "c/a/b/d"))
self.assertEquals([], xp(input, "i/r/t"))
def test_flattens_lists(self):
xp = utils.minixpath_select
input = [{'a': [1, 2, 3]}]
self.assertEquals([1, 2, 3], xp(input, "a"))
self.assertEquals([], xp(input, "a/b"))
self.assertEquals([], xp(input, "a/b/c"))
input = [{'a': {'b': [1, 2, 3]}}]
self.assertEquals([{'b': [1, 2, 3]}], xp(input, "a"))
self.assertEquals([1, 2, 3], xp(input, "a/b"))
self.assertEquals([], xp(input, "a/b/c"))
input = [{'a': {'b': [1, 2, 3]}}, {'a': {'b': [4, 5, 6]}}]
self.assertEquals([1, 2, 3, 4, 5, 6], xp(input, "a/b"))
self.assertEquals([], xp(input, "a/b/c"))
input = [{'a': [{'b': [1, 2, 3]}, {'b': [4, 5, 6]}]}]
self.assertEquals([1, 2, 3, 4, 5, 6], xp(input, "a/b"))
self.assertEquals([], xp(input, "a/b/c"))
input = [{'a': [1, 2, {'b': 'b_1'}]}]
self.assertEquals([1, 2, {'b': 'b_1'}], xp(input, "a"))
self.assertEquals(['b_1'], xp(input, "a/b"))
def test_bad_xpath(self):
xp = utils.minixpath_select
self.assertRaises(exception.Error, xp, [], None)
self.assertRaises(exception.Error, xp, [], "")
self.assertRaises(exception.Error, xp, [], "/")
self.assertRaises(exception.Error, xp, [], "/a")
self.assertRaises(exception.Error, xp, [], "/a/")
self.assertRaises(exception.Error, xp, [], "//")
self.assertRaises(exception.Error, xp, [], "//a")
self.assertRaises(exception.Error, xp, [], "a//a")
self.assertRaises(exception.Error, xp, [], "a//a/")
self.assertRaises(exception.Error, xp, [], "a/a/")
def test_real_failure1(self):
# Real world failure case...
# We weren't coping when the input was a Dictionary instead of a List
# This led to test_accepts_dictionaries
xp = utils.minixpath_select
inst = {'fixed_ip': {'floating_ips': [{'address': '1.2.3.4'}],
'address': '192.168.0.3'},
'hostname': ''}
private_ips = xp(inst, 'fixed_ip/address')
public_ips = xp(inst, 'fixed_ip/floating_ips/address')
self.assertEquals(['192.168.0.3'], private_ips)
self.assertEquals(['1.2.3.4'], public_ips)
def test_accepts_dictionaries(self):
xp = utils.minixpath_select
input = {'a': [1, 2, 3]}
self.assertEquals([1, 2, 3], xp(input, "a"))
self.assertEquals([], xp(input, "a/b"))
self.assertEquals([], xp(input, "a/b/c"))
input = {'a': {'b': [1, 2, 3]}}
self.assertEquals([{'b': [1, 2, 3]}], xp(input, "a"))
self.assertEquals([1, 2, 3], xp(input, "a/b"))
self.assertEquals([], xp(input, "a/b/c"))
input = {'a': [{'b': [1, 2, 3]}, {'b': [4, 5, 6]}]}
self.assertEquals([1, 2, 3, 4, 5, 6], xp(input, "a/b"))
self.assertEquals([], xp(input, "a/b/c"))
input = {'a': [1, 2, {'b': 'b_1'}]}
self.assertEquals([1, 2, {'b': 'b_1'}], xp(input, "a"))
self.assertEquals(['b_1'], xp(input, "a/b"))

View File

@@ -32,10 +32,10 @@ import string
import struct
import sys
import time
import types
from xml.sax import saxutils
import re
import netaddr
import types
from eventlet import event
from eventlet import greenthread
@@ -503,18 +503,19 @@ def ensure_b64_encoding(val):
return base64.b64encode(val)
def minixpath_select(items, minixpath):
""" Takes an xpath-like expression e.g. prop1/prop2/prop3, and for each
item in items, looks up items[prop1][prop2][prop3]. Like XPath, if any of
the intermediate results are lists it will treat each list item
individually. A 'None' in items or any child expressions will be ignored,
this function will not throw because of None (anywhere) in items. The
returned list will contain no None values."""
def get_from_path(items, path):
""" Returns a list of items matching the specified path. Takes an
XPath-like expression e.g. prop1/prop2/prop3, and for each item in items,
looks up items[prop1][prop2][prop3]. Like XPath, if any of the
intermediate results are lists it will treat each list item individually.
A 'None' in items or any child expressions will be ignored, this function
will not throw because of None (anywhere) in items. The returned list
will contain no None values."""
if minixpath is None:
if path is None:
raise exception.Error("Invalid mini_xpath")
(first_token, sep, remainder) = minixpath.partition("/")
(first_token, sep, remainder) = path.partition("/")
if first_token == "":
raise exception.Error("Invalid mini_xpath")
@@ -537,7 +538,6 @@ def minixpath_select(items, minixpath):
child = get_method(first_token)
if child is None:
continue
#print "%s => %s" % (first_token, child)
if isinstance(child, types.ListType):
# Flatten intermediate lists
for x in child:
@@ -549,4 +549,4 @@ def minixpath_select(items, minixpath):
# No more tokens
return results
else:
return minixpath_select(results, remainder)
return get_from_path(results, remainder)