Skip to content

Commit

Permalink
Move evaluateTarget, evaluateTokens into separate module
Browse files Browse the repository at this point in the history
  • Loading branch information
iain-buclaw-sociomantic committed Jul 20, 2016
1 parent e040170 commit cac6197
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 77 deletions.
75 changes: 4 additions & 71 deletions graphite_api/app.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import os
import csv
import json
import itertools
import math
import pytz
import shutil
Expand All @@ -20,9 +19,8 @@
from .config import configure
from .encoders import JSONEncoder
from .render.attime import parseATTime
from .render.datalib import fetchData, TimeSeries
from .render.datalib import fetchData
from .render.glyph import GraphTypes
from .render.grammar import grammar
from .utils import RequestParams, hash_request

logger = get_logger()
Expand Down Expand Up @@ -471,74 +469,6 @@ def render():
return response


def pathsFromTarget(target):
tokens = grammar.parseString(target)
return list(pathsFromTokens(tokens))


def pathsFromTokens(tokens):
iters = []
if tokens.expression:
iters.append(pathsFromTokens(tokens.expression))
elif tokens.pathExpression:
iters.append([tokens.pathExpression])
elif tokens.call:
iters.extend([pathsFromTokens(arg)
for arg in tokens.call.args])
iters.extend([pathsFromTokens(kwarg.args[0])
for kwarg in tokens.call.kwargs])
for path in itertools.chain(*iters):
yield path


def evaluateTarget(requestContext, target, data_store=None):
if data_store is None:
paths = pathsFromTarget(target)
data_store = fetchData(requestContext, paths)

tokens = grammar.parseString(target)
result = evaluateTokens(requestContext, tokens, data_store)

if isinstance(result, TimeSeries):
return [result] # we have to return a list of TimeSeries objects

return result


def evaluateTokens(requestContext, tokens, data_store):
if tokens.expression:
return evaluateTokens(requestContext, tokens.expression, data_store)

elif tokens.pathExpression:
return data_store.get_series_list(tokens.pathExpression)

elif tokens.call:
func = app.functions[tokens.call.funcname]
args = [evaluateTokens(requestContext,
arg, data_store) for arg in tokens.call.args]
kwargs = dict([(kwarg.argname,
evaluateTokens(requestContext,
kwarg.args[0],
data_store))
for kwarg in tokens.call.kwargs])
ret = func(requestContext, *args, **kwargs)
return ret

elif tokens.number:
if tokens.number.integer:
return int(tokens.number.integer)
elif tokens.number.float:
return float(tokens.number.float)
elif tokens.number.scientific:
return float(tokens.number.scientific[0])

elif tokens.string:
return tokens.string[1:-1]

elif tokens.boolean:
return tokens.boolean[0] == 'true'


def tree_json(nodes, base_path, wildcards=False):
results = []

Expand Down Expand Up @@ -597,3 +527,6 @@ def doImageRender(graphClass, graphOptions):
imageData = pngData.getvalue()
pngData.close()
return imageData


from .evaluator import evaluateTarget, pathsFromTarget # noqa
74 changes: 74 additions & 0 deletions graphite_api/evaluator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import itertools

from .render.datalib import fetchData, TimeSeries
from .render.grammar import grammar


def pathsFromTarget(target):
tokens = grammar.parseString(target)
return list(pathsFromTokens(tokens))


def pathsFromTokens(tokens):
iters = []
if tokens.expression:
iters.append(pathsFromTokens(tokens.expression))
elif tokens.pathExpression:
iters.append([tokens.pathExpression])
elif tokens.call:
iters.extend([pathsFromTokens(arg)
for arg in tokens.call.args])
iters.extend([pathsFromTokens(kwarg.args[0])
for kwarg in tokens.call.kwargs])
for path in itertools.chain(*iters):
yield path


def evaluateTarget(requestContext, target, data_store=None):
if data_store is None:
paths = pathsFromTarget(target)
data_store = fetchData(requestContext, paths)

