Python function calling - python

I have the following class
class GUI( QtGui.QMainWindow ):
'''
classdocs
'''
"""**********************************************************************"""
""" Constructor """
"""**********************************************************************"""
def __init__( self, parent = None ):
self.udpClass = MCUDP.MCUDP()
def insertText( self, string ):
string = time.ctime() + ': ' + string + '\n'
self.messageField.insertPlainText( string )
And I also have MCUDP class created in the GUI class. My question is how can I reach the GUI class insertText function in MCUDP
UPDATED
this is the MCUDP
'''
Created on 09.06.2011
#author: robu
'''
import socket
import time
import MCGui;
class MCUDP( object ):
'''
classdocs
'''
"""**********************************************************************"""
""" UDP: Broadcasting """
"""**********************************************************************"""
def UDPBroadcast( self, ip = "255.255.255.255", UDPport = 15000, message = 'whoisthere', timeout = 10, TCPport = 30000 ):
# ip="255.255.255.255" stands for a broadcast
ip = str( ip )
s = socket.socket( socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP )
s.setsockopt( socket.SOL_SOCKET, socket.SO_BROADCAST, True )
s.settimeout( timeout )
ownIP = socket.gethostbyname( socket.gethostname() )
if message.upper() == 'WHOISTHERE':
message = message + ';' + ownIP + ':' + str( TCPport )
#print "Trying to send '%s' to IP %s, Port %s!" %(message, ip, port)
#self.Eingang.put("Trying to send '%s' to IP %s, Port %s!" %(message, ip, UDPport))
s.sendto( message, ( ip, UDPport ) )
answer = "%s: '%s' broadcasted to %s!" % ( time.asctime(), message, ip )
GUI.insertText( 'test' );
#print answer
s.close()
return answer

You have two objects that need to communicate with each other, which is a fairly standard communication problem. There's a number of ways that this problem can be solved:
(1) Dependency Injection - Make your MCUDP() class require the MCGUI class at construction time.
You'll then have it available whenever you need:
class MCUDP(object):
def __init__(self, gui): self.gui = gui
def UDPBroadcast(...):
# ... as necessary ...
self.gui.insertText("YourText")
class MCGUI(...)
def __init__( self, parent = None ):
self.udpClass = MCUDP.MCUDP(self)
If you do this your MCUDP class becomes dependent on an object that implements all the methods of self.gui that MCUDP uses. In other words, MCUDP is now coupled directly to the MCGUI class. Of course, the MCGUI class is already dependent on MCUDP to some extent.
(2) Message passing - In Qt, Signals and slots. The idiomatic Qt route uses messages instead of function calls:
class MCGUI(...)
def __init__( self, parent = None ):
self.udpClass = MCUDP.MCUDP()
self.connect(self.udpClass, PYSIGNAL("textUpdated"), self.insertText);
And then you just need to make your MCUDP class a QObject so that it can emit events:
class MCUDP(QObject):
def __init__(self, parent = None):
QObject.__init__(self, parent)
def UDPBroadcast(...):
# ... as necessary ...
self.emit(PYSIGNAL("textUpdated"), ("yourText",))
The benefit of this is now MCUDP doesn't need to know anything about the MCGUI class which will make both testing and future changes easier.

It is available as insertText during declaration and as GUI.insertText or GUI().insertText during execution. If you are not sure where you are, try both :).
I would say which one you need if you posted the actual full code.
[update]
Your MCDUP class is not 'created in the GUI class'. You just create a an instance of MCDUP and hold a reference to it inside GUI. The reference is one-way, so if you need to access parent GUI instance, you need a back-reference, something like:
class GUI(QtGui.QMainWindow):
def __init__(self, parent=None):
self.udp = MCUDP.MCUDP(gui=self)
And then in MCDUP:
class MCUDP(object):
def __init__(self, gui):
self.gui = gui
def udp_broadcast(self, ...):
...
self.gui.insertText('test')
...
I also made the code a little more PEP8-friedly.

Generally the second option suggested by Kaleb Pederson is the way to go.
Nevertheless if you want a reference to the MainWindow you can save it
as a property of your QApplication's instance.
When you start your application:
app = QApplication(sys.argv)
...
mainwindow = GUI()
app.setProperty("mainwindow", QVariant(mainwindow))
Then when you want to use the reference:
...
mainwindow = qApp.property('mainwindow').toPyObject()
...

Related

Return an object from a class

