[fix] Updates to use cached jsonpath

Layering code was not using a parse cache for jsonpath
This change adds use of the cache around all calls to jsonpath_ng.parse

Change-Id: I800eb397badf19ed2ea47b88fa7c91e4a09225ef
This commit is contained in:
Bryan Strassner 2018-04-02 14:34:23 -05:00
parent 5c9efa9d74
commit c50501cc89
1 changed files with 29 additions and 16 deletions

View File

@ -26,7 +26,9 @@ from deckhand import errors
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
path_cache = dict() # Cache for JSON paths computed from path strings because jsonpath_ng
# is computationally expensive.
_PATH_CACHE = dict()
def to_camel_case(s): def to_camel_case(s):
@ -41,6 +43,28 @@ def to_snake_case(name):
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower() return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
def _normalize_jsonpath(jsonpath):
"""Changes jsonpath starting with a `.` character with a `$`"""
if jsonpath == '.':
jsonpath = '$'
elif jsonpath.startswith('.'):
jsonpath = '$' + jsonpath
return jsonpath
def _jsonpath_parse_cache(jsonpath):
"""Retrieve the parsed jsonpath path
Utilizes a cache of parsed values to eliminate re-parsing
"""
if jsonpath not in _PATH_CACHE:
p = jsonpath_ng.parse(jsonpath)
_PATH_CACHE[jsonpath] = p
else:
p = _PATH_CACHE[jsonpath]
return p
def jsonpath_parse(data, jsonpath, match_all=False): def jsonpath_parse(data, jsonpath, match_all=False):
"""Parse value in the data for the given ``jsonpath``. """Parse value in the data for the given ``jsonpath``.
@ -69,16 +93,8 @@ def jsonpath_parse(data, jsonpath, match_all=False):
src_secret = utils.jsonpath_parse(src_doc['data'], src_path) src_secret = utils.jsonpath_parse(src_doc['data'], src_path)
# Do something with the extracted secret from the source document. # Do something with the extracted secret from the source document.
""" """
if jsonpath == '.': jsonpath = _normalize_jsonpath(jsonpath)
jsonpath = '$' p = _jsonpath_parse_cache(jsonpath)
elif jsonpath.startswith('.'):
jsonpath = '$' + jsonpath
if jsonpath not in path_cache:
p = jsonpath_ng.parse(jsonpath)
path_cache[jsonpath] = p
else:
p = path_cache[jsonpath]
matches = p.find(data) matches = p.find(data)
if matches: if matches:
@ -152,10 +168,7 @@ def jsonpath_replace(data, value, jsonpath, pattern=None):
data = copy.copy(data) data = copy.copy(data)
value = copy.copy(value) value = copy.copy(value)
if jsonpath == '.': jsonpath = _normalize_jsonpath(jsonpath)
jsonpath = '$'
elif jsonpath.startswith('.'):
jsonpath = '$' + jsonpath
if not jsonpath == '$' and not jsonpath.startswith('$.'): if not jsonpath == '$' and not jsonpath.startswith('$.'):
LOG.error('The provided jsonpath %s does not begin with "." or "$"', LOG.error('The provided jsonpath %s does not begin with "." or "$"',
@ -164,7 +177,7 @@ def jsonpath_replace(data, value, jsonpath, pattern=None):
'or "$"' % jsonpath) 'or "$"' % jsonpath)
def _do_replace(): def _do_replace():
p = jsonpath_ng.parse(jsonpath) p = _jsonpath_parse_cache(jsonpath)
p_to_change = p.find(data) p_to_change = p.find(data)
if p_to_change: if p_to_change: