Skip to content

Commit d0295a2

Browse files
authored
Merge pull request #1566 from cbowman0/coverage_render_glyph
Adding test coverage for render/glyph.py mark ii
2 parents 6cecfd5 + 6e6c77a commit d0295a2

File tree

2 files changed

+1059
-16
lines changed

2 files changed

+1059
-16
lines changed

webapp/graphite/render/glyph.py

Lines changed: 85 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,12 @@ def __init__(self, minValue, maxValue, unitSystem=None):
165165

166166
@staticmethod
167167
def checkFinite(value, name='value'):
168+
"""Check that value is a finite number.
169+
170+
If it is, return it. If not, raise GraphError describing the
171+
problem, using name in the error message.
172+
"""
173+
168174
if math.isnan(value):
169175
raise GraphError('Encountered NaN %s' % (name,))
170176
elif math.isinf(value):
@@ -173,12 +179,31 @@ def checkFinite(value, name='value'):
173179

174180
@staticmethod
175181
def chooseDelta(x):
182+
"""Choose a reasonable axis range given that one limit is x.
183+
184+
Given that end of the axis range (i.e., minValue or maxValue) is
185+
x, choose a reasonable distance to the other limit.
186+
"""
187+
176188
if abs(x) < 1.0e-9:
177189
return 1.0
178190
else:
179191
return 0.1 * abs(x)
180192

181193
def reconcileLimits(self):
194+
"""If self.minValue is not less than self.maxValue, fix the problem.
195+
196+
If self.minValue is not less than self.maxValue, adjust
197+
self.minValue and/or self.maxValue (depending on which was not
198+
specified explicitly by the user) to make self.minValue <
199+
self.maxValue. If the user specified both limits explicitly, then
200+
raise GraphError.
201+
"""
202+
203+
if self.minValue < self.maxValue:
204+
# The limits are already OK.
205+
return
206+
182207
minFixed = (self.minValueSource in ['min'])
183208
maxFixed = (self.maxValueSource in ['max', 'limit'])
184209

@@ -196,6 +221,26 @@ def reconcileLimits(self):
196221
self.maxValue = average + delta
197222

198223
def applySettings(self, axisMin=None, axisMax=None, axisLimit=None):
224+
"""Apply the specified settings to this axis.
225+
226+
Set self.minValue, self.minValueSource, self.maxValue,
227+
self.maxValueSource, and self.axisLimit reasonably based on the
228+
parameters provided.
229+
230+
Arguments:
231+
232+
axisMin -- a finite number, or None to choose a round minimum
233+
limit that includes all of the data.
234+
235+
axisMax -- a finite number, 'max' to use the maximum value
236+
contained in the data, or None to choose a round maximum limit
237+
that includes all of the data.
238+
239+
axisLimit -- a finite number to use as an upper limit on maxValue,
240+
or None to impose no upper limit.
241+
242+
"""
243+
199244
if axisMin is not None and not math.isnan(axisMin):
200245
self.minValueSource = 'min'
201246
self.minValue = self.checkFinite(axisMin, 'axis min')
@@ -206,24 +251,32 @@ def applySettings(self, axisMin=None, axisMax=None, axisLimit=None):
206251
self.maxValueSource = 'max'
207252
self.maxValue = self.checkFinite(axisMax, 'axis max')
208253

