I am struggling to find a way to access a widget by its id in another class.
Here comes a code example that will make it easy for you to understand.
class LoginScreen(Screen):
def login(self, username, password):
if user_exists(username, password):
self.manager.current = "login_success"
class LoginSuccess(Screen):
pass
.kv
<LoginSuccess>
Label:
id: greeting
text: "" #this should be "Hey, "+username
I have access to username in the login method of the LoginScreen class, but I need to use that variable in the LoginSuccess class.
How can I do that
Still missing a bit of information (the name property of your LoginSuccess Screen). In your login() method try:
self.manager.get_screen("the_name_of_your_LoginSuccess_Screen").ids.greeting.text = "Hey, "+username
Related
I want to get instances of the attributes in each class, such as the users password and email, but I also want to be able to get the add_widget to come up with only the name, yet:
Here is my code so far
from kivy.uix import Screen, ScreenManager
class WindowManager(ScreenManager):
pass
sm = WindowManager()
In login window
class LoginWindow(Popups, Screen, FloatLayout, BoxLayout):
def __init__(self, email, password, checkBox, **kwargs):
self.email = email
self.password = password
self.checkBox = checkBox
super(self, **kwargs).__init__()
self.name = "login"
And in main app window
sm.add_widget(LoginWindow(name="login"))
#actual phone app class
class PhoneAssistantApp(App):
def __init__(self):
super(self).__init__()
def build(self):
if LoginWindow.checkBox == True:
sm.current = "main"
else:
sm.current = "login" #user sent to login page whenever program is ran
return sm
if __name__ == "__main__":
PhoneAssistantApp().run()
But it comes up with error:
line 352, in <module>
sm.add_widget(LoginWindow(name="login"))
TypeError: __init__() missing 3 required positional arguments: 'email', 'password', and 'checkBox'
My login window in my kv file is simply:
<LoginWindow>:
name: "login" #name used to know where to send
email: email #links to object property in py file class
password: password #links to object property in py file class
checkBox: checkBox #links to boolean property in py file class
I believe the error is in my main program, as I'm trying to figure out how to fit both the attributes instances in with the kivy.
First I had my sm.add_widget and classes names in the App class, like
class PhoneAssistantApp(App):
def __init__(self, **kwargs):
super(self, **kwargs).__init__()
self.screens = ((LoginWindow(name="login"), CreateAccountWindow(name="Create))
self.sm = ScreenManager()
def build(self):
for screen in self.screens:
self.sm.add_widget(screens)
if LoginWindow.checkBox == True:
self.sm.current = "main"
else:
self.sm.current = "login" #user sent to login page whenever program is ran
return self.sm
if __name__ == "__main__":
PhoneAssistantApp().run()
And
class PhoneAssistantApp(App):
def __init__(self, **kwargs):
super(self, **kwargs).__init__()
self.screens = ((LoginWindow(name="login"), CreateAccountWindow(name="Create))
def build(self):
for screen in self.screens:
sm.add_widget(screens)
if LoginWindow.checkBox == True:
sm.current = "main"
else:
sm.current = "login" #user sent to login page whenever program is ran
return sm
if __name__ == "__main__":
PhoneAssistantApp().run()
Yet taking it away didn't get rid of the problem. In addition, getting rid of the **kwargs likely didn't help much either.
It worked fine until I added the init into the classes.
I'm using visual studio code, where before I added the init hovering over name in above would display 'name=[literal]"login', yet now only displays 'name = "any"'
However, when hovering over name in the login class in my new code, it also returned 'name = [literal]login'.
Rather, I want to be able to use the name without having to indent the other attributes into my sm.add_widget.
While I did try putting the attributes in to see what would work, I tended to put:
sm.add_widget(LoginWindow(name="login", email=LoginWindow.email, password=LoginWindow.password, checkBox=LoginWindow.checkBox))
As I simply wanted the instances of the attributes, but I don't think that's what I should do as it only got me error.
line 352, in <module>
sm.add_widget(LoginWindow(name="login", email=LoginWindow.email, password=LoginWindow.password, checkBox=LoginWindow.checkBox))
AttributeError: type object 'LoginWindow' has no attribute 'email'
Thanks to anyone who'd be able to help out.
When you define a method as you have:
def __init__(self, email, password, checkBox, **kwargs):
all those arguments are required whenever an instance of LoginWindow is created. Your code:
sm.add_widget(LoginWindow(name="login"))
does not provide those required arguments, thus you get that error. You can instead use optional arguments by using keywords. See the documentation.
For example
class Signup:
def __init__(self): # i want to call the functions in this class
self.user_input()
self.get_password()
def user_input(self):
username = input("Enter your username: ")
return username
def get_password(self):
password = input("Enter a password: ")
return password
class Data(Signup):
def __init__(self):
super().__init__()
self.username = self.user_input() # When I call these two functions they execute it again
self.password = self.get_password()
So I want the string to be returned when I call those functions in the Data class. The problem is that the function calls itself here again too.
And I know I can just call the functions inside the Data class, but I want to call it in the Signup class and get the string back inside the Data class.
Thanks!
Hey there I'm new to python and try to program a simple login module which salts a password
When I use this class I get the following error:
TypeError: salting() missing 1 required positional argument: 'password'
class Login():
def salting(self, username, password):
self.password = password
self.username = username
print(self.username + self.password)
Login.salting("user1","pw1")
My Only Solutions were to use Login.salting("","user1","pw1") with an empty string for self or calling self as username end reuse it like this, but I think that I ran in an error, can someone help me :D
But when I compare that with my previous code which was like this (I learned that with this code) - the error doesn't appear...
class car():
name = "BMW"
color = "red"
def redesign(self, color):
self.color = color
c = car()
print(c.name)
print(c.color)
c.redesign("blue")
print(c.color)
THANKS
salting is an object method, not a class method. Each object has its own username and password attributes. You need to create a Login object, and then call the method on that.
s = Login()
s.salting("user1", "pw2")
This is analogous to using c = car() in the second block of code.
I'm building a web crawler with Python. I created a parent class to save the user and the password, that I'd like to be inputed via keyboard.
The parent class looks like this:
class ParentCrawler(object):
def __init__(self):
"""Saves the user and the password"""
self.user = input("Email: ")
self.password = getpass.getpass("Password: ")
Then I created a subclass of that parent class with the idea of running parallel instances of it to make the crawling faster. But everytime I create a new object of the child class, I'm asked to input user and pass again, like in the pic below, and that's not what I want.
When a child object is created...
I know I could just hard code my user and pass into the parent class constructor method, but I'd like to know how to input them manually every time the program runned.
Th __init__ method of a class will be run every time you create a new instance. Since this values are needed just once, and you don't need different values for them for each instance, it makes little sense for their values to be requested inside the class initialiser, or other method.
Moreover, if your classes have nothing to do with user interaction on the terminal, there is no reason to hardcode this user interaction in the class code - if you make modifications to your program that will use the same class, and get this information from a configuration file, or from a POSTed web form, for example, you won't be able to use these classes in this way.
There is nothing wrong to pass the credentials as mandatory values when instantiating a class. To continue development and use of your program using it interactivelly at the terminal, you can create a simple function that will request these input data, and return them -
NUM_WORKERS = 4
def get_credentials():
user = input("Email: ")
password = getpass.getpass("Password: ")
return user, password
def main():
workers = []
user, password = get_credentials()
for i in range(NUM_WORKERS):
worker = Crawler(user, password)
workers.append(worker)
worker.start()
...
class Crawler:
def __init__(self, user, password):
...
I am working with locust and I am working in mimicking the behavior of a user. However I am getting trouble accessing the parent class variable. Any idea how I can pass it?
class User(TaskSet):
some_user = ''
def on_start(self):
self.get_user()
def get_user(self):
some_user = self.client.get...#gets user
#task
class UpdatingUser(TaskSet):
def updating(self):
path = "/posts/" + User.some_user
By the time I get to User.some_user I never have the user.
You've not provided all of the code, but the problem may be that get_user() is setting some_user as an instance attribute somewhere, as in self.some_user = foo.
This will only set some_user for that specific instance of User however (so for Bob, Lisa, Beto, User53, etc.), but not for the User class itself. When accessing some_user with self, as in self.some_user, you set it for the specific instance that's executing those statements, not the class. In updating() you're accessing the class attribute User.some_user, not a specific instance attribute like usr53.some_user. In order to update the class attribute, invariant by default for all instances of User, you ought to be setting it with User.some_user = foo in get_user().
Right now in path = "/posts/" + User.some_user, it's trying to access the class attribute which may never have been set. Because nested classes like UpdatingUser can't access the instances of the nesting class (User) that they're called from, UpdatingUser won't be able to access any some_user set with self or any other instance attributes of User. So the solution would be to have get_user() set the class attribute instead of the instance attribute as described in the previous paragraph.
This answer is a bit late but, if anyone has this issue, the TaskSet has a parent property, which can be used to access the parent's instance variables. The following is what I used for a basic one-time login:
class UserBehaviour(TaskSet):
def on_start(self):
self.token = self.login()
self.headers = {'Authorization': 'Bearer ' + self.token}
def login(self):
with self.client.post("/login", catch_response = True) as response:
return response.json()['token']
#task
class UserTask1(TaskSet):
#task
def get_data(self):
self.client.get("/data", headers = self.parent.headers)
class WebsiteUser(HttpLocust):
task_set = UserBehaviour