how to block the loops when storing in a database? - python

I have got a problem with my current script where I'm working on the keyboard event for xbmc. When I'm pressing on the enter button of the keyboard, the code will keep firing by re-fetching the same values from the XML tags which it will keep doing it over and over for number of times and it will keep storing the same values in the database when there are few values from the XML tags called 'display-name'.
Here's the code:
import xbmc
import xbmcgui
import xbmcaddon
import os
import urllib2
import StringIO
import sqlite3
from sqlite3 import dbapi2 as database
from xml.etree import ElementTree
class Channel:
def __init__(self):
self.__display_name = None
self.__icon = None
self.__programs = []
def get_display_name(self):
return self.__display_name
def get_icon(self):
return self.__icon
def get_programs(self):
return self.__programs
def set_display_name(self, value):
self.__display_name = value
def set_icon(self, value):
self.__icon = value
def set_programs(self, value):
self.__programs = value
def del_display_name(self):
del self.__display_name
def del_icon(self):
del self.__icon
def del_programs(self):
del self.__programs
display_name = property(get_display_name, set_display_name, del_display_name, "display_name's docstring")
icon = property(get_icon, set_icon, del_icon, "icon's docstring")
programs = property(get_programs, set_programs, del_programs, "programs's docstring")
class Programme:
def __init__(self):
self.__start = None
self.__stop = None
self.__title = None
self.__sub_title = None
self.__desc = None
self.__category = []
self.__credits = []
self.__icon = None
self.__episode_num = None
def get_episode_num(self):
return self.__episode_num
def set_episode_num(self, value):
self.__episode_num = value
def del_episode_num(self):
del self.__episode_num
def get_start(self):
return self.__start
def get_stop(self):
return self.__stop
def get_title(self):
return self.__title
def get_sub_title(self):
return self.__sub_title
def get_desc(self):
return self.__desc
def get_category(self):
return self.__category
def get_credits(self):
return self.__credits
def get_icon(self):
return self.__icon
def set_start(self, value):
self.__start = value
def set_stop(self, value):
self.__stop = value
def set_title(self, value):
self.__title = value
def set_sub_title(self, value):
self.__sub_title = value
def set_desc(self, value):
self.__desc = value
def set_category(self, value):
self.__category = value
def set_credits(self, value):
self.__credits = value
def set_icon(self, value):
self.__icon = value
def del_start(self):
del self.__start
def del_stop(self):
del self.__stop
def del_title(self):
del self.__title
def del_sub_title(self):
del self.__sub_title
def del_desc(self):
del self.__desc
def del_category(self):
del self.__category
def del_credits(self):
del self.__credits
def del_icon(self):
del self.__icon
start = property(get_start, set_start, del_start, "start's docstring")
stop = property(get_stop, set_stop, del_stop, "stop's docstring")
title = property(get_title, set_title, del_title, "title's docstring")
sub_title = property(get_sub_title, set_sub_title, del_sub_title, "sub_title's docstring")
desc = property(get_desc, set_desc, del_desc, "desc's docstring")
category = property(get_category, set_category, del_category, "category's docstring")
creditss = property(get_credits, set_credits, del_credits, "credits's docstring")
icon = property(get_icon, set_icon, del_icon, "icon's docstring")
episode_num = property(get_episode_num, set_episode_num, del_episode_num, "episode_num's docstring")
class Credits:
def __init__(self):
self.__type = None
self.__role = None
self.__name = None
def get_type(self):
return self.__type
def get_role(self):
return self.__role
def get_name(self):
return self.__name
def set_type(self, value):
self.__type = value
def set_role(self, value):
self.__role = value
def set_name(self, value):
self.__name = value
def del_type(self):
del self.__type
def del_role(self):
del self.__role
def del_name(self):
del self.__name
type = property(get_type, set_type, del_type, "type's docstring")
role = property(get_role, set_role, del_role, "role's docstring")
name = property(get_name, set_name, del_name, "name's docstring")
class MyClass(xbmcgui.WindowXML):
def __new__(cls):
return super(MyClass, cls).__new__(cls, 'script-tvguide-mainmenu.xml', ADDON.getAddonInfo('path'))
def onInit(self):
pass
def load_channel(self, elem):
channel = Channel()
for elem in elem.getchildren():
if elem.tag == 'display-name':
channel.set_display_name(elem.text)
elif elem.tag == 'icon':
channel.set_icon(elem.attrib['src'])
return channel
def load_programme(self, elem):
programme = Programme()
programme.set_start(elem.attrib['start'])
programme.set_stop(elem.attrib['stop'])
for elem in elem.getchildren():
if elem.tag == 'title':
programme.set_title(elem.text)
elif elem.tag == 'sub-title':
programme.set_title(elem.text)
elif elem.tag == 'desc':
programme.set_desc(elem.text)
elif elem.tag == 'category':
categories = programme.get_category()
categories.append(elem.text)
elif elem.tag == 'episode-num':
programme.set_episode_num(elem.text)
elif elem.tag == 'credits':
creditss = programme.get_credits()
creditss.append(self.load_credits(elem))
elif elem.tag == 'icon':
programme.set_icon(elem.attrib['src'])
return programme
def load_credits(self, elem):
creditss = Credits()
for elem in elem.getchildren():
if elem.tag == 'actor':
creditss.set_name(elem.text)
creditss.set_type('actor')
elif elem.tag == 'presenter':
creditss.set_name(elem.text)
creditss.set_type('presenter')
elif elem.tag == 'director':
creditss.set_name(elem.text)
creditss.set_type('director')
return credits
def onAction(self, action):
if action == ACTION_ENTER:
#OPEN THE XML SOURCE
url = ADDON.getSetting('ontv.url')
req = urllib2.Request(url)
response = urllib2.urlopen(req)
data = response.read()
response.close()
profilePath = xbmc.translatePath(os.path.join('special://userdata/addon_data/script.tvguide', ''))
if os.path.exists(profilePath):
profilePath = profilePath + 'source.db'
con = database.connect(profilePath)
cur = con.cursor()
cur.execute('CREATE TABLE programs(id TEXT, channel TEXT, title TEXT, start_date TIMESTAMP, end_date TIMESTAMP, description TEXT)')
con.commit()
con.close
tv_elem = ElementTree.parse(StringIO.StringIO(data)).getroot()
channels = {}
for elem in tv_elem.getchildren():
if elem.tag == 'channel':
channels[elem.attrib['id']] = self.load_channel(elem)
elif elem.tag == 'programme':
# get channel
channel = channels[elem.attrib['channel']]
# load program in channel
channel.get_programs().append(self.load_programme(elem))
# Print the loaded data
for channel_key in channels:
channel = channels[channel_key]
print channel.get_display_name() + ' :: ' + channel.get_icon() + ' :: Total programs = ' + str(len(channel.get_programs()))
display_name = channel.get_display_name()
profilePath = xbmc.translatePath(os.path.join('special://userdata/addon_data/script.tvguide', ''))
profilePath = profilePath + 'source.db'
con = sqlite3.connect(profilePath)
cur = con.cursor()
if not display_name in cur:
cur.execute("INSERT INTO programs(id, channel)" + " VALUES(?, ?)", [display_name, 0])
con.commit()
cur.close
print 'Channels store into database are now successfully!'
Here's the xml logs: http://xbmclogs.com/show.php?id=143587
Here's the database: http://testbox.elementfx.com/source.db
And here's the xml file: http://ontv.dk/xmltv/c81e728d9d4c2f636f067f89cc14862c
I only want to write the values in a database without keep re-fetching the same values over and over when I get the values from the XML tags.
Do you know how I can stop re-fetching the same values over and over when I store them in a database without keep running like a loop?