tokens = grammar.parseString(target)
result = evaluateTokens(requestContext, tokens, data_store)

if isinstance(result, TimeSeries):
return [result] # we have to return a list of TimeSeries objects

return result


def evaluateTokens(requestContext, tokens, data_store):
if tokens.expression:
return evaluateTokens(requestContext, tokens.expression, data_store)

elif tokens.pathExpression:
return data_store.get_series_list(tokens.pathExpression)

elif tokens.call:
func = app.functions[tokens.call.funcname]
args = [evaluateTokens(requestContext,
arg, data_store) for arg in tokens.call.args]
kwargs = dict([(kwarg.argname,
evaluateTokens(requestContext,
kwarg.args[0],
data_store))
for kwarg in tokens.call.kwargs])
ret = func(requestContext, *args, **kwargs)
return ret

elif tokens.number:
if tokens.number.integer:
return int(tokens.number.integer)
elif tokens.number.float:
return float(tokens.number.float)
elif tokens.number.scientific:
return float(tokens.number.scientific[0])

elif tokens.string:
return tokens.string[1:-1]

elif tokens.boolean:
return tokens.boolean[0] == 'true'

from .app import app # noqa
7 changes: 1 addition & 6 deletions graphite_api/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

from six.moves import zip_longest, map, reduce

from .evaluator import evaluateTarget, pathsFromTarget
from .render.attime import parseTimeOffset, parseATTime
from .render.glyph import format_units
from .render.datalib import TimeSeries, fetchData
Expand Down Expand Up @@ -1934,7 +1935,6 @@ def useSeriesAbove(requestContext, seriesList, value, search, replace):
&target=useSeriesAbove(ganglia.metric1.reqs,10,"reqs","time")
"""
from .app import evaluateTarget
newSeries = []

for series in seriesList:
Expand Down Expand Up @@ -2061,7 +2061,6 @@ def _fetchWithBootstrap(requestContext, seriesList, **delta_kwargs):
"""
Request the same data but with a bootstrap period at the beginning.
"""
from .app import evaluateTarget, pathsFromTarget
bootstrapContext = requestContext.copy()
bootstrapContext['startTime'] = (
requestContext['startTime'] - timedelta(**delta_kwargs))
Expand Down Expand Up @@ -2422,7 +2421,6 @@ def timeStack(requestContext, seriesList, timeShiftUnit, timeShiftStart,
# create a series for today and each of the previous 7 days
&target=timeStack(Sales.widgets.largeBlue,"1d",0,7)
"""
from .app import evaluateTarget
# Default to negative. parseTimeOffset defaults to +
if timeShiftUnit[0].isdigit():
timeShiftUnit = '-' + timeShiftUnit
Expand Down Expand Up @@ -2477,7 +2475,6 @@ def timeShift(requestContext, seriesList, timeShift, resetEnd=True):
&target=timeShift(Sales.widgets.largeBlue,"+1h")
"""
from .app import evaluateTarget
# Default to negative. parseTimeOffset defaults to +
if timeShift[0].isdigit():
timeShift = '-' + timeShift
Expand Down Expand Up @@ -2904,7 +2901,6 @@ def smartSummarize(requestContext, seriesList, intervalString, func='sum'):
"""
Smarter experimental version of summarize.
"""
from .app import evaluateTarget, pathsFromTarget
results = []
delta = parseTimeOffset(intervalString)
interval = to_seconds(delta)
Expand Down Expand Up @@ -3113,7 +3109,6 @@ def hitcount(requestContext, seriesList, intervalString,
or coarse-grained records) and handles rarely-occurring events
gracefully.
"""
from .app import evaluateTarget, pathsFromTarget
results = []
delta = parseTimeOffset(intervalString)
interval = to_seconds(delta)
Expand Down

0 comments on commit cac6197

Please sign in to comment.