209-
if axisLimit is not None and not math.isnan(axisLimit):
210-
if axisLimit < self.maxValue:
211-
self.maxValue = self.checkFinite(axisLimit, 'axis limit')
212-
self.maxValueSource = 'limit'
213-
# The limit has already been imposed, so there is no need to
214-
# remember it:
215-
self.axisLimit = None
216-
elif not math.isinf(axisLimit):
217-
# We still need to remember axisLimit to avoid rounding top to
218-
# a value larger than axisLimit:
219-
self.axisLimit = axisLimit
220-
else:
254+
if axisLimit is None or math.isnan(axisLimit):
221255
self.axisLimit = None
256+
elif axisLimit < self.maxValue:
257+
self.maxValue = self.checkFinite(axisLimit, 'axis limit')
258+
self.maxValueSource = 'limit'
259+
# The limit has already been imposed, so there is no need to
260+
# remember it:
261+
self.axisLimit = None
262+
elif math.isinf(axisLimit):
263+
# It must be positive infinity, which is the same as no limit:
264+
self.axisLimit = None
265+
else:
266+
# We still need to remember axisLimit to avoid rounding top to
267+
# a value larger than axisLimit:
268+
self.axisLimit = axisLimit
222269

223-
if not (self.minValue < self.maxValue):
224-
self.reconcileLimits()
270+
self.reconcileLimits()
225271

226272
def makeLabel(self, value):
273+
"""Create a label for the specified value.
274+
275+
Create a label string containing the value and its units (if any),
276+
based on the values of self.step, self.span, and self.unitSystem.
277+
278+
"""
279+
227280
value, prefix = format_units(value, self.step, system=self.unitSystem)
228281
span, spanPrefix = format_units(self.span, self.step, system=self.unitSystem)
229282
if prefix:
@@ -246,11 +299,17 @@ def makeLabel(self, value):
246299

247300

248301
class _LinearAxisTics(_AxisTics):
302+
"""Axis ticmarks with uniform spacing."""
303+
249304
def __init__(self, minValue, maxValue, unitSystem=None):
250305
_AxisTics.__init__(self, minValue, maxValue, unitSystem=unitSystem)
251306
self.step = None
307+
self.span = None
308+
self.binary = None
252309

253310
def setStep(self, step):
311+
"""Set the size of steps between ticmarks."""
312+
254313
self.step = self.checkFinite(float(step), 'axis step')
255314

256315
def generateSteps(self, minStep):
@@ -279,7 +338,7 @@ def computeSlop(self, step, divisor):
279338
"""Compute the slop that would result from step and divisor.
280339
281340
Return the slop, or None if this combination can't cover the full
282-
range.
341+
range. See chooseStep() for the definition of "slop".
283342
284343
"""
285344

@@ -419,6 +478,8 @@ def __init__(self, minValue, maxValue, unitSystem=None, base=10.0):
419478
if base <= 1.0:
420479
raise GraphError('Logarithmic base must be greater than one')
421480
self.base = self.checkFinite(base, 'log base')
481+
self.step = None
482+
self.span = None
422483

423484
def setStep(self, step):
424485
# step is ignored for Logarithmic tics:
@@ -1780,7 +1841,7 @@ def toSeconds(t):
17801841

17811842

17821843
def safeArgs(args):
1783-
"""Iterate over valid, finite values an in iterable.
1844+
"""Iterate over valid, finite values in an iterable.
17841845
17851846
Skip any items that are None, NaN, or infinite.
17861847
"""
@@ -1862,6 +1923,9 @@ def format_units(v, step=None, system="si"):
18621923
http://en.wikipedia.org/wiki/Binary_prefix
18631924
"""
18641925

1926+
if v is None:
1927+
return v, ""
1928+
18651929
if step is None:
18661930
condition = lambda size: abs(v) >= size
18671931
else:
@@ -1880,6 +1944,11 @@ def format_units(v, step=None, system="si"):
18801944

18811945

18821946
def find_x_times(start_dt, unit, step):
1947+
if not isinstance(start_dt, datetime):
1948+
raise ValueError("Invalid start_dt: %s" % start_dt)
1949+
if not isinstance(step, int) or not step > 0:
1950+
raise ValueError("Invalid step value: %s" % step)
1951+
18831952
if unit == SEC:
18841953
dt = start_dt.replace(second=start_dt.second - (start_dt.second % step))
18851954
x_delta = timedelta(seconds=step)

0 commit comments

Comments
 (0)