i made a test app for reasons like this. I am trying to have the ButtonRelease-1 event call a function inside another file. I am getting a syntax when trying to run the app.
TypeError: listb() takes exactly 2 arguments (1 given)
this is pretty strait forward syntax but i cannot fix it in this specific situation. I am basically just having the event get the clicked info printed. It's the event that is no working because function inside other file is not reconizing the event?
anyways, curious how to fix this code so it works. The function has to stay in another file. This would be easy if it was in same file but it cannot be.
start.py
from Tkinter import *
import example_funcs as EF
class Page_three(Frame):
def __init__(self):
Frame.__init__(self)
self.pack()
self.listboxs()
def listboxs(self):
self.z = Listbox(self)
self.z.grid()
for item in range(1,10):
self.z.insert(END, item)
self.z.bind("<ButtonRelease-1>", EF.listb(self))
root = Tk()
app = Page_three()
app.mainloop()
example_funcs.py
from Tkinter import *
import Tkinter as tk
def listb(self, event):
selection = self.z.curselection()
print selection
self is used so variables can be called inside the function, if do not call self as instance it will have syntax of not finding my listbox variable.
Passing EF.listb(self) doesn't do what you want it to do. It doesn't partially bind the self parameter to the instance you're calling it from, then let the event paramter get filled in by the callback. Instead, it just calls the function immediately (before the bind call is made) and you get an error about using the wrong number of arguments.
There are a few different ways you could fix this issue.
One option would be to manually bind the self parameter to the listb function using functools.partial:
import example_funcs as EF
import functools
class Page_three(Frame):
...
def listboxs(self):
...
self.z.bind("<ButtonRelease-1>", functools.partial(EF.listb, self)) # bind self
Another approach would be to make listb an actual method in your class, so that you can reference it as a method on self. That could look like this:
import example_funcs as EF
class Page_three(Frame):
...
def listboxs(self):
...
self.z.bind("<ButtonRelease-1>", self.listb) # refer to a method without calling it
listb = EF.listb # add the function from the other module as a method on this class
If listb isn't used anywhere else though, then defining it in another module and copying it over here would be pretty silly. You should just move the definition into this class instead of adding a reference to it after the fact. On the other hand, if listb is being used in several different classes, it suggests that the classes should be using some kind of inheritance to share the method, rather than crudely copying references to the one definition around.
Related
SEFC.py:
import time
import traceback
import platform
sefc_verbose = False
obj_sefc = None
class CSEFC():
def __init__(self):
self.fp_platform = False
self.bbu_platform = False
return
def __del__(self):
return
def ipmi_cmd_trace(self):
return False
KCS.py:
import SEFC as sefc
class CKCS(CLogger):
def __init__(self, str_ip = None, int_port = _DEFAULT_ATRAGON_PORT):
CLogger.__init__(self)
self.obj_json_client = None
def send_ipmi_target(self, targetstr, raw_request, int_retry = 3):
if sefc.obj_sefc.ipmi_cmd_trace():
##do stuff
I am reading code written by someone else.I can't seem to understand in if sefc.obj_sefc.ipmi_cmd_trace(): obj_sefc is used to call ipmi_cmd_trace() function. sefc_obj is a global variable I belive. But this code should not work. Also, I doubt my programming ability. This code seems to compile and work for others. Is this correct? Am I missing something here?
With just the code you've shown, you're right, it won't work, since obj_sefc is None in the SEFC module. However, I suspect that some other code that you haven't shown that creates an instance of the CSEFC class and assigns it to that global variable. Then the code you've shown will work.
Its probably not a good design for the code you've shown to be reliant on some other code to be run first, since it will fail if it gets run in the wrong order. However, using a global variable to contain a single instance of a class is not problematic in general. You just want to make sure the code that creates the instance is put somewhere that ensures it will be run before the instance is needed. For instance, the code could be put at the bottom of the SEFC module, or at the top of the KCS module.
I have been following the page object model for my Selenium Webdriver tests in Python. I have followed the sample from GitHub.
URL is: https://github.com/baijum/selenium-python/blob/master/source/page-objects.rst
When you call the locator from the MainPageLocators class e.g from the URL.
element = self.driver.find_element(*MainPageLocators.GO_BUTTON)
It uses an asterisk in front of the class name *MainPageLocators.
Why does it use * ?
It does not work if you use MainPageLocators, you have to use *MainPageLocators.
This is no good because when i use the WebDriverWait it does not work with *MainPageLocators or MainPageLocators.
E.g.
element = WebDriverWait(self.driver, 20).until(EC.element_to_be_clickable((*MainPageLocators.locator)))
I have to to do it this way for it to work which defeats the purpose of having the locators in one place.
element = WebDriverWait(self.driver, 20).until(EC.element_to_be_clickable((By.ID, 'button_id')))
Why the asterisk in front of MainPageLocators?
Why does *MainPageLocators not work inside the WebDriverWait?
It does work if you do
self.driver.find_element(*MainPageLocators.locator)
But it does not work if you use it in the WebDriverWait
Thanks,
Riaz
In this context, * is the argument-unpacking operator. It tells Python to unpack the values in the sequence that follows and pass them as arguments to the function. For example,
foo(*(1, 2, 3))
is equivalent to
foo(1, 2, 3)
Since MainPageLocators.GO_BUTTON is defined like this:
class MainPageLocators(object):
"""A class for main page locators. All main page locators should come here"""
GO_BUTTON = (By.ID, 'submit')
it follows that find_element(*MainPageLocators.GO_BUTTON) is equivalent to
find_element(By.ID, 'submit')
This works since find_element expects 2 arguments.
In contrast, EC.element_to_be_clickable expects a single 2-tuple as its argument. Therefore you would not want to use the argument-unpacking operator here. Instead, just pass the 2-tuple directly:
wait = WebDriverWait(self.driver, 20)
element = wait.until(EC.element_to_be_clickable((By.ID, 'submit'))
or use
element = wait.until(EC.element_to_be_clickable(MainPageLocators.GO_BUTTON)
I have a coordinate system that it makes sense to treat as a "whole group". They initialize, change, and reset simultaneously. I also like to not re-render as many times as I have coordinates when one changes. Here is the simplified version of what I have in mind, but I can't quite get there. Thanks.
Cleaner code is better in my case even if it uses more advanced features. Could the class 'Coord' be wrapped as a trait itself?
from traits.api import *
class Coord(HasTraits):
x=Float(1.0)
y=Float(1.0)
def __init__(self,**traits):
HasTraits.__init__(self,**traits)
class Model:
coord=Instance(Coord)
#on_trait_change('coord')##I would so have liked this to "just work"
def render(self):#reupdate render whenever coordinates change
class Visualization:
model=Instance(Model)
def increment_x(self):
self.model.coord.x+=1 ##should play well with Model.render
def new_coord(self):
self.model.coord=Coord(x=2,y=2) ##should play well with Model.render
There are a couple of issues with your source code. Model and Visualization both need to be HasTraits classes for the listener to work.
Also, it is rare to actually need to write the __init__ method of a HasTraits class. Traits is designed to work without it. That said, if you do write an __init__ method, make sure to use super to properly traverse the method resolution order. (Note that you will find this inconsistently implemented in the extant documentation and examples.)
Finally, use the 'anytrait' name to listen for any trait:
from traits.api import Float, HasTraits, Instance, on_trait_change
class Coord(HasTraits):
x=Float(1.0)
y=Float(1.0)
class Model(HasTraits):
coord=Instance(Coord, ())
#on_trait_change('coord.anytrait') # listens for any trait on `coord`.
def render(self):
print "I updated"
class Visualization(HasTraits):
model=Instance(Model, ())
def increment_x(self):
self.model.coord.x+=1 # plays well with Model.render
def new_coord(self):
self.model.coord=Coord(x=2,y=2) # plays well with Model.render
Here's my output:
>>> v = Visualization()
>>> v.increment_x()
I updated
>>> v.new_coord()
I updated
I am trying to use this calendar widget code within an existing tkinter. I want to have the clicked date returned, so that I can do things with it. I have tried calling the pressed function like so
from ttkcalendar import *
def clicked(event):
print cal.selection()
...
root = Tk()
cal=Calendar(mainframe)
cal.bind("<Button-1>",clicked)
However this returns a Type Error: 'datetime.datetime' object not callable. Suggestions? I am sure there is a correct way to do this...thanks in advance!
Method selection() has decorator #property, thus you should do as follows:
def clicked(event):
print cal.selection
# i.e. not cal.selection()
I have a django application xxx which does a number of things.
I also have a sepaerate application yyy. Which wants to call one of the functions of xxx.
Is there a way for me to import the functions?
For example, in yyy can i say
from toplevel.xxx import doit
Or what is the best approach, I dont want to duplicate code.
Of course, you can fo it.
With a proper import and parameter, you can do it.
#app: app1
#someview.py
def a_view(request, someparam):
#some code here
#app: app2
#otherview.py
from app1.someview import a_view
def another_view(request):
param = 1
a_view(request, param)
As for an example
UPDATE: Wish to mention that, your function a_view() do not have to get a parameter at all. So you can call functions with no paramaters. I just wish to mention that, if your function have paramaters, you have to pass them as if you do within an application.