Related

Transferring Classes/Tables from a module to a main function:

recently I have been trying to recreate lua's Table module in python:
class Table():
def __init__(self):
try:
self.Size = enumerate(self)
except:
self.Size = 0
def size(query):
index = 0
for v in query.__dict__.items():
index+=1
return index
def create(query, items=None, t=None):
if items == None and t == None:
class temp():
def __init__(self):
self.Size = Table.size(self)
globals()[query] = temp
elif items != None and t == None:
class test():
def add_child(self, child, val):
setattr(self, child, val)
Size = 6
globals()[query] = test
_ = items.split(',')
Table.create('tempe')
for _z in _:
_f = _z.split('=')
setattr(tempe,_f[0],_f[1])
msg = ('v',str(Table.size(test)+1))
setattr(test,''.join(msg),tempe)
elif t == 'child' and query is not None and type(query) == type:
_ = items.split(',')
Table.create('tempe')
for _z in _:
_f = _z.split('=')
setattr(tempe, _f[0], _f[1])
msg = ('v',str(Table.size(query)+1))
setattr(query,''.join(msg),tempe)
else:
pass
def insert(query, items):
Table.create(query, items, 'child')
def remove(query, item):
temp = ('v', str(item))
item = ''.join(temp)
for k in query.__dict__.items():
for m in k:
if m == item:
del m
def pairs(query,func):
index = 0
for _ in query.__dict__.items():
index+=1
if index > query.Size:
for out in _:
if type(out) == type:
i = index-query.Size
v = out
func(i,v)
Now on its own, that works fine. But now I'm trying to put it into a seperate file so I can do:
from Resources import Table, #other stuff
Table.create('test', 'var1 = 10, var2=Hello World!, var3 = 69')
def pr(i,v):
print(f'{i} = [var1 = {v.var1}, var2 = {v.var2}, var3 = {v.var3}]')
pairs(test,pr)
If I ran that not as a module, I would get:
#1 = [var1 = 10, var2 = Hello World!, var3 = 69]
However when its in a separate file, 'test' does not become a variable.
Any advice/tips are apprecianted.

How to insert row data in QAbstractItemModel through a QSortFilterProxyModel?