Is it possible to return an object just by calling a class? Take for exemple, I am trying to connect to a client server and just by calling the class, I get the connection.
And if I want to start a new project on that server, I would only need to init the project and the connection is called automatically.
class LabellingProject():
def __init__(self,
web_app=False,
port=8888,
data_dir="/xxxx/xxx/",
local_files_root="/xxxx/datasets",
disable_signup_without_link=True,
username= "xxxx#xxxx"):
self.web_app = web_app
self.port = port
self.data_dir = data_dir
self.local_files_root = local_files_root
self.disable_signup_without_link = disable_signup_without_link
self.username = username
def connection(cls):
"""
"""
config = Config(web_app=cls.web_app,
port = cls.port,
data_dir = cls.data_dir,
local_files_root=cls.local_files_root,
disable_signup_without_link=cls.disable_signup_without_link,
username=cls.username)
server = LabelStudioServer()
server.start(config)
client = Client(url="http://localhost:"+str(config.port),
api_key=config.token)
return client
def create_new(self,client):
"""
"""
project = client.start_project()
return project
I want to call the function like this.
labelling = LabellingProject() => it will return the connection
project = labelling.create_new() => it will return the project and the client it should take it from the __init__.
createFromA needs to be a staticmethod as it does not operate on instances of the class Constructor
class A:
def __init__(self):
pass
def create_project(self,argA):
newA = self.Constructor.createFromA(argA)
return newA
class Constructor:
def __init__(self):
pass
#staticmethod
def createFromA(argA):
A = 2*argA
return A
cons = A()
cons.create_project(2)

Python global empty in class

I tried to get array parameters values in another class , where and why i wrong here ?
My second python file => myModule.py :
parameters = ([])
class MyFirstClass():
def __init__(self, params):
global parameters
parameters = params
class MySecondClass():
def __init__(self):
global parameters
print parameters
class MyClassWhereIHaveAProblem(http.HTTPFactory):
proto = .....
global parameters
print parameters **// array is empty here**
class start_server():
def __init__(self, params):
self.x_params = params[0] //ip
self.y_params = int(params[1]) //port
global parameters
parameters = params[2]
def start():
reactor.listenTCP(self.y, MyClassWhereIHaveAProblem(), interface=self.x)
My first python file => Handle.py :
from myModule import MyFisrtClass
from myModule import MySecondClass
from myModule import MyClassWhereIHaveAProblem
from myModule import start_server
class Handle():
def __init__(self):
params = (["vector1", "vector2"])
self.params = (["127.0.0.1","3128", params])
def go_to_another(self):
s = start_server(self.params)
s.start()
if __name__ == '__main__':
H = Handle()
H.go_to_another()
I tried to get array parameters values in another class , where and why i wrong here ?
It looks like you are simply:
forgetting the second set of double underscores for the special method names
making typos in the class names, you had "First" spelled "Fisrt"
you never did anything to use the MySecondClass class, so I initialized one in your main routine with: y = MySecondClass()
Handle.py:
#!/usr/bin/env python
from myModule import MyFirstClass
from myModule import MySecondClass
class Handle():
def __init__(self):
self.params = (["ele1","ele2","ele3"])
def go_to_another(self):
X = MyFirstClass(self.params)
if __name__ == '__main__':
H = Handle()
H.go_to_another()
y = MySecondClass()
myModule.py:
#!/usr/bin/env python
parameters = ([])
class MyFirstClass():
def __init__(self, params):
global parameters
parameters = params
class MySecondClass():
def __init__(self):
global parameters
print 'this should not be empty: %s' % parameters # array is no longer empty here
Output:
this should not be empty: ['ele1', 'ele2', 'ele3']
You have X = MyFisrtClass(self.params) instead of X = MyFirstClass(self.params)! Also __init should be __init__.
You are printing the variable when the class is first defined, but defining the variable when the class is initialized.
In Python, anything here:
class MyClass:
# here
Is evaluated as soon as the interpreter reaches that line-- not when the class is initialized.
Try running this code to get a better idea of what I mean:
my_global_var = 'set initially!'
class MyClass():
# Will print 'set initially', as this
# print statement is run before an instance of the
# class ever gets initialized,
print 'in class defn: %s' % my_global_var
def __init__( self ):
global my_global_var
my_global_var = 'set by the class instance!'
x = MyClass()
# Will print 'set by the class instance', as now
# you are printing it after the class has been initialized
# at least once
print 'after class is initialized: %s' % my_global_var
For your code:
# I have a problem here
class MyClassWhereIHaveAProblem(http.HTTPFactory):
#proto = .....
#global = parameters
print 'not set here, this is static: %s' % parameters #**// array is empty here**
def __init__(self):
print 'now it is set: %s' % parameters
But make sure you actually initialize one of those MyClassWhereIHaveAProblem.
From what I think is the documentation:
listenTCP(port, factory, backlog=50, interface='')
port a port number on which to listen
factory a twisted.internet.protocol.ServerFactory instance
backlog size of the listen queue
interface The local IPv4 or IPv6 address to which to bind; defaults to '', ie all IPv4 addresses. To bind to all IPv4 and IPv6 addresses, you must call this method twice.
So I think you want to simply do:
listenTCP(self.y_params, YourProblemClass(), interface=self.x_params)
Where:
- y_params is what you called the port, and
- x_params is what you called the address.
ok, I'll go to sleep :) I had also itinialise my object (logical), now everything is ok, Thanks for your time Alex.B, solution here:
class MyClassWhereIHaveAProblem(http.HTTPFactory):
proto = .....
def __init__(self):
http.HTTPFactory.__init__(self)
global parameters
print parameters

