pygdchart2alpha2 0040755 0001750 0001750 00000000000 07774433232 0012635 5 ustar 00aldo aldo pygdchart2alpha2/CVS 0040755 0001750 0001750 00000000000 07774433231 0013267 5 ustar 00aldo aldo pygdchart2alpha2/CVS/Root 0100644 0001750 0001750 00000000031 07774433231 0014203 0 ustar 00aldo aldo aldo@ryoku:/home/cvs/cvs
pygdchart2alpha2/CVS/Repository 0100644 0001750 0001750 00000000012 07774433231 0015436 0 ustar 00aldo aldo pygdchart
pygdchart2alpha2/CVS/Entries 0100644 0001750 0001750 00000000556 07774433231 0014705 0 ustar 00aldo aldo /CHANGELOG/1.1.1.1/Tue Oct 14 12:46:28 2003//
/INSTALL/1.1.1.1/Tue Oct 14 12:46:28 2003//
/README/1.1.1.1/Tue Oct 14 12:46:28 2003//
/TODO/1.1.1.1/Tue Oct 14 12:46:28 2003//
/_gdchartc.c/1.1.1.1/Tue Oct 14 12:46:28 2003//
/gdchart.py/1.1.1.1/Tue Oct 14 12:46:29 2003//
/lint/1.1.1.1/Tue Oct 14 12:46:29 2003//
/setup.py/1.1.1.1/Tue Oct 14 12:46:29 2003//
D/test////
pygdchart2alpha2/test 0040755 0001750 0001750 00000000000 07774433232 0013614 5 ustar 00aldo aldo pygdchart2alpha2/test/CVS 0040755 0001750 0001750 00000000000 07774433231 0014246 5 ustar 00aldo aldo pygdchart2alpha2/test/CVS/Root 0100644 0001750 0001750 00000000031 07774433231 0015162 0 ustar 00aldo aldo aldo@ryoku:/home/cvs/cvs
pygdchart2alpha2/test/CVS/Repository 0100644 0001750 0001750 00000000017 07774433231 0016422 0 ustar 00aldo aldo pygdchart/test
pygdchart2alpha2/test/CVS/Entries 0100644 0001750 0001750 00000000245 07774433231 0015657 0 ustar 00aldo aldo /README/1.1.1.1/Tue Oct 14 12:46:29 2003//
/test_gdchart.py/1.1.1.1/Tue Oct 14 12:46:29 2003//
/test_gdchartc.py/1.1.1.1/Tue Oct 14 12:46:29 2003//
D/testgraphs////
pygdchart2alpha2/test/testgraphs 0040755 0001750 0001750 00000000000 07774433232 0016000 5 ustar 00aldo aldo pygdchart2alpha2/test/testgraphs/CVS 0040755 0001750 0001750 00000000000 07774433231 0016432 5 ustar 00aldo aldo pygdchart2alpha2/test/testgraphs/CVS/Root 0100644 0001750 0001750 00000000031 07774433231 0017346 0 ustar 00aldo aldo aldo@ryoku:/home/cvs/cvs
pygdchart2alpha2/test/testgraphs/CVS/Repository 0100644 0001750 0001750 00000000032 07774433231 0020603 0 ustar 00aldo aldo pygdchart/test/testgraphs
pygdchart2alpha2/test/testgraphs/CVS/Entries 0100644 0001750 0001750 00000000054 07774433231 0020041 0 ustar 00aldo aldo /error/1.1.1.1/Tue Oct 14 12:46:29 2003//
D
pygdchart2alpha2/test/testgraphs/colors 0040755 0001750 0001750 00000000000 07774433231 0017300 5 ustar 00aldo aldo pygdchart2alpha2/test/testgraphs/fonts 0040755 0001750 0001750 00000000000 07774433232 0017131 5 ustar 00aldo aldo pygdchart2alpha2/test/testgraphs/error 0100644 0001750 0001750 00000000000 07774433232 0017116 0 ustar 00aldo aldo pygdchart2alpha2/test/README 0100644 0001750 0001750 00000000513 07774433232 0014547 0 ustar 00aldo aldo The unit tests in this directory were written to be run by PyLid:
http://www.nullcube.com/software/pylid
That said, PyLid is built on the standard Python unit-testing framework, so it
should not be hard to run the tests without it. After running the tests, check
the testgraphs directory to make sure everything ran OK.
pygdchart2alpha2/test/test_gdchart.py 0100644 0001750 0001750 00000062656 07774433232 0016734 0 ustar 00aldo aldo import unittest, os, shutil
import gdchart
class uUtilityFunctions(unittest.TestCase):
def test_uniformLength(self):
self.failUnlessEqual(gdchart._uniformLength(*([1, 2], [1, 2])), 2)
self.failUnlessEqual(gdchart._uniformLength(*([1, 2],)), 2)
self.failUnlessEqual(gdchart._uniformLength(*([1], [1, 2])), -1)
def test_flattenList(self):
expected = [1, 2, 3, 4]
self.failUnless(gdchart._flattenList(*([1, 2], [3, 4])) == expected)
self.failUnless(gdchart._flattenList(*([1, 2, 3], [4])) == expected)
self.failUnless(gdchart._flattenList(*([1, 2, 3, 4],)) == expected)
self.failUnless(gdchart._flattenList(*([],)) == [])
class uRGB(unittest.TestCase):
def test_int(self):
rgb = gdchart.RGB(0,0,0)
self.failUnlessEqual(repr(rgb), "0x0")
rgb.r = 0xFF
self.failUnlessEqual(repr(rgb), "0xff0000")
rgb.g = 0xFF
self.failUnlessEqual(repr(rgb), "0xffff00")
rgb.b = 0xFF
self.failUnlessEqual(repr(rgb), "0xffffff")
def test_err(self):
self.failUnlessRaises(ValueError, gdchart.RGB, 0, 0, 257)
self.failUnlessRaises(ValueError, gdchart.RGB, 0, 257, 0)
self.failUnlessRaises(ValueError, gdchart.RGB, 257, 0, 0)
def test_rgbFactory(self):
gdchart.rgbFactory("black")
class uChartBase(unittest.TestCase):
def setUp(self):
# We use the graph class to test the ChartBase functionality.
self.g = gdchart.GraphBase()
def test_setOption_err(self):
self.failUnlessRaises(ValueError, self.g.setOption, "foo", 2)
def test_setOption(self):
self.g.setOption("hard_graphwidth", 12)
def test_getOption(self):
self.failUnless(self.g.getOption("hard_graphwidth") == 0)
self.g.setOption("hard_graphwidth", 10)
self.failUnless(self.g.getOption("hard_graphwidth") == 10)
self.failUnlessRaises(ValueError, self.g.getOption, "foo")
def test_getAllOptions(self):
x = self.g.getAllOptions()["hard_graphwidth"]
self.g.setOption("hard_graphwidth", 99)
self.failUnlessEqual(self.g.getAllOptions()["hard_graphwidth"], 99)
def test_noattr(self):
try:
self.g.asfdasdf
except AttributeError:
pass
else:
fail()
def test_noattrSet(self):
try:
self.g.asfdasdf = "foo"
except AttributeError:
pass
else:
fail()
class uOptions(unittest.TestCase):
# FIXME: Generalise this to test ALL options for both types
def setUp(self):
self.graph = gdchart.GraphBase()
self.pie = gdchart.Pie()
def _testOption(self, opType, testValue, chartType):
"""
First we zero out all options. Then we retrieve the options, and
check that they are zero. Then we restore the defaults, retrieve
the options again, and check that the value agrees with the cached
default dictionary.
"""
# Set all options to testValue
for i in chartType._defaultOptions:
# Ignore constrained values
if not chartType._lookupOptions.has_key(i) and not chartType._maskOptions.has_key(i):
o = chartType._defaultOptions[i]
if o[1] == opType:
chartType.setOption(i, testValue)
chartType._actualiseOptions()
# Retrieve the options, and check that they are all testValue
zeros = gdchart._gdchartc.getOptions(chartType._myType)
for i in zeros:
o = zeros[i]
if o[1] == opType:
# Ignore constrained values
if not chartType._lookupOptions.has_key(i) and not chartType._maskOptions.has_key(i):
self.failUnlessEqual(o[2], testValue)
# Now restore the defaults
chartType.restoreDefaultOptions()
chartType._actualiseOptions()
# Retrieve the options, and check that they are all set to the defaults
defaults = gdchart._gdchartc.getOptions(chartType._myType)
for i in defaults:
# Ignore constrained values
if not chartType._lookupOptions.has_key(i) and not chartType._maskOptions.has_key(i):
self.failUnlessEqual(defaults[i], chartType._defaultOptions[i])
def test_options(self):
self._testOption(gdchart._gdchartc.OPT_INT, 0, self.graph)
self._testOption(gdchart._gdchartc.OPT_COLOR, 0, self.graph)
self._testOption(gdchart._gdchartc.OPT_SHORT, 0, self.graph)
self._testOption(gdchart._gdchartc.OPT_USHORT, 0, self.pie)
self._testOption(gdchart._gdchartc.OPT_UCHAR, 0, self.graph)
self._testOption(gdchart._gdchartc.OPT_BOOL, 0, self.graph)
self._testOption(gdchart._gdchartc.OPT_FONTSIZE, 0, self.graph)
self._testOption(gdchart._gdchartc.OPT_LONG, 0, self.graph)
self._testOption(gdchart._gdchartc.OPT_FLOAT, 0.0, self.graph)
self._testOption(gdchart._gdchartc.OPT_STRING, "foo", self.graph)
self._testOption(gdchart._gdchartc.OPT_INT_A, range(500), self.pie)
self._testOption(gdchart._gdchartc.OPT_COLOR_A, range(500), self.pie)
self._testOption(gdchart._gdchartc.OPT_BOOL_A, [1, 0, 1]*100, self.pie)
def test_optionsColor(self):
self.graph.bg_color = "black"
self.failUnlessEqual(self.graph.bg_color, 0)
def test_optionsColorA(self):
self.graph.ext_color = ["black", "black", "black"]
self.failUnlessEqual(self.graph.ext_color, [0, 0, 0])
def test_maskOptions(self):
self.graph.setOption("border", ("TOP", "X"))
self.failUnlessRaises(gdchart.GDChartError, self.graph.setOption, "border", ("TOP", "foo"))
def test_lookupOptions(self):
self.graph.setOption("image_type", "GIF")
self.failUnlessRaises(gdchart.GDChartError, self.graph.setOption, "image_type", "foo")
def test_getOptions(self):
self.graph.setOption("border", ("TOP", "X"))
ret = self.graph.getOption("border")
ret.sort()
self.failUnlessEqual(ret, ["TOP", "X"])
ret = self.graph.border
ret.sort()
self.failUnlessEqual(ret, ["TOP", "X"])
self.graph.setOption("image_type", "GIF")
self.failUnlessEqual(self.graph.getOption("image_type"), "GIF")
def test_getOptions_dimensions(self):
self.graph.width
self.graph.height
def test_getAllOptions(self):
self.graph.setOption("border", ("TOP", "X"))
self.graph.setOption("image_type", "GIF")
all = self.graph.getAllOptions()
border = all["border"]
border.sort()
self.failUnlessEqual(border, ["TOP", "X"])
self.failUnlessEqual(all["image_type"], "GIF")
def test_typeErr(self):
self.failUnlessRaises(gdchart.GDChartError, self.graph.setOption, "threeD_depth", "foo")
self.failUnlessRaises(gdchart.GDChartError, self.graph.setOption, "annotation_font_size", "foo")
self.failUnlessRaises(gdchart.GDChartError, self.graph.setOption, "border", "foo")
self.failUnlessRaises(gdchart.GDChartError, self.graph.setOption, "bg_color", "foo")
self.failUnlessRaises(gdchart.GDChartError, self.graph.setOption, "xlabel_spacing", "foo")
self.failUnlessRaises(gdchart.GDChartError, self.pie.setOption, "perspective", "foo")
self.failUnlessRaises(gdchart.GDChartError, self.graph.setOption, "bar_width", "foo")
self.failUnlessRaises(gdchart.GDChartError, self.graph.setOption, "bar_width", 101)
self.graph.setOption("bar_width", 100)
self.failUnlessRaises(gdchart.GDChartError, self.graph.setOption, "threeD_angle", "foo")
self.failUnlessRaises(gdchart.GDChartError, self.pie.setOption, "other_threshold", "foo")
self.failUnlessRaises(gdchart.GDChartError, self.pie.setOption, "explode", [1, 2, "a"])
class uSimpleBase(unittest.TestCase):
def setUp(self):
self.sb = gdchart.SimpleBase()
def test_getSimpleData(self):
data = [(1, 2), (3, 4), (5, 6)]
len, lst = self.sb._getSimpleData(*data)
self.failUnlessEqual(len, 2)
self.failUnlessEqual(lst, [1, 2, 3, 4, 5, 6])
def test_getSimpleDataErr(self):
data = [(1,), (3, 4), (5, 6)]
self.failUnlessRaises(gdchart.GDChartError, self.sb._getSimpleData, *data)
class uMultisetBase(unittest.TestCase):
def setUp(self):
self.fb = gdchart.FloatingBarBase()
def test_getMultisetData(self):
data = [
[ (1, 2, 3), (4, 5, 6)],
[ (7, 8, 9), (10, 11, 12)]
]
len, lst = self.fb._getMultisetData(2, *data)
self.failUnlessEqual(len, 3)
self.failUnlessEqual(lst, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
data = [
[ (1, 2, 3), (4, 5, 6), (7, 8, 9)],
[ (10, 11, 12), (13, 14, 15), (16, 17, 18)]
]
len, lst = self.fb._getMultisetData(3, *data)
self.failUnlessEqual(len, 3)
self.failUnlessEqual(lst, range(1, 19))
def test_getMultisetDataErr(self):
data = [
[ (1, 2, 3), (4, 5, 6)],
[ (7, 8, 9), (11, 12)]
]
self.failUnlessRaises(gdchart.GDChartError, self.fb._getMultisetData, 2, *data)
data = [
[ (1, 2, 3), (4, 5, 6)],
[ (7, 8, 9)]
]
self.failUnlessRaises(gdchart.GDChartError, self.fb._getMultisetData, 2, *data)
data = [
[ (1, 2, 3), (4, 5, 6)],
[ (1, 2, 3), (4, 5, 6)],
[ (7, 8), (11, 12)]
]
self.failUnlessRaises(gdchart.GDChartError, self.fb._getMultisetData, 2, *data)
class uConformanceErrors(unittest.TestCase):
def test_conformance(self):
gd = gdchart.Line()
gd.setData(range(100))
self.failUnlessRaises(gdchart.GDChartError, gd.setLabels, range(10))
gd = gdchart.Line()
gd.setLabels(range(100))
self.failUnlessRaises(gdchart.GDChartError, gd.setData, range(10))
gd = gdchart.LineLineCombo()
gd.setLabels(range(100))
gd.setComboData(range(100))
self.failUnlessRaises(gdchart.GDChartError, gd.setData, range(10))
gd = gdchart.LineLineCombo()
gd.setComboData(range(100))
self.failUnlessRaises(gdchart.GDChartError, gd.setData, range(10))
gd = gdchart.LineLineCombo()
gd.setLabels(range(100))
gd.setData(range(100))
self.failUnlessRaises(gdchart.GDChartError, gd.setComboData, range(10))
gd = gdchart.LineLineCombo()
gd.setLabels(range(100))
self.failUnlessRaises(gdchart.GDChartError, gd.setData, range(10))
gd = gdchart.LineLineCombo()
gd.setLabels(range(100))
gd.setData(range(100))
self.failUnlessRaises(gdchart.GDChartError, gd.setComboData, range(10))
def test_conformance(self):
gd = gdchart.Pie()
gd.setLabels(range(100))
self.failUnlessRaises(gdchart.GDChartError, gd.setData, range(10))
class uComboErrors(unittest.TestCase):
def test_comboerr(self):
gd = gdchart.HLCAreaCombo()
gd.setData(((5, 7, 10), (0, 2, 4), (3, 4, 6)))
gd.setLabels([1, 2, 3])
self.failUnlessRaises(gdchart.GDChartError, gd.draw, os.path.join("error"))
gd = gdchart.LineBarCombo()
gd.setData((5, 7, 10))
gd.setLabels([1, 2, 3])
self.failUnlessRaises(gdchart.GDChartError, gd.draw, os.path.join("error"))
class uPie(unittest.TestCase):
def setUp(self):
self.gp = gdchart.Pie()
def test_empty(self):
self.failUnlessRaises(gdchart.GDChartError, self.gp.draw, "err")
class uPieSuite(unittest.TestCase):
OUTPUT = "testgraphs"
def setUp(self):
try:
os.mkdir(self.OUTPUT)
except OSError:
pass
def test_simple(self):
p = gdchart.Pie()
p.setData(*range(5))
p.setLabels(range(5))
colors = ["red", "green", "blue", "yellow", "orange"]
p.color = colors
p.draw(os.path.join(self.OUTPUT, "pie.png"))
def test_simple3d(self):
p = gdchart.Pie3D()
p.setData(*range(5))
p.setLabels(range(5))
colors = [
gdchart.rgbFactory("red"),
gdchart.rgbFactory("green"),
gdchart.rgbFactory("blue"),
gdchart.rgbFactory("yellow"),
gdchart.rgbFactory("orange"),
]
p.color = colors
p.draw(os.path.join(self.OUTPUT, "pie3d.png"))
def test_explode(self):
p = gdchart.Pie3D()
p.setData(*range(5))
p.setLabels(range(5))
colors = [
gdchart.rgbFactory("red"),
gdchart.rgbFactory("green"),
gdchart.rgbFactory("blue"),
gdchart.rgbFactory("yellow"),
gdchart.rgbFactory("orange"),
]
p.color = colors
p.explode = [0, 0, 0, 20, 80]
p.draw(os.path.join(self.OUTPUT, "explode.png"))
def test_drawtofp(self):
p = gdchart.Pie()
p.setData(*range(5))
p.setLabels(range(5))
colors = ["red", "green", "blue", "yellow", "orange"]
p.color = colors
f = file(os.path.join(self.OUTPUT, "tofile-pie.png"), "w")
p.draw(f)
class uScatter(unittest.TestCase):
def setUp(self):
self.s = gdchart.Scatter(0, 0)
def test_type(self):
try:
self.s.type = "foo"
except ValueError:
pass
else:
self.fail()
self.s.type = "TRIANGLE_DOWN"
self.failUnlessEqual(self.s.type, "TRIANGLE_DOWN")
def test_width(self):
try:
self.s.width = "foo"
except ValueError:
pass
else:
self.fail()
try:
self.s.width = 101
except (ValueError):
pass
else:
self.fail()
self.s.width = 99
self.failUnlessEqual(self.s.width, 99)
def test_setScatter(self):
gd = gdchart.GraphBase()
gd.setLabels(["one", "two", "three"])
scats = []
for i in range(10):
s = gdchart.Scatter(0, 0)
s.point = i
scats.append(s)
self.failUnlessRaises(ValueError, gd.setScatter, scats)
class uAnnotate(unittest.TestCase):
def setUp(self):
self.s = gdchart.GraphBase()
def test_datalen(self):
self.s._datalen = 5
self.failUnlessRaises(ValueError, self.s.annotate, 10)
self.s._datalen = None
self.s._labels = [1, 2, 3]
self.failUnlessRaises(ValueError, self.s.annotate, 10)
def test_label(self):
self.s._labels = ["one", "two", "three"]
self.failUnlessRaises(ValueError, self.s.annotate, 10)
def test_label(self):
self.failUnlessRaises(ValueError, self.s.annotate, 10, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
def test_color(self):
self.failUnlessRaises(gdchart.GDChartError, self.s.annotate, 10, color="foo")
def test_clear(self):
self.s.annotate(10, "aaaaaaaaa", 1)
self.s.clearAnnotation()
self.failIf(self.s._annotation)
class uGraphSuite(unittest.TestCase):
OUTPUT = "testgraphs"
def setUp(self):
try:
os.mkdir(self.OUTPUT)
except OSError:
pass
def test_size(self):
gd = gdchart.Line()
gd.setData(range(100))
gd.setLabels(range(100))
gd.draw(os.path.join(self.OUTPUT, "sizetest-default.png"))
gd = gdchart.Line()
gd.setData(range(100))
gd.setLabels(range(100))
gd.setOption("width", 0)
self.failUnlessRaises(gdchart.GDChartError, gd.draw, os.path.join(self.OUTPUT, "error"))
gd = gdchart.Line()
gd.setData(range(100))
gd.setLabels(range(100))
gd.setOption("width", 500)
gd.setOption("height", 0)
self.failUnlessRaises(gdchart.GDChartError, gd.draw, os.path.join(self.OUTPUT, "error"))
gd = gdchart.Line()
gd.setOption("width", 60)
gd.setOption("height", 60)
gd.setData(range(2))
gd.setLabels(range(2))
gd.draw(os.path.join(self.OUTPUT, "sizetest-tiny.png"))
gd = gdchart.Line()
gd.setOption("width", 1000)
gd.setOption("height", 1000)
gd.setData(range(100))
gd.setLabels(range(100))
gd.draw(os.path.join(self.OUTPUT, "sizetest-big.png"))
def test_mydata(self):
gd = gdchart.Line()
gd.setData(range(100000))
gd.setLabels(range(100000))
gd.draw(os.path.join(self.OUTPUT, "data-big.png"))
gd = gdchart.Line()
gd.setData(range(1))
gd.setLabels(range(1))
gd.draw(os.path.join(self.OUTPUT, "data-small.png"))
gd = gdchart.Line()
gd.setData([])
gd.setLabels([])
self.failUnlessRaises(gdchart.GDChartError, gd.draw, os.path.join(self.OUTPUT, "error"))
def test_simpleTypes(self):
gd = gdchart.Line()
gd.setData(range(100), range(100, 0, -1))
gd.setLabels(range(100))
gd.draw(os.path.join(self.OUTPUT, "types-Line.png"))
gd = gdchart.Line3D()
gd.setData(range(100), range(100, 0, -1))
gd.setLabels(range(100))
gd.draw(os.path.join(self.OUTPUT, "types-Line3D.png"))
gd = gdchart.Area()
gd.setData(range(100), range(100, 0, -1))
gd.setLabels(range(100))
gd.draw(os.path.join(self.OUTPUT, "types-Area.png"))
gd = gdchart.Area3D()
gd.setData(range(100), range(100, 0, -1))
gd.setLabels(range(100))
gd.draw(os.path.join(self.OUTPUT, "types-Area3D.png"))
gd = gdchart.Bar()
gd.setData((50, 100, 300))
gd.setLabels([50, 100, 300])
gd.draw(os.path.join(self.OUTPUT, "types-Bar.png"))
gd = gdchart.Bar3D()
gd.setData((50, 100, 300))
gd.setLabels([50, 100, 300])
gd.draw(os.path.join(self.OUTPUT, "types-Bar.png"))
def test_floatingBarTypes(self):
gd = gdchart.FloatingBar()
gd.setData(((1, 2, 3), (5, 6, 7)))
gd.setLabels([1, 2, 3])
gd.draw(os.path.join(self.OUTPUT, "types-floatingBar.png"))
gd = gdchart.FloatingBar3D()
gd.setData(((1, 2, 3), (5, 6, 7)))
gd.setLabels([1, 2, 3])
gd.draw(os.path.join(self.OUTPUT, "types-floatingBar3D.png"))
def test_HLCTypes(self):
gd = gdchart.HLC()
gd.setData(((5, 7, 10), (0, 2, 4), (3, 4, 6)))
gd.setLabels([1, 2, 3])
gd.draw(os.path.join(self.OUTPUT, "types-HLC.png"))
gd = gdchart.HLC3D()
gd.setData(((5, 7, 10), (0, 2, 4), (3, 4, 6)))
gd.setLabels([1, 2, 3])
gd.draw(os.path.join(self.OUTPUT, "types-HLC3D.png"))
def test_HLCComboTypes(self):
gd = gdchart.HLCAreaCombo()
gd.setData(((5, 7, 10), (0, 2, 4), (3, 4, 6)))
gd.setLabels([1, 2, 3])
gd.setComboData((5, 7, 10))
gd.draw(os.path.join(self.OUTPUT, "types-HLCAreaCombo.png"))
gd = gdchart.HLCAreaCombo3D()
gd.setData(((5, 7, 10), (0, 2, 4), (3, 4, 6)))
gd.setLabels([1, 2, 3])
gd.setComboData((5, 7, 10))
gd.draw(os.path.join(self.OUTPUT, "types-HLCAreaCombo3D.png"))
gd = gdchart.HLCBarCombo()
gd.setData(((5, 7, 10), (0, 2, 4), (3, 4, 6)))
gd.setLabels([1, 2, 3])
gd.setComboData((5, 7, 10))
gd.draw(os.path.join(self.OUTPUT, "types-HLCBarCombo.png"))
gd = gdchart.HLCBarCombo3D()
gd.setData(((5, 7, 10), (0, 2, 4), (3, 4, 6)))
gd.setLabels([1, 2, 3])
gd.setComboData((5, 7, 10))
gd.draw(os.path.join(self.OUTPUT, "types-HLCBarCombo3D.png"))
def test_SimpleComboTypes(self):
gd = gdchart.LineBarCombo()
gd.setData(range(5))
gd.setComboData(range(5, 0, -1))
gd.setLabels(range(5))
gd.draw(os.path.join(self.OUTPUT, "types-LineBarCombo.png"))
gd = gdchart.LineAreaCombo()
gd.setData(range(5))
gd.setComboData(range(5, 0, -1))
gd.setLabels(range(5))
gd.draw(os.path.join(self.OUTPUT, "types-LineAreaCombo.png"))
gd = gdchart.LineLineCombo()
gd.setData(range(5))
gd.setComboData(range(5, 0, -1))
gd.setLabels(range(5))
gd.draw(os.path.join(self.OUTPUT, "types-LineLineCombo.png"))
gd = gdchart.LineBarCombo3D()
gd.setData(range(5))
gd.setComboData(range(5, 0, -1))
gd.setLabels(range(5))
gd.draw(os.path.join(self.OUTPUT, "types-LineBarCombo3D.png"))
gd = gdchart.LineAreaCombo3D()
gd.setData(range(5))
gd.setComboData(range(5, 0, -1))
gd.setLabels(range(5))
gd.draw(os.path.join(self.OUTPUT, "types-LineAreaCombo3D.png"))
gd = gdchart.LineLineCombo3D()
gd.setData(range(5))
gd.setComboData(range(5, 0, -1))
gd.setLabels(range(5))
gd.draw(os.path.join(self.OUTPUT, "types-LineLineCombo3D.png"))
def test_colors(self):
gd = gdchart.Line()
colorPath = os.path.join(self.OUTPUT, "colors")
try:
os.mkdir(colorPath)
except OSError:
pass
gd.setOption("width", 100)
gd.setOption("height", 100)
gd.setData(range(10))
gd.setLabels(range(10))
x = gdchart.RGB()
for r in range(0, 256, 64):
x.r = r
for g in range(0, 256, 64):
x.g = g
for b in range(0, 256, 64):
x.b = b
gd.setOption("bg_color", x)
gd.draw(os.path.join(colorPath, "color-%s.png"%int(x)))
def test_scolors(self):
gd = gdchart.Bar()
gd.setData(range(5), range(2, 7), range(4, 9))
colors = [
gdchart.rgbFactory("red"),
gdchart.rgbFactory("blue"),
gdchart.rgbFactory("green"),
]
gd.set_color = colors
gd.draw(os.path.join(self.OUTPUT, "set_color.png"))
def test_xlabel_ctl(self):
gd = gdchart.Bar()
gd.setData(range(5))
gd.setLabels(range(5))
gd.xlabel_ctl = [1, 0, 1, 0, 1]
gd.draw(os.path.join(self.OUTPUT, "xlabel_ctl.png"))
def test_options(self):
gd = gdchart.Line()
gd.setData(range(100))
gd.setLabels(range(100))
gd.setOption("xtitle", "xtitle")
gd.setOption("ytitle", "ytitle")
gd.setOption("title", "Main Title")
gd.draw(os.path.join(self.OUTPUT, "titles.png"))
def test_maskoptions(self):
gd = gdchart.Line()
gd.setData(range(100))
gd.setLabels(range(100))
gd.setOption("border", ("TOP", "X"))
gd.draw(os.path.join(self.OUTPUT, "borders.png"))
def test_fonts(self):
fontPath = os.path.join(self.OUTPUT, "fonts")
try:
os.mkdir(fontPath)
except OSError:
pass
gd = gdchart.Line()
gd.setData(range(100))
gd.setLabels(range(100))
gd.setOption("xtitle", "xtitle")
gd.setOption("ytitle", "ytitle")
gd.setOption("ytitle_font_size", "TINY")
gd.setOption("xtitle_font_size", "TINY")
gd.draw(os.path.join(fontPath, "TINY.png"))
gd = gdchart.Line()
gd.setData(range(100))
gd.setLabels(range(100))
gd.setOption("xtitle", "xtitle")
gd.setOption("ytitle", "ytitle")
gd.setOption("ytitle_font_size", "SMALL")
gd.setOption("xtitle_font_size", "SMALL")
gd.draw(os.path.join(fontPath, "SMALL.png"))
gd = gdchart.Line()
gd.setData(range(100))
gd.setLabels(range(100))
gd.setOption("xtitle", "xtitle")
gd.setOption("ytitle", "ytitle")
gd.setOption("ytitle_font_size", "MEDBOLD")
gd.setOption("xtitle_font_size", "MEDBOLD")
gd.draw(os.path.join(fontPath, "MEDBOLD.png"))
gd = gdchart.Line()
gd.setData(range(100))
gd.setLabels(range(100))
gd.setOption("xtitle", "xtitle")
gd.setOption("ytitle", "ytitle")
gd.setOption("ytitle_font_size", "LARGE")
gd.setOption("xtitle_font_size", "LARGE")
gd.draw(os.path.join(fontPath, "LARGE.png"))
gd = gdchart.Line()
gd.setData(range(100))
gd.setLabels(range(100))
gd.setOption("xtitle", "xtitle")
gd.setOption("ytitle", "ytitle")
gd.setOption("ytitle_font_size", "GIANT")
gd.setOption("xtitle_font_size", "GIANT")
gd.draw(os.path.join(fontPath, "GIANT.png"))
def test_scatter(self):
gd = gdchart.Line()
gd.setData(range(100))
gd.setLabels(range(100))
gd.grid = "NONE"
scats = [
gdchart.Scatter(10, 30, type="CIRCLE", width=100, color=gdchart.rgbFactory("red")),
gdchart.Scatter(30, 50, width=100, color=gdchart.rgbFactory("blue")),
]
gd.setScatter(scats)
gd.draw(os.path.join(self.OUTPUT, "scatter.png"))
def test_annotate(self):
gd = gdchart.Line()
gd.setData(range(100))
gd.setLabels(range(100))
gd.annotate(5, "foo")
gd.draw(os.path.join(self.OUTPUT, "annotate.png"))
def test_missingvalues(self):
gd = gdchart.Bar()
gd.setData([1, 2, None, 3, None, 5])
gd.draw(os.path.join(self.OUTPUT, "missingvalues.png"))
def test_tofile(self):
gd = gdchart.Line()
gd.setData(range(100), range(100, 0, -1))
gd.setLabels(range(100))
f = file(os.path.join(self.OUTPUT, "tofile-graph.png"), "w")
gd.draw(f)
pygdchart2alpha2/test/test_gdchartc.py 0100644 0001750 0001750 00000011460 07774433232 0017062 0 ustar 00aldo aldo import unittest, os, os.path, shutil
import _gdchartc
class uPyGDChart(unittest.TestCase):
SCRATCH = "scratch"
def setUp(self):
try:
os.mkdir(self.SCRATCH)
except OSError:
pass
def tearDown(self):
shutil.rmtree(self.SCRATCH)
def test_constants(self):
# Check a random constant...
self.failUnless(hasattr(_gdchartc, "GDC_LINE"))
# Check the single float constant
self.failUnless(hasattr(_gdchartc, "GDC_INTERP_VALUE"))
def test_options(self):
self.failUnless(_gdchartc.getOptions(_gdchartc.GRAPH))
self.failUnless(_gdchartc.getOptions(_gdchartc.PIE))
def test_out_graph_nonfile(self):
try:
_gdchartc.out_graph(1, 2, 1, 1, 1, ["one", "two"], 1, [1, 2], [1, 2])
except TypeError:
pass
else:
self.fail()
def test_out_graph_nonlist(self):
f = file(os.path.join(self.SCRATCH, "outgraph"), "w")
self.failUnlessRaises(TypeError, _gdchartc.out_graph, 1, 2, f, 1, 1, 2, 1, [1, 2], [1, 2])
self.failUnlessRaises(TypeError, _gdchartc.out_graph, 1, 2, f, 1, 1, [1, 2], 1, 2, [1, 2])
self.failUnlessRaises(TypeError, _gdchartc.out_graph, 1, 2, f, 1, 1, [1, 2], 1, [1, 2], 2)
_gdchartc.out_graph(100, 100, f, 1, 1, [1, 2], 1, [1, 2], [1, 2])
def test_out_graph_notfloats(self):
f = file(os.path.join(self.SCRATCH, "outgraph"), "w")
self.failUnlessRaises(TypeError, _gdchartc.out_graph, 1, 2, f, 1, 1, [1, 2], 1, ["one", "two"], [1, 2])
def test_out_graph_nulls(self):
f = file(os.path.join(self.SCRATCH, "outgraph"), "w")
_gdchartc.out_graph(100, 100, f, 1, 1, None, 1, [1, 2], [1, 2])
_gdchartc.out_graph(100, 100, f, 1, 1, None, 1, [1, 2], None)
_gdchartc.out_graph(100, 100, f, 1, 1, None, 1, [1, 2], [1, 2, None, 3, None])
self.failUnlessRaises(TypeError, _gdchartc.out_graph, 1, 2, f, 1, 1, None, 1, None, None)
def test_out_graph_succeed(self):
f = file(os.path.join(self.SCRATCH, "outgraph"), "w")
_gdchartc.out_graph(100, 100, f, 1, 1, ["one", "two"], 1, [1, 2], [1, 2])
class uPyGDChartOptions(unittest.TestCase):
def _testOption(self, setFunction, option, testvalue, chartType=_gdchartc.GRAPH):
opts = _gdchartc.getOptions(chartType)
val = opts[option][2]
setFunction(chartType, opts[option][0], testvalue)
opts = _gdchartc.getOptions(chartType)
self.failUnlessEqual(opts[option][2], testvalue)
# Now we restore the value...
setFunction(chartType, opts[option][0], val)
def test_setoptions(self):
self._testOption(_gdchartc.setOption, "grid", 99) # INT
self._testOption(_gdchartc.setOption, "xlabel_spacing", 99) # SHORT
self._testOption(_gdchartc.setOption, "perspective", 99, _gdchartc.PIE) # USHORT
self._testOption(_gdchartc.setOption, "threeD_angle", 20) # UCHAR
self._testOption(_gdchartc.setOption, "bg_transparent", 20) # BOOL
self._testOption(_gdchartc.setOption, "annotation_font_size", 20) # FONT
self._testOption(_gdchartc.setOption, "bar_width", 20) # PERCENT
self._testOption(_gdchartc.setOption, "other_threshold", 20, _gdchartc.PIE) # CHAR
self._testOption(_gdchartc.setOption, "bg_color", 20) # LONG
self._testOption(_gdchartc.setOption, "threeD_depth", 20) # FLOAT
self._testOption(_gdchartc.setOption, "bg_image", "foinklebar") # STRING
self._testOption(_gdchartc.setOption, "explode", range(500), _gdchartc.PIE) # INT_A
bools = [1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0]
self._testOption(_gdchartc.setOption, "xlabel_ctl", bools) # BOOL_A
self._testOption(_gdchartc.setOption, "ext_color", range(500)) # COLORL_A
class Scat:
point = 0
val = 0
width = 0
color = 0
_type = 0
class uScatter(unittest.TestCase):
def test_scatter(self):
self.failUnlessRaises(TypeError, _gdchartc.setScatter, 1)
s = Scat()
s.point = "foo"
self.failUnlessRaises(TypeError, _gdchartc.setScatter, [s, Scat(), Scat(), Scat()])
_gdchartc.setScatter([Scat(), Scat(), Scat(), Scat()])
_gdchartc.setScatter(None)
class Anno:
point = 0
color = 0
note = "foo"
class uAnnotate(unittest.TestCase):
def test_anno(self):
_gdchartc.annotate(None)
a = Anno()
_gdchartc.annotate(a)
_gdchartc.annotate(None)
_gdchartc.annotate(None)
try:
_gdchartc.annotate(1)
except TypeError:
pass
_gdchartc.annotate(None)
pygdchart2alpha2/lint 0100755 0001750 0001750 00000000425 07774433232 0013606 0 ustar 00aldo aldo #!/bin/sh
# This is only of use to developers of PyGDChart. We used the version of lint
# distributed with OpenBSD - you may have to modify it to work with your local
# version.
lint -vubh -I../gdchart0.11.4dev -I/usr/local/include/python2.2 -DHAVE_LIBFREETYPE _gdchartc.c
pygdchart2alpha2/gdchart.py 0100644 0001750 0001750 00000067546 07774433232 0014721 0 ustar 00aldo aldo # PyGDChart
#
# Copyright (c) 2003, Nullcube Pty Ltd
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Nullcube nor the names of its contributors may be used to
# endorse or promote products derived from this software without specific prior
# written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
PyGDChart is an interface to the gdchart graphing library.
"""
import types
import _gdchartc
class GDChartError(Exception): pass
class _Bucket:
"""
An internal PyGDChart general dataholder class.
"""
def __init__(self, **kwargs):
self.__dict__ = kwargs
def _uniformLength(*lst):
"""
Takes a list of lists, and tests wether all lists have the same length.
Returns a 0 if lengths differ, 1 if not.
This is an internal PyGDChart utility function.
"""
baselen = len(lst[0])
for l in lst:
if len(l) != baselen:
return -1
return baselen
def _flattenList(*lst):
"""
Takes a set of lists, and flattens them by appending them all
together.
This is an internal PyGDChart utility function.
"""
flat = []
for i in lst:
flat.extend(i)
return flat
class RGB:
"""
A simple class for representing RGB colors.
"""
def __init__(self, r=0, g=0, b=0):
self.r, self.g, self.b = r, g, b
self._sanity()
def _sanity(self):
checks = [0 <= i <= 256 for i in (self.r, self.g, self.b)]
if 0 in checks:
raise ValueError("All RGB values should be 0 <= val <= 100")
def __int__(self):
self._sanity()
intval = self.r*(256**2)
intval += self.g*(256)
intval += self.b
return intval
def __hex__(self):
return hex(int(self))
def __repr__(self):
return hex(self)
def rgbFactory(color):
"""
Manufacture an RGB object by colour name. Included colours are:
black, white, blue, green, yellow, red, orange
"""
# This should be re-written using a dictionary.
if color == "black":
return RGB(0,0,0)
elif color == "white":
return RGB(255,255,255)
elif color == "blue":
return RGB(50,50,204)
elif color == "green":
return RGB(37,180,21)
elif color == "yellow":
return RGB(255,255,21)
elif color == "red":
return RGB(255,0,0)
elif color == "orange":
return RGB(255,127,0)
raise GDChartError, "No such colour: %s."%color
class ChartBase(object):
"""
Base class of both Pie and Graph chart classes.
"""
_ImageTypes = {
"GIF": _gdchartc.GDC_GIF,
"JPEG": _gdchartc.GDC_JPEG,
"PNG": _gdchartc.GDC_PNG,
"WBMP": _gdchartc.GDC_WBMP
}
_FontSizes = {
"TINY": _gdchartc.GDC_TINY,
"SMALL": _gdchartc.GDC_SMALL,
"MEDBOLD": _gdchartc.GDC_MEDBOLD,
"LARGE": _gdchartc.GDC_LARGE,
"GIANT": _gdchartc.GDC_GIANT
}
_lookupOptions = {}
_maskOptions = {}
def __init__(self):
self.__dict__["_options"] = {}
self.__dict__["_width"] = 500
self.__dict__["_height"] = 500
self.__dict__["_data"] = None
self.__dict__["_labels"] = None
self.__dict__["_datalen"] = None
self.__dict__["_scatterPoints"] = None
def __getattr__(self, attr):
try:
return self.getOption(attr)
except ValueError:
raise AttributeError
def __setattr__(self, attr, val):
try:
return self.setOption(attr, val)
except ValueError:
if self.__dict__.has_key(attr):
self.__dict__[attr] = val
else:
raise AttributeError
def _actualiseOptions(self):
for i in self._defaultOptions.values():
_gdchartc.setOption(self._myType, i[0], i[2])
for k, v in self._options.iteritems():
index = self._defaultOptions[k][0]
_gdchartc.setOption(self._myType, index, v)
_gdchartc.setScatter(self._scatterPoints)
def setOption(self, option, myval):
"""
Set an option. Using this function explicitly is discouraged - it
is equivalent to using explicit attribute assignment, like so:
myclass.foo = val
"""
if self._defaultOptions.has_key(option):
if self._lookupOptions.has_key(option):
# We have to look the value up in our dictionary
if self._lookupOptions[option].has_key(myval):
val = self._lookupOptions[option][myval]
else:
values = ", ".join([k for k in self._lookupOptions[option].keys()])
raise GDChartError("%s must be one of the following: %s"%(option, values))
elif self._maskOptions.has_key(option):
val = 0
for i in myval:
bits = self._maskOptions[option].get(i, None)
if bits is not None:
val |= bits
else:
values = ", ".join([k for k in self._maskOptions[option].keys()])
raise GDChartError("%s must be a list chosen from the following strings: %s"%
(option, values))
else:
# Now we do some standard format checks
type = self._defaultOptions[option][1]
if type == _gdchartc.OPT_FLOAT:
try:
val = float(myval)
except ValueError:
raise GDChartError("%s must be representable as a float."%(option))
elif type in ( _gdchartc.OPT_FONTSIZE,
_gdchartc.OPT_INT,
_gdchartc.OPT_LONG,
_gdchartc.OPT_SHORT,
_gdchartc.OPT_USHORT,
_gdchartc.OPT_UCHAR,
_gdchartc.OPT_CHAR):
try:
val = int(myval)
except ValueError:
raise GDChartError("%s must be representable as an int."%(option))
elif type == _gdchartc.OPT_COLOR:
try:
rgb = rgbFactory(myval)
except GDChartError:
try:
val = int(myval)
except ValueError:
raise GDChartError("%s must be representable as an int."%(option))
else:
val = int(rgb)
elif type == _gdchartc.OPT_PERCENT:
try:
val = int(myval)
except ValueError:
raise GDChartError("%s must be representable as an int."%(option))
if not (0 <= val <= 100):
raise GDChartError, "Percentage must be > 0, and < 100"
elif type == _gdchartc.OPT_COLOR_A:
try:
colours = [rgbFactory(i) for i in myval]
except GDChartError:
colours = myval
try:
val = [int(i) for i in colours]
except ValueError:
raise GDChartError("%s must be representable as a list of ints."%(option))
elif type in [_gdchartc.OPT_COLOR_A, _gdchartc.OPT_INT_A, _gdchartc.OPT_BOOL_A]:
try:
val = [int(i) for i in myval]
except ValueError:
raise GDChartError("%s must be representable as a list of ints."%(option))
else:
val = myval
self.__dict__["_options"][option] = val
elif option == "width":
self.__dict__["_width"] = int(myval)
elif option == "height":
self.__dict__["_height"] = int(myval)
else:
raise ValueError, "No such option: %s"%option
def getOption(self, option):
"""
Retrieve an option. Using this function is equivalent to just
referring to an option as a chart-object attribute.
"""
if self._options.has_key(option):
# Now convert it to a value the user will recognise...
val = self._options[option]
if self._lookupOptions.has_key(option):
for k, v in self._lookupOptions[option].items():
if v == val:
return k
else:
raise GDChartError, "Lookup value not known - this should never happen. Please contact software authors."
elif self._maskOptions.has_key(option):
lst = []
for k, v in self._maskOptions[option].items():
if (val&v):
lst.append(k)
return lst
else:
return self._options[option]
elif self._defaultOptions.has_key(option):
return self._defaultOptions[option][2]
elif option == "width":
return self._width
elif option == "height":
return self._height
else:
raise ValueError, "No such option: %s"%option
def getAllOptions(self):
"""
Retrieve a dictionary of all options.
"""
x = {}
for i in self._defaultOptions:
x[i] = self.getOption(i)
x["width"] = self._width
x["height"] = self._height
return x
def restoreDefaultOptions(self):
"""
Restore options to their default values.
"""
self._options = {}
self._scatterPoints = None
def setLabels(self, labels):
"""
Set chart labels. The argument is a single list of strings.
"""
if self._datalen:
if len(labels) != self._datalen:
raise GDChartError, "List of labels must have same length as data."
self._labels = labels
class PieBase(ChartBase):
"""
Base class of all Pie chart classes.
"""
_myType = _gdchartc.PIE
_defaultOptions = _gdchartc.getOptions(_gdchartc.PIE)
_ChartTypes = {
"3D": _gdchartc.GDC_3DPIE,
"2D": _gdchartc.GDC_2DPIE,
}
_PercentPlacement = {
"NONE": _gdchartc.GDCPIE_PCT_NONE,
"ABOVE": _gdchartc.GDCPIE_PCT_ABOVE,
"BELOW": _gdchartc.GDCPIE_PCT_BELOW,
"RIGHT": _gdchartc.GDCPIE_PCT_RIGHT,
"LEFT": _gdchartc.GDCPIE_PCT_LEFT,
}
_lookupOptions = {
"title_size": ChartBase._FontSizes,
"label_size": ChartBase._FontSizes,
"image_type": ChartBase._ImageTypes,
"percent_labels": _PercentPlacement,
}
def __init__(self, *args, **kwargs):
ChartBase.__init__(self, *args, **kwargs)
def _conformanceCheck(self):
if self._labels:
if self._datalen:
if self._datalen != len(self._labels):
raise GDChartError, "Datasets must be of same length as list of labels."
def draw(self, filedef):
"""
Draw a graph to filename.
"""
if not self._datalen:
raise GDChartError, "No data to graph"
if type(filedef) in types.StringTypes:
filedef = open(filedef, "w")
self._actualiseOptions()
try:
_gdchartc.out_pie( self._width,
self._height,
filedef,
self._type,
self._datalen,
self._labels,
self._data,
)
except _gdchartc.PGError, val:
raise GDChartError, val
def setData(self, *data):
"""
Set pie data to be graphed.
mypie.setData(1, 2, 3, 4)
"""
self._datalen = len(data)
self._data = data
self._conformanceCheck()
class Pie(PieBase):
"""
A 2D pie chart.
"""
_type = _gdchartc.GDC_2DPIE
class Pie3D(PieBase):
"""
A 3D pie chart.
"""
_type = _gdchartc.GDC_3DPIE
class Scatter(object):
"""
This class represents a scatter point. You would normally construct an
array of these to pass to the setScatter method of graph classes.
The constructor takes the following arguments:
type - Scatter graph types are:
TRIANGLE_DOWN
TRIANGLE_UP
CIRCLE
point - X-axis co-ordinate
val - Y-axis co-ordinate
width - 0-100%
color - An RGB object, or an integer representing the point colour.
"""
_ScatterTypes = {
"TRIANGLE_DOWN": _gdchartc.GDC_SCATTER_TRIANGLE_DOWN,
"TRIANGLE_UP": _gdchartc.GDC_SCATTER_TRIANGLE_UP,
"CIRCLE": _gdchartc.GDC_SCATTER_CIRCLE,
}
def __init__(self, point, val, type="TRIANGLE_DOWN", width=100, color="white"):
self.type = type
self.point = point
self.val = val
self.width = width
try:
color = rgbFactory(color)
except GDChartError:
pass
try:
self.color = int(color)
except ValueError:
raise GDChartError, "Colour must be representable as an int."
def _setType(self, val):
if not self._ScatterTypes.has_key(val):
values = ", ".join([k for k in self._ScatterTypes.keys()])
raise ValueError("Scatter type must be one of %s"%values)
else:
self._type = self._ScatterTypes[val]
def _getType(self):
for k, v in self._ScatterTypes.items():
if (v == self._type):
return k
else:
raise GDChartError("Unknown type set. This should never happen.")
def _setWidth(self, val):
i = int(val)
if (i < 0) or (i > 100):
raise ValueError("Width must be 0 > width > 100.")
self._width = val
def _getWidth(self):
return self._width
type = property(_getType, _setType)
width = property(_getWidth, _setWidth)
class GraphBase(ChartBase):
"""
Base class for all Graph charts.
"""
_myType = _gdchartc.GRAPH
_defaultOptions = _gdchartc.getOptions(_gdchartc.GRAPH)
_StackTypes = {
"DEPTH": _gdchartc.GDC_STACK_DEPTH,
"SUM": _gdchartc.GDC_STACK_SUM,
"BESIDE": _gdchartc.GDC_STACK_BESIDE,
"LAYER": _gdchartc.GDC_STACK_LAYER,
}
_TickTypes = {
"LABELS": _gdchartc.GDC_TICK_LABELS,
"POINTS": _gdchartc.GDC_TICK_POINTS,
"NONE": _gdchartc.GDC_TICK_NONE,
}
_BorderTypes = {
"NONE": _gdchartc.GDC_BORDER_NONE,
"ALL": _gdchartc.GDC_BORDER_ALL,
"X": _gdchartc.GDC_BORDER_X,
"Y": _gdchartc.GDC_BORDER_Y,
"Y2": _gdchartc.GDC_BORDER_Y2,
"TOP": _gdchartc.GDC_BORDER_TOP,
}
_HilocloseTypes = {
"DIAMOND": _gdchartc.GDC_HLC_DIAMOND,
"CLOSE_CONNECTED": _gdchartc.GDC_HLC_CLOSE_CONNECTED,
"CONNECTING": _gdchartc.GDC_HLC_CONNECTING,
"I_CAP": _gdchartc.GDC_HLC_I_CAP,
}
_lookupOptions = {
"image_type": ChartBase._ImageTypes,
"stack_type": _StackTypes,
"grid": _TickTypes,
"ticks": _TickTypes,
"title_font_size": ChartBase._FontSizes,
"xtitle_font_size": ChartBase._FontSizes,
"ytitle_font_size": ChartBase._FontSizes,
"xaxisfont_size": ChartBase._FontSizes,
"yaxisfont_size": ChartBase._FontSizes,
"annotation_font_size": ChartBase._FontSizes,
}
_maskOptions = {
"hlc_style": _HilocloseTypes,
"border": _BorderTypes,
}
def __init__(self, *args, **kwargs):
ChartBase.__init__(self, *args, **kwargs)
self.__dict__["_numsets"] = None
self.__dict__["_combodata"] = None
self.__dict__["_combodatalen"] = None
self.__dict__["_combonumsets"] = None
self.__dict__["_annotation"] = None
def _conformanceCheck(self):
if self._labels:
if self._datalen:
if self._datalen != len(self._labels):
raise GDChartError, "Datasets must be of same length as list of labels."
if self._combodatalen:
if self._combodatalen != len(self._labels):
raise GDChartError, "Combo datasets must be of same length as list of labels."
if self._datalen:
if self._combodatalen:
if self._datalen != self._combodatalen:
raise GDChartError, "Main and combo datasets must be of same length."
def setScatter(self, scatterpoints):
"""
Set scatter points. This should be a list of Scatter objects.
"""
slen = None
if self._datalen:
slen = self._datalen
elif self._labels:
slen = len(self._labels)
if slen:
for i in scatterpoints:
if i.point > slen or i.point < 0:
raise ValueError("Scatter point value must be > 0 and < numpoints.")
self._scatterPoints = scatterpoints
def clearAnnotation(self):
self._annotation = None
def annotate(self, point=0, note = "", color="white"):
"""
Set an annotation. At the moment the gdchart library is limited to
one annotation per graph.
"""
slen = None
if self._datalen:
slen = self._datalen
elif self._labels:
slen = len(self._labels)
if slen:
if (point>slen) or (point<0):
raise ValueError("Annotation point value must be > 0 and < numpoints.")
if len(note) > _gdchartc.MAX_NOTE_LEN:
raise ValueError("Annotation note length must be < %i."%(_gdchartc.MAX_NOTE_LEN))
try:
intcolor = rgbFactory(color)
except GDChartError:
try:
intcolor = int(color)
except ValueError:
raise GDChartError("color must be representable as an int.")
intcolor = int(intcolor)
b = _Bucket(point=point, note=note, color=intcolor)
self._annotation = b
def draw(self, filedef):
"""
Draw a graph to file.
"""
if not self._datalen:
raise GDChartError, "No data to graph"
if type(filedef) in types.StringTypes:
filedef = open(filedef, "w")
self._actualiseOptions()
_gdchartc.annotate(self._annotation)
try:
_gdchartc.out_graph( self._width,
self._height,
filedef,
self._type,
self._datalen,
self._labels,
self._numsets,
self._data,
self._combodata
)
except _gdchartc.PGError, val:
raise GDChartError, val
#
# Simple data graphs
#
class SimpleBase(GraphBase):
"""
Base class for "Simple" graph types.
"""
def _getSimpleData(self, *data):
"""
Returns the data length, the number of sets and the flattened data
"""
length = _uniformLength(*data)
if length < 0:
raise GDChartError, "All data sets have to be of the same length."
return length, _flattenList(*data)
def setData(self, *data):
"""
Set the data to graph. This method takes a set of lists of data,
that should all be of the same length. I.e.
x.setData([1, 2, 3], [4, 5, 6])
"""
self._numsets = len(data)
self._datalen, self._data = self._getSimpleData(*data)
self._conformanceCheck()
class Line(SimpleBase):
"""
A simple line graph.
"""
_type = _gdchartc.GDC_LINE
class Area(SimpleBase):
"""
A graph with the area under the data filled.
"""
_type = _gdchartc.GDC_AREA
class Bar(SimpleBase):
"""
A classical bar graph.
"""
_type = _gdchartc.GDC_BAR
class Area3D(SimpleBase):
"""
A 3D graph with the area under the line filled.
"""
_type = _gdchartc.GDC_3DAREA
class Line3D(SimpleBase):
"""
A 3D line graph.
"""
_type = _gdchartc.GDC_3DLINE
class Bar3D(SimpleBase):
"""
A 3D bar graph.
"""
_type = _gdchartc.GDC_3DBAR
class MultisetGraphBase(GraphBase):
"""
The base class of all multiset graphs.
"""
def _getMultisetData(self, setlen, *data):
"""
Returns the data length, the number of sets and the flattened data
"""
baseLength = None
allData = []
for i in data:
if len(i) != setlen:
raise GDChartError("Sets of %s data lists required."%setlen)
length = _uniformLength(*i)
if length < 0:
raise GDChartError, "All data sets must be of the same length."
if baseLength:
if length != baseLength:
raise GDChartError, "All data sets must be of the same length."
else:
baseLength = length
allData += _flattenList(*i)
return baseLength, allData
#
# Floating Bars
#
class FloatingBarBase(MultisetGraphBase):
"""
Base class of all floating bar graphs.
"""
def setData(self, *data):
"""
This function takes a set of data tuples, where the first element
of the tuple are all of the lower values, and the second element
the upper values. Eg.
x.setData(((1, 2, 3), (4, 5, 6)), ((3, 6, 9), (6, 9, 12)))
"""
self._numsets = len(data)
self._datalen, self._data = self._getMultisetData(2, *data)
self._conformanceCheck()
class FloatingBar(FloatingBarBase):
"""
A floating bar graph.
"""
_type = _gdchartc.GDC_FLOATINGBAR
class FloatingBar3D(FloatingBarBase):
"""
A 3D floating bar graph.
"""
_type = _gdchartc.GDC_3DFLOATINGBAR
#
# HLC
#
class HLCBase(MultisetGraphBase):
"""
Base class for High-Low-Close graphs.
"""
def setData(self, *data):
"""
Takes a list of data triplets, where the first element is high, the
second, low, and the third close. Eg.
x.setData(((6, 9, 12), (1, 2, 3), (5, 6, 7)))
"""
self._numsets = len(data)
self._datalen, self._data = self._getMultisetData(3, *data)
self._conformanceCheck()
class HLC(HLCBase):
_type = _gdchartc.GDC_HILOCLOSE
class HLC3D(HLCBase):
_type = _gdchartc.GDC_3DHILOCLOSE
#
# HLC Combo Graphs
#
class HLCComboBase(HLCBase, SimpleBase):
"""
Base class for HLC combo data.
"""
def setComboData(self, *data):
"""
Set the combo data for this graph. This function takes a simple
list of data sets.
"""
self._combonumsets = len(data)
self._combodatalen, self._combodata = self._getSimpleData(*data)
self._conformanceCheck()
def draw(self, filename):
"""
Write the graph to file.
"""
if not self._combodata:
raise GDChartError, "Combo data must be specified for a combo graph."
# We should be using super for this...
SimpleBase.draw(self, filename)
class HLCAreaCombo(HLCComboBase):
"""
A High-Low-Close/Area combo graph.
"""
_type = _gdchartc.GDC_COMBO_HLC_AREA
class HLCAreaCombo3D(HLCComboBase):
"""
A 3D High-Low-Close/Area combo graph.
"""
_type = _gdchartc.GDC_3DCOMBO_HLC_AREA
class HLCBarCombo(HLCComboBase):
"""
A High-Low-Close/Bar combo graph.
"""
_type = _gdchartc.GDC_COMBO_HLC_BAR
class HLCBarCombo3D(HLCComboBase):
"""
A 3D High-Low-Close/Bar combo graph.
"""
_type = _gdchartc.GDC_3DCOMBO_HLC_BAR
#
# Simple Combo Graphs
#
class SimpleComboBase(SimpleBase):
"""
Base class for "simple" combo graph types.
"""
def setData(self, *data):
"""
Set the data to graph. This method takes a set of lists of data,
that should all be of the same length. I.e.
x.setData([1, 2, 3], [4, 5, 6])
"""
self._numsets = len(data)
self._datalen, self._data = self._getSimpleData(*data)
self._conformanceCheck()
def setComboData(self, *data):
"""
Set the combo data to graph. This method takes a set of lists of data,
that should all be of the same length. I.e.
x.setComboData([1, 2, 3], [4, 5, 6])
"""
self._combonumsets = len(data)
self._combodatalen, self._combodata = self._getSimpleData(*data)
self._conformanceCheck()
def draw(self, filename):
if not self._combodata:
raise GDChartError, "Combo data must be specified for a combo graph."
# We should be using super for this...
SimpleBase.draw(self, filename)
class LineBarCombo(SimpleComboBase):
"""
A Line/Bar combo graph.
"""
_type = _gdchartc.GDC_COMBO_LINE_BAR
class LineAreaCombo(SimpleComboBase):
"""
A Line/Area combo graph.
"""
_type = _gdchartc.GDC_COMBO_LINE_AREA
class LineLineCombo(SimpleComboBase):
"""
A Line/Line combo graph.
"""
_type = _gdchartc.GDC_COMBO_LINE_LINE
class LineBarCombo3D(SimpleComboBase):
"""
A 3D Line/Bar combo graph.
"""
_type = _gdchartc.GDC_3DCOMBO_LINE_BAR
class LineAreaCombo3D(SimpleComboBase):
"""
A 3D Line/Area combo graph.
"""
_type = _gdchartc.GDC_3DCOMBO_LINE_AREA
class LineLineCombo3D(SimpleComboBase):
"""
A 3D Line/Line combo graph.
"""
_type = _gdchartc.GDC_3DCOMBO_LINE_LINE
pygdchart2alpha2/_gdchartc.c 0100644 0001750 0001750 00000130344 07774433232 0015000 0 ustar 00aldo aldo /*
PyGDChart
Copyright (c) 2003, Nullcube Pty Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Nullcube Pty Ltd nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include
#include
#include
#include "Python.h"
#include "gdchart.h"
#include "gdcpie.h"
#include "gdc.h"
#ifndef HAVE_JPEG
#define GDC_JPEG 1
#endif
static PyObject *PGError;
typedef enum {
GRAPH,
PIE
} charttype;
typedef enum {
OPT_BOOL, /* CHAR */
OPT_BOOL_A, /* CHAR */
OPT_COLOR,
OPT_COLOR_A,
OPT_CHAR,
OPT_FLOAT,
OPT_DOUBLE,
OPT_FONTSIZE, /* INT */
OPT_INT,
OPT_INT_A,
OPT_LONG,
OPT_PERCENT, /* Unsigned char */
OPT_SHORT,
OPT_STRING,
OPT_USHORT,
OPT_UCHAR
} options;
typedef struct Option Option;
struct Option {
char *keyword;
int type;
void *var;
int size;
};
Option GraphOptions[] = {
{ "annotation_font_size", OPT_FONTSIZE, &GDC_annotation_font_size, 0},
{ "bar_width", OPT_PERCENT, &GDC_bar_width, 0},
{ "bg_color", OPT_COLOR, &GDC_BGColor, 0},
{ "bg_image", OPT_STRING, &GDC_BGImage, 0},
{ "bg_transparent", OPT_BOOL, &GDC_transparent_bg, 0},
{ "border", OPT_INT, &GDC_border, 0},
{ "ext_color", OPT_COLOR_A, &GDC_ExtColor, 0}, /* numsets * numpoints */
{ "ext_vol_color", OPT_COLOR_A, &GDC_ExtVolColor, 0}, /* numpoints */
{ "generate_img", OPT_BOOL, &GDC_generate_img, 0},
{ "grid", OPT_INT, &GDC_grid, 0},
{ "grid_color", OPT_COLOR, &GDC_GridColor, 0},
{ "hard_graphheight", OPT_INT, &GDC_hard_grapheight, 0},
{ "hard_graphwidth", OPT_INT, &GDC_hard_graphwidth, 0},
{ "hard_size", OPT_BOOL, &GDC_hard_size, 0},
{ "hard_xorig", OPT_INT, &GDC_hard_xorig, 0},
{ "hard_yorig", OPT_INT, &GDC_hard_yorig, 0},
{ "hlc_cap_width", OPT_PERCENT, &GDC_HLC_cap_width, 0},
{ "hlc_style", OPT_INT, &GDC_HLC_style, 0},
{ "hold_img", OPT_INT, &GDC_hold_img, 0},
{ "interpolations", OPT_BOOL, &GDC_interpolations, 0},
{ "image_type", OPT_INT, &GDC_image_type, 0},
{ "jpeg_quality", OPT_INT, &GDC_jpeg_quality, 0},
{ "line_color", OPT_COLOR, &GDC_LineColor, 0},
{ "plot_color", OPT_COLOR, &GDC_PlotColor, 0},
{ "requested_yinterval", OPT_FLOAT, &GDC_requested_yinterval, 0},
{ "requested_ymax", OPT_FLOAT, &GDC_requested_ymax, 0},
{ "requested_ymin", OPT_FLOAT, &GDC_requested_ymin, 0},
{ "set_color", OPT_COLOR_A, &GDC_SetColor, 0}, /* numsets */
{ "stack_type", OPT_INT, &GDC_stack_type, 0},
/* Python names cannot start with digits - so we rename these options slightly:*/
{ "threeD_angle", OPT_UCHAR, &GDC_3d_angle, 0},
{ "threeD_depth", OPT_FLOAT, &GDC_3d_depth, 0},
{ "thumblabel", OPT_STRING, &GDC_thumblabel, 0},
{ "thumbnail", OPT_BOOL, &GDC_thumbnail, 0},
{ "thumbval", OPT_FLOAT, &GDC_thumbval, 0},
{ "ticks", OPT_INT, &GDC_ticks, 0},
{ "title", OPT_STRING, &GDC_title, 0},
{ "title_color", OPT_COLOR, &GDC_TitleColor, 0},
{ "title_font_size", OPT_FONTSIZE, &GDC_title_size, 0},
{ "vol_color", OPT_COLOR, &GDC_VolColor, 0},
{ "xaxis", OPT_BOOL, &GDC_xaxis, 0},
{ "xaxis_angle", OPT_DOUBLE, &GDC_xaxis_angle, 0},
{ "xaxis_font_size", OPT_FONTSIZE, &GDC_xaxisfont_size, 0},
{ "xlabel_color", OPT_COLOR, &GDC_XLabelColor, 0},
{ "xlabel_spacing", OPT_SHORT, &GDC_xlabel_spacing, 0},
{ "xlabel_ctl", OPT_BOOL_A, &GDC_xlabel_ctl, 0}, /* numpoints */
{ "xtitle", OPT_STRING, &GDC_xtitle, 0},
{ "xtitle_color", OPT_COLOR, &GDC_XTitleColor, 0},
{ "xtitle_font_size", OPT_FONTSIZE, &GDC_xtitle_size, 0},
{ "yaxis", OPT_BOOL, &GDC_yaxis, 0},
{ "yaxis2", OPT_BOOL, &GDC_yaxis2, 0},
{ "yaxis_font_size", OPT_FONTSIZE, &GDC_yaxisfont_size, 0},
{ "ylabel_color", OPT_COLOR, &GDC_YLabelColor, 0},
{ "ylabel_density", OPT_PERCENT, &GDC_ylabel_density, 0},
{ "ylabel_fmt", OPT_STRING, &GDC_ylabel_fmt, 0},
{ "ylabel2_color", OPT_COLOR, &GDC_YLabel2Color, 0},
{ "ylabel2_fmt", OPT_STRING, &GDC_ylabel2_fmt, 0},
{ "ytitle", OPT_STRING, &GDC_ytitle, 0},
{ "ytitle_color", OPT_COLOR, &GDC_YTitleColor, 0},
{ "ytitle_font_size", OPT_FONTSIZE, &GDC_ytitle_size, 0},
{ "ytitle2", OPT_STRING, &GDC_ytitle2, 0},
{ "ytitle2_color", OPT_COLOR, &GDC_YTitle2Color, 0},
{ "yval_style", OPT_BOOL, &GDC_yval_style, 0},
{ "zeroshelf", OPT_BOOL, &GDC_0Shelf, 0},
#ifdef HAVE_LIBFREETYPE
{ "annotation_font", OPT_STRING, &GDC_annotation_font, 0},
{ "annotation_ptsize", OPT_DOUBLE, &GDC_annotation_ptsize, 0},
{ "title_font", OPT_STRING, &GDC_title_font, 0},
{ "title_ptsize", OPT_DOUBLE, &GDC_title_ptsize, 0},
{ "xaxis_font", OPT_STRING, &GDC_xaxis_font, 0},
{ "xaxis_ptsize", OPT_DOUBLE, &GDC_xaxis_ptsize, 0},
{ "xtitle_font", OPT_STRING, &GDC_xtitle_font, 0},
{ "xtitle_ptsize", OPT_DOUBLE, &GDC_xtitle_ptsize, 0},
{ "yaxis_font", OPT_STRING, &GDC_yaxis_font, 0},
{ "yaxis_ptsize", OPT_DOUBLE, &GDC_yaxis_ptsize, 0},
{ "ytitle_font", OPT_STRING, &GDC_ytitle_font, 0},
{ "ytitle_ptsize", OPT_DOUBLE, &GDC_ytitle_ptsize, 0},
#endif
{ NULL }
};
Option PieOptions[] = {
{ "bg_color", OPT_COLOR, &GDCPIE_BGColor, 0},
{ "bg_image", OPT_STRING, &GDC_BGImage, 0},
{ "edge_color", OPT_COLOR, &GDCPIE_EdgeColor, 0},
{ "explode", OPT_INT_A, &GDCPIE_explode, 0}, /* numpoints */
{ "generate_img", OPT_BOOL, &GDC_generate_img, 0},
{ "image_type", OPT_INT, &GDC_image_type, 0},
{ "jpeg_quality", OPT_INT, &GDC_jpeg_quality, 0},
{ "label_dist", OPT_INT, &GDCPIE_label_dist, 0},
{ "label_font_size", OPT_FONTSIZE, &GDCPIE_label_size, 0},
{ "label_line", OPT_BOOL, &GDCPIE_label_line, 0},
{ "line_color", OPT_COLOR, &GDCPIE_LineColor, 0},
{ "missing", OPT_BOOL_A, &GDCPIE_missing, 0}, /* numpoints */
{ "other_threshold", OPT_CHAR, &GDCPIE_other_threshold, 0},
{ "percent_format", OPT_STRING, &GDCPIE_percent_fmt, 0},
{ "percent_labels", OPT_INT, &GDCPIE_percent_labels, 0},
{ "perspective", OPT_USHORT, &GDCPIE_perspective, 0},
{ "color", OPT_COLOR_A, &GDCPIE_Color, 0}, /* numpoints */
{ "plot_color", OPT_COLOR, &GDCPIE_PlotColor, 0},
{ "threeD_angle", OPT_USHORT, &GDCPIE_3d_angle, 0},
{ "threeD_depth", OPT_USHORT, &GDCPIE_3d_depth, 0},
{ "title", OPT_STRING, &GDCPIE_title, 0},
{ "title_font_size", OPT_FONTSIZE, &GDCPIE_title_size, 0},
#ifdef HAVE_LIBFREETYPE
{ "label_font", OPT_STRING, &GDCPIE_label_font, 0},
{ "label_ptsize", OPT_FLOAT, &GDCPIE_label_ptsize, 0},
{ "title_font", OPT_STRING, &GDCPIE_title_font, 0},
{ "title_ptsize", OPT_FLOAT, &GDCPIE_title_ptsize, 0},
#endif
{ NULL }
};
#define MEMPOOLSIZE 256
void *mempool[MEMPOOLSIZE]; /* The global memory pool array. */
int mempool_final = -1; /* The greatest filled array index. */
/* Add a float constant to a module. Same as PyModule_AddIntConstant. */
int AddFloatConstant(PyObject *m, char *name, double value){
return PyModule_AddObject(m, name, PyFloat_FromDouble(value));
}
/* Frees all memory in mempool. */
void clearMempool(void){
int i;
for (i = 0; i < mempool_final; i++){
if (mempool[i]){
free(mempool[i]);
mempool[i] = NULL;
}
}
}
/*
* Add a piece of allocated memory to the mempool. As arguments, it takes the
* new pointer, and the old pointer. If the old pointer is found in the
* mempool, it is free()d, and replaced with the new pointer. Otherwise, the
* new pointer is placed in an empty slot.
* The new pointer can be NULL.
* The function returns the new pointer. */
void addMempool(void *new, void *old){
int i;
for (i = 0; i < MEMPOOLSIZE; i++) {
if (mempool[i] == NULL){
if (new == NULL){
return;
}
mempool[i] = new;
mempool_final = i;
return;
} else if (mempool[i] == old){
free(old);
if (new == NULL){
mempool[i] = mempool[mempool_final];
mempool[mempool_final] = NULL;
--mempool_final;
} else
mempool[i] = new;
return;
}
}
/* FIXME: Error here... */
fprintf(stderr, "Mempool is full. This should never happen - please contact software authors.\n");
}
PyObject *getInt(Option opt){
return PyInt_FromLong((long)*(int*)opt.var);
}
PyObject *getShort(Option opt){
return PyInt_FromLong((long)*(short*)opt.var);
}
PyObject *getUshort(Option opt){
return PyInt_FromLong((long)(*(unsigned short*)opt.var));
}
PyObject *getUchar(Option opt){
return PyInt_FromLong((long)(*((unsigned char*)opt.var)));
}
PyObject *getChar(Option opt){
return PyInt_FromLong((long)(*(char *)opt.var));
}
PyObject *getDouble(Option opt){
return PyFloat_FromDouble(*(double *)opt.var);
}
PyObject *getFloat(Option opt){
return PyFloat_FromDouble((double)(*(float *)opt.var));
}
PyObject *getString(Option opt){
if (!(*(char**)opt.var)){
Py_INCREF(Py_None);
return Py_None;
}
return PyString_FromString(*(char**)opt.var);
}
PyObject *getIntA(Option opt){
int i;
PyObject *pint;
PyObject *list = PyList_New(0);
if (!list)
return NULL;
if (!(*(int**)opt.var)){
Py_INCREF(Py_None);
return Py_None;
}
for (i = 0; i < opt.size; i++){
pint = PyInt_FromLong((long)(*(int **)opt.var)[i]);
if (!pint || PyList_Append(list, pint) < 0)
goto cleanup;
Py_DECREF(pint);
}
return list;
cleanup:
Py_DECREF(list);
return NULL;
}
PyObject *getBoolA(Option opt){
int i;
PyObject *pint;
PyObject *list = PyList_New(0);
if (!list)
return NULL;
if (!(*(char**)opt.var)){
Py_INCREF(Py_None);
return Py_None;
}
for (i = 0; i < opt.size; i++){
pint = PyInt_FromLong((long)(*(char**)opt.var)[i]);
if (!pint || PyList_Append(list, pint) < 0)
goto cleanup;
Py_DECREF(pint);
}
return list;
cleanup:
Py_DECREF(list);
return NULL;
}
PyObject *getColorA(Option opt){
int i;
PyObject *pint;
PyObject *list = PyList_New(0);
if (!list)
return NULL;
if (!(*(char**)opt.var)){
Py_INCREF(Py_None);
return Py_None;
}
for (i = 0; i < opt.size; i++){
pint = PyInt_FromLong((*(long**)opt.var)[i]);
if (!pint || PyList_Append(list, pint) < 0)
goto cleanup;
Py_DECREF(pint);
}
return list;
cleanup:
Py_DECREF(list);
return NULL;
}
/* Construct a dictionary of the following format:
* option: (index, type, value) */
PyObject *makeOptionDict(Option *opts){
PyObject *(*funcptr)(Option);
PyObject *ret;
int optIndex = 0;
PyObject *tup;
PyObject *dict = PyDict_New();
while (opts[optIndex].keyword != NULL) {
tup = PyTuple_New(3);
PyTuple_SET_ITEM(tup, 0, PyInt_FromLong((long)optIndex));
PyTuple_SET_ITEM(tup, 1, PyInt_FromLong((long)opts[optIndex].type));
switch (opts[optIndex].type){
case OPT_INT:
case OPT_LONG:
case OPT_COLOR:
funcptr = getInt;
break;
case OPT_SHORT:
funcptr = getShort;
break;
case OPT_USHORT:
funcptr = getUshort;
break;
case OPT_PERCENT:
case OPT_BOOL:
case OPT_FONTSIZE:
case OPT_UCHAR:
funcptr = getUchar;
break;
case OPT_CHAR:
funcptr = getChar;
break;
case OPT_STRING:
funcptr = getString;
break;
case OPT_FLOAT:
funcptr = getFloat;
break;
case OPT_DOUBLE:
funcptr = getDouble;
break;
case OPT_INT_A:
funcptr = getIntA;
break;
case OPT_BOOL_A:
funcptr = getBoolA;
break;
case OPT_COLOR_A:
funcptr = getColorA;
break;
default:
PyErr_SetString(PyExc_ValueError, "Argument is not a valid option type.");
goto clean;
}
if (funcptr && opts[optIndex].var){
ret = funcptr(opts[optIndex]);
if (!ret)
goto clean;
PyTuple_SET_ITEM(tup, 2, ret);
} else {
PyTuple_SET_ITEM(tup, 2, Py_None);
}
if (PyDict_SetItemString(dict, opts[optIndex].keyword, tup) < 0)
goto clean;
optIndex ++;
}
return dict;
clean:
Py_DECREF(dict);
return NULL;
}
/*
* Retrieve current values of the specified chart options. Returns a
* dictionary.
*/
PyObject *getOptions(PyObject *self, PyObject *args){
int type;
if (!PyArg_ParseTuple(args, "i", &type))
return NULL;
if (type == GRAPH)
return makeOptionDict(GraphOptions);
else if (type == PIE)
return makeOptionDict(PieOptions);
else{
PyErr_SetString(PyExc_ValueError, "Argument is neither PIE nor GRAPH.");
return NULL;
}
}
/*
* Set an option.
*/
PyObject *setOption(PyObject *self, PyObject *args){
int type, optIndex;
PyObject *val, *tmp;
long ival;
double dval;
char *sval, *mstr;
Option *table;
if (!PyArg_ParseTuple(args, "iiO", &type, &optIndex, &val)){
return NULL;
}
if (type == GRAPH)
table = GraphOptions;
else if (type == PIE)
table = PieOptions;
else{
PyErr_SetString(PyExc_ValueError, "Argument is neither PIE nor GRAPH.");
return NULL;
}
switch (table[optIndex].type){
case OPT_INT:
case OPT_COLOR:
case OPT_SHORT:
case OPT_USHORT:
case OPT_UCHAR:
case OPT_BOOL:
case OPT_FONTSIZE:
case OPT_PERCENT:
case OPT_CHAR:
case OPT_LONG:
/* FIXME: Check return value... */
tmp = PyNumber_Int(val);
if (PyErr_Occurred())
return NULL;
ival = PyInt_AsLong(tmp);
Py_DECREF(tmp);
if (PyErr_Occurred())
return NULL;
switch (table[optIndex].type){
case OPT_INT:
*(int*)table[optIndex].var = ival;
break;
case OPT_SHORT:
*(short*)table[optIndex].var = ival;
break;
case OPT_USHORT:
*(unsigned short*)table[optIndex].var = ival;
break;
case OPT_UCHAR:
case OPT_PERCENT:
*(unsigned char*)table[optIndex].var = ival;
break;
case OPT_BOOL:
*(char*)table[optIndex].var = ival;
break;
case OPT_FONTSIZE:
*(int*)table[optIndex].var = ival;
break;
case OPT_CHAR:
*(char*)table[optIndex].var = ival;
break;
case OPT_LONG:
case OPT_COLOR:
*(long*)table[optIndex].var = ival;
break;
}
break;
case OPT_FLOAT:
case OPT_DOUBLE:
tmp = PyNumber_Float(val);
if (PyErr_Occurred())
return NULL;
dval = PyFloat_AsDouble(tmp);
Py_DECREF(tmp);
if (PyErr_Occurred())
return NULL;
if (table[optIndex].type == OPT_FLOAT)
*(float*)table[optIndex].var = dval;
else
*(double*)table[optIndex].var = dval;
break;
case OPT_STRING:
if (val == Py_None){
addMempool(NULL, *(char**)table[optIndex].var);
*(char**)table[optIndex].var = NULL;
} else {
tmp = PyObject_Str(val);
if (!tmp)
return NULL;
sval = PyString_AsString(tmp);
Py_DECREF(tmp);
if (!sval)
return NULL;
mstr = malloc(strlen(sval) + 1);
if (!mstr){
PyErr_NoMemory();
return NULL;
}
addMempool(mstr, *(char**)table[optIndex].var);
strcpy(mstr, sval);
*(char**)table[optIndex].var = mstr;
}
break;
case OPT_INT_A:
if (val == Py_None){
addMempool(NULL, *(int**)table[optIndex].var);
*(int**)table[optIndex].var = NULL;
} else {
int i, len;
int *arr;
PyObject *aval;
len = PyObject_Length(val);
if (len < 0){
PyErr_SetString(PyExc_ValueError, "Cannot retrieve length of item.");
return NULL;
}
arr = calloc((size_t)len, sizeof(int));
if (!arr){
PyErr_NoMemory();
return NULL;
}
for (i = 0; i < len; i++){
aval = PySequence_GetItem(val, i);
if (aval == NULL){
free(arr);
PyErr_SetString(PyExc_ValueError, "Cannot access list item.");
return NULL;
};
arr[i] = (int)PyInt_AsLong(aval);
Py_DECREF(aval);
if (PyErr_Occurred()){
free(arr);
return NULL;
}
}
addMempool(arr, *(int**)table[optIndex].var);
*(int**)table[optIndex].var = arr;
table[optIndex].size = len;
}
break;
case OPT_BOOL_A:
if (val == Py_None){
addMempool(NULL, *(char**)table[optIndex].var);
*(char**)table[optIndex].var = NULL;
} else {
int i, len;
char *arr;
PyObject *aval;
len = PyObject_Length(val);
if (len < 0){
PyErr_SetString(PyExc_ValueError, "Cannot retrieve length of item.");
return NULL;
}
arr = calloc((size_t)len, sizeof(char));
if (!arr){
PyErr_NoMemory();
return NULL;
}
for (i = 0; i < len; i++){
aval = PySequence_GetItem(val, i);
if (aval == NULL){
free(arr);
PyErr_SetString(PyExc_ValueError, "Cannot access list item.");
return NULL;
};
arr[i] = (char)PyInt_AsLong(aval);
Py_DECREF(aval);
if (PyErr_Occurred()){
free(arr);
return NULL;
}
}
addMempool(arr, *(char**)table[optIndex].var);
*(char**)table[optIndex].var = arr;
table[optIndex].size = len;
}
break;
case OPT_COLOR_A:
if (val == Py_None){
addMempool(NULL, *(long**)table[optIndex].var);
*(long**)table[optIndex].var = NULL;
} else {
int i, len;
long *arr;
PyObject *aval;
len = PyObject_Length(val);
if (len < 0){
PyErr_SetString(PyExc_ValueError, "Cannot retrieve length of item.");
return NULL;
}
arr = calloc((size_t)len, sizeof(long));
if (!arr){
PyErr_NoMemory();
return NULL;
}
for (i = 0; i < len; i++){
aval = PySequence_GetItem(val, i);
if (aval == NULL){
free(arr);
PyErr_SetString(PyExc_ValueError, "Cannot access list item.");
return NULL;
};
arr[i] = PyInt_AsLong(aval);
Py_DECREF(aval);
if (PyErr_Occurred()){
free(arr);
return NULL;
}
}
addMempool(arr, *(long**)table[optIndex].var);
*(long**)table[optIndex].var = arr;
table[optIndex].size = len;
}
break;
default:
PyErr_SetString(PyExc_ValueError, "Option type unknown.");
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
/*
* The argument should be a list containing only strings.
* The function returns an array of C strings. Both the
* array and the strings should be freed after use.
* Returns NULL on error.
*/
char **getStringsFromSequence(PyObject *lst){
int i, j, slen;
size_t len;
char **strings;
char *mem;
PyObject *pobj, *pstr;
len = PyObject_Length(lst);
if (len < 0)
return NULL;
strings = calloc((size_t)len, sizeof(char*));
if (!strings){
PyErr_NoMemory();
return NULL;
}
for (i = 0; i < len; i++){
pobj = PySequence_GetItem(lst, i);
pstr = PyObject_Str(pobj);
Py_DECREF(pobj);
if (pstr == NULL)
goto cleanup;
slen = PyString_Size(pstr);
if (slen == NULL)
goto cleanup;
mem = malloc((size_t)slen+1);
if (mem == NULL){
PyErr_NoMemory();
goto cleanup;
}
strcpy(mem, PyString_AsString(pstr));
Py_DECREF(pstr);
strings[i] = mem;
}
return strings;
cleanup:
for (j = 0; j < len; j++){
if (strings[j])
free(strings[j]);
else
break;
}
free(strings);
PyErr_SetString(PyExc_ValueError, "Label cannot be converted to string.");
return NULL;
}
/*
* The argument should be a list containing only floats, ints and None objects.
* The function returns a list of C floats. Note that the caller should free
* this list after use.
*
* Returns NULL on error.
*/
float *getFloatsFromSequence(PyObject *lst){
int i, len;
float *floats;
PyObject *pnum;
len = PyObject_Length(lst);
floats = malloc(len * sizeof(float));
if (floats == NULL){
PyErr_NoMemory();
return NULL;
}
for (i = 0; i < len; i++){
pnum = PySequence_GetItem(lst, i);
if (pnum == Py_None){
floats[i] = GDC_NOVALUE;
} else {
if ((!pnum) || (!PyNumber_Check(pnum))){
PyMem_Free(floats);
return NULL;
}
floats[i] = (float)PyFloat_AsDouble(pnum);
}
Py_DECREF(pnum);
}
return floats;
}
PyObject *pygd_out_pie(PyObject *self, PyObject *args){
int width, height, graphtype, numpoints;
int i;
PyObject *pfile;
PyObject *labels = NULL;
PyObject *data = NULL;
PyObject *ret = NULL;
char **labels_strings = NULL;
float *data_floats = NULL;
FILE *fp;
if (!PyArg_ParseTuple(args, "iiO!iiOO", &width, &height, &PyFile_Type, &pfile,
&graphtype, &numpoints, &labels, &data)){
return NULL;
}
if (!PySequence_Check(data)){
PyErr_SetString(PyExc_TypeError, "Argument data should be a list.");
goto cleanup;
}
if (PyObject_IsTrue(labels)){
if (!PySequence_Check(labels)){
PyErr_SetString(PyExc_TypeError, "Argument labels should be a list.");
goto cleanup;
}
if (!PyObject_Length(labels) == numpoints){
PyErr_SetString(PyExc_TypeError, "Number of labels should equal numpoints.");
goto cleanup;
}
labels_strings = getStringsFromSequence(labels);
if (labels_strings == NULL){
PyErr_SetString(PyExc_TypeError, "Could not convert labels arguments to strings.");
goto cleanup;
}
}
if (!PyObject_Length(data) == numpoints){
PyErr_SetString(PyExc_TypeError, "Number of data points should equal numpoints.");
goto cleanup;
}
data_floats = getFloatsFromSequence(data);
if (data_floats == NULL){
PyErr_SetString(PyExc_TypeError, "Could not convert data arguments to floats.");
goto cleanup;
}
fp = PyFile_AsFile(pfile);
/* Why doesn't this function have a return value? */
GDC_out_pie( width, height, fp, graphtype, numpoints, labels_strings, data_floats);
Py_INCREF(Py_None);
ret = Py_None;
cleanup:
if (labels_strings){
for (i = 0; i < numpoints; i++)
free(labels_strings[i]);
free(labels_strings);
}
if (data_floats)
free(data_floats);
return ret;
}
PyObject *pygd_out_graph(PyObject *self, PyObject *args){
int width, height, graphtype, numpoints, numsets, retval;
int i;
PyObject *pfile, *labels, *data, *combodata;
PyObject *ret = NULL;
char **labels_strings = NULL;
float *data_floats = NULL;
float *combodata_floats = NULL;
FILE *fp;
if (!PyArg_ParseTuple(args, "iiO!iiOiOO", &width, &height, &PyFile_Type, &pfile,
&graphtype, &numpoints, &labels, &numsets,
&data, &combodata)){
return NULL;
}
if (!PySequence_Check(data)){
PyErr_SetString(PyExc_TypeError, "Argument data should be a list.");
goto cleanup;
}
if (PyObject_IsTrue(labels)){
if (!PySequence_Check(labels)){
PyErr_SetString(PyExc_TypeError, "Argument labels should be a list.");
goto cleanup;
}
if (!PyObject_Length(labels) == numpoints){
PyErr_SetString(PyExc_TypeError, "Number of labels should equal numpoints.");
goto cleanup;
}
labels_strings = getStringsFromSequence(labels);
if (labels_strings == NULL){
PyErr_SetString(PyExc_TypeError, "Could not convert labels arguments to strings.");
goto cleanup;
}
}
if (PyObject_IsTrue(combodata)){
if (!PySequence_Check(combodata)){
PyErr_SetString(PyExc_TypeError, "Argument combodata should be a list.");
goto cleanup;
}
if (!PyObject_Length(combodata) == numpoints){
PyErr_SetString(PyExc_TypeError, "Number of combo data points should equal numpoints.");
goto cleanup;
}
combodata_floats = getFloatsFromSequence(combodata);
if (combodata_floats == NULL){
PyErr_SetString(PyExc_TypeError, "Could not convert combodata arguments to floats.");
goto cleanup;
}
}
if (!PyObject_Length(data) == numpoints){
PyErr_SetString(PyExc_TypeError, "Number of data points should equal numpoints.");
goto cleanup;
}
data_floats = getFloatsFromSequence(data);
if (data_floats == NULL){
PyErr_SetString(PyExc_TypeError, "Could not convert data arguments to floats.");
goto cleanup;
}
fp = PyFile_AsFile(pfile);
retval = GDC_out_graph( width, height, fp, graphtype,
numpoints, labels_strings, numsets,
data_floats, combodata_floats);
if (retval){
PyErr_SetString(PGError, "Generic error: could not draw graph.");
ret = NULL;
} else {
Py_INCREF(Py_None);
ret = Py_None;
}
cleanup:
if (labels_strings){
for (i = 0; i < numpoints; i++)
free(labels_strings[i]);
free(labels_strings);
}
if (combodata_floats)
free(combodata_floats);
if (data_floats)
free(data_floats);
return ret;
}
PyObject *pygd_set_scatter(PyObject *self, PyObject *args){
int i, len;
GDC_SCATTER_T *scatters;
PyObject *scatList, *s, *attr, *aval;
if (!PyArg_ParseTuple(args, "O", &scatList)){
return NULL;
}
if (scatList == Py_None){
addMempool(NULL, GDC_scatter);
GDC_scatter = NULL;
GDC_num_scatter_pts = 0;
Py_INCREF(Py_None);
return Py_None;
}
/* TODO: If scatlist is None, we clear the scatter points. */
if (!PySequence_Check(scatList)){
PyErr_SetString(PyExc_TypeError, "Argument data should be a list.");
return NULL;
}
len = PyObject_Length(scatList);
scatters = malloc(len * sizeof(GDC_SCATTER_T));
for (i = 0; i < len; i++){
s = PySequence_GetItem(scatList, i);
attr = PyObject_GetAttrString(s, "point");
if (attr == NULL)
goto cleanup;
aval = PyNumber_Float(attr);
Py_DECREF(attr);
if (aval == NULL){
PyErr_SetString(PyExc_TypeError, "Point value must be representable as a float.");
goto free;
}
scatters[i].point = (float)PyFloat_AsDouble(aval);
Py_DECREF(aval);
attr = PyObject_GetAttrString(s, "val");
if (attr == NULL)
goto cleanup;
aval = PyNumber_Float(attr);
Py_DECREF(attr);
if (aval == NULL){
PyErr_SetString(PyExc_TypeError, "Value must be representable as a float.");
goto free;
}
scatters[i].val = (float)PyFloat_AsDouble(aval);
Py_DECREF(aval);
attr = PyObject_GetAttrString(s, "width");
if (attr == NULL)
goto cleanup;
aval = PyNumber_Int(attr);
Py_DECREF(attr);
if (aval == NULL){
PyErr_SetString(PyExc_TypeError, "Width must be representable as an int.");
goto free;
}
scatters[i].width = (int)PyInt_AsLong(aval);
Py_DECREF(aval);
attr = PyObject_GetAttrString(s, "color");
if (attr == NULL)
goto cleanup;
aval = PyNumber_Int(attr);
Py_DECREF(attr);
if (aval == NULL){
PyErr_SetString(PyExc_TypeError, "Color must be representable as an int.");
goto free;
}
scatters[i].color = (unsigned long)PyInt_AsLong(aval);
Py_DECREF(aval);
attr = PyObject_GetAttrString(s, "_type");
if (attr == NULL)
goto cleanup;
aval = PyNumber_Int(attr);
Py_DECREF(aval);
if (aval == NULL){
PyErr_SetString(PyExc_TypeError, "Type must be representable as an int.");
goto free;
}
scatters[i].ind = (int)PyInt_AsLong(aval);
Py_DECREF(aval);
Py_DECREF(s);
}
addMempool(scatters, GDC_scatter);
GDC_scatter = scatters;
GDC_num_scatter_pts = len;
Py_INCREF(Py_None);
return Py_None;
cleanup:
PyErr_SetString(PyExc_TypeError, "Object does not seem to be a scatter point object.");
free:
free(scatters);
return NULL;
}
PyObject *pygd_annotate(PyObject *self, PyObject *args){
PyObject *anno, *attr, *aval;
GDC_ANNOTATION_T *canno;
if (!PyArg_ParseTuple(args, "O", &anno)){
return NULL;
}
if (anno == Py_None){
if (GDC_annotation)
free(GDC_annotation);
GDC_annotation = NULL;
} else {
canno = malloc(sizeof(GDC_ANNOTATION_T));
if (canno == NULL){
PyErr_NoMemory();
return NULL;
}
attr = PyObject_GetAttrString(anno, "point");
if (attr == NULL)
goto cleanup;
aval = PyNumber_Float(attr);
Py_DECREF(attr);
if (aval == NULL){
PyErr_SetString(PyExc_TypeError, "Point value must be representable as a float.");
goto free;
}
canno->point = (float)PyFloat_AsDouble(aval);
Py_DECREF(aval);
attr = PyObject_GetAttrString(anno, "color");
if (attr == NULL)
goto cleanup;
aval = PyNumber_Int(attr);
Py_DECREF(attr);
if (aval == NULL){
PyErr_SetString(PyExc_TypeError, "Color value must be representable as a long.");
goto free;
}
canno->color = PyInt_AsLong(aval);
Py_DECREF(aval);
attr = PyObject_GetAttrString(anno, "note");
if (attr == NULL)
goto cleanup;
aval = PyObject_Str(attr);
Py_DECREF(attr);
if (aval == NULL){
PyErr_SetString(PyExc_TypeError, "Note must be representable as a str.");
goto free;
}
strncpy(canno->note, PyString_AsString(aval), MAX_NOTE_LEN+1);
Py_DECREF(aval);
if (GDC_annotation)
free(GDC_annotation);
GDC_annotation = canno;
}
Py_INCREF(Py_None);
return Py_None;
cleanup:
PyErr_SetString(PyExc_TypeError, "Object does not seem to be an annotation object.");
free:
free(canno);
return NULL;
}
static PyMethodDef methods[] = {
{"out_graph", pygd_out_graph, METH_VARARGS, "Output a graph." },
{"out_pie", pygd_out_pie, METH_VARARGS, "Output a pie." },
{"getOptions", getOptions, METH_VARARGS, "Retrieve all chart options." },
{"setOption", setOption, METH_VARARGS, "Set an option." },
{"setScatter", pygd_set_scatter, METH_VARARGS, "Set scatter points." },
{"annotate", pygd_annotate, METH_VARARGS, "Set an annotation point." },
{ NULL, NULL }
};
void init_gdchartc(void){
PyObject *module;
Py_AtExit(clearMempool);
module = Py_InitModule4("_gdchartc", methods, NULL, NULL, PYTHON_API_VERSION);
PGError = PyErr_NewException("_gdchartc.PGError", NULL, NULL);
PyModule_AddObject(module, "PGError", PGError);
/* Expose our option type identifiers. */
PyModule_AddIntConstant(module, "OPT_BOOL", (long) OPT_BOOL);
PyModule_AddIntConstant(module, "OPT_BOOL_A", (long) OPT_BOOL_A);
PyModule_AddIntConstant(module, "OPT_COLOR", (long) OPT_COLOR);
PyModule_AddIntConstant(module, "OPT_COLOR_A", (long) OPT_COLOR_A);
PyModule_AddIntConstant(module, "OPT_FLOAT", (long) OPT_FLOAT);
PyModule_AddIntConstant(module, "OPT_FONTSIZE", (long) OPT_FONTSIZE);
PyModule_AddIntConstant(module, "OPT_INT", (long) OPT_INT);
PyModule_AddIntConstant(module, "OPT_INT_A", (long) OPT_INT_A);
PyModule_AddIntConstant(module, "OPT_LONG", (long) OPT_LONG);
PyModule_AddIntConstant(module, "OPT_SHORT", (long) OPT_SHORT);
PyModule_AddIntConstant(module, "OPT_USHORT", (long) OPT_USHORT);
PyModule_AddIntConstant(module, "OPT_PERCENT", (long) OPT_PERCENT);
PyModule_AddIntConstant(module, "OPT_STRING", (long) OPT_STRING);
PyModule_AddIntConstant(module, "OPT_UCHAR", (long) OPT_UCHAR);
PyModule_AddIntConstant(module, "OPT_CHAR", (long) OPT_CHAR);
/* Expose the chart type identifiers */
PyModule_AddIntConstant(module, "GRAPH", (long) GRAPH);
PyModule_AddIntConstant(module, "PIE", (long) PIE);
/*
************************
gdc.h
************************
*/
/* Max annotation length: */
PyModule_AddIntConstant(module, "MAX_NOTE_LEN", (long) MAX_NOTE_LEN);
/* Image formats: */
PyModule_AddIntConstant(module, "GDC_GIF", (long) GDC_GIF);
PyModule_AddIntConstant(module, "GDC_JPEG", (long) GDC_JPEG);
PyModule_AddIntConstant(module, "GDC_PNG", (long) GDC_PNG);
PyModule_AddIntConstant(module, "GDC_WBMP", (long) GDC_WBMP);
/* Font sizes: */
PyModule_AddIntConstant(module, "GDC_TINY", (long) GDC_TINY);
PyModule_AddIntConstant(module, "GDC_SMALL", (long) GDC_SMALL);
PyModule_AddIntConstant(module, "GDC_MEDBOLD", (long) GDC_MEDBOLD);
PyModule_AddIntConstant(module, "GDC_LARGE", (long) GDC_LARGE);
PyModule_AddIntConstant(module, "GDC_GIANT", (long) GDC_GIANT);
/* Chart styles */
PyModule_AddIntConstant(module, "GDC_LINE", (long) GDC_LINE);
PyModule_AddIntConstant(module, "GDC_AREA", (long) GDC_AREA);
PyModule_AddIntConstant(module, "GDC_BAR", (long) GDC_BAR);
PyModule_AddIntConstant(module, "GDC_FLOATINGBAR", (long) GDC_FLOATINGBAR);
PyModule_AddIntConstant(module, "GDC_HILOCLOSE", (long) GDC_HILOCLOSE);
PyModule_AddIntConstant(module, "GDC_COMBO_LINE_BAR", (long) GDC_COMBO_LINE_BAR);
PyModule_AddIntConstant(module, "GDC_COMBO_HLC_BAR", (long) GDC_COMBO_HLC_BAR);
PyModule_AddIntConstant(module, "GDC_COMBO_LINE_AREA", (long) GDC_COMBO_LINE_AREA);
PyModule_AddIntConstant(module, "GDC_COMBO_LINE_LINE", (long) GDC_COMBO_LINE_LINE);
PyModule_AddIntConstant(module, "GDC_COMBO_HLC_AREA", (long) GDC_COMBO_HLC_AREA);
PyModule_AddIntConstant(module, "GDC_3DHILOCLOSE", (long) GDC_3DHILOCLOSE);
PyModule_AddIntConstant(module, "GDC_3DCOMBO_LINE_BAR", (long) GDC_3DCOMBO_LINE_BAR);
PyModule_AddIntConstant(module, "GDC_3DCOMBO_LINE_AREA",(long) GDC_3DCOMBO_LINE_AREA);
PyModule_AddIntConstant(module, "GDC_3DCOMBO_LINE_LINE",(long) GDC_3DCOMBO_LINE_LINE);
PyModule_AddIntConstant(module, "GDC_3DCOMBO_HLC_BAR", (long) GDC_3DCOMBO_HLC_BAR);
PyModule_AddIntConstant(module, "GDC_3DCOMBO_HLC_AREA", (long) GDC_3DCOMBO_HLC_AREA);
PyModule_AddIntConstant(module, "GDC_3DBAR", (long) GDC_3DBAR);
PyModule_AddIntConstant(module, "GDC_3DFLOATINGBAR", (long) GDC_3DFLOATINGBAR);
PyModule_AddIntConstant(module, "GDC_3DAREA", (long) GDC_3DAREA);
PyModule_AddIntConstant(module, "GDC_3DLINE", (long) GDC_3DLINE);
/* Pie styles */
PyModule_AddIntConstant(module, "GDC_3DPIE", (long) GDC_3DPIE);
PyModule_AddIntConstant(module, "GDC_2DPIE", (long) GDC_2DPIE);
/* TODO: Justification, font type, font size */
/* ************************
gdchart.h
************************
*/
/* Stack options: */
PyModule_AddIntConstant(module, "GDC_STACK_DEPTH", (long) GDC_STACK_DEPTH);
PyModule_AddIntConstant(module, "GDC_STACK_SUM", (long) GDC_STACK_SUM);
PyModule_AddIntConstant(module, "GDC_STACK_BESIDE", (long) GDC_STACK_BESIDE);
PyModule_AddIntConstant(module, "GDC_STACK_LAYER", (long) GDC_STACK_LAYER);
/* Hi-lo-close styles: */
PyModule_AddIntConstant(module, "GDC_HLC_DIAMOND", (long) GDC_HLC_DIAMOND);
PyModule_AddIntConstant(module, "GDC_HLC_CLOSE_CONNECTED", (long) GDC_HLC_CLOSE_CONNECTED);
PyModule_AddIntConstant(module, "GDC_HLC_CONNECTING", (long) GDC_HLC_CONNECTING);
PyModule_AddIntConstant(module, "GDC_HLC_I_CAP", (long) GDC_HLC_I_CAP);
/* Scatter point styles: */
PyModule_AddIntConstant(module, "GDC_SCATTER_TRIANGLE_DOWN", (long) GDC_SCATTER_TRIANGLE_DOWN);
PyModule_AddIntConstant(module, "GDC_SCATTER_TRIANGLE_UP", (long) GDC_SCATTER_TRIANGLE_UP);
PyModule_AddIntConstant(module, "GDC_SCATTER_CIRCLE", (long) GDC_SCATTER_CIRCLE);
/* Tick styles: */
PyModule_AddIntConstant(module, "GDC_TICK_LABELS", (long) GDC_TICK_LABELS);
PyModule_AddIntConstant(module, "GDC_TICK_POINTS", (long) GDC_TICK_POINTS);
PyModule_AddIntConstant(module, "GDC_TICK_NONE", (long) GDC_TICK_NONE);
/* Border styles: */
PyModule_AddIntConstant(module, "GDC_BORDER_NONE", (long) GDC_BORDER_NONE);
PyModule_AddIntConstant(module, "GDC_BORDER_ALL", (long) GDC_BORDER_ALL);
PyModule_AddIntConstant(module, "GDC_BORDER_X", (long) GDC_BORDER_X);
PyModule_AddIntConstant(module, "GDC_BORDER_Y", (long) GDC_BORDER_Y);
PyModule_AddIntConstant(module, "GDC_BORDER_Y2", (long) GDC_BORDER_Y2);
PyModule_AddIntConstant(module, "GDC_BORDER_TOP", (long) GDC_BORDER_TOP);
/* Other magic: */
AddFloatConstant(module, "GDC_INTERP_VALUE", (double) GDC_INTERP_VALUE);
/* ************************
gdcpie.h
************************
*/
/* Percent placement (pie charts): */
PyModule_AddIntConstant(module, "GDCPIE_PCT_NONE", (long) GDCPIE_PCT_NONE);
PyModule_AddIntConstant(module, "GDCPIE_PCT_ABOVE", (long) GDCPIE_PCT_ABOVE);
PyModule_AddIntConstant(module, "GDCPIE_PCT_BELOW", (long) GDCPIE_PCT_BELOW);
PyModule_AddIntConstant(module, "GDCPIE_PCT_RIGHT", (long) GDCPIE_PCT_RIGHT);
PyModule_AddIntConstant(module, "GDCPIE_PCT_LEFT", (long) GDCPIE_PCT_LEFT);
}
pygdchart2alpha2/TODO 0100644 0001750 0001750 00000000377 07774433232 0013410 0 ustar 00aldo aldo TODO
====
- We may want to support drawing to StringIO and cStringIO
objects.
- The project needs to be fully distutils-ified. Ideally,
gdchart itself should be built using autoconf. We may do
this ourselves when we have time.
- Expand the manual.
pygdchart2alpha2/README 0100644 0001750 0001750 00000000321 07774433232 0013565 0 ustar 00aldo aldo
PyGDChart 2.0 Beta
==================
This is the Beta release of the new version of PyGDChart2. It is essentially a
bugfix release, fixing problems affecting setting some options, and using
TrueType fonts.
pygdchart2alpha2/INSTALL 0100644 0001750 0001750 00000001265 07774433232 0013746 0 ustar 00aldo aldo
PyGDChart 2.0 Beta 31/12/03
==================
Since this is a Beta release, we'll assume our users know what
they're doing:
1. Install the latest version of Bruce Verderaime's GDChart
library (0.11.4dev, at the time of writing).
2. Edit the setup.py file to point to the appropriate
libraries on your system.
3. Now do
python setup.py build_ext -i
This will build the C extension in-place, allowing you to
test it before installation. Preferably, you should do the
testing with PyLid (also available at www.nullcube.com):
cd test
/path/to/pylid.py
5. Once the unit-tests have run successfully (please report
any errors):
cd ..
python setup.py install
pygdchart2alpha2/test.py 0100644 0001750 0001750 00000000764 07774433232 0014251 0 ustar 00aldo aldo #!/usr/bin/env python2.2
import sys
import gdchart
g = gdchart.Line()
g.bg_color = "white"
g.width = 600
g.height = 600
g.title = "Risk Event Trend Graph"
g.set_color = ["red", "blue"]
g.ytitle = "Risk"
g.xtitle = "Assessments"
g.setData((10, 20, 30), (30, 20, 10))
g.setLabels(("one", "two", "three"))
g.ticks = "NONE"
g.ylabel_density = 40
#g.title_font_size = "GIANT"
g.title_font = "/home/aldo/.fonts/Elephnt.ttf"
g.title_ptsize = 12
print "Content-Type: image/png"
print
g.draw(sys.stdout)
pygdchart2alpha2/CHANGELOG 0100644 0001750 0001750 00000001744 07774433232 0014131 0 ustar 00aldo aldo Alpha 1 - Initial release
Alpha 2 - Many code cleanups
- Attempting to assign to a non-option attribute on Chart classes
now raises AttributeError. This prevents errors like accidental
mistyping of option attributes from going unnoticed.
- setData now accepts None values to indicate missing data.
- .draw methods now accept either a string filename, or a file
pointer.
- .setLabels now takes a single list as argument. The previous
calling convention was found to be too confusing by some people.
- .getAllOptions now inlcudes the "with" and "height" options.
- Rename 3d* options to threeD*. Python properties can't start
with a digit.
Beta - Fix a type bug that stopped TrueType fonts from working (thanks to Amit J. Patel)
- Fix a bug that manifested itself when setting some options to "None" (thanks to Perry Tew)
pygdchart2alpha2/setup.py 0100644 0001750 0001750 00000003037 07774433232 0014426 0 ustar 00aldo aldo from distutils.core import setup, Extension
GDCHART_PATH = "../gdchart0.11.4dev"
GD_PATH = "../gd-1.8.4"
setup(
name="pygdchart",
version="2.0 Beta",
description="Python bindings to the GDChart library",
author="Nullcube Pty Ltd",
author_email="aldo@nullcube.com",
url="http://www.nullcube.com",
py_modules = ["gdchart"],
ext_modules=[
Extension(
"_gdchartc",
["_gdchartc.c"],
include_dirs=[GDCHART_PATH],
library_dirs=[
GD_PATH,
GDCHART_PATH,
"/usr/local/lib",
"/usr/X11R6/lib",
"/usr/lib"
],
define_macros=[
("HAVE_LIBFREETYPE", 1),
("HAVE_JPEG", 1),
],
libraries=["gdc", "gd", "png", "z", "jpeg", "freetype"]
)
]
)
pygdchart2alpha2/doc 0040755 0001750 0001750 00000000000 07774433232 0013402 5 ustar 00aldo aldo pygdchart2alpha2/doc/graphs 0040755 0001750 0001750 00000000000 07774433232 0014666 5 ustar 00aldo aldo pygdchart2alpha2/doc/graphs/combined 0040755 0001750 0001750 00000000000 07774433232 0016446 5 ustar 00aldo aldo pygdchart2alpha2/doc/graphs/combined/hlcarea.html 0100644 0001750 0001750 00000002716 07774433232 0021015 0 ustar 00aldo aldo
<--previous |
contents |
next-->
HLCAreaCombo
HLCAreaCombo
HLCAreaCombo3D
Data Format
The .setData() method accepts the same data format as the HLC .setData() method.
The .setComboData() method accepts the same data format as the Area .setData() method.
PyGDChart User's Manual
pygdchart2alpha2/doc/graphs/combined/hlcbar.html 0100644 0001750 0001750 00000002700 07774433232 0020642 0 ustar 00aldo aldo
<--previous |
contents |
next-->
HLCBarCombo
HLCBarCombo
HLCBarCombo3D
Data Format
The .setData() method accepts the same data format as the HLC .setData() method.
The .setComboData() method accepts the same data format as the Bar .setData() method.
PyGDChart User's Manual
pygdchart2alpha2/doc/graphs/combined/linebar.html 0100644 0001750 0001750 00000002710 07774433232 0021024 0 ustar 00aldo aldo
<--previous |
contents |
next-->
LineBarCombo
LineBarCombo
LineBarCombo3D
Data Format
The .setData() method accepts the same data format as the Line .setData() method.
The .setComboData() method accepts the same data format as the Bar .setData() method.
PyGDChart User's Manual
pygdchart2alpha2/doc/graphs/combined/linearea.html 0100644 0001750 0001750 00000002720 07774433232 0021171 0 ustar 00aldo aldo
<--previous |
contents |
next-->
LineAreaCombo
LineAreaCombo
LineAreaCombo3D
Data Format
The .setData() method accepts the same data format as the Line .setData() method.
The .setComboData() method accepts the same data format as the Area .setData() method.
PyGDChart User's Manual
pygdchart2alpha2/doc/graphs/combined/lineline.html 0100644 0001750 0001750 00000002730 07774433232 0021211 0 ustar 00aldo aldo
<--previous |
contents |
next-->
LineLineCombo
LineLineCombo
LineLineCombo3D
The 2D form of the LineLineCombo graph is functionally the same as using a
Line graph, and plotting multiple
Data Format
The .setData() and setComboData() methods accept the same data format as the Line .setData() method.
PyGDChart User's Manual
pygdchart2alpha2/doc/graphs/line.html 0100644 0001750 0001750 00000002316 07774433232 0016561 0 ustar 00aldo aldo
<--previous |
contents |
next-->
Line Graphs
Line
Line3D
Data Format
As for Bar Graphs .
PyGDChart User's Manual
pygdchart2alpha2/doc/graphs/area.html 0100644 0001750 0001750 00000002330 07774433232 0016536 0 ustar 00aldo aldo
<--previous |
contents |
next-->
Area Graphs
Area
Area3D
Data Format
As for Bar Graphs .
PyGDChart User's Manual
pygdchart2alpha2/doc/graphs/floating.html 0100644 0001750 0001750 00000011752 07774433232 0017441 0 ustar 00aldo aldo
<--previous |
contents |
next-->
Floating Bar Graphs
FloatingBar
FloatingBar3D
Data Format
The FloatingBar .setData() method accepts an arbitrary number of tuples.
The first element of the tuple is a list of the lower values of the floating
bar, and the second element is a list of the upper values. Here is an example
that plots a single set of data (spaced for clarity):
x . setData (
(
[ 10 , 20 , 40 , 20 , 0 ] ,
[ 60 , 90 , 80 , 50 , 80 ]
)
)
... and for multiple sets we might do the following:
x . setData (
(
[ 10 , 20 , 40 , 20 , 0 ] ,
[ 60 , 90 , 80 , 50 , 80 ]
) ,
(
[ 0 , 80 , 40 , 10 , 0 ] ,
[ 30 , 100 , 90 , 20 , 40 ]
)
)
PyGDChart User's Manual
pygdchart2alpha2/doc/graphs/hlc.html 0100644 0001750 0001750 00000015231 07774433232 0016400 0 ustar 00aldo aldo
<--previous |
contents |
next-->
High-Low-Close Graphs
HLC
HLC3D
High-Low-Close graphs are commonly used do depict stock-market price
movements - "high" indicates the highest value reached during a period of
trading, "low" the lowest, and "close" the value at close of markets.
Data Format
The HLC .setData() method accepts an arbitrary number of lists of the form
[high, low, close], where each element is a list of values. To draw a single
HLC graph, we might invoke .setData() as follows:
x . setData (
(
[ 40 , 100 , 80 , 30 , 50 ] ,
[ 0 , 60 , 70 , 0 , 10 ] ,
[ 10 , 95 , 75 , 25 , 20 ]
)
)
... and for multiple sets we might do the following (spaced to make things
clearer):
x . setData (
(
[ 40 , 100 , 80 , 30 , 50 ] ,
[ 0 , 60 , 70 , 0 , 10 ] ,
[ 10 , 95 , 75 , 25 , 20 ]
) ,
(
[ 20 , 30 , 40 , 50 , 60 ] ,
[ 0 , 10 , 20 , 30 , 40 ] ,
[ 10 , 20 , 30 , 40 , 50 ]
)
)
Options
There are a number of special options associated with HLC graphs.
hlc_style
This option affects the drawing style of HLC graphs. It should be a list,
containing one or more of the following strings "DIAMOND", "CLOSE_CONNECTED",
"CONNECTING", "I_CAP".
hlc_cap_width
The width of the HLC cap. This is a percentage, i.e. it should be an
integer between 0 and 100.
PyGDChart User's Manual
pygdchart2alpha2/doc/graphs/combined.html 0100644 0001750 0001750 00000002414 07774433232 0017411 0 ustar 00aldo aldo
<--previous |
contents |
next-->
Combination Graphs
Combination graphs allow you to place two different plot types at on the
same graph. The primary data (i.e. data for the graph type that occurs first in
the combo graph name) is set using the usual .setData() method. Secondary data
is set using the .setComboData() method. Note that the .setData() and
.setComboData() methods enforce data conformance - that is, you cannot plot
data of different lengths in your primary and secondary graphs.
Each combination graph type also as a corresponding 3D graph type. The 3D
types plot the primary graph type in 3D, with the secondary data type as a 2D
backdrop.
PyGDChart User's Manual
pygdchart2alpha2/doc/graphs/scatter.html 0100644 0001750 0001750 00000016205 07774433232 0017301 0 ustar 00aldo aldo
<--previous |
contents |
next-->
Scatter
Scatter Graph
GDChart provides the ability to add scatter points to any of the standard
graph types. In PyGDChart, this is done by instantiating a number of Scatter
objects, and adding them to a graph using the .setScatter() method.
The Scatter Class
Scatter objects are instantiated as follows:
x = Scatter ( x , y , type , width , color )
The x value should not exceed the number of points in the
associated graph.
type is one of "TRIANGLE_DOWN", "TRIANGLE_UP" and "CIRCLE",
defaulting to "TRIANGLE_DOWN".
width is a precentage defaulting to 100.
color defaults to "white".
Example
The graph at the head of this chapter was drawn using the following program:
import random
import gdchart
sgraph = gdchart . Line ( )
sgraph . width = 250
sgraph . height = 250
sgraph . sgraphtitle = "Weekday"
sgraph . ytitle = "Percentage"
sgraph . title = "Scatter"
sgraph . plot_color = "red"
sgraph . sgraphtitle_color = "white"
sgraph . ytitle_color = "white"
sgraph . setData ( range ( 100 ) )
sgraph . setLabels ( range ( 100 ) )
scats = [ ]
for i in range ( 150 ) :
x = random . randrange ( 30 , 80 )
y = random . randrange ( 30 , 80 )
s = gdchart . Scatter ( x , y , "CIRCLE" , 100 , "blue" )
scats . append ( s )
sgraph . setScatter ( scats )
sgraph . draw ( "scatter.png" )
PyGDChart User's Manual
pygdchart2alpha2/doc/graphs/bar.html 0100644 0001750 0001750 00000007241 07774433232 0016400 0 ustar 00aldo aldo
<--previous |
contents |
next-->
Bar Graphs
Bar
Bar3D
Data Format
The .setData() method accepts simple lists of integers or floats. The
following would plot a single set of data:
x . setData ( [ 20 , 100 , 80 , 30 , 50 ] )
... and this would plot multiple sets of data:
x . setData ( [ 20 , 100 , 80 , 30 , 50 ] , [ 30 , 60 , 70 , 20 , 10 ] , [ 80 , 100 , 10 , 30 , 40 ] )
PyGDChart User's Manual
pygdchart2alpha2/doc/graphs/options.html 0100644 0001750 0001750 00000024206 07774433232 0017327 0 ustar 00aldo aldo
<--previous |
contents |
next-->
Graph Options
Below is a complete list of all options that can be set on Graph objects.
Not all options are explained, but the names are fairly self-explanatory. In
time, the descriptions in this table will become more complete.
See the Type Legend table at the bottom of this page for an explanation of
the various data types.
Option
Type
Description
annotation_font
STRING
annotation_font_size
FONTSIZE
annotation_ptsize
FLOAT
bar_width
PERCENT
bg_color
COLOR
Background colour.
bg_image
STRING
Set a background image.
bg_transparent
BOOL
border
CUSTOM
A list of one or more of the following: "NONE", "ALL", "X", "Y", "Y2", "TOP".
ext_color
COLOR_A
The colour of the primary graph.
ext_vol_color
COLOR_A
The colour of the secondary graph.
generate_img
BOOL
grid
CUSTOM
One of "LABELS", "POINTS", "NONE".
grid_color
COLOR
hard_graphheight
INT
hard_graphwidth
INT
hard_size
BOOL
hard_xorig
INT
hard_yorig
INT
hlc_cap_width
PERCENT
The width of the HLC cap. See HLC Graph for more detail.
hlc_style
INT
The HLC style. This is option is a list, consisting of one or more
of the following: "DIAMOND", "CLOSE_CONNECTED", "CONNECTING" and
"I_CAP". See HLC Graph for more
detail.
hold_img
INT
interpolations
BOOL
image_type
INT
One of the following: "GIF", "JPEG", "PNG", "WBMP".
jpeg_quality
INT
line_color
COLOR
plot_color
COLOR
The colour of the primary plot.
requested_yinterval
FLOAT
requested_ymax
FLOAT
requested_ymin
FLOAT
set_color
COLOR_A
stack_type
CUSTOM
One of "DEPTH", "SUM", "BESIDE", "LAYER".
thumblabel
STRING
threeD_angle
UCHAR
threeD_depth
FLOAT
thumbnail
BOOL
thumbval
FLOAT
ticks
CUSTOM
One of "LABELS", "POINTS", "NONE"
title
STRING
Title at the top of the graph.
title_color
COLOR
title_font
STRING
title_font_size
FONTSIZE
title_ptsize
FLOAT
vol_color
COLOR
xaxis
BOOL
xaxis_angle
FLOAT
xaxis_font
STRING
xaxis_font_size
FONTSIZE
xaxis_ptsize
FLOAT
xlabel_color
COLOR
xlabel_spacing
SHORT
xlabel_ctl
BOOL_A
xtitle
STRING
Label on the X axis.
xtitle_color
COLOR
Colour of the label on the X axis.
xtitle_font
STRING
xtitle_font_size
FONTSIZE
xtitle_ptsize
FLOAT
yaxis
BOOL
yaxis2
BOOL
yaxis_font
STRING
yaxis_font_size
FONTSIZE
yaxis_ptsize
FLOAT
ylabel_color
COLOR
ylabel_density
PERCENT
ylabel_fmt
STRING
ylabel2_color
COLOR
ylabel2_fmt
STRING
ytitle
STRING
Title on the Y axis.
ytitle_color
COLOR
Colour of the title on the Y axis.
ytitle_font
STRING
ytitle_font_size
FONTSIZE
ytitle_ptsize
FLOAT
ytitle2
STRING
ytitle2_color
COLOR
yval_style
BOOL
zeroshelf
BOOL
Type Legend
Type*
Description
BOOL
True if the value passed evaluates to true (ie. "if a: print 1"
prints 1).
BOOL_A
An array of BOOL values.
COLOR
Values can be specified as a descriptive name (i.e. "blue"), as an
integer (i.e. 0xFF0000), or as an RGB object (i.e. RGB(0xFF, 0x00,
0x00)).
COLOR_A
An array of COLOR values.
FLOAT
A floating point value.
FONTSIZE
One of "TINY", "SMALL", "MEDBOLD", "LARGE", "GIANT".
INT
An integer.
PERCENT
An integer x, such that 0 <= x <= 100.
STRING
A string.
UCHAR
An unsigned char. That is, a small positive integer.
* Note that types are NOT enforced by type check - that means that
you don't have to pass a Python integer to an integer option: an object with an
__int__ method will do. Same goes for string options and objects with a __str__
or __repr__ method, etc.
PyGDChart User's Manual
pygdchart2alpha2/doc/pies 0040755 0001750 0001750 00000000000 07774433232 0014342 5 ustar 00aldo aldo pygdchart2alpha2/doc/pies/options.html 0100644 0001750 0001750 00000015105 07774433232 0017001 0 ustar 00aldo aldo
<--previous |
contents |
next-->
Pie Options
Below is a complete list of all options that can be set on Pie objects.
Not all options are explained, but the names are fairly self-explanatory. In
time, the descriptions in this table will become more complete.
See the Type Legend table at the bottom of this page for an explanation of
the various data types.
Option
Type
Description
bg_color
COLOR
bg_image
STRING
edge_color
COLOR
explode
INT_A
An array that specifies which slices of the pie to "explode", and
by how much. See the Pie Chart chapter
for an example of use.
generate_img
BOOL
image_type
INT
jpeg_quality
INT
label_dist
INT
label_font
STRING
label_font_size
FONTSIZE
label_line
BOOL
label_ptsize
FLOAT
line_color
COLOR
missing
BOOL_A
If an element is true, the corresponding "slice" of the pie will
be missing.
other_threshold
CHAR
percent_format
STRING
percent_labels
INT
perspective
USHORT
color
COLOR_A
A list of color entries. Each entry specifies the color for the
corresponding slice of the pie.
plot_color
COLOR
threeD_angle
USHORT
threeD_depth
USHORT
title
STRING
The title at the top of the chart.
title_font
STRING
title_font_size
FONTSIZE
title_ptsize
FLOAT
Type Legend
Type*
Description
BOOL
True if the value passed evaluates to true (ie. "if a: print 1"
prints 1).
BOOL_A
An array of BOOL values.
COLOR
Values can be specified as a descriptive name (i.e. "blue"), as an
integer (i.e. 0xFF0000), or as an RGB object (i.e. RGB(0xFF, 0x00,
0x00)).
COLOR_A
An array of COLOR values.
FLOAT
A floating point value.
FONTSIZE
One of "TINY", "SMALL", "MEDBOLD", "LARGE", "GIANT".
INT
An integer.
INT_A
An array of integers.
PERCENT
An integer x, such that 0 <= x <= 100.
STRING
A string.
UCHAR
An unsigned char. That is, a small positive integer.
* Note that types are NOT enforced by type check - that means that
you don't have to pass a Python integer to an integer option: an object with an
__int__ method will do. Same goes for string options and objects with a __str__
or __repr__ method, etc.
PyGDChart User's Manual
pygdchart2alpha2/doc/style 0040755 0001750 0001750 00000000000 07774433232 0014542 5 ustar 00aldo aldo pygdchart2alpha2/doc/style/style.css 0100644 0001750 0001750 00000000662 07774433232 0016474 0 ustar 00aldo aldo BODY { font-family: verdana,arial,helvetica,sans-serif; font-size:medium; color: #333333; }
CODE { font-size: medium; color: blue;}
code.TEMPLATE { color: blue; }
code.OUTPUT { color: green; }
A:link { text-decoration:none; color: #6666aa; }
A:visited { text-decoration:none; color: #6666aa; }
A:active { text-decoration:none; color: #6666aa; }
A:hover { text-decoration; color:#FF0000 }
pygdchart2alpha2/doc/images 0040755 0001750 0001750 00000000000 07774433232 0014647 5 ustar 00aldo aldo pygdchart2alpha2/doc/images/simple.png 0100644 0001750 0001750 00000003150 07774433232 0016721 0 ustar 00aldo aldo PNG
IHDR zG $PLTE
22f%Z
n4 IDATxKr0Ql$ EQT#>66zG5n$c4?=n\(9^\B U֑Pj%?iڞ>i}455VU=A5}=Le%!}!iuj7h}z5R}, =}֥vu=˩
_5FY<}w?95M^H^XeeK eKeeK o3^}B(Dӟ57ܹ^o+ҏ\;(.;s҉z>@s傤ӥu?ѝN_#ĝ˝(*}:\}u
z>d~5Ў3>.wGw6]Ԧr6.wCn|є]t.vz;zxab$.O(wңKr]LsPz.]/ϑ.\$wSv?Ȥʔكw{آO1:>8c1%xwAUCG<cO gKinTr]Pyk3F kwK`OSQj>]2pg7]?w 75. #:fw[YkފF.<.m']p4s҅]Ty4s.vy>I͜0]]ZvUt|sq
.x|莠߁yx|CtJJ%f|Gcۉc)Iּ5ƕ=qǿURt*xsr#t'h{k[%%݅"Zk"nxwQH/t 5^|@W4"'&hmZvuV&쫬Bgv2ŋs|܅.3Ž.VBz ү)*M:IOWiСLzҠC쵉/0ʴ?Ê
zM/gKq.]rz]jb/b?b/H?M^n(:rPz}1wqFuU|^qmZd:8koE=]~hZǖC^gϊyxeyxe摻hAovkMN,](/Dӏtݢ]8?F~#zZ¦!_"'JkܸW&u=vL¢!_"'I݅E7o
h9`+.L_ %_!zZU#bv-Ӥ[!{b>GwO^_11vFP]u3@yD04ˆ2A9vN#f^hytt;!k9"au4Ï%#z\4"zSn~c#̸ۥxᅠHgeNTx#}l8[5?5?]t4zVZOp/TI͞ IENDB` pygdchart2alpha2/doc/images/area.png 0100644 0001750 0001750 00000002445 07774433232 0016346 0 ustar 00aldo aldo PNG
IHDR PLTE IDATx;6 PQ)@jhhYJ)#e&,ay?ymIt1y,;х m$Uɞ^M|%#bO}wxEF
oEA2>}Bbr1SEz^%H=