This is a follow up to a question that I asked yesterday: QTreeView QAbstractItemModel parent collapses after deleting item and sometimes crashes
As i was writing this, i thought it would be cool to add some search features, so I attempted incorporating a QSortFiltertProxyModel. By doing this I realize now that totally complicated things, but I really like where this is going so i would like to keep up with it.
Now a lot of the functionality that i want mostly seems to work, but especially when attempting to add new row data it seems to crash. And at various times i get these errors that says QSortFilterProxyModel: index from wrong model passed to mapFromSource (im really not sure where this is coming from)
the current code for this:
import sys
from functools import partial
from PyQt4 import QtGui, QtCore
HORIZONTAL_HEADERS = ("Asset Name", "Date Added")
class AssetClass(object):
'''
a trivial custom data object
'''
def __init__(self, **kwargs):
if not kwargs.get('name') or not kwargs.get('type'):
return
self.name = kwargs.get('name')
self.date_added = kwargs.get('date_added')
self.type = kwargs.get('type')
def __repr__(self):
return "%s - %s %s" % (self.type, self.name, self.date_added)
class TreeItem(object):
'''
a python object used to return row/column data, and keep note of
it's parents and/or children
'''
def __init__(self, asset, header, parent_item):
self.asset = asset
self.parent_item = parent_item
self.header = header
self.child_items = []
def appendChild(self, item):
self.child_items.append(item)
def removeChild(self, row):
print 'removeChild: item is %s' % self.child_items[row]
del self.child_items[row]
def child(self, row):
return self.child_items[row]
def childCount(self):
return len(self.child_items)
def columnCount(self):
return 2
def data(self, column):
if self.asset == None:
if column == 0:
return QtCore.QVariant(self.header)
if column == 1:
return QtCore.QVariant("")
else:
if column == 0:
return QtCore.QVariant(self.asset.name)
if column == 1:
return QtCore.QVariant(self.asset.date_added)
return QtCore.QVariant()
def parent(self):
return self.parent_item
def row(self):
if self.parent_item:
return self.parent_item.child_items.index(self)
return 0
class TreeModel(QtCore.QAbstractItemModel):
'''
a model to display a few names, ordered by sex
'''
def __init__(self, parent=None):
super(TreeModel, self).__init__(parent)
self.assets = []
model_data = (("VEHICLE", "Truck", 'May 27th, 2020'),
("VEHICLE", "Car", 'May 25th, 2020'),
("CHARACTER", "Peter", 'May 27th, 2020'),
("CHARACTER", "Rachel", 'May 29th, 2020'),
("PROP", "Chair", 'May 27th, 2020'),
("PROP", "Axe", 'May 17th, 2020'))
for asset_type, name, date in model_data:
asset = AssetClass(type=asset_type, name=name, date_added=date)
self.assets.append(asset)
self.rootItem = TreeItem(None, "ALL", None)
self.parents = {0: self.rootItem}
self.setupModelData()
def columnCount(self, parent=None):
if parent and parent.isValid():
return parent.internalPointer().columnCount()
else:
return len(HORIZONTAL_HEADERS)
def data(self, index, role):
if not index.isValid():
return QtCore.QVariant()
item = index.internalPointer()
if role == QtCore.Qt.DisplayRole:
return item.data(index.column())
if role == QtCore.Qt.UserRole:
if item:
return item.asset
return QtCore.QVariant()
def headerData(self, column, orientation, role):
if (orientation == QtCore.Qt.Horizontal and
role == QtCore.Qt.DisplayRole):
try:
return QtCore.QVariant(HORIZONTAL_HEADERS[column])
except IndexError:
pass
return QtCore.QVariant()
def index(self, row, column, parent):
if not self.hasIndex(row, column, parent):
return QtCore.QModelIndex()
if not parent.isValid():
parent_item = self.rootItem
else:
parent_item = parent.internalPointer()
childItem = parent_item.child(row)
if childItem:
return self.createIndex(row, column, childItem)
else:
return QtCore.QModelIndex()
def parent(self, index):
if not index.isValid():
return QtCore.QModelIndex()
childItem = index.internalPointer()
if not childItem:
return QtCore.QModelIndex()
parent_item = childItem.parent()
if parent_item == self.rootItem:
return QtCore.QModelIndex()
return self.createIndex(parent_item.row(), 0, parent_item)
def rowCount(self, parent=QtCore.QModelIndex()):
if parent.column() > 0:
return 0
if not parent.isValid():
p_Item = self.rootItem
else:
p_Item = parent.internalPointer()
return p_Item.childCount()
def setupModelData(self):
for asset in self.assets:
asset_type = asset.type
if not self.parents.has_key(asset_type):
new_parent = TreeItem(None, asset_type, self.rootItem)
self.rootItem.appendChild(new_parent)
self.parents[asset_type] = new_parent
parent_item = self.parents[asset_type]
new_item = TreeItem(asset, "", parent_item)
parent_item.appendChild(new_item)
def addSubRow(self, new_asset):
asset_type, name, date = new_asset
asset = AssetClass(type=asset_type, name=name, date_added=date)
parent_item = self.parents[asset_type]
already_exists = False
for child in parent_item.child_items:
if child.asset.name == name and child.asset.type == asset_type:
already_exists = True
if already_exists:
print 'this asset already exists'
return
new_item = TreeItem(asset, "", parent_item)
parent_item.appendChild(new_item)
def removeRows(self, row, rows, parent=QtCore.QModelIndex()):
# Determine parent
if parent.internalPointer() is None:
parent_node = self.root
else:
parent_node = parent.internalPointer()
# # Delete it from the parent
self.beginRemoveRows(parent, row, row + rows - 1)
parent_node.removeChild(row)
self.endRemoveRows()
return True
def searchModel(self, asset):
'''
get the modelIndex for a given appointment
'''
def searchNode(node):
'''
a function called recursively, looking at all nodes beneath node
'''
for child in node.child_items:
print child.childCount()
if asset == child.asset:
index = self.createIndex(child.row(), 0, child)
return index
if child.childCount() > 0:
result = searchNode(child)
if result:
return result
retarg = searchNode(self.parents[0])
print retarg
return retarg
def findAssetName(self, name):
app = None
for asset in self.assets:
if asset.name == name:
app = asset
break
if app != None:
index = self.searchModel(app)
return (True, index)
return (False, None)
class TreeView(QtGui.QTreeView):
right_button_clicked = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(TreeView, self).__init__(parent)
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.openMenu)
def selectedRows(self):
rows = []
for index in self.selectedIndexes():
if index.column() == 0:
rows.append(index.row())
print type(rows)
return rows
def openMenu(self, position):
indexes = self.selectedIndexes()
if len(indexes) > 0:
level = 0
index = indexes[0]
while index.parent().isValid():
index = index.parent()
level += 1
menu = QtGui.QMenu()
editMenu = None
if level == 0:
editMenu = QtGui.QAction("Edit person", self)
menu.addAction(editMenu)
elif level == 1:
editMenu = QtGui.QAction("Delete", self)
menu.addAction(editMenu)
elif level == 2:
editMenu = QtGui.QAction("Edit object", self)
menu.addAction(editMenu)
if editMenu:
editMenu.triggered.connect(self._on_right_click)
menu.exec_(self.viewport().mapToGlobal(position))
def _on_right_click(self):
self.right_button_clicked.emit()
class Proxy01(QtGui.QSortFilterProxyModel):
def __init__(self):
super(Proxy01, self).__init__()
self.keyword = None
self.searched_parents = None
def setFilterRegExp(self, pattern):
if isinstance(pattern, str):
pattern = QtCore.QRegExp(pattern, QtCore.Qt.CaseInsensitive,
QtCore.QRegExp.FixedString)
super(Proxy01, self).setFilterRegExp(pattern)
def setData(self, index, value, role=QtCore.Qt.EditRole):
# Call source model's setData()
super(Proxy01, self).setData(index, value, role)
self.invalidate()
def _accept_index(self, idx):
if idx.isValid():
text = idx.data(QtCore.Qt.DisplayRole).toString()
if self.filterRegExp().indexIn(text) >= 0:
return True
for row in range(idx.model().rowCount(idx)):
if self._accept_index(idx.model().index(row, 0, idx)):
return True
return False
def filterAcceptsRow(self, source_row, source_parent):
idx = self.sourceModel().index(source_row, 0, source_parent)
return self._accept_index(idx)
class Dialog(QtGui.QDialog):
add_signal = QtCore.pyqtSignal(int)
def __init__(self, parent=None):
super(Dialog, self).__init__(parent)
self.setMinimumSize(300, 150)
self.model = TreeModel()
self.proxy1 = Proxy01()
self.proxy1.setSourceModel(self.model)
self.proxy1.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
layout = QtGui.QVBoxLayout(self)
self.tree_view = TreeView(self)
self.tree_view.setModel(self.proxy1)
self.tree_view.setAlternatingRowColors(True)
self.tree_view.right_button_clicked.connect(self.deleteMenuButtonClicked)
layout.addWidget(self.tree_view)
label = QtGui.QLabel("Search for the following person")
layout.addWidget(label)
search_layout = QtGui.QHBoxLayout(self)
self.search_line_edit = QtGui.QLineEdit()
self.search_line_edit.textChanged.connect(self.updateFilter)
search_layout.addWidget(self.search_line_edit)
search_line_button = QtGui.QPushButton('Search')
search_line_button.setMaximumWidth(75)
search_layout.addWidget(search_line_button)
layout.addLayout(search_layout)
self.add_button = QtGui.QPushButton("Add \"Character - Smith\"")
layout.addWidget(self.add_button)
QtCore.QObject.connect(self.add_button, QtCore.SIGNAL("clicked()"), self.addButtonClicked)
self.delete_button = QtGui.QPushButton("Delete Selected")
layout.addWidget(self.delete_button)
QtCore.QObject.connect(self.delete_button, QtCore.SIGNAL("clicked()"), self.deleteButtonClicked)
self.but = QtGui.QPushButton("Clear Selection")
layout.addWidget(self.but)
QtCore.QObject.connect(self.but, QtCore.SIGNAL("clicked()"), self.tree_view.clearSelection)
QtCore.QObject.connect(self.tree_view, QtCore.SIGNAL("clicked(QModelIndex)"), self.row_clicked)
def row_clicked(self, index):
'''
when a row is clicked... show the name
'''
real_index = self.tree_view.model().mapToSource(index)
print self.tree_view.model().sourceModel().data(real_index, QtCore.Qt.UserRole)
def but_clicked(self):
'''
when a name button is clicked, I iterate over the model,
find the person with this name, and set the treeviews current item
'''
name = self.sender().text()
print "BUTTON CLICKED:", name
result, index = self.model.findAssetName(name)
if result:
if index:
self.tree_view.setCurrentIndex(index)
return
self.tree_view.clearSelection()
def addButtonClicked(self):
new_asset = ("CHARACTER", "Smith", 'May 28th, 2020')
self.tree_view.model().sourceModel().addSubRow(new_asset)
self.tree_view.model().sourceModel().layoutChanged.emit()
#QtCore.pyqtSlot()
def deleteMenuButtonClicked(self):
self.deleteButtonClicked()
def deleteButtonClicked(self):
model = self.tree_view.model()
current = self.tree_view.currentIndex()
model.removeRows(current.row(), 1, model.parent(current))
def customFilter(self):
self.proxy1.setKeyword(self.search_line_edit.text())
def updateFilter(self, text):
self.proxy1.setFilterRegExp(text)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
dialog = Dialog()
dialog.show()
sys.exit(app.exec_())
Based on what I have found, I am sure I need to insert new rows similar to how I am deleting the rows, but the examples i can find I can only find scenarios where the new row to add is declared, but the data is only "inputed" afterwards via edit(). But I would rather pass a AssetClass object directly.
How can I utilize the insertRows(self, row, rows, parent=QtCore.QModelIndex()) method format while actually passing a custom object?
after some inspection, i was able to get this working without any observable errors. I was able to essentially just insert items by directly adjusting the source model, and calling invalidate() on the QSortFilterProxyModel which seems to basically just redraw/refresh it (not sure if this is correct though). I did something similar to deleting an existing row.
full code:
# http://rowinggolfer.blogspot.com/2010/05/qtreeview-and-qabractitemmodel-example.html
import sys
from functools import partial
from PyQt4 import QtGui, QtCore
HORIZONTAL_HEADERS = ("Asset Name", "Date Added")
class AssetClass(object):
'''
a trivial custom data object
'''
def __init__(self, **kwargs):
if not kwargs.get('name') or not kwargs.get('type'):
return
self.name = kwargs.get('name')
self.date_added = kwargs.get('date_added')
self.type = kwargs.get('type')
def __repr__(self):
return "%s - %s %s" % (self.type, self.name, self.date_added)
class TreeItem(object):
'''
a python object used to return row/column data, and keep note of
it's parents and/or children
'''
def __init__(self, asset, header, parent_item):
self.asset = asset
self.parent_item = parent_item
self.header = header
self.child_items = []
def appendChild(self, item):
self.child_items.append(item)
def removeChild(self, item):
self.child_items.remove(item)
def child(self, row):
return self.child_items[row]
def childCount(self):
return len(self.child_items)
def columnCount(self):
return 2
def data(self, column):
if self.asset == None:
if column == 0:
return QtCore.QVariant(self.header)
if column == 1:
return QtCore.QVariant("")
else:
if column == 0:
return QtCore.QVariant(self.asset.name)
if column == 1:
return QtCore.QVariant(self.asset.date_added)
return QtCore.QVariant()
def parent(self):
return self.parent_item
def row(self):
if self.parent_item:
return self.parent_item.child_items.index(self)
return 0
class TreeModel(QtCore.QAbstractItemModel):
'''
a model to display a few names, ordered by sex
'''
def __init__(self, parent=None):
super(TreeModel, self).__init__(parent)
self.assets = []
model_data = (("VEHICLE", "Truck", 'May 27th, 2020'),
("VEHICLE", "Car", 'May 25th, 2020'),
("CHARACTER", "Peter", 'May 27th, 2020'),
("CHARACTER", "Rachel", 'May 29th, 2020'),
("PROP", "Chair", 'May 27th, 2020'),
("PROP", "Axe", 'May 17th, 2020'))
for asset_type, name, date in model_data:
asset = AssetClass(type=asset_type, name=name, date_added=date)
self.assets.append(asset)
self.rootItem = TreeItem(None, "ALL", None)
self.parents = {0: self.rootItem}
self.setupModelData()
def columnCount(self, parent=None):
if parent and parent.isValid():
return parent.internalPointer().columnCount()
else:
return len(HORIZONTAL_HEADERS)
def data(self, index, role):
if not index.isValid():
return QtCore.QVariant()
item = index.internalPointer()
if role == QtCore.Qt.DisplayRole:
return item.data(index.column())
if role == QtCore.Qt.UserRole:
if item:
return item.asset
return QtCore.QVariant()
def headerData(self, column, orientation, role):
if (orientation == QtCore.Qt.Horizontal and
role == QtCore.Qt.DisplayRole):
try:
return QtCore.QVariant(HORIZONTAL_HEADERS[column])
except IndexError:
pass
return QtCore.QVariant()
def index(self, row, column, parent):
if not self.hasIndex(row, column, parent):
return QtCore.QModelIndex()
if not parent.isValid():
parent_item = self.rootItem
else:
parent_item = parent.internalPointer()
childItem = parent_item.child(row)
if childItem:
return self.createIndex(row, column, childItem)
else:
return QtCore.QModelIndex()
def parent(self, index):
if not index.isValid():
return QtCore.QModelIndex()
childItem = index.internalPointer()
if not childItem:
return QtCore.QModelIndex()
parent_item = childItem.parent()
if parent_item == self.rootItem:
return QtCore.QModelIndex()
return self.createIndex(parent_item.row(), 0, parent_item)
def rowCount(self, parent=QtCore.QModelIndex()):
if parent.column() > 0:
return 0
if not parent.isValid():
p_Item = self.rootItem
else:
p_Item = parent.internalPointer()
return p_Item.childCount()
def setupModelData(self):
for asset in self.assets:
asset_type = asset.type
if not self.parents.has_key(asset_type):
new_parent = TreeItem(None, asset_type, self.rootItem)
self.rootItem.appendChild(new_parent)
self.parents[asset_type] = new_parent
parent_item = self.parents[asset_type]
new_item = TreeItem(asset, "", parent_item)
parent_item.appendChild(new_item)
def addSubRow(self, new_asset):
asset_type, name, date = new_asset
asset = AssetClass(type=asset_type, name=name, date_added=date)
parent_item = self.parents[asset_type]
already_exists = False
for child in parent_item.child_items:
if child.asset.name == name and child.asset.type == asset_type:
already_exists = True
if already_exists:
print 'this asset already exists'
return
new_item = TreeItem(asset, "", parent_item)
parent_item.appendChild(new_item)
def customRemoveRow(self, rowIndex):
child_tree_item = rowIndex.internalPointer()
asset_type = rowIndex.parent().data().toString()
parent_item = self.parents[str(asset_type)]
self.beginRemoveRows(rowIndex.parent(), rowIndex.row(), rowIndex.row() + 1)
parent_item.removeChild(child_tree_item)
self.endRemoveRows()
def searchModel(self, asset):
'''
get the modelIndex for a given appointment
'''
def searchNode(node):
'''
a function called recursively, looking at all nodes beneath node
'''
for child in node.child_items:
print child.childCount()
if asset == child.asset:
index = self.createIndex(child.row(), 0, child)
return index
if child.childCount() > 0:
result = searchNode(child)
if result:
return result
retarg = searchNode(self.parents[0])
print retarg
return retarg
def findAssetName(self, name):
app = None
for asset in self.assets:
if asset.name == name:
app = asset
break
if app != None:
index = self.searchModel(app)
return (True, index)
return (False, None)
class TreeView(QtGui.QTreeView):
right_button_clicked = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(TreeView, self).__init__(parent)
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.openMenu)
def selectedRows(self):
rows = []
for index in self.selectedIndexes():
if index.column() == 0:
rows.append(index.row())
print type(rows)
return rows
def openMenu(self, position):
indexes = self.selectedIndexes()
if len(indexes) > 0:
level = 0
index = indexes[0]
while index.parent().isValid():
index = index.parent()
level += 1
menu = QtGui.QMenu()
editMenu = None
if level == 0:
editMenu = QtGui.QAction("Edit person", self)
menu.addAction(editMenu)
elif level == 1:
editMenu = QtGui.QAction("Delete", self)
menu.addAction(editMenu)
elif level == 2:
editMenu = QtGui.QAction("Edit object", self)
menu.addAction(editMenu)
if editMenu:
editMenu.triggered.connect(self._on_right_click)
menu.exec_(self.viewport().mapToGlobal(position))
def _on_right_click(self):
self.right_button_clicked.emit()
class Proxy01(QtGui.QSortFilterProxyModel):
def __init__(self):
super(Proxy01, self).__init__()
self.keyword = None
self.searched_parents = None
def setFilterRegExp(self, pattern):
if isinstance(pattern, str):
pattern = QtCore.QRegExp(pattern, QtCore.Qt.CaseInsensitive,
QtCore.QRegExp.FixedString)
super(Proxy01, self).setFilterRegExp(pattern)
def _accept_index(self, idx):
if idx.isValid():
text = idx.data(QtCore.Qt.DisplayRole).toString()
if self.filterRegExp().indexIn(text) >= 0:
return True
for row in range(idx.model().rowCount(idx)):
if self._accept_index(idx.model().index(row, 0, idx)):
return True
return False
def filterAcceptsRow(self, source_row, source_parent):
idx = self.sourceModel().index(source_row, 0, source_parent)
return self._accept_index(idx)
class Dialog(QtGui.QDialog):
add_signal = QtCore.pyqtSignal(int)
def __init__(self, parent=None):
super(Dialog, self).__init__(parent)
self.setMinimumSize(300, 150)
self.model = TreeModel()
self.proxy1 = Proxy01()
self.proxy1.setSourceModel(self.model)
self.proxy1.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
layout = QtGui.QVBoxLayout(self)
self.tree_view = TreeView(self)
self.tree_view.setModel(self.proxy1)
self.tree_view.setAlternatingRowColors(True)
self.tree_view.right_button_clicked.connect(self.deleteMenuButtonClicked)
layout.addWidget(self.tree_view)
label = QtGui.QLabel("Search for the following person")
layout.addWidget(label)
search_layout = QtGui.QHBoxLayout(self)
self.search_line_edit = QtGui.QLineEdit()
self.search_line_edit.textChanged.connect(self.updateFilter)
search_layout.addWidget(self.search_line_edit)
search_line_button = QtGui.QPushButton('Search')
search_line_button.setMaximumWidth(75)
search_layout.addWidget(search_line_button)
layout.addLayout(search_layout)
self.add_button = QtGui.QPushButton("Add \"Character - Smith\"")
layout.addWidget(self.add_button)
QtCore.QObject.connect(self.add_button, QtCore.SIGNAL("clicked()"), self.addButtonClicked)
self.delete_button = QtGui.QPushButton("Delete Selected")
layout.addWidget(self.delete_button)
QtCore.QObject.connect(self.delete_button, QtCore.SIGNAL("clicked()"), self.deleteButtonClicked)
self.but = QtGui.QPushButton("Clear Selection")
layout.addWidget(self.but)
QtCore.QObject.connect(self.but, QtCore.SIGNAL("clicked()"), self.tree_view.clearSelection)
QtCore.QObject.connect(self.tree_view, QtCore.SIGNAL("clicked(QModelIndex)"), self.row_clicked)
def row_clicked(self, index):
'''
when a row is clicked... show the name
'''
real_index = self.tree_view.model().mapToSource(index)
print self.tree_view.model().sourceModel().data(real_index, QtCore.Qt.UserRole)
def but_clicked(self):
'''
when a name button is clicked, I iterate over the model,
find the person with this name, and set the treeviews current item
'''
name = self.sender().text()
print "BUTTON CLICKED:", name
result, index = self.model.findAssetName(name)
if result:
if index:
self.tree_view.setCurrentIndex(index)
return
self.tree_view.clearSelection()
def addButtonClicked(self):
new_asset = ("CHARACTER", "Smith", 'May 28th, 2020')
self.model.addSubRow(new_asset)
self.proxy1.invalidate()
#QtCore.pyqtSlot()
def deleteMenuButtonClicked(self):
self.deleteButtonClicked()
def deleteButtonClicked(self):
current = self.tree_view.currentIndex()
source_index = self.proxy1.mapToSource(current)
self.model.customRemoveRow(source_index)
self.proxy1.invalidate()
def customFilter(self):
self.proxy1.setKeyword(self.search_line_edit.text())
def updateFilter(self, text):
self.proxy1.setFilterRegExp(text)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
dialog = Dialog()
dialog.show()
sys.exit(app.exec_())