(PyQt) Uncheck pushbutton from outside button's class?

A QPushButton is set 'asCheckable'. Whence toggled, a class bool is changed.
This altered bool allows a method in a different class to proceed, and upon completion of this outside method I need to return the button to its initial state, 'setChecked(False)'.
While I am able to return the class housed bool to its default state at the end of this external method, I am unable to externally access a method which un-clicks the button.
I assume its due to the arguments in the classes init, but these are necessary - and I'm wondering if there is another means to achieve the described workflow.
Related code snips below:
(command in question is distinguished at bottom of 'Class 2')
Class 1:
class shapeCSVeditor(QtGui.QDialog, QtGui.QWidget):
valueShare = []
rowOverride = False# <<=== equivalent to 'override' in 'Class 2'
def __init__(self, iface, fileName, editorType, parent=None):
super(shapeCSVeditor, self).__init__(parent)
self.iface = iface
self.editorType = editorType
self.fileName = filename
self.pushButtonSetBase = QtGui.QPushButton(self)
self.pushButtonSetBase.setText("Set Base Shape")
self.pushButtonSetBase.setCheckable(True)
self.pushButtonSetBase.toggled.connect(self.on_pushButtonSetBase_toggled)
self.layoutHorizontal.addWidget(self.pushButtonSetBase)
#some other things here...
#QtCore.pyqtSlot()
def on_pushButtonSetBase_toggled(self):
shapeCSVeditor.rowOverride = True
pass
def on_BaseRow_Changed(self):
self.pushButtonSetBase.setChecked(False)
return
Class 2:
class CSVModel(QtCore.QAbstractTableModel):
# Establish inital settings and branch processes
def __init__(self, iface, fileName, editorType, parent=None):
super(CSVModel,self).__init__()
self.propertiesFile = r'some file'
self.areaStressFile = r'some other file'
self.iface = iface
self.rows = []
self.editorType = editorType
self.loadCSV()
self.iface.mapCanvas().selectionChanged.connect(self.addRow)
# add rows to the TableView based on object selection(s) in Qgis.mapCanvas
def addRow(self):
override = shapeCSVeditor.rowOverride
selectedFeatures = selectedLayer.selectedFeatures()
if override:
for feature in selectedFeatures:
self.rows.pop(0)
feat_Attributes = []
feat_Attributes.extend([self.iface.activeLayer().name()+'_'+str(feature.id())])
feat_Attributes.extend(['',]*(len(self.header)-1))
self.beginResetModel()
self.rows.insert(0,feat_Attributes)
shapeCSVeditor.rowOverride = False
self.endResetModel()
shapeCSVeditor.on_BaseRow_Changed# <<<=== wrong-diddily!
break
PS - if parentheticals are added to the 'shapeCSVeditor()' 3 arguments are requisite as referenced in the Button class, and if parentheticals are added to 'on_BaseRow_Changed', the return is;
TypeError: unbound method on_BaseRow_Changed() must be called with
shapeCSVeditor instance as first argument (got nothing instead)
What you are doing is strange.
In python, the first argument of a class method is always the object itself.
So, in your:
def on_BaseRow_Changed(self):
self.pushButtonSetBase.setChecked(False)
# return => This return is useless
if you don't provide an object then you can't access the pushbutton.
You didn't gave us all the code but I think you should provide your addRow with the shapeCSVeditor object that you want to update:
def addRow(self, shapeCSVObj):
override = shapeCSVObj.rowOverride
if override:
for feature in selectedFeatures:
self.rows.pop(0)
feat_Attributes = []
feat_Attributes.extend([self.iface.activeLayer().name()+'_'+str(feature.id())])
feat_Attributes.extend(['',]*(len(self.header)-1))
self.beginResetModel()
self.rows.insert(0,feat_Attributes)
shapeCSVObj.rowOverride = False
self.endResetModel()
shapeCSVObj.on_BaseRow_Changed()
break
Somewhere you must have a shapeCSVeditor that is created. You should provide it to you outside class.
Hope this helps.
class shapeCSVeditor(QtGui.QDialog, QtGui.QWidget):
valueShare = []
rowOverride = False
def __init__(self, iface, fileName, editorType, parent=None):
super(shapeCSVeditor, self).__init__(parent)
self.iface = iface
self.editorType = editorType
self.fileName = fileName
self.tableView = QtGui.QTableView(self)
self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)
self.tableData = CSVModel(self,iface,fileName,editorType)
^^==not implementing 'self' (shapeCSVeditor object) was the problem!
self.tableView.setModel(self.tableData)
...
self.pushButtonSetBase = QtGui.QPushButton(self)
self.pushButtonSetBase.setText("Set Base Shape")
self.pushButtonSetBase.setCheckable(True)
self.pushButtonSetBase.clicked.connect(self.on_pushButtonSetBase_toggled)
...
#QtCore.pyqtSlot()
def on_pushButtonSetBase_toggled(self):
self.rowOverride = True
#QtCore.pyqtSlot()
def on_BaseRow_Changed(self):
self.rowOverride = False
self.pushButtonSetBase.setChecked(False)
///////////////////////////////////////////////////////////////////////////////////////
class CSVModel(QtCore.QAbstractTableModel):
def __init__(self, shapeCSVeditor, iface, fileName, editorType):
super(CSVModel,self).__init__()
self.propertiesFile = r'foo'
self.areaStressFile = r'bar'
self.tableView = shapeCSVeditor <<== proper passing of shapeCSVeditor object! (?)
self.iface = iface
self.rows = []
self.editorType = editorType
self.loadCSV()
self.iface.mapCanvas().selectionChanged.connect(self.addRow)
...
def addRow(self):
selectedFeatures = selectedLayer.selectedFeatures()
if self.tableView.rowOverride:
for feature in selectedFeatures:
self.rows.pop(0)
feat_Attributes = []
feat_Attributes.extend([self.iface.activeLayer().name()+'_'+str(feature.id())])
feat_Attributes.extend(['',]*(len(self.header)-1))
self.beginResetModel()
self.rows.insert(0,feat_Attributes)
self.endResetModel()
self.tableView.rowOverride = False
self.tableView.on_BaseRow_Changed()
Radical. Works for the current needs.
Now the question is if its proper to python 'standards'.
Quite new to writing, so its possible more needs fixed.
High thanks to Plouff for the clues.

