Plots added
This commit is contained in:
parent
6aefad8ab1
commit
f5309c96e1
71
forms.py
71
forms.py
@ -13,8 +13,13 @@ ID_DUPLICATE_MODEL = wx.NewId()
|
|||||||
ID_DUPLICATE_TREE = wx.NewId()
|
ID_DUPLICATE_TREE = wx.NewId()
|
||||||
ID_DELETE_MODEL = wx.NewId()
|
ID_DELETE_MODEL = wx.NewId()
|
||||||
ID_PROCESS_MODEL = wx.NewId()
|
ID_PROCESS_MODEL = wx.NewId()
|
||||||
|
|
||||||
ID_SHOW_RESULT = wx.NewId()
|
ID_SHOW_RESULT = wx.NewId()
|
||||||
ID_SHOW_PLOT = wx.NewId()
|
ID_SHOW_PLOT = wx.NewId()
|
||||||
|
ID_ADD_PLOT = wx.NewId()
|
||||||
|
ID_ADD_LINE = wx.NewId()
|
||||||
|
|
||||||
|
ID_ABOUT = wx.NewId()
|
||||||
|
|
||||||
class TreeListCtrl(wx.gizmos.TreeListCtrl):
|
class TreeListCtrl(wx.gizmos.TreeListCtrl):
|
||||||
|
|
||||||
@ -55,12 +60,13 @@ class MainFrame (wx.Frame):
|
|||||||
|
|
||||||
self.m_user_models = TreeListCtrl(self,
|
self.m_user_models = TreeListCtrl(self,
|
||||||
style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT
|
style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT
|
||||||
| wx.TR_EDIT_LABELS | wx.TR_ROW_LINES | wx.TR_MULTIPLE)
|
| wx.TR_FULL_ROW_HIGHLIGHT | wx.TR_ROW_LINES | wx.TR_MULTIPLE)
|
||||||
self.m_user_models.SetMinSize(wx.Size(-1, 300))
|
self.m_user_models.SetMinSize(wx.Size(-1, 300))
|
||||||
self.m_user_models.AddColumn("Model name")
|
self.m_user_models.AddColumn("Model name")
|
||||||
self.m_user_models.AddColumn("Status")
|
self.m_user_models.AddColumn("Status")
|
||||||
self.m_user_models.AddColumn("Progress")
|
self.m_user_models.AddColumn("Progress")
|
||||||
self.m_user_models.AddColumn("Comment")
|
self.m_user_models.AddColumn("Comment")
|
||||||
|
self.m_user_models.SetMainColumn(0)
|
||||||
|
|
||||||
bSizer4.Add(self.m_user_models, 0, wx.ALL | wx.EXPAND, 1)
|
bSizer4.Add(self.m_user_models, 0, wx.ALL | wx.EXPAND, 1)
|
||||||
|
|
||||||
@ -79,6 +85,7 @@ class MainFrame (wx.Frame):
|
|||||||
bSizer5.Add(self.m_quick_result, 1, wx.EXPAND | wx.ALL, 1)
|
bSizer5.Add(self.m_quick_result, 1, wx.EXPAND | wx.ALL, 1)
|
||||||
|
|
||||||
self.m_plots = wx.TreeCtrl(self, style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
|
self.m_plots = wx.TreeCtrl(self, style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
|
||||||
|
self.m_plots.AddRoot('root')
|
||||||
bSizer5.Add(self.m_plots, 1, wx.EXPAND | wx.ALL, 1)
|
bSizer5.Add(self.m_plots, 1, wx.EXPAND | wx.ALL, 1)
|
||||||
|
|
||||||
bSizer3.Add(bSizer5, 0, wx.ALL | wx.EXPAND, 1)
|
bSizer3.Add(bSizer5, 0, wx.ALL | wx.EXPAND, 1)
|
||||||
@ -90,13 +97,16 @@ class MainFrame (wx.Frame):
|
|||||||
self.SetMenuBar(mbar)
|
self.SetMenuBar(mbar)
|
||||||
self.BuildContextMenu()
|
self.BuildContextMenu()
|
||||||
|
|
||||||
|
#tbar = self.BuildToolBar()
|
||||||
|
#self.SetToolBar(tbar)
|
||||||
|
|
||||||
self.SetSizer(bSizer3)
|
self.SetSizer(bSizer3)
|
||||||
self.Layout()
|
self.Layout()
|
||||||
|
|
||||||
self.Centre(wx.BOTH)
|
self.Centre(wx.BOTH)
|
||||||
|
|
||||||
def __del__(self):
|
il = wx.ImageList(16, 16)
|
||||||
pass
|
|
||||||
|
|
||||||
def BuildMenu(self):
|
def BuildMenu(self):
|
||||||
menubar = wx.MenuBar()
|
menubar = wx.MenuBar()
|
||||||
@ -106,9 +116,7 @@ class MainFrame (wx.Frame):
|
|||||||
menubar.Append(menu, '&File')
|
menubar.Append(menu, '&File')
|
||||||
|
|
||||||
menu = wx.Menu()
|
menu = wx.Menu()
|
||||||
menu.Append(ID_PROCESS_MODEL, 'Process\tCtrl+R')
|
menu.Append(ID_PROCESS_MODEL, 'Process\tF5')
|
||||||
menu.Append(ID_SHOW_RESULT, 'Show result\tCtrl+S')
|
|
||||||
menu.Append(ID_SHOW_PLOT, 'Show plot\tCtrl+G')
|
|
||||||
menu.AppendSeparator()
|
menu.AppendSeparator()
|
||||||
menu.Append(ID_ADD_MODEL_ROOT, 'Add model to root')
|
menu.Append(ID_ADD_MODEL_ROOT, 'Add model to root')
|
||||||
menu.Append(ID_ADD_MODEL_SELECTED, 'Append model to selected')
|
menu.Append(ID_ADD_MODEL_SELECTED, 'Append model to selected')
|
||||||
@ -121,8 +129,15 @@ class MainFrame (wx.Frame):
|
|||||||
menubar.Append(menu, '&Model')
|
menubar.Append(menu, '&Model')
|
||||||
|
|
||||||
menu = wx.Menu()
|
menu = wx.Menu()
|
||||||
menu.Append(3, "&Log In\tCtrl+L")
|
menu.Append(ID_SHOW_RESULT, 'Show result\tCtrl+S')
|
||||||
menu.Append(2, "&Options\tCtrl+P")
|
menu.AppendSeparator()
|
||||||
|
menu.Append(ID_SHOW_PLOT, 'Show plot\tCtrl+G')
|
||||||
|
menu.Append(ID_ADD_PLOT, 'Add plot')
|
||||||
|
menu.Append(ID_ADD_LINE, 'Add line')
|
||||||
|
menubar.Append(menu, '&Result')
|
||||||
|
|
||||||
|
menu = wx.Menu()
|
||||||
|
menu.Append(ID_ABOUT, "&About\tF1")
|
||||||
menubar.Append(menu, '&Help')
|
menubar.Append(menu, '&Help')
|
||||||
|
|
||||||
return menubar
|
return menubar
|
||||||
@ -135,6 +150,19 @@ class MainFrame (wx.Frame):
|
|||||||
self.m_specs.Bind(wx.EVT_CONTEXT_MENU,
|
self.m_specs.Bind(wx.EVT_CONTEXT_MENU,
|
||||||
lambda x: self.m_specs.PopupMenu(menu))
|
lambda x: self.m_specs.PopupMenu(menu))
|
||||||
|
|
||||||
|
menu1 = wx.Menu()
|
||||||
|
menu1.Append(ID_ADD_PLOT, 'Add plot')
|
||||||
|
menu1.Append(ID_ADD_LINE, 'Add line')
|
||||||
|
self.m_plots.Bind(wx.EVT_CONTEXT_MENU,
|
||||||
|
lambda x: self.m_plots.PopupMenu(menu1))
|
||||||
|
|
||||||
|
|
||||||
|
def BuildToolBar(self):
|
||||||
|
tbar = wx.ToolBar(self, -1)
|
||||||
|
tbar.AddLabelTool(ID_SHOW_PLOT, 'Show plot', wx.Bitmap('share/show-plot.png'))
|
||||||
|
tbar.Realize()
|
||||||
|
return tbar
|
||||||
|
|
||||||
class ResultFrame(wx.Frame):
|
class ResultFrame(wx.Frame):
|
||||||
def __init__(self, parent, title):
|
def __init__(self, parent, title):
|
||||||
wx.Frame.__init__ (self, parent, -1, title, size = wx.Size(500, 500),
|
wx.Frame.__init__ (self, parent, -1, title, size = wx.Size(500, 500),
|
||||||
@ -155,8 +183,35 @@ class ResultFrame(wx.Frame):
|
|||||||
self.Layout()
|
self.Layout()
|
||||||
self.Centre(wx.BOTH)
|
self.Centre(wx.BOTH)
|
||||||
|
|
||||||
|
class LineSelectDialog(wx.Dialog):
|
||||||
|
def __init__(self, parent, title):
|
||||||
|
wx.Dialog.__init__ (self, parent, -1, title, size = wx.Size(400, 300))
|
||||||
|
|
||||||
|
bSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
self.left = wx.ListBox(self)
|
||||||
|
self.right = wx.ListBox(self, style = wx.LB_EXTENDED)
|
||||||
|
|
||||||
|
bSizer.Add(self.left, 1, wx.EXPAND | wx.ALL, 2)
|
||||||
|
bSizer.Add(self.right, 1, wx.EXPAND | wx.ALL, 2)
|
||||||
|
|
||||||
|
buttonsSizer = self.CreateButtonSizer(wx.OK | wx.CANCEL)
|
||||||
|
|
||||||
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
|
sizer.Add(bSizer, 1, wx.EXPAND | wx.ALL, 0)
|
||||||
|
sizer.Add(buttonsSizer, 0, wx.EXPAND | wx.ALL, 5)
|
||||||
|
|
||||||
|
self.SetSizer(sizer)
|
||||||
|
self.Layout()
|
||||||
|
self.Centre(wx.BOTH)
|
||||||
|
|
||||||
|
|
||||||
class PlotFrame(wx.Frame):
|
class PlotFrame(wx.Frame):
|
||||||
def __init__(self, parent, title):
|
def __init__(self, parent, title):
|
||||||
wx.Frame.__init__ (self, parent, -1, title, size = wx.Size(600, 400))
|
wx.Frame.__init__ (self, parent, -1, title, size = wx.Size(600, 400))
|
||||||
|
|
||||||
self.plot = wxplot.PlotCanvas(self)
|
self.plot = wxplot.PlotCanvas(self)
|
||||||
|
self.plot.SetGridColour(wx.Color(200, 200, 200))
|
||||||
|
self.plot.SetEnableGrid(True)
|
||||||
|
self.plot.SetEnableAntiAliasing(True)
|
||||||
|
self.plot.SetEnableHiRes(True)
|
||||||
|
176
opal.py
176
opal.py
@ -15,6 +15,7 @@ import server
|
|||||||
import task
|
import task
|
||||||
import wx
|
import wx
|
||||||
import wx.propgrid as wxpg
|
import wx.propgrid as wxpg
|
||||||
|
import wx.lib.plot as wxplot
|
||||||
import forms
|
import forms
|
||||||
import time
|
import time
|
||||||
import datetime
|
import datetime
|
||||||
@ -69,6 +70,8 @@ class MainFrame(forms.MainFrame):
|
|||||||
self.OnAddModelToSelected)
|
self.OnAddModelToSelected)
|
||||||
self.m_user_models.Bind(wx.EVT_TREE_ITEM_ACTIVATED,
|
self.m_user_models.Bind(wx.EVT_TREE_ITEM_ACTIVATED,
|
||||||
self.OnModelProcess)
|
self.OnModelProcess)
|
||||||
|
self.m_plots.Bind(wx.EVT_TREE_ITEM_ACTIVATED,
|
||||||
|
self.OnPlotProcess)
|
||||||
|
|
||||||
|
|
||||||
self.Bind(wx.EVT_MENU, self.OnTest,
|
self.Bind(wx.EVT_MENU, self.OnTest,
|
||||||
@ -85,12 +88,27 @@ class MainFrame(forms.MainFrame):
|
|||||||
id = forms.ID_DELETE_MODEL)
|
id = forms.ID_DELETE_MODEL)
|
||||||
self.Bind(wx.EVT_MENU, self.OnModelProcess,
|
self.Bind(wx.EVT_MENU, self.OnModelProcess,
|
||||||
id = forms.ID_PROCESS_MODEL)
|
id = forms.ID_PROCESS_MODEL)
|
||||||
|
|
||||||
self.Bind(wx.EVT_MENU, self.OnShowResult,
|
self.Bind(wx.EVT_MENU, self.OnShowResult,
|
||||||
id = forms.ID_SHOW_RESULT)
|
id = forms.ID_SHOW_RESULT)
|
||||||
|
self.Bind(wx.EVT_MENU, self.OnShowPlot,
|
||||||
|
id = forms.ID_SHOW_PLOT)
|
||||||
|
self.Bind(wx.EVT_MENU, self.OnAddPlot,
|
||||||
|
id = forms.ID_ADD_PLOT)
|
||||||
|
self.Bind(wx.EVT_MENU, self.OnAddLines,
|
||||||
|
id = forms.ID_ADD_LINE)
|
||||||
|
|
||||||
self.Bind(wx.EVT_CLOSE, self.OnClose)
|
self.Bind(wx.EVT_CLOSE, self.OnClose)
|
||||||
self.Bind(wx.EVT_IDLE, self.OnIdle)
|
self.Bind(wx.EVT_IDLE, self.OnIdle)
|
||||||
|
|
||||||
|
# если установлен в True, то обработчик состояний работ
|
||||||
|
# будет работать вхолостую, чтобы не создать deadlock
|
||||||
|
# проблема возникает в том, что при одновременной блокировке
|
||||||
|
# GUI и вызова модального диалога, последний весит все приложение напрочь
|
||||||
|
# в момент своего закрытия. а так как диалог все равно модальный,
|
||||||
|
# форме не обязательно обновляться в тот момент, когда он открыт
|
||||||
|
self.do_nothing = False
|
||||||
|
|
||||||
ov = threading.Thread(target = self.Overseer)
|
ov = threading.Thread(target = self.Overseer)
|
||||||
ov.daemon = True
|
ov.daemon = True
|
||||||
ov.start()
|
ov.start()
|
||||||
@ -126,7 +144,14 @@ class MainFrame(forms.MainFrame):
|
|||||||
um = self.m_user_models
|
um = self.m_user_models
|
||||||
cycle_count = 0
|
cycle_count = 0
|
||||||
while True:
|
while True:
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
# если нужно подождать, то мы подождем
|
||||||
|
if self.do_nothing:
|
||||||
|
continue
|
||||||
|
|
||||||
wx.MutexGuiEnter()
|
wx.MutexGuiEnter()
|
||||||
|
try:
|
||||||
# print 'cycle{:-8}'.format(cycle_count)
|
# print 'cycle{:-8}'.format(cycle_count)
|
||||||
cycle_count += 1
|
cycle_count += 1
|
||||||
# просматриваем всю иерархию моделей
|
# просматриваем всю иерархию моделей
|
||||||
@ -150,9 +175,9 @@ class MainFrame(forms.MainFrame):
|
|||||||
# то сразу же показываем этот результат
|
# то сразу же показываем этот результат
|
||||||
if um.IsSelected(item):
|
if um.IsSelected(item):
|
||||||
self.ShowQuickResult(data.res)
|
self.ShowQuickResult(data.res)
|
||||||
|
finally:
|
||||||
wx.MutexGuiLeave()
|
wx.MutexGuiLeave()
|
||||||
time.sleep(0.1)
|
pass
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print 'Error in overseer: ', e
|
print 'Error in overseer: ', e
|
||||||
|
|
||||||
@ -227,16 +252,22 @@ class MainFrame(forms.MainFrame):
|
|||||||
um.Expand(root)
|
um.Expand(root)
|
||||||
|
|
||||||
def NewProject(self, model):
|
def NewProject(self, model):
|
||||||
# 1. загрузить спецификации модели
|
"""
|
||||||
# 2. создать одну модель по умолчанию
|
Начать новый проект:
|
||||||
|
1. Построить дерево спецификаций
|
||||||
|
2. Создать одну пользовательскую модель (по умолчанию)
|
||||||
|
3. Сделать заготовки для графиков/отчетов/прочего
|
||||||
|
"""
|
||||||
|
# Строим спецификации
|
||||||
self.BuildSpecs(model)
|
self.BuildSpecs(model)
|
||||||
|
# Очищаем окно пользовательских моделей
|
||||||
|
# и создаем там одну
|
||||||
um = self.m_user_models
|
um = self.m_user_models
|
||||||
um.DeleteAllItems()
|
um.DeleteAllItems()
|
||||||
um.AddRoot('Root')
|
um.AddRoot('root')
|
||||||
|
|
||||||
self.AddModelToRoot(model)
|
self.AddModelToRoot(model)
|
||||||
|
# Создаем корневой элемент для окна с графиками
|
||||||
|
self.m_plots.AddRoot('root')
|
||||||
|
|
||||||
return True # Project(model)
|
return True # Project(model)
|
||||||
|
|
||||||
@ -394,6 +425,89 @@ class MainFrame(forms.MainFrame):
|
|||||||
rframe = ResultFrame(self, title, data.res)
|
rframe = ResultFrame(self, title, data.res)
|
||||||
rframe.Show()
|
rframe.Show()
|
||||||
|
|
||||||
|
def GetLines(self):
|
||||||
|
"""
|
||||||
|
Возвращает набор линий, которые пользователь указал для
|
||||||
|
построения графика к выбранной модели.
|
||||||
|
|
||||||
|
Линии представляют из себя кортежи из 4х элементов:
|
||||||
|
[ внутренний индекс в иерархии моделей,
|
||||||
|
данные модели,
|
||||||
|
колонка-х,
|
||||||
|
колонка-у ]
|
||||||
|
"""
|
||||||
|
um = self.m_user_models
|
||||||
|
item, data = self.GetSelectedItemData(um)
|
||||||
|
title = um.GetItemText(item)
|
||||||
|
if not data.res:
|
||||||
|
self.SetStatusText("There is no results in model")
|
||||||
|
return []
|
||||||
|
f = LineSelectDialog(self, 'Select lines for "{}"'.format(title))
|
||||||
|
for index, col in enumerate(data.res.columns):
|
||||||
|
row_title = col.GetTitle()
|
||||||
|
row_data = index
|
||||||
|
f.Add(row_title, row_data)
|
||||||
|
f.SetSelections()
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
self.do_nothing = True
|
||||||
|
try:
|
||||||
|
if f.ShowModal() == wx.ID_OK:
|
||||||
|
lines = [ (item, data, x, y) for x, y in f.GetData() ]
|
||||||
|
finally:
|
||||||
|
self.do_nothing = False
|
||||||
|
|
||||||
|
return lines
|
||||||
|
|
||||||
|
def ShowPlot(self, lines, title = ''):
|
||||||
|
if not lines:
|
||||||
|
return
|
||||||
|
|
||||||
|
data = []
|
||||||
|
for item, moddata, x, y in lines:
|
||||||
|
data.append(moddata.res.Zip(x, y))
|
||||||
|
|
||||||
|
p = PlotFrame(self, 'Plot for model "%s"' % title, data)
|
||||||
|
p.Show()
|
||||||
|
|
||||||
|
|
||||||
|
def OnShowPlot(self, event):
|
||||||
|
lines = self.GetLines()
|
||||||
|
self.ShowPlot(lines)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def OnAddPlot(self, event):
|
||||||
|
root = self.m_plots.GetRootItem()
|
||||||
|
child = self.m_plots.AppendItem(root, 'New plot')
|
||||||
|
self.m_plots.SetPyData(child, 'plot')
|
||||||
|
|
||||||
|
def OnAddLines(self, event):
|
||||||
|
item = self.m_plots.GetSelection()
|
||||||
|
data = self.m_plots.GetItemPyData(item)
|
||||||
|
if data != 'plot':
|
||||||
|
return
|
||||||
|
lines = self.GetLines()
|
||||||
|
if not lines:
|
||||||
|
return
|
||||||
|
for line in lines:
|
||||||
|
child = self.m_plots.AppendItem(item, 'Line')
|
||||||
|
self.m_plots.SetPyData(child, line)
|
||||||
|
|
||||||
|
def OnPlotProcess(self, event):
|
||||||
|
item = self.m_plots.GetSelection()
|
||||||
|
data = self.m_plots.GetItemPyData(item)
|
||||||
|
lines = []
|
||||||
|
if data == 'plot':
|
||||||
|
child, cookie = self.m_plots.GetFirstChild(item)
|
||||||
|
while child.IsOk():
|
||||||
|
lines.append(self.m_plots.GetItemPyData(child))
|
||||||
|
child, cookie = self.m_plots.GetNextChild(item, cookie)
|
||||||
|
else:
|
||||||
|
lines = [data]
|
||||||
|
|
||||||
|
self.ShowPlot(lines)
|
||||||
|
|
||||||
def OnIdle(self, event):
|
def OnIdle(self, event):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -431,6 +545,52 @@ class ResultFrame(forms.ResultFrame):
|
|||||||
for label, param in self.result.data.iteritems():
|
for label, param in self.result.data.iteritems():
|
||||||
pg.Append(wxpg.StringProperty(label, value = str(param.GetValue())))
|
pg.Append(wxpg.StringProperty(label, value = str(param.GetValue())))
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Форма с выбором наборов значений для построения графика
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class LineSelectDialog(forms.LineSelectDialog):
|
||||||
|
def __init__(self, parent, title):
|
||||||
|
forms.LineSelectDialog.__init__(self, parent, title)
|
||||||
|
|
||||||
|
def Add(self, title, data = None):
|
||||||
|
self.left.Append(title, data)
|
||||||
|
self.right.Append(title, data)
|
||||||
|
|
||||||
|
def SetSelections(self):
|
||||||
|
if self.left.GetCount():
|
||||||
|
self.left.Select(0)
|
||||||
|
for i in xrange(1, self.right.GetCount()):
|
||||||
|
self.right.Select(i)
|
||||||
|
|
||||||
|
def GetData(self):
|
||||||
|
item = self.left.GetSelection()
|
||||||
|
x = self.left.GetClientData(item)
|
||||||
|
|
||||||
|
items = self.right.GetSelections()
|
||||||
|
ys = [ self.right.GetClientData(i) for i in items ]
|
||||||
|
|
||||||
|
return [ (x, y) for y in ys ]
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Форма с изображением графика
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class PlotFrame(forms.PlotFrame):
|
||||||
|
def __init__(self, parent, title, lines_with_data):
|
||||||
|
forms.PlotFrame.__init__(self, parent, title)
|
||||||
|
#self.data = data
|
||||||
|
data = lines_with_data
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
colours = ['red', 'blue', 'green']
|
||||||
|
for i, d in enumerate(data):
|
||||||
|
lines.append( wxplot.PolyLine(d, colour = colours[i % len(colours)]) )
|
||||||
|
|
||||||
|
graph = wxplot.PlotGraphics(lines)
|
||||||
|
self.plot.Draw(graph)
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
# Приложение
|
# Приложение
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
|
BIN
share/show-plot.png
Normal file
BIN
share/show-plot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 472 B |
6
task.py
6
task.py
@ -181,3 +181,9 @@ class ResultData:
|
|||||||
return self.table
|
return self.table
|
||||||
|
|
||||||
rows = property(GetRows)
|
rows = property(GetRows)
|
||||||
|
|
||||||
|
def GetColumn(self, index):
|
||||||
|
return [ row[index] for row in self.rows ]
|
||||||
|
|
||||||
|
def Zip(self, col1, col2):
|
||||||
|
return [ (row[col1], row[col2]) for row in self.rows ]
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
"author": "Anton Vakhrushev",
|
"author": "Anton Vakhrushev",
|
||||||
"date": "2012-03-08",
|
"date": "2012-03-08",
|
||||||
|
|
||||||
"exec": false,
|
"exec": true,
|
||||||
|
|
||||||
"params": {
|
"params": {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user