ValueError: filedescriptor out of range in select() while using thrift?

I'm tring to provide a remote server by thrift, and below is my server-side trial:
from test_thrift.test_server.TestService import Iface,Processor
from thrift.Thrift import TType,TException
from thrift.Thrift import TProcessor
from thrift.transport import TSocket
from thrift.protocol import TBinaryProtocol
from thrift.server import TNonblockingServer
port = int(config["server"]["port"])
handler = SmbService()
processor = Processor(handler)
socket = TSocket.TServerSocket(port=port)
server = TNonblockingServer.TNonblockingServer(processor, socket)
server.setNumThreads(100)
server.serve()
At my client-side, for every request I will create a new connect and close it after got response from server.
from thrift.transport.TSocket import TTransportException
from thrift.Thrift import TException
from thrift.protocol import TBinaryProtocol, TCompactProtocol
from thrift.transport import TTransport
from thrift.transport import TSocket
from thrift import Thrift
from test_thrift.test_server import TestService
class SmbClient(object):
def __init__(self):
try:
self.tsocket = TSocket.TSocket(settings.THRIFT_HOST, settings.THRIFT_PORT_PRODUCT)
self.transportFactory = TTransport.TFramedTransportFactory()
self.transport = self.transportFactory.getTransport(self.tsocket)
self.protocol = TBinaryProtocol.TBinaryProtocol(self.transport)
self.client = TestService.Client(self.protocol)
self.transport.open()
except Thrift.TException as e:
self.logger.info(e)
class BaseService(object):
def __init__(self):
self.commonLogger = logging.getLogger('ads')
self.header = "header111"
def search_ads_list(self, request, account_id):
self.smbClient.client.getFBAdsByAccount(param1, param2)
def __enter__(self):
self.smbClient = SmbClient()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.smbClient.transport.close()
ech request call is like this:
with BaseService() as BaseSingleService:
status, data, info = BaseSingleService.search_ads_list(
request, account_id)
The actual amount of requests from client are not big enough , but after period of time. I got error like :
Traceback (most recent call last):
File "/home/xxx/xxx/src/smb_thrift_server.py", line 2200, in <module>
server.serve()
File "/home/xxx/xxx/venv3/lib/python3.5/site-packages/thrift/server/TNonblockingServer.py", line 350, in serve
self.handle()
File "/home/xxx/xxxx/venv3/lib/python3.5/site-packages/thrift/server/TNonblockingServer.py", line 310, in handle
rset, wset, xset = self._select()
File "/home/luban/smb_thrift_server/venv3/lib/python3.5/site-packages/thrift/server/TNonblockingServer.py", line 302, in _select
return select.select(readable, writable, readable)
ValueError: filedescriptor out of range in select()
Why error happended as I've closed the client connect each time after receiving the response?
update TestService codes below:
#
# Autogenerated by Thrift Compiler (0.9.1)
#
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
#
# options string: py:new_style
#
from thrift.Thrift import TType, TMessageType, TException, TApplicationException
from .ttypes import *
from thrift.Thrift import TProcessor
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol, TProtocol
try:
from thrift.protocol import fastbinary
except:
fastbinary = None
class Iface(object):
"""..."""
def getFBAdsByAccount(self, header, account_id, effective_status, access_token):
"""
Parameters:
- header
- account_id
- effective_status
- access_token
"""
pass
"""..."""
class Client(Iface):
def __init__(self, iprot, oprot=None):
self._iprot = self._oprot = iprot
if oprot is not None:
self._oprot = oprot
self._seqid = 0
def getFBAdsByAccount(self, header, account_id, effective_status, access_token):
"""
Parameters:
- header
- account_id
- effective_status
- access_token
"""
self.send_getFBAdsByAccount(header, account_id, effective_status, access_token)
return self.recv_getFBAdsByAccount()
def send_getFBAdsByAccount(self, header, account_id, effective_status, access_token):
self._oprot.writeMessageBegin('getFBAdsByAccount', TMessageType.CALL, self._seqid)
args = getFBAdsByAccount_args()
args.header = header
args.account_id = account_id
args.effective_status = effective_status
args.access_token = access_token
args.write(self._oprot)
self._oprot.writeMessageEnd()
self._oprot.trans.flush()
def recv_getFBAdsByAccount(self):
(fname, mtype, rseqid) = self._iprot.readMessageBegin()
if mtype == TMessageType.EXCEPTION:
x = TApplicationException()
x.read(self._iprot)
self._iprot.readMessageEnd()
raise x
result = getFBAdsByAccount_result()
result.read(self._iprot)
self._iprot.readMessageEnd()
if result.success is not None:
return result.success
if result.e is not None:
raise result.e
raise TApplicationException(TApplicationException.MISSING_RESULT, "getFBAdsByAccount failed: unknown result");
class Processor(Iface, TProcessor):
def __init__(self, handler):
self._handler = handler
self._processMap = {}
self._processMap["getFBAdsByAccount"] = Processor.process_getFBAdsByAccount
def process(self, iprot, oprot):
(name, type, seqid) = iprot.readMessageBegin()
if name not in self._processMap:
iprot.skip(TType.STRUCT)
iprot.readMessageEnd()
x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name))
oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid)
x.write(oprot)
oprot.writeMessageEnd()
oprot.trans.flush()
return
else:
self._processMap[name](self, seqid, iprot, oprot)
return True
def process_getFBAdsByAccount(self, seqid, iprot, oprot):
args = getFBAdsByAccount_args()
args.read(iprot)
iprot.readMessageEnd()
result = getFBAdsByAccount_result()
try:
result.success = self._handler.getFBAdsByAccount(args.header, args.account_id, args.effective_status, args.access_token)
except test_thrift.common.ttypes.ServerException as e:
result.e = e
oprot.writeMessageBegin("getFBAdsByAccount", TMessageType.REPLY, seqid)
result.write(oprot)
oprot.writeMessageEnd()
oprot.trans.flush()
class getFBAdsByAccount_args(object):
"""
Attributes:
- header
- account_id
- effective_status
- access_token
"""
thrift_spec = (
None, # 0
(1, TType.STRUCT, 'header', (test_thrift.common.ttypes.RequestHeader, test_thrift.common.ttypes.RequestHeader.thrift_spec), None, ), # 1
(2, TType.STRING, 'account_id', None, None, ), # 2
(3, TType.LIST, 'effective_status', (TType.STRING,None), None, ), # 3
(4, TType.STRING, 'access_token', None, None, ), # 4
)
def __init__(self, header=None, account_id=None, effective_status=None, access_token=None,):
self.header = header
self.account_id = account_id
self.effective_status = effective_status
self.access_token = access_token
def read(self, iprot):
if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
return
iprot.readStructBegin()
while True:
(fname, ftype, fid) = iprot.readFieldBegin()
if ftype == TType.STOP:
break
if fid == 1:
if ftype == TType.STRUCT:
self.header = test_thrift.common.ttypes.RequestHeader()
self.header.read(iprot)
else:
iprot.skip(ftype)
elif fid == 2:
if ftype == TType.STRING:
self.account_id = iprot.readString();
else:
iprot.skip(ftype)
elif fid == 3:
if ftype == TType.LIST:
self.effective_status = []
(_etype24, _size21) = iprot.readListBegin()
for _i25 in range(_size21):
_elem26 = iprot.readString();
self.effective_status.append(_elem26)
iprot.readListEnd()
else:
iprot.skip(ftype)
elif fid == 4:
if ftype == TType.STRING:
self.access_token = iprot.readString();
else:
iprot.skip(ftype)
else:
iprot.skip(ftype)
iprot.readFieldEnd()
iprot.readStructEnd()
def write(self, oprot):
if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
return
oprot.writeStructBegin('getFBAdsByAccount_args')
if self.header is not None:
oprot.writeFieldBegin('header', TType.STRUCT, 1)
self.header.write(oprot)
oprot.writeFieldEnd()
if self.account_id is not None:
oprot.writeFieldBegin('account_id', TType.STRING, 2)
oprot.writeString(self.account_id)
oprot.writeFieldEnd()
if self.effective_status is not None:
oprot.writeFieldBegin('effective_status', TType.LIST, 3)
oprot.writeListBegin(TType.STRING, len(self.effective_status))
for iter27 in self.effective_status:
oprot.writeString(iter27)
oprot.writeListEnd()
oprot.writeFieldEnd()
if self.access_token is not None:
oprot.writeFieldBegin('access_token', TType.STRING, 4)
oprot.writeString(self.access_token)
oprot.writeFieldEnd()
oprot.writeFieldStop()
oprot.writeStructEnd()
def validate(self):
return
def __repr__(self):
L = ['%s=%r' % (key, value)
for key, value in self.__dict__.items()]
return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
def __eq__(self, other):
return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
def __ne__(self, other):
return not (self == other)
class getFBAdsByAccount_result(object):
"""
Attributes:
- success
- e
"""
thrift_spec = (
(0, TType.STRUCT, 'success', (test_thrift.common.ttypes.ResponseListMap, test_thrift.common.ttypes.ResponseListMap.thrift_spec), None, ), # 0
(1, TType.STRUCT, 'e', (test_thrift.common.ttypes.ServerException, test_thrift.common.ttypes.ServerException.thrift_spec), None, ), # 1
)
def __init__(self, success=None, e=None,):
self.success = success
self.e = e
def read(self, iprot):
if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
return
iprot.readStructBegin()
while True:
(fname, ftype, fid) = iprot.readFieldBegin()
if ftype == TType.STOP:
break
if fid == 0:
if ftype == TType.STRUCT:
self.success = test_thrift.common.ttypes.ResponseListMap()
self.success.read(iprot)
else:
iprot.skip(ftype)
elif fid == 1:
if ftype == TType.STRUCT:
self.e = test_thrift.common.ttypes.ServerException()
self.e.read(iprot)
else:
iprot.skip(ftype)
else:
iprot.skip(ftype)
iprot.readFieldEnd()
iprot.readStructEnd()
def write(self, oprot):
if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
return
oprot.writeStructBegin('getFBAdsByAccount_result')
if self.success is not None:
oprot.writeFieldBegin('success', TType.STRUCT, 0)
self.success.write(oprot)
oprot.writeFieldEnd()
if self.e is not None:
oprot.writeFieldBegin('e', TType.STRUCT, 1)
self.e.write(oprot)
oprot.writeFieldEnd()
oprot.writeFieldStop()
oprot.writeStructEnd()
def validate(self):
return
def __repr__(self):
L = ['%s=%r' % (key, value)
for key, value in self.__dict__.items()]
return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
def __eq__(self, other):
return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
def __ne__(self, other):
return not (self == other)

Class inheritance type checking after pickling in Python

Is there a sure-fire way to check that the class of an object is a sub-class of the desired super?
For Example, in a migration script that I'm writing, I have to convert objects of a given type to dictionaries in a given manner to ensure two-way compatability of the data.
This is best summed up like so:
Serializable
User
Status
Issue
Test
Set
Step
Cycle
However, when I'm recursively checking objects after depickling, I receive a Test object that yields the following results:
Testing data object type:
type(data)
{type}< class'__main.Test' >
Testing Class type:
type(Test())
{type}< class'__main.Test' >
Testing object type against class type:
type(Test()) == type(data)
{bool}False
Testing if object isinstance() of Class:
isinstance(data, Test)
{bool}False
Testing if Class isinstance() of Super Class:
isinstance(Test(), Serializable)
{bool}True
Testing isinstance() of Super Class::
isinstance(data, Serializable)
{bool}False
Interestingly, it doesn't appear to have any such problem prior to pickling as it handles the creation of dictionary and integrity hash just fine.
This only crops up with depickled objects in both Pickle and Dill.
For Context, here's the code in it's native environment - the DataCache object that is pickled:
class DataCache(object):
_hash=""
_data = None
#staticmethod
def genHash(data):
dataDict = DataCache.dictify(data)
datahash = json.dumps(dataDict, sort_keys=True)
return hashlib.sha256(datahash).digest()
#staticmethod
def dictify(data):
if isinstance(data,list):
datahash = []
for item in data:
datahash.append(DataCache.dictify(item))
elif isinstance(data,(dict, collections.OrderedDict)):
datahash = collections.OrderedDict()
for key,value in datahash.iteritems():
datahash[key]= DataCache.dictify(value)
elif isinstance(data, Serializable):
datahash = data.toDict()
else:
datahash = data
return datahash
def __init__(self, restoreDict = {}):
if restoreDict:
self.__dict__.update(restoreDict)
def __getinitargs__(self):
return (self.__dict__)
def set(self, data):
self._hash = DataCache.genHash(data)
self._data = data
def verify(self):
dataHash = DataCache.genHash(self._data)
return (self._hash == dataHash)
def get(self):
return self._data
Finally, I know there's arguments for using JSON for readability in storage, I needed Pickle's ability to convert straight to and from Objects without specifying the object type myself. (thanks to the nesting, it's not really feasible)
Am I going mad here or does pickling do something to the class definitions?
EDIT:
Minimal Implementation:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import requests
from aenum import Enum
import json # _tricks
import base64
import argparse
import os
import sys
import datetime
import dill
import hashlib
import collections
class Serializable(object):
def __init__(self, initDict={}):
if initDict:
self.__dict__.update(initDict)
def __str__(self):
return str(self.sortSelf())
def sortSelf(self):
return collections.OrderedDict(sorted(self.__dict__.items()))
def toDict(self):
return self.__dict__
def fromDict(self, dict):
# Not using __dict__.update(...) to avoid polluting objects with the excess data
varMap = self.__dict__
if dict and varMap:
for key in varMap:
if (key in dict):
varMap[key] = dict[key]
self.__dict__.update(varMap)
return self
return None
class Issue(Serializable):
def __init__(self, initDict={}):
self.id = 0
self.key = ""
self.fields = {}
if initDict:
self.__dict__.update(initDict)
Serializable.__init__(self)
def fieldToDict(self, obj, key, type):
if key in obj:
result = obj[key]
else:
return None
if result is None:
return None
if isinstance(result, type):
return result.toDict()
return result
def fromDict(self, jsonDict):
super(Issue, self).fromDict(jsonDict)
self.fields["issuetype"] = IssueType().fromDict(self.fields["issuetype"])
self.fields["assignee"] = User().fromDict(self.fields["assignee"])
self.fields["creator"] = User().fromDict(self.fields["creator"])
self.fields["reporter"] = User().fromDict(self.fields["reporter"])
return self
def toDict(self):
result = super(Issue, self).toDict()
blankKeys = []
for fieldName, fieldValue in self.fields.iteritems():
if fieldValue is None:
blankKeys.append(fieldName)
if blankKeys:
for key in blankKeys:
self.fields.pop(key, None)
result["fields"]["issuetype"] = self.fieldToDict(result["fields"], "issuetype", IssueType)
result["fields"]["creator"] = self.fieldToDict(result["fields"], "creator", User)
result["fields"]["reporter"] = self.fieldToDict(result["fields"], "reporter", User)
result["fields"]["assignee"] = self.fieldToDict(result["fields"], "assignee", User)
return result
class IssueType(Serializable):
def __init__(self):
self.id = 0
self.name = ""
def toDict(self):
return {"id": str(self.id)}
class Project(Serializable):
def __init__(self):
Serializable.__init__(self)
self.id = 0
self.name = ""
self.key = ""
class Cycle(Serializable):
def __init__(self):
self.id = 0
self.name = ""
self.totalExecutions = 0
self.endDate = ""
self.description = ""
self.totalExecuted = 0
self.started = ""
self.versionName = ""
self.projectKey = ""
self.versionId = 0
self.environment = ""
self.totalCycleExecutions = 0
self.build = ""
self.ended = ""
self.name = ""
self.modifiedBy = ""
self.projectId = 0
self.startDate = ""
self.executionSummaries = {'executionSummary': []}
class Step(Serializable):
def __init__(self):
self.id = ""
self.orderId = 0
self.step = ""
self.data = ""
self.result = ""
self.attachmentsMap = {}
def toDict(self):
dict = {}
dict["step"] = self.step
dict["data"] = self.data
dict["result"] = self.result
dict["attachments"] = []
return dict
class Status(Serializable):
def __init__(self):
self.id = 0
self.name = ""
self.description = ""
self.isFinal = True
self.color = ""
self.isNative = True
self.statusCount = 0
self.statusPercent = 0.0
class User(Serializable):
def __init__(self):
self.displayName = ""
self.name = ""
self.emailAddress = ""
self.key = ""
self.active = False
self.timeZone = ""
class Execution(Serializable):
def __init__(self):
self.id = 0
self.orderId = 0
self.cycleId = -1
self.cycleName = ""
self.issueId = 0
self.issueKey = 0
self.projectKey = ""
self.comment = ""
self.versionId = 0,
self.versionName = "",
self.executedOn = ""
self.creationDate = ""
self.executedByUserName = ""
self.assigneeUserName = ""
self.status = {}
self.executionStatus = ""
def fromDict(self, jsonDict):
super(Execution, self).fromDict(jsonDict)
self.status = Status().fromDict(self.status)
# This is already listed as Execution Status, need to associate and convert!
return self
def toDict(self):
result = super(Execution, self).toDict()
result['status'] = result['status'].toDict()
return result
class ExecutionContainer(Serializable):
def __init__(self):
self.executions = []
def fromDict(self, jsonDict):
super(ExecutionContainer, self).fromDict(jsonDict)
self.executions = []
for executionDict in jsonDict["executions"]:
self.executions.append(Execution().fromDict(executionDict))
return self
class Test(Issue):
def __init__(self, initDict={}):
if initDict:
self.__dict__.update(initDict)
Issue.__init__(self)
def toDict(self):
result = super(Test, self).toDict()
stepField = "CustomField_0001"
if result["fields"][stepField]:
steps = []
for step in result["fields"][stepField]["steps"]:
steps.append(step.toDict())
result["fields"][stepField] = steps
return result
def fromDict(self, jsonDict):
super(Test, self).fromDict(jsonDict)
stepField = "CustomField_0001"
steps = []
if stepField in self.fields:
for step in self.fields[stepField]["steps"]:
steps.append(Step().fromDict(step))
self.fields[stepField] = {"steps": steps}
return self
class Set(Issue):
def __init__(self, initDict={}):
self.__dict__.update(initDict)
Issue.__init__(self)
class DataCache(object):
_hash = ""
_data = None
#staticmethod
def genHash(data):
dataDict = DataCache.dictify(data)
datahash = json.dumps(dataDict, sort_keys=True)
return hashlib.sha256(datahash).digest()
#staticmethod
def dictify(data):
if isinstance(data, list):
datahash = []
for item in data:
datahash.append(DataCache.dictify(item))
elif isinstance(data, (dict, collections.OrderedDict)):
datahash = collections.OrderedDict()
for key, value in datahash.iteritems():
datahash[key] = DataCache.dictify(value)
elif isinstance(data, Serializable):
datahash = data.toDict()
else:
datahash = data
return datahash
def __init__(self, restoreDict={}):
if restoreDict:
self.__dict__.update(restoreDict)
def __getinitargs__(self):
return (self.__dict__)
def set(self, data):
self._hash = DataCache.genHash(data)
self._data = data
def verify(self):
dataHash = DataCache.genHash(self._data)
return (self._hash == dataHash)
def get(self):
return self._data
def saveCache(name, projectKey, object):
filePath = "migration_caches/{projectKey}".format(projectKey=projectKey)
if not os.path.exists(path=filePath):
os.makedirs(filePath)
cache = DataCache()
cache.set(object)
targetFile = open("{path}/{name}".format(name=name, path=filePath), 'wb')
dill.dump(obj=cache, file=targetFile)
targetFile.close()
def loadCache(name, projectKey):
filePath = "migration_caches/{projectKey}/{name}".format(name=name, projectKey=projectKey)
result = False
try:
targetFile = open(filePath, 'rb')
try:
cache = dill.load(targetFile)
if isinstance(cache, DataCache):
if cache.verify():
result = cache.get()
except EOFError:
# except BaseException:
print ("Failed to load cache from file: {filePath}\n".format(filePath=filePath))
except IOError:
("Failed to load cache file at: {filePath}\n".format(filePath=filePath))
targetFile.close()
return result
testIssue = Test().fromDict({"id": 1000,
"key": "TEST",
"fields": {
"issuetype": {
"id": 1,
"name": "TestIssue"
},
"assignee": "Minothor",
"reporter": "Minothor",
"creator": "Minothor",
}
})
saveCache("Test", "TestProj", testIssue)
result = loadCache("Test", "TestProj")
EDIT 2
The script in it's current form, now seems to work correctly with vanilla Pickle, (initially switched to Dill due to a similar issue, which was solved by the switch).
However, if you are here with this issue and require Dill's features, then as Mike noted in the comments - it's possible to change the settings in dill.settings to have Dill behave pickle referenced items only with joblib mode, effectively mirroring pickle's standard pickling behaviour.

Python generate sorted list

I want to compress my movies automatically. So I've written a mediainfo wrapper class in python, to generate a xml output, which I then parse to a movieinfo class, with a list of audio and subtitle tracks.
__author__ = 'dominik'
class Error(Exception):
""" Error class
"""
class ValidationError(Error):
""" Invalid or missing xml items
"""
class MovieInfo(object):
""" Description of movie file
"""
def __init__(self, media_info):
self._video_track = None
self._audio_tracks = []
self._subtitle_tracks = []
self.valid_movie = True
for track in media_info.tracks:
if track.track_type == "Audio":
self._audio_tracks.append(AudioTrack(track))
elif track.track_type == "Text":
self._subtitle_tracks.append(SubtitleTrack(track))
elif track.track_type == "Video":
self._video_track = VideoTrack(track)
#property
def audio_tracks(self):
if not hasattr(self, "_audio_tracks"):
self._audio_tracks = []
if len(self._audio_tracks) != 0:
return self._audio_tracks
#property
def subtitle_tracks(self):
if not hasattr(self, "_subtitle_tracks"):
self._subtitle_tracks = []
if len(self._subtitle_tracks) != 0:
return self._subtitle_tracks
class Track(object):
""" Abstract track class for audio and subtitle tracks
"""
__KNOWN_LANGUAGE_CODES = {"en": "ENG", "de": "DE"}
def __init__(self, track, valid_codecs):
self._valid = True
track_id = int(track.id)
codec_id = self._determine_codec(track.codec_id, valid_codecs)
language = self._determine_language(track.language)
self._id = track_id
self._codec_id = codec_id
self._language = language
def _determine_codec(self, track_codec, types):
result = types.get(track_codec, None)
if result is None:
self._valid = False
return result
def _determine_language(self, track_language, types=__KNOWN_LANGUAGE_CODES):
result = types.get(track_language, None)
if result is None:
self._valid = False
return result
class AudioTrack(Track):
""" Audio track class
"""
__KNOWN_AUDIO_CODECS = {"A_DTS": "DTS", "A_AC3": "AC3"}
def __init__(self, track):
self._type = 1
Track.__init__(self, track, self.__KNOWN_AUDIO_CODECS)
class SubtitleTrack(Track):
""" Subtitle track class
"""
__KNOWN_SUBTITLE_CODECS = {"S_VOBSUB": "VOBSUB"}
def __init__(self, track):
self._type = 2
if track.forced == "Yes":
self._forced = True
else:
self._forced = False
Track.__init__(self, track, self.__KNOWN_SUBTITLE_CODECS)
class VideoTrack(object):
""" Video track class (only one video track in movie info!)
"""
def __init__(self, track):
self._type = 0
self._framerate = float(track.frame_rate)
self._width = track.width
self._height = track.height
Here is the mediainfo class (it's the pymediainfo class):
from subprocess import Popen
import os
from tempfile import mkstemp
from bs4 import BeautifulSoup, NavigableString
from setuptools.compat import unicode
class Track(object):
""" Hold the track information
"""
def __getattr__(self, item):
try:
return object.__getattribute__(self, item)
except:
pass
return None
def __init__(self, xml_track):
self.xml_track = xml_track
self.track_type = xml_track.attrs["type"]
for child in self.xml_track.children:
if not isinstance(child, NavigableString):
node_name = child.name.lower().strip()
node_value = unicode(child.string)
node_other_name = "other_%s" % node_name
if getattr(self, node_name) is None:
setattr(self, node_name, node_value)
else:
if getattr(self, node_other_name) is None:
setattr(self, node_other_name, [node_value, ])
else:
getattr(self, node_other_name).append(node_value)
for key in [c for c in self.__dict__.keys() if c.startswith("other_")]:
try:
primary = key.replace("other_", "")
setattr(self, primary, int(getattr(self, primary)))
except:
for value in getattr(self, key):
try:
actual = getattr(self, primary)
setattr(self, primary, int(value))
getattr(self, key).append(actual)
break
except:
pass
def __repr__(self):
return("<Track id='{0}', type='{1}'>".format(self.id, self.track_type))
def to_data(self):
data = {}
for k, v in self.__dict__.items():
if k != 'xml_track':
data[k] = v
return data
class Mediainfo(object):
""" MediaInfo wrapper
"""
def __init__(self, xml):
self.xml_dom = xml
if isinstance(xml, str):
self.xml_dom = BeautifulSoup(xml, "xml")
def _populate_tracks(self):
if self.xml_dom is None:
return
for xml_track in self.xml_dom.Mediainfo.File.find_all("track"):
self._tracks.append(Track(xml_track))
#property
def tracks(self):
if not hasattr(self, "_tracks"):
self._tracks = []
if len(self._tracks) == 0:
self._populate_tracks()
return self._tracks
#staticmethod
def parse(filename):
filehandler_out, filename_out = mkstemp(".xml", "mediainfo-")
filehandler_err, filename_err = mkstemp(".error", "mediainfo-")
filepointer_out = os.fdopen(filehandler_out, "r+b")
filepointer_err = os.fdopen(filehandler_err, "r+b")
mediainfo_command = ["mediainfo", "-f", "--Output=XML", filename]
p = Popen(mediainfo_command, stdout=filepointer_out, stderr=filepointer_err)
p.wait()
filepointer_out.seek(0)
xml_dom = BeautifulSoup(filepointer_out.read(), "xml")
filepointer_out.close()
filepointer_err.close()
print(xml_dom)
return Mediainfo(xml_dom)
def to_data(self):
data = {'tracks': []}
for track in self.tracks:
data['tracks'].append(track.to_data())
return data
This class gives me every track in the xml and then I parse the relevant info in movieinfo.
Ok now I have a list of audiotracks e.g. 3 tracks one in german language and DTS, one in german and AC3 and one in english and AC3. Now I want to get the ids from the tracks in the format "1,2,3" to give it to handbrake cli.
My problem is the order of the tracks. If there is a german DTS track this schould be the first track, the second track should be also the first, but compressed to aac and the third track should be one english track in AAC. If there is only a german AC3 track then the first track should be this track but compressed to AAC, and the second track should englisch and AAC.
I don't know exactly how I can achive that, can you help me? I'm new to python, and come from C, C++ and C#. In C# this is very easy to get with lambda.
Assuming you know to define a compare-tor that given two items can define which is bigger then Python functions as well as C or C++.
Start here -
1. https://wiki.python.org/moin/HowTo/Sorting/
https://developers.google.com/edu/python/sorting
http://docs.python.org/2/library/functions.html#sorted
Using sorted method and define the key you want.

Categories