I have the following coding:-
Progam 1
class Person :
'''A base to define Person properties.'''
def __inti__( self , name ):
self.name = name
def speak( self , msg = '(Calling The Base Class)' ):
print( self.name , msg )
Program 2
from Person import *
'''A derived class to define Man properties.'''
class Man( Person ):
def speak( self , msg ):
print( self.name , ':\n\tHello!' , msg )
Program 3
from Person import *
'''A derived class to define Hombre properties.'''
class Hombre( Person ):
def speak( self , msg ):
print( self.name , ':\n\tHola!' , msg )
Program 4
from Man import *
from Hombre import *
guy__1 = Man('Richard')
guy__2 = Hombre('Ricardo')
guy__1.speak( 'It\'s a beautiful evening.\n' )
guy__2.speak( 'Es una tarde hermosa.\n' )
Person.speak( guy__1 )
Person.speak( guy__2 )
I get the following error;-
guy__1 = Man('Richard')
TypeError: object() takes no parameters
change
def __inti__( self , name ):
to
def __init__( self , name ):
Related
I am trying to implement a QAbstractProxyModel that maps an SqlTableModel to a tree-like data structure. The table has a column called parent_id, whose value is added to the createIndex call as a third argument. The question is similar to this user's post, only that I am working in Python not in C++.
The TreeView loads correctly:
But when I try to expand an item, the application crashes. Debugging tells me that there seems to be an infinite loop of index, rowCount and mapToSource being called.
I am at the end of my wits. Do you have any ideas? See the MWE below.
from __future__ import annotations
from PySide6.QtWidgets import QGridLayout
from PySide6.QtWidgets import QTreeView
from PySide6.QtWidgets import QApplication
from PySide6.QtWidgets import QMainWindow
from PySide6.QtWidgets import QWidget
from PySide6.QtCore import QModelIndex
from PySide6.QtCore import Qt
from PySide6.QtCore import Slot
from PySide6.QtCore import QAbstractProxyModel
from PySide6.QtSql import QSqlDatabase
from PySide6.QtSql import QSqlQuery
from PySide6.QtSql import QSqlTableModel
class CustomTreeModel(QAbstractProxyModel):
def __init__(self, database: str, parent: QWidget = None):
QAbstractProxyModel.__init__(self, parent)
sourceModel = QSqlTableModel(parent, database)
sourceModel.setTable('test')
sourceModel.select()
self.setSourceModel(sourceModel)
def flags(self, proxyIndex: QModelIndex) -> Qt.ItemFlags:
return Qt.ItemIsEnabled | Qt.ItemIsEditable
def data(self, proxyIndex: QModelIndex, role: int):
print("data")
if proxyIndex.isValid:
sourceIndex = self.mapToSource(proxyIndex)
return sourceIndex.data(role)
return None
def index(
self,
row: int,
column: int,
parentIndex: QModelIndex
) -> QModelIndex:
print("index")
if row < 0 and column < 0:
return QModelIndex()
parentId = parentIndex.internalPointer()
return self.createIndex(row, column, parentId)
def mapFromSource(self, sourceIndex: QModelIndex) -> QModelIndex:
print("mapFromSource")
if self.isRootItem(sourceIndex):
return QModelIndex()
if sourceIndex.column() == 0:
sourceId = sourceIndex.data()
else:
sourceId = sourceIndex.siblingAtColumn(0).data()
parentId = self.getParentId(sourceId)
childIds = self.getChildIds(parentId)
row = childIds.index(sourceId)
column = sourceIndex.column()
proxyIndex = self.createIndex(row, column, parentId)
return proxyIndex
def mapToSource(self, proxyIndex: QModelIndex) -> QModelIndex:
print("mapToSource")
if self.isRootItem(proxyIndex):
return QModelIndex()
parentId = proxyIndex.internalPointer()
childIds = self.getChildIds(parentId)
rowId = childIds[proxyIndex.row()]
rowIds = self.getAllIds()
sourceRow = rowIds.index(rowId)
sourceColumn = proxyIndex.column()
sourceIndex = self.sourceModel().index(sourceRow, sourceColumn)
return sourceIndex
def rowCount(self, parentIndex: QModelIndex) -> int:
print("rowCount")
if parentIndex.column() > 0:
return 0
parentId = parentIndex.internalPointer()
childIds = self.getChildIds(parentId)
return len(childIds)
def columnCount(self, parentIndex: QModelIndex) -> int:
print("columnCount")
if parentIndex.column() > 0:
return 0
numColumns = self.sourceModel().columnCount(parentIndex)
return numColumns
def parent(self, childIndex: QModelIndex) -> QModelIndex:
print("parent")
if childIndex.column() > 0:
return QModelIndex()
sourceIndex = self.mapToSource(childIndex)
childId = sourceIndex.siblingAtColumn(0).data()
parentId = self.getParentId(childId)
if not parentId:
return QModelIndex()
parentParentId = self.getParentId(parentId)
parentIds = self.getChildIds(parentParentId)
parentRow = parentIds.index(parentId)
parentIndex = self.createIndex(parentRow, 0, parentId)
return parentIndex
def getParentId(self, childId: str) -> str | None:
table = self.sourceModel().tableName()
query = QSqlQuery()
query.prepare(f"""
SELECT parent_id
FROM {table}
WHERE id=?
""")
query.addBindValue(childId)
query.exec_()
if query.first():
parentId = query.value(0)
return parentId if parentId else None
return None
def hasChildren(self, parentIndex: QModelIndex) -> bool:
if parentIndex.column() > 0:
return False
parentId = parentIndex.internalPointer()
childIds = self.getChildIds(parentId)
return len(childIds) > 0
def getAllIds(self) -> list[str]:
table = self.sourceModel().tableName()
query = QSqlQuery()
query.prepare(f"""
SELECT id
FROM {table}
""")
query.exec_()
ids = []
while query.next():
ids.append(query.value(0))
return ids
def getChildIds(self, parentId: str | None) -> list[str]:
table = self.sourceModel().tableName()
query = QSqlQuery()
if not parentId or parentId == '':
query.prepare(f"""
SELECT id
FROM {table}
WHERE parent_id IS NULL OR parent_id=''
""")
else:
query.prepare(f"""
SELECT id
FROM {table}
WHERE parent_id=?""")
query.addBindValue(parentId)
query.exec_()
childIds = []
while query.next():
childIds.append(query.value(0))
return childIds
def isRootItem(self, index: QModelIndex):
return index.row() == -1 and index.column() == -1
class CustomTreeWidget(QWidget):
def __init__(self, parent: QWidget = None):
QWidget.__init__(self, parent)
self.model: CustomTreeModel
self.view = QTreeView(self)
layout = QGridLayout(self)
layout.addWidget(self.view)
self.setLayout(layout)
#Slot()
def setDatabase(self):
database = QSqlDatabase.database()
model = CustomTreeModel(database, self)
self.view.setModel(model)
self.model = model
def initTestDatabase():
query = QSqlQuery()
query.prepare("""
CREATE TABLE test (
"id" TEXT,
"text" TEXT,
"parent_id" TEXT,
PRIMARY KEY("id")
);
""")
query.exec_()
query = QSqlQuery()
query.prepare("""
INSERT INTO test (
id, text, parent_id)
VALUES
(?, ?, ?),
(?, ?, ?),
(?, ?, ?),
(?, ?, ?);
""")
query.addBindValue("ID101")
query.addBindValue("Text")
query.addBindValue(None)
query.addBindValue("ID102")
query.addBindValue("Text")
query.addBindValue("ID101")
query.addBindValue("ID103")
query.addBindValue("Text")
query.addBindValue("ID101")
query.addBindValue("ID104")
query.addBindValue("Text")
query.addBindValue(None)
query.exec_()
if __name__ == "__main__":
projectDb = QSqlDatabase.addDatabase("QSQLITE")
projectDb.setDatabaseName(":memory:")
projectDb.open()
initTestDatabase()
app = QApplication()
mainWindow = QMainWindow()
widget = CustomTreeWidget(mainWindow)
widget.setDatabase()
mainWindow.setCentralWidget(widget)
mainWindow.showMaximized()
app.exec_()
The code below is about reflection.
It tries to do 2 things:
case1() creates an instance from SimpleStudent class, it works.
case2() creates an instance from Student class, not work.
The reason that case2() not work as well as the question, is that inside that generateValue():
I don't know how to check it is kotlin type or my own type(I have a dirty way to check param.type.toString() not contain "kotlin" but I wonder if there is a better solution
I don't know how to get its class reference when it's a custom class. The problem is that even though param.type.toString() == "Lesson", when I tried to get param.type::class, it's class kotlin.reflect.jvm.internal.KTypeImpl
So, how to solve it? Thanks
==============
import kotlin.reflect.KParameter
import kotlin.reflect.full.primaryConstructor
import kotlin.test.assertEquals
data class Lesson(val title:String, val length:Int)
data class Student(val name:String, val major:Lesson )
data class SimpleStudent(val name:String, val age:Int )
fun generateValue(param:KParameter, originalValue:Map<*,*>):Any? {
var value = originalValue[param.name]
// if (param.type is not Kotlin type){
// // Get its ::class so that we could create the instance of it, here, I mean Lesson class?
// }
return value
}
fun case1(){
val classDesc = SimpleStudent::class
val constructor = classDesc.primaryConstructor!!
val value = mapOf<Any,Any>(
"name" to "Tom",
"age" to 16
)
val params = constructor.parameters.associateBy (
{it},
{generateValue(it, value)}
)
val result:SimpleStudent = constructor.callBy(params)
assertEquals("Tom", result.name)
assertEquals(16, result.age)
}
fun case2(){
val classDesc = Student::class
val constructor = classDesc.primaryConstructor!!
val value = mapOf<Any,Any>(
"name" to "Tom",
"major" to mapOf<Any,Any>(
"title" to "CS",
"length" to 16
)
)
val params = constructor.parameters.associateBy (
{it},
{generateValue(it, value)}
)
val result:Student = constructor.callBy(params)
assertEquals("Tom", result.name)
assertEquals(Lesson::class, result.major::class)
assertEquals("CS", result.major.title)
}
fun main(args : Array<String>) {
case1()
case2()
}
Problem solved:
You could get that ::class by using param.type.classifier as KClass<T> where param is KParameter
I try to begin an app with scala, play, slick, specs2 & sqlite.here is a trait for sqlite integration:
import scala.slick.driver.SQLiteDriver.simple._
import metier.Objets._
import scala.slick.lifted.ProvenShape
import java.sql.Date
package models {
trait sqlite {
val db = Database.forURL("jdbc:sqlite:rdvs.txt", driver = "org.sqlite.JDBC")
//val db = Database.forDataSource(DB.getDataSource())
class Personnes(tag: Tag) extends Table[Rdv](tag, "RDV") {
def id = column[Int]("ID", O.PrimaryKey, O.AutoInc)
def nom = column[String]("NOM", O.NotNull)
def prénom = column[String]("PRENOM")
def sexe = column[Int]("SEXE")
def télPortable = column[String]("TELPOR")
def télBureau = column[String]("TELBUR")
def télPrivé = column[String]("TELPRI")
def siteRDV = column[String]("SITE")
def typeRDV = column[String]("TYPE")
def libelléRDV = column[String]("LIBELLE")
def numRDV = column[String]("NUMRDV")
def étape = column[String]("ETAPE")
def dateRDV = column[Date]("DATE")
def heureRDVString = column[String]("HEURE")
def statut = column[String]("STATUT")
def orderId = column[String]("ORDERID")
def * = (id.?, nom, prénom, sexe, télPortable, télBureau, télPrivé,
siteRDV, typeRDV, libelléRDV, numRDV, étape, dateRDV, heureRDVString,
statut, orderId) <> (Rdv.tupled, Rdv.unapply _)
}
}
}
the test is this:
package tests {
#RunWith(classOf[JUnitRunner])
class SqliteSpec extends Specification with sqlite {
sequential
"la base sqlite" should {
"create a new database file" in new Sqlite_avant_chaque_test {
todo
}
}
class Sqlite_avant_chaque_test extends Scope {
println("avant test")
//db.withDynSession {
db.withSession { implicit session: Session =>
val personnes = TableQuery[Personnes]
personnes.ddl.create
println("avant tests, après création base")
}
}
}
}
and when I launch the test in eclipse I get this error:
java.lang.Exception: Could not instantiate class tests.SqliteSpec: org.sqlite.JDBC
In my test class, I however have this import :
import scala.slick.driver.SQLiteDriver.simple._
which should load the sqlite driver of slick.
can you help me?
i really need help to finish this task since it's related to my research and I’m new to python and scrapy .
*the task is to select all input field (type=text or password or file ) and store it's (id) in back-end DB , besides the page link where this input belongs *
my code to select input fields
def parse_item(self, response):
self.log('%s' % response.url)
hxs = HtmlXPathSelector(response)
item=IsaItem()
item['response_fld']=response.url
item['text_input']=hxs.select("//input[(#id or #name) and (#type = 'text' )]/#id ").extract()
item['pass_input']=hxs.select("//input[(#id or #name) and (#type = 'password')]/#id").extract()
item['file_input']=hxs.select("//input[(#id or #name) and (#type = 'file')]/#id").extract()
return item
Database pipeline code :
class SQLiteStorePipeline(object):
def __init__(self):
self.conn = sqlite3.connect('./project.db')
self.cur = self.conn.cursor()
def process_item(self, item, spider):
self.cur.execute("insert into inputs ( input_name) values(?)" , (item['text_input'][0] ), )
self.cur.execute("insert into inputs ( input_name) values(?)" , (item['pass_input'][0] ,))
self.cur.execute("insert into inputs ( input_name) values(?)" ,(item['file_input'][0] , ))
self.cur.execute("insert into links (link) values(?)", (item['response_fld'][0], ))
self.conn.commit()
return item
but i still get error like this
self.cur.execute("insert into inputs ( input_name) values(?)" , (item['text_input'][0] ), )
exceptions.IndexError: list index out of range
or database store only first letter !!
Database links table
╔════════════════╗
║ links ║
╠════════════════╣
║ id │input ║
╟──────┼─────────╢
║ 1 │ t ║
╟──────┼─────────╢
║ 2 │ t ║
╚══════╧═════════╝
Note it should "tbPassword" or "tbUsername"
ouput fron json file
{"pass_input": ["tbPassword"], "file_input": [], "response_fld": "http://testaspnet.vulnweb.com/Signup.aspx", "text_input": ["tbUsername"]}
{"pass_input": [], "file_input": [], "response_fld": "http://testaspnet.vulnweb.com/default.aspx", "text_input": []}
{"pass_input": ["tbPassword"], "file_input": [], "response_fld": "http://testaspnet.vulnweb.com/login.aspx", "text_input": ["tbUsername"]}
{"pass_input": [], "file_input": [], "response_fld": "http://testaspnet.vulnweb.com/Comments.aspx?id=0", "text_input": []}
You are getting IndexError because you try to get the first item in the list, which sometimes is empty.
I would do it like this.
The spider:
def parse_item(self, response):
self.log('%s' % response.url)
hxs = HtmlXPathSelector(response)
item = IsaItem()
item['response_fld'] = response.url
res = hxs.select("//input[(#id or #name) and (#type = 'text' )]/#id ").extract()
item['text_input'] = res[0] if res else None # None is default value in case no field found
res = hxs.select("//input[(#id or #name) and (#type = 'password')]/#id").extract()
item['pass_input'] = res[0] if res else None # None is default value in case no field found
res = hxs.select("//input[(#id or #name) and (#type = 'file')]/#id").extract()
item['file_input'] = res[0] if res else None # None is default value in case no field found
return item
The pipeline:
class SQLiteStorePipeline(object):
def __init__(self):
self.conn = sqlite3.connect('./project.db')
self.cur = self.conn.cursor()
def process_item(self, item, spider):
self.cur.execute("insert into inputs ( input_name) values(?)", (item['text_input'],))
self.cur.execute("insert into inputs ( input_name) values(?)", (item['pass_input'],))
self.cur.execute("insert into inputs ( input_name) values(?)", (item['file_input'],))
self.cur.execute("insert into links (link) values(?)", (item['response_fld'],))
self.conn.commit()
return item
I don't really know anything about this technology, but here's my guess:
Try
insert into inputs ( input_name) values(?)" , (item['text_input'] )
instead of
insert into inputs ( input_name) values(?)" , (item['text_input'][0] ).
As for the 'list index out of range' error, it seems like your item is empty, something you should check for.
I'm trying to set up a custom sort behaviour for my model/view structure in PySide.
All items are dictionaries and I need to filter by their keys (I'm not after a table view of those dictionaries but rather need to present them as one entity each).
I inherited from QSortFilterProxyModel and re-implemented the lessThan method. It works fine the first time the sort widget is changed (which triggers the proxy's sort() method), but after that the lessThan method is no longer called. I have no idea why and an hoping to get some help here. I'm more than happy to consider any suggestions how to tackle this in a different way if that is where the solution lies.
This is my proxy:
class ProxyModel ( QSortFilterProxyModel ):
def __init__( self, parent=None ):
super( ProxyModel, self).__init__( parent )
self.setFilterCaseSensitivity( Qt.CaseInsensitive )
self.setSortCaseSensitivity( Qt.CaseInsensitive )
self.setDynamicSortFilter( True )
def sortBy( self, attr ):
print 'sorting by', attr
self.__sortBy = attr
self.sort( 0, Qt.AscendingOrder ) # THIS DOES NOT GET CALLED WHEN THE COMBO BOX CHANGES A SECOND TIME
def lessThan( self, left, right ):
'''Custom sorting behaviour'''
leftTool = ( self.sourceModel().itemFromIndex( left ) )
rightTool = ( self.sourceModel().itemFromIndex( right ) )
leftData = leftTool.data()[ self.__sortBy ]
rightData = rightTool.data()[ self.__sortBy ]
return leftData < rightData
And here is the complete test code:
import sys
from PySide.QtGui import *
from PySide.QtCore import *
class MainWidget( QWidget ) :
def __init__( self, parent=None ):
super( MainWidget, self ).__init__()
self.listView = MyListView()
model = MyModel()
# MODELS AND VIEWS
self.proxyModel = ProxyModel()
self.proxyModel.setSourceModel( model )
self.listView.setModel(self.proxyModel)
# LAYOUTS
verticalLayout = QVBoxLayout()
filterLayout = QHBoxLayout()
# SORTING WIDGET
sortLayout = QHBoxLayout()
sortLabel = QLabel( 'sort:' )
self.sortWidget = QComboBox()
self.sortWidget.addItems( ['title', 'author', 'downloads'] )
self.sortWidget.currentIndexChanged.connect( self.sortTools )
sortLayout.addWidget( sortLabel )
sortLayout.addWidget( self.sortWidget )
verticalLayout.addLayout( filterLayout )
verticalLayout.addLayout( sortLayout )
verticalLayout.insertWidget(0, self.listView)
self.setLayout( verticalLayout )
def sortTools( self ):
text = self.sortWidget.currentText()
self.proxyModel.sortBy( text )
class ProxyModel ( QSortFilterProxyModel ):
def __init__( self, parent=None ):
super( ProxyModel, self).__init__( parent )
self.setFilterCaseSensitivity( Qt.CaseInsensitive )
self.setSortCaseSensitivity( Qt.CaseInsensitive )
self.setDynamicSortFilter( True )
def sortBy( self, attr ):
print 'sorting by', attr
self.__sortBy = attr
self.sort( 0, Qt.AscendingOrder ) # THIS DOES NOT GET CALLED WHEN THE COMBO BOX CHANGES A SECOND TIME
def lessThan( self, left, right ):
'''Custom sorting behaviour'''
leftTool = ( self.sourceModel().itemFromIndex( left ) )
rightTool = ( self.sourceModel().itemFromIndex( right ) )
leftData = leftTool.data()[ self.__sortBy ]
rightData = rightTool.data()[ self.__sortBy ]
return leftData < rightData
class MyListView( QListView ):
def __init__( self, parent=None ):
super( MyListView, self).__init__( parent )
self.setEditTriggers( QListView.NoEditTriggers )
self.setViewMode( QListView.IconMode )
self.setMovement( QListView.Static )
self.setResizeMode( QListView.Adjust )
self.setDragEnabled( True )
class MyModel( QStandardItemModel ):
def __init__( self, parent=None ):
super( MyModel, self).__init__( parent )
self.init_data()
def init_data(self):
row = 0
toolData = [ {'title':'ToolA', 'author':'John Doe', 'downloads':123, 'category':'color'},
{'title':'ToolB', 'author':'me', 'downloads':13, 'category':'color'},
{'title':'ToolC', 'author':'you', 'downloads':321, 'category':'transform'},
{'title':'ToolD', 'author':'unknown', 'downloads':2, 'category':'transform'}]
for tool in toolData:
item = QStandardItem( '%(title)s by %(author)s (%(category)s) - %(downloads)s downloads' % tool )
item.setData( tool )
self.setItem( row, 0, item )
row += 1
if __name__ == '__main__':
app = QApplication( sys.argv )
mainWidget = MainWidget()
mainWidget.resize( 400, 400 )
mainWidget.show()
sys.exit( app.exec_() )
Basically Qt "thinks" your Proxy is already sorted. To be precise it checks in C++ whether:
(d->dynamic_sortfilter &&
d->proxy_sort_column == column &&
d->sort_order == order)
So, to solve your problem, you can either set dynamic_sortfilter to False (it will have side-effects) or, maybe better, invalidate your sorting:
def sortBy( self, attr ):
print 'sorting by', attr
self.__sortBy = attr
self.invalidate() #invalidate helps
self.sort( 0, Qt.AscendingOrder )