How to access python class method from main and transfering and accessing the variable in another python file

I have S8Test.py with testFirewallS8 class and some methods. I want to access the method declared inside this class form the main method. and set the variable from that method another python file contains the same variable to modify. How can I do this:
#! /usr/bin/env python
__author__ = 'Milson Munakami'
__revision__ = '0.0.2'
import json
import urllib
import httplib
from scapy.all import *
import unittest
import os, sys, socket, struct, select, time
from threading import Thread
import logging
import traceback
from mininet.net import Mininet
from mininet.node import OVSSwitch, OVSKernelSwitch, Controller, RemoteController
from mininet.log import setLogLevel, info
from mininet.cli import CLI
class TestFirewallS8( unittest.TestCase ):
def setUp(self):
self.controllerIp="127.0.0.1"
self.switch = "00:00:00:00:00:00:00:01"
self.destinationIp = "10.0.0.1"
self.startTime_ = time.time()
self.failed = False
self.reportStatus_ = True
self.name_ = "Firewall"
self.log = logging.getLogger("unittest")
"Create an empty network and add nodes to it."
self.net = Mininet( controller=RemoteController )
#Want to move this method call from outside the setUp method because it need to be initiated only once for the whole test but
#it need to access the class variables and pass it to another python file i.e. Events.py to perform some task on the object i.e. self
#self.CreateNet()
def createNet(self):
print "Me"
info( '*** Adding controller\n' )
self.net.addController( 'c0' , controller=RemoteController,ip= "127.0.0.1", port=6633)
info( '*** Adding hosts\n' )
h1 = self.net.addHost( 'h1', ip='10.0.0.1' )
h2 = self.net.addHost( 'h2', ip='10.0.0.2' )
h3 = self.net.addHost( 'h3', ip='10.0.0.3' )
info( '*** Adding switch\n' )
s1 = self.net.addSwitch( 's1' )
info( '*** Creating links\n' )
self.net.addLink( h1, s1 )
self.net.addLink( h2, s1 )
self.net.addLink( h3, s1 )
def setFinalcondition(self):
Precondition.SetFinalcondition(self)
info( '*** Stopping network' )
self.net.stop()
def testCreateFlow(self):
Events.createFlow(self)
def suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestFirewallS8))
return suite
if __name__ == '__main__':
#How to get run the method of testFirewallS8 class and set the variable of it like self.net
suiteFew = unittest.TestSuite(testCreateFlow)
TestFirewallS8("createNet")
In another Events.py I have:
def createFlow(self):
info( '*** Starting network\n')
self.net.start()
info( '*** Testing network connecivity\n')
#self.net.pingAll()
h1 = self.net.get('h1')
h3 = self.net.get('h3')
h1.cmd('ping -c1 %s' % h3.IP())
I'm not completely clear what you're asking, but if you have a class definition:
class MyClass(object):
def __init__(self, name):
self.name = name
def big_name(self):
print(self.name.upper())
After you instantiate it (MyClass('Bob')), assign it to a variable.
bob = MyClass('Bob')
You can then execute methods of that class instance by simply accessing it's attributes.
bob.big_name # accesses the "big_name" attribute on "bob": a bound method
bob.big_name() # executes the bound method
Attributes can also be variables, and you can freely access and reassign them as well:
bob.name # accesses the "name" attribute on "bob": a string
bob.name = 'Robert' # reassigns the "name" attribute

SQLAlchemy - mapping one class to two tables

I have two implementations of database queue (they use different tables) and want them to use objects of the same class. So, they both look really similar:
class AbstractDBQueue(object):
def __init__(self, tablename):
self.tablename = tablename
self.metadata = MetaData()
self.engine = create_engine('mysql+mysqldb://%s:%s#%s:%d/%s' % (
settings.DATABASE.get('USER'),
settings.DATABASE.get('PASSWORD'),
settings.DATABASE.get('HOST') or '127.0.0.1',
settings.DATABASE.get('PORT') or 3306,
settings.DATABASE.get('NAME')
), encoding='cp1251', echo=True, pool_recycle=7200)
self.metadata.bind = self.engine
self.session = sessionmaker(bind=self.engine)()
def setup_table(self, table, entity_name):
self.table = table
newcls = type(entity_name, (SMSMessage, ), {})
mapper(newcls, table)
return newcls
def put(self, message=None, many_messages=[]):
if message:
self.session.add(message)
else:
for m in many_messages:
self.session.add(m)
self.session.commit()
def get(self, limit=None):
if limit:
q = self.session.query(self.SMSClass).limit(limit)
else:
q = self.session.query(self.SMSClass)
smslist = []
for sms in q:
smslist.append(sms)
self.session.expunge_all()
return smslist
class DBQueue(AbstractDBQueue):
"""
MySQL database driver with queue interface
"""
def __init__(self):
self.tablename = settings.DATABASE.get('QUEUE_TABLE')
super(DBQueue, self).__init__(self.tablename)
self.logger = logging.getLogger('DBQueue')
self.SMSClass = self.setup_table(Table(self.tablename, self.metadata, autoload=True), "SMSQueue")
class DBWorkerQueue(AbstractDBQueue):
"""
MySQL database driver with queue interface for separate workers queue
"""
def __init__(self):
self.tablename = settings.DATABASE.get('WORKER_TABLE')
super(DBWorkerQueue, self).__init__(self.tablename)
self.logger = logging.getLogger('DBQueue')
self.SMSClass = self.setup_table(Table(self.tablename, self.metadata, autoload=True), "SMSWorkerQueue")
def _install(self):
self.metadata.create_all(self.engine)
SMSMessage is the name of the class I want to use. The map_class_to_table() function is a hack I've found in SQLAlchemy documentation: http://www.sqlalchemy.org/trac/wiki/UsageRecipes/EntityName
But it doesn't seems to help - when the first queue instance maps SMSMessage to it's table, then all objects I pass to second queue's put() are implicitly casted to first queue's mapped class, and second database is still empty after session.commit().
I need to use both queues at the same time, maybe even using threads (I think, pool connection will be useful), but I just can't make this work. Could you help, please?
I think your problem relates to the tablename variable. It's a class variable which gets defined when you create the class, and then does not change. So, it will be the same for both of your instances, when they access it with self.tablename. To fix this, move it inside the init function, and make it a self.tablename. That will initialize it each time you create a new object.

Categories