Commit cd3d6b1b authored by Giorgos Korfiatis's avatar Giorgos Korfiatis

Revert "common: Do not encode key paths as string"

This reverts commit b10f66b9a20fb9dca0a56c88d5d224f1e3fa25ea.
parent 6685ff8d
......@@ -34,5 +34,4 @@
from astakos.im.settings import astakos_services
from synnefo.util.keypath import get_path
resources = get_path(
astakos_services, ['astakos_account', 'resources']).values()
resources = get_path(astakos_services, 'astakos_account.resources').values()
......@@ -50,11 +50,11 @@ BASE_HOST, BASE_PATH = parse_base_url(BASE_URL)
astakos_services = deepcopy(vanilla_astakos_services)
fill_endpoints(astakos_services, BASE_URL)
ACCOUNTS_PREFIX = get_path(astakos_services, ['astakos_account', 'prefix'])
VIEWS_PREFIX = get_path(astakos_services, ['astakos_ui', 'prefix'])
KEYSTONE_PREFIX = get_path(astakos_services, ['astakos_identity', 'prefix'])
WEBLOGIN_PREFIX = get_path(astakos_services, ['astakos_weblogin', 'prefix'])
ADMIN_PREFIX = get_path(astakos_services, ['astakos_admin', 'prefix'])
ACCOUNTS_PREFIX = get_path(astakos_services, 'astakos_account.prefix')
VIEWS_PREFIX = get_path(astakos_services, 'astakos_ui.prefix')
KEYSTONE_PREFIX = get_path(astakos_services, 'astakos_identity.prefix')
WEBLOGIN_PREFIX = get_path(astakos_services, 'astakos_weblogin.prefix')
ADMIN_PREFIX = get_path(astakos_services, 'astakos_admin.prefix')
# Set the expiration time of newly created auth tokens
# to be this many hours after their creation time.
......
......@@ -39,16 +39,16 @@ from urlparse import urlparse
def fill_endpoints(services, base_url):
for name, service in services.iteritems():
prefix = get_path(service, ['prefix'])
endpoints = get_path(service, ['endpoints'])
prefix = get_path(service, 'prefix')
endpoints = get_path(service, 'endpoints')
for endpoint in endpoints:
version = get_path(endpoint, ['versionId'])
publicURL = get_path(endpoint, ['publicURL'])
version = get_path(endpoint, 'versionId')
publicURL = get_path(endpoint, 'publicURL')
if publicURL is not None:
continue
publicURL = join_urls(base_url, prefix, version).rstrip('/')
set_path(endpoint, ['publicURL'], publicURL)
set_path(endpoint, 'publicURL', publicURL)
def filter_public(services):
......
......@@ -36,49 +36,52 @@ import re
integer_re = re.compile('-?[0-9]+')
def unpack(pathstr, sep='.'):
"""
>>> unpack('a.-2.x')
['a', -2, 'x']
"""
names = pathstr.split(sep)
parse = lambda x: int(x) if integer_re.match(x) else x
return [parse(x) for x in names]
def join_path(sep, path):
iterable = ((str(n) if isinstance(n, (int, long)) else n) for n in path)
return sep.join(iterable)
def lookup_path(container, path, createpath=False):
def lookup_path(container, path, sep='.', createpath=False):
"""
return (['a','b'],
[container['a'], container['a']['b']],
'c') where path=['a','b','c']
'c') where path=sep.join(['a','b','c'])
"""
dirnames = path[:-1]
basename = path[-1]
names = path.split(sep)
dirnames = names[:-1]
basename = names[-1]
if integer_re.match(basename):
basename = int(basename)
node = container
name_path = []
node_path = [node]
for name in dirnames:
name_path.append(name)
if integer_re.match(name):
name = int(name)
try:
node = node[name]
except KeyError as e:
if not createpath:
m = "{0}: path not found".format(name_path)
m = "'{0}': path not found".format(join_path(sep, name_path))
raise KeyError(m)
node[name] = {}
node = node[name]
except IndexError as e:
if not createpath:
m = "{0}: path not found: {1}".format(name_path, e)
m = "'{0}': path not found: {1}".format(
join_path(sep, name_path), e)
raise KeyError(m)
size = name if name > 0 else -name
node += (dict() for _ in xrange(len(node), size))
node = node[name]
except TypeError as e:
m = "{0}: cannot traverse path beyond this node: {1}"
m = m.format(name_path, str(e))
m = "'{0}': cannot traverse path beyond this node: {1}"
m = m.format(join_path(sep, name_path), str(e))
raise ValueError(m)
node_path.append(node)
......@@ -94,49 +97,49 @@ def walk_paths(container):
yield [name] + names, [node] + nodes
def list_paths(container):
def list_paths(container, sep='.'):
"""
>>> sorted(list_paths({'a': {'b': {'c': 'd'}}}))
[(['a', 'b', 'c'], 'd')]
[('a.b.c', 'd')]
>>> sorted(list_paths({'a': {'b': {'c': 'd'}, 'e': 3}}))
[(['a', 'b', 'c'], 'd'), (['a', 'e'], 3)]
[('a.b.c', 'd'), ('a.e', 3)]
>>> sorted(list_paths({'a': {'b': {'c': 'd'}, 'e': {'f': 3}}}))
[(['a', 'b', 'c'], 'd'), (['a', 'e', 'f'], 3)]
[('a.b.c', 'd'), ('a.e.f', 3)]
>>> sorted(list_paths({'a': [{'b': 3}, 2]}))
[(['a'], [{'b': 3}, 2])]
[('a', [{'b': 3}, 2])]
>>> list_paths({})
[]
"""
return [(name_path, node_path[-1])
return [(join_path(sep, name_path), node_path[-1])
for name_path, node_path in walk_paths(container)]
def del_path(container, path, collect=True):
def del_path(container, path, sep='.', collect=True):
"""
del container['a']['b']['c'] where path=['a','b','c']
del container['a']['b']['c'] where path=sep.join(['a','b','c'])
>>> d = {'a': {'b': {'c': 'd'}}}; del_path(d, ['a', 'b', 'c']); d
>>> d = {'a': {'b': {'c': 'd'}}}; del_path(d, 'a.b.c'); d
{}
>>> d = {'a': {'b': {'c': 'd'}}}; del_path(d, ['a', 'b', 'c'],\
collect=False); d
>>> d = {'a': {'b': {'c': 'd'}}}; del_path(d, 'a.b.c', collect=False); d
{'a': {'b': {}}}
>>> d = {'a': {'b': {'c': 'd'}}}; del_path(d, ['a', 'b', 'c', 'd'])
>>> d = {'a': {'b': {'c': 'd'}}}; del_path(d, 'a.b.c.d')
Traceback (most recent call last):
ValueError: ['a', 'b', 'c']: cannot traverse path beyond this node:\
ValueError: 'a.b.c': cannot traverse path beyond this node:\
'str' object does not support item deletion
"""
name_path, node_path, basename = \
lookup_path(container, path, createpath=False)
lookup_path(container, path, sep=sep, createpath=False)
lastnode = node_path.pop()
lastname = basename
try:
if basename in lastnode:
del lastnode[basename]
except (TypeError, KeyError) as e:
m = "{0}: cannot traverse path beyond this node: {1}"
m = m.format(name_path, str(e))
m = "'{0}': cannot traverse path beyond this node: {1}"
m = m.format(join_path(sep, name_path), str(e))
raise ValueError(m)
if collect:
......@@ -146,111 +149,100 @@ def del_path(container, path, collect=True):
del lastnode[basename]
def get_path(container, path):
def get_path(container, path, sep='.'):
"""
return container['a']['b']['c'] where path=['a','b','c']
return container['a']['b']['c'] where path=sep.join(['a','b','c'])
>>> get_path({'a': {'b': {'c': 'd'}}}, ['a', 'b', 'c', 'd'])
>>> get_path({'a': {'b': {'c': 'd'}}}, 'a.b.c.d')
Traceback (most recent call last):
ValueError: ['a', 'b', 'c', 'd']: cannot traverse path beyond this node:\
ValueError: 'a.b.c.d': cannot traverse path beyond this node:\
string indices must be integers, not str
>>> get_path({'a': {'b': {'c': 1}}}, ['a', 'b', 'c', 'd'])
>>> get_path({'a': {'b': {'c': 1}}}, 'a.b.c.d')
Traceback (most recent call last):
ValueError: ['a', 'b', 'c', 'd']: cannot traverse path beyond this node:\
'int' object has no attribute '__getitem__'
>>> get_path({'a': {'b': {'c': 1}}}, ['a', 'b', 'c'])
ValueError: 'a.b.c.d': cannot traverse path beyond this node:\
'int' object is unsubscriptable
>>> get_path({'a': {'b': {'c': 1}}}, 'a.b.c')
1
>>> get_path({'a': {'b': {'c': 1}}}, ['a', 'b'])
>>> get_path({'a': {'b': {'c': 1}}}, 'a.b')
{'c': 1}
>>> get_path({'a': [{'z': 1}]}, ['a', 'b'])
Traceback (most recent call last):
ValueError: ['a', 'b']: cannot traverse path beyond this node:\
list indices must be integers, not str
>>> get_path({'a': [{'z': 1}]}, ['a', 0])
>>> get_path({'a': [{'z': 1}]}, 'a.0')
{'z': 1}
>>> get_path({'a': [{'z': 1}]}, ['a', 1])
Traceback (most recent call last):
KeyError: "['a', 1]: path not found: list index out of range"
>>> get_path({'a': [{'z': 1}]}, ['a', 0, 'z'])
>>> get_path({'a': [{'z': 1}]}, 'a.0.z')
1
>>> get_path({'a': [{'z': 1}]}, ['a', -1, 'z'])
>>> get_path({'a': [{'z': 1}]}, 'a.-1.z')
1
"""
name_path, node_path, basename = \
lookup_path(container, path, createpath=False)
lookup_path(container, path, sep=sep, createpath=False)
name_path.append(basename)
node = node_path[-1]
try:
return node[basename]
except TypeError as e:
m = "{0}: cannot traverse path beyond this node: {1}"
m = m.format(name_path, str(e))
m = "'{0}': cannot traverse path beyond this node: {1}"
m = m.format(join_path(sep, name_path), str(e))
raise ValueError(m)
except KeyError as e:
m = "{0}: path not found: {1}"
m = m.format(name_path, str(e))
raise KeyError(m)
except IndexError as e:
m = "{0}: path not found: {1}"
m = m.format(name_path, str(e))
m = "'{0}': path not found: {1}"
m = m.format(join_path(sep, name_path), str(e))
raise KeyError(m)
def set_path(container, path, value, createpath=False, overwrite=True):
def set_path(container, path, value, sep='.',
createpath=False, overwrite=True):
"""
container['a']['b']['c'] = value where path=['a','b','c']
container['a']['b']['c'] = value where path=sep.join(['a','b','c'])
>>> set_path({'a': {'b': {'c': 'd'}}}, ['a', 'b', 'c', 'd'], 1)
>>> set_path({'a': {'b': {'c': 'd'}}}, 'a.b.c.d', 1)
Traceback (most recent call last):
ValueError: ['a', 'b', 'c', 'd']: cannot index, node is neither dict nor\
list
>>> set_path({'a': {'b': {'c': 'd'}}}, ['a', 'b', 'x', 'd'], 1)
ValueError: 'a.b.c.d': cannot index non-object node with string
>>> set_path({'a': {'b': {'c': 'd'}}}, 'a.b.x.d', 1)
Traceback (most recent call last):
KeyError: "['a', 'b', 'x']: path not found"
>>> set_path({'a': {'b': {'c': 'd'}}}, ['a', 'b', 'x', 'd'], 1,\
createpath=True)
>>> set_path({'a': {'b': {'c': 'd'}}}, ['a', 'b', 'c'], 1)
>>> set_path({'a': {'b': {'c': 'd'}}}, ['a', 'b', 'c'], 1, overwrite=False)
KeyError: "'a.b.x': path not found"
>>> set_path({'a': {'b': {'c': 'd'}}}, 'a.b.x.d', 1, createpath=True)
>>> set_path({'a': {'b': {'c': 'd'}}}, 'a.b.c', 1)
>>> set_path({'a': {'b': {'c': 'd'}}}, 'a.b.c', 1, overwrite=False)
Traceback (most recent call last):
ValueError: will not overwrite path ['a', 'b', 'c']
>>> d = {'a': [{'z': 1}]}; set_path(d, ['a', -2, 1], 2, createpath=False)
ValueError: will not overwrite path 'a.b.c'
>>> d = {'a': [{'z': 1}]}; set_path(d, 'a.-2.1', 2, createpath=False)
Traceback (most recent call last):
KeyError: "['a', -2]: path not found: list index out of range"
>>> d = {'a': [{'z': 1}]}; set_path(d, ['a', -2, 1], 2, createpath=True); \
d['a'][-2][1]
KeyError: "'a.-2': path not found: list index out of range"
>>> d = {'a': [{'z': 1}]}; set_path(d, 'a.-2.1', 2, createpath=True)
Traceback (most recent call last):
ValueError: 'a.-2.1': will not index object node with integer
>>> d = {'a': [{'z': 1}]}; set_path(d, 'a.-2.z', 2, createpath=True); \
d['a'][-2]['z']
2
"""
name_path, node_path, basename = \
lookup_path(container, path, createpath=createpath)
lookup_path(container, path, sep=sep, createpath=createpath)
name_path.append(basename)
node = node_path[-1]
if basename in node and not overwrite:
m = "will not overwrite path {0}".format(path)
m = "will not overwrite path '{0}'".format(path)
raise ValueError(m)
is_object_node = hasattr(node, 'keys')
is_list_node = isinstance(node, list)
if not is_object_node and not is_list_node:
m = "{0}: cannot index, node is neither dict nor list"
m = m.format(name_path)
is_string_name = isinstance(basename, basestring)
if not is_string_name and is_object_node:
m = "'{0}': will not index object node with integer"
m = m.format(join_path(sep, name_path))
raise ValueError(m)
is_integer = isinstance(basename, (int, long))
if is_list_node and not is_integer:
m = "{0}: cannot index list node without an integer"
m = m.format(name_path)
if is_string_name and not is_object_node:
m = "'{0}': cannot index non-object node with string"
m = m.format(join_path(sep, name_path))
raise ValueError(m)
try:
node[basename] = value
except TypeError as e:
m = "{0}: cannot traverse path beyond this node: {1}"
m = m.format(name_path, str(e))
m = "'{0}': cannot traverse path beyond this node: {1}"
m = m.format(join_path(sep, name_path), str(e))
raise ValueError(m)
......
......@@ -35,7 +35,7 @@ import logging
from django.conf import settings
from synnefo.lib import join_urls, parse_base_url
from synnefo.util.keypath import get_path, set_path, unpack
from synnefo.util.keypath import get_path, set_path
from synnefo.api.services import cyclades_services as vanilla_cyclades_services
from synnefo.lib.services import fill_endpoints
from astakosclient import AstakosClient
......@@ -57,16 +57,16 @@ CUSTOMIZE_SERVICES = getattr(settings, 'CYCLADES_CUSTOMIZE_SERVICES', ())
cyclades_services = deepcopy(vanilla_cyclades_services)
fill_endpoints(cyclades_services, BASE_URL)
for path, value in CUSTOMIZE_SERVICES:
set_path(cyclades_services, unpack(path), value, createpath=True)
COMPUTE_PREFIX = get_path(cyclades_services, ['cyclades_compute', 'prefix'])
NETWORK_PREFIX = get_path(cyclades_services, ['cyclades_network', 'prefix'])
VMAPI_PREFIX = get_path(cyclades_services, ['cyclades_vmapi', 'prefix'])
PLANKTON_PREFIX = get_path(cyclades_services, ['cyclades_plankton', 'prefix'])
HELPDESK_PREFIX = get_path(cyclades_services, ['cyclades_helpdesk', 'prefix'])
UI_PREFIX = get_path(cyclades_services, ['cyclades_ui', 'prefix'])
USERDATA_PREFIX = get_path(cyclades_services, ['cyclades_userdata', 'prefix'])
ADMIN_PREFIX = get_path(cyclades_services, ['cyclades_admin', 'prefix'])
set_path(cyclades_services, path, value, createpath=True)
COMPUTE_PREFIX = get_path(cyclades_services, 'cyclades_compute.prefix')
NETWORK_PREFIX = get_path(cyclades_services, 'cyclades_network.prefix')
VMAPI_PREFIX = get_path(cyclades_services, 'cyclades_vmapi.prefix')
PLANKTON_PREFIX = get_path(cyclades_services, 'cyclades_plankton.prefix')
HELPDESK_PREFIX = get_path(cyclades_services, 'cyclades_helpdesk.prefix')
UI_PREFIX = get_path(cyclades_services, 'cyclades_ui.prefix')
USERDATA_PREFIX = get_path(cyclades_services, 'cyclades_userdata.prefix')
ADMIN_PREFIX = get_path(cyclades_services, 'cyclades_admin.prefix')
COMPUTE_ROOT_URL = join_urls(BASE_URL, COMPUTE_PREFIX)
......
......@@ -35,5 +35,5 @@ from synnefo.util.keypath import get_path
from synnefo.api.services import cyclades_services
resources = \
get_path(cyclades_services, ['cyclades_compute', 'resources']).values() +\
get_path(cyclades_services, ['cyclades_network', 'resources']).values()
get_path(cyclades_services, 'cyclades_compute.resources').values() +\
get_path(cyclades_services, 'cyclades_network.resources').values()
......@@ -34,5 +34,4 @@
from synnefo.util.keypath import get_path
from pithos.api.settings import pithos_services
resources = get_path(pithos_services,
['pithos_object-store', 'resources']).values()
resources = get_path(pithos_services, 'pithos_object-store.resources').values()
......@@ -59,9 +59,9 @@ BASE_HOST, BASE_PATH = parse_base_url(BASE_URL)
pithos_services = deepcopy(vanilla_pithos_services)
fill_endpoints(pithos_services, BASE_URL)
PITHOS_PREFIX = get_path(pithos_services, ['pithos_object-store', 'prefix'])
PUBLIC_PREFIX = get_path(pithos_services, ['pithos_public', 'prefix'])
UI_PREFIX = get_path(pithos_services, ['pithos_ui', 'prefix'])
PITHOS_PREFIX = get_path(pithos_services, 'pithos_object-store.prefix')
PUBLIC_PREFIX = get_path(pithos_services, 'pithos_public.prefix')
UI_PREFIX = get_path(pithos_services, 'pithos_ui.prefix')
VIEW_PREFIX = join_urls(UI_PREFIX, 'view')
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment