Error when passing argument to QThread subclass in PyQt5 - python-3.x

I'm new in PyQt5, there is something wrong when I tried to pass arguments to a QThread subclass. Here is the code:
class DrClientThread(QtCore.QThread):
def __int__(self, server, username, password):
QtCore.QThread.__init__(self)
self.server = server
self.username = username
self.password = password
def run(self):
print(self.username, self.password, self.server)
class DrCOM_UI(Ui_Login_Dialog):
def __init__(self, dialog):
Ui_Login_Dialog.__init__(self)
self.setupUi(dialog)
self.login_btn.clicked.connect(self.login_and_keep_alive)
...
def login_and_keep_alive(self):
server, username, password = self.write_data_before_login()
self.drclient = DrClientThread(server, username, password)
self.drclient.start()
When I run the code, it gave me the exception:
in login_and_keep_alive
self.mydrclient = DrClientThread(server, username, password)
builtins.TypeError: QThread(QObject parent=None): argument 1 has unexpected type 'str'
I did some google work, and read almost every question on stackoverflow related to this problem, but I can't find out a solution. Actually, I want to do like this: How can I pass arguments to QThread Worker class?
Anyone can help me?

class DrClientThread(QtCore.QThread):
def __int__(self, server, username, password):
QtCore.QThread.__init__(self)
self.server = server
self.username = username
self.password = password
def run(self):
print(self.username, self.password, self.server)
class DrCOM_UI(Ui_Login_Dialog):
def __init__(self, dialog):
Ui_Login_Dialog.__init__(self)
self.setupUi(dialog)
self.login_btn.clicked.connect(self.login_and_keep_alive)
...
def login_and_keep_alive(self):
server, username, password = self.write_data_before_login()
self.drclient = DrClientThread(self, server, username, password) # <<-----
self.drclient.start()

Related

Trying to create generic CRUD class for all endpoints

I am fairly new to FastAPI(migrating from Django) and I am trying to create a generic CRUD operations class that I can inherit and use across my CBV endpoints.
Something like this :
class AbstractCrud
model: Base = NotImplemented
session: Session = NotImplemented
def get_items(self, limit, **filters):
""" Read operation """
def get_item(self, pk: int):
def create_item(self, obj: BaseModel):
""" Create operation """
def update_item(self, pk: int, **params):
""" Update operation"""
def delete_item(self, pk: int):
""" Delete operation """
router = InferringRouter()
#cbv(router)
class UserAPI(AbstractCrud):
router.tags = ["User"]
router.prefix = "/users"
model = User
session: Session = Depends(get_db)
# my endpoints
#e.g. #router.get(...)
#cbv(router)
class PostAPI(AbstractCrud):
router.tags = ["Post"]
router.prefix = "/posts"
model = Post
session: Session = Depends(get_db)
# my endpoints
#e.g. #router.get(...)
I get the following error if I try to do the above:
fastapi.exceptions.FastAPIError: Invalid args for response field! Hint: check that <class 'sqlalchemy.orm.decl_api.Base'> is a valid pydantic field type
For now, I am able to achieve this as follows:
class AbstractCrud
model: Base = NotImplemented
session: Session = NotImplemented
def get_items(self, limit, **filters):
""" Read operation """
def get_item(self, pk: int):
def create_item(self, obj: BaseModel):
""" Create operation """
def update_item(self, pk: int, **params):
""" Update operation"""
def delete_item(self, pk: int):
""" Delete operation """
class UserCrud(AbstractCrud):
def __init__(self, session: Session):
self.session = session
self.model = User
class PostCrud(AbstractCrud):
def __init__(self, session: Session):
self.session = session
self.model = Post
router = InferringRouter()
#cbv(router)
class UserAPI:
router.tags = ["User"]
router.prefix = "/users"
def __init__(self, session=Depends(get_db)):
self.session = session
self.crud = UserCrud(self.session)
# my endpoints
#e.g. #router.get(...)
#cbv(router)
class PostAPI:
router.tags = ["Post"]
router.prefix = "/posts"
def __init__(self, session=Depends(get_db)):
self.session = session
self.crud = PostCrud(self.session)
# my endpoints
#e.g. #router.get(...)
Although this is working fine for me now, I can't help but think if there is a better(or correct) way to do this.
Also, Is my use of a single router variable across multiple classes correct?

Django login/register issue

I am new to Django and am building a database-driven website using PyCharm.
I am having an issue with users registering/logging in. What is happening is, when a user registers, I check the "Database" tab to the right, and the information will be passed into a table named "SavBlock_user", which will have the users name, password, etc.. Then, when I try to log in, it won't allow me to login due to incorrect username/password. However, if I try to login using a username/password from a different table named "auth_user" (like username: admin / password: admin), then I can successfully login. I'm not sure how to fix this.
Ideally, what I would like to do is completely remove the "SavBlock_user" table and strictly use "auth_user" for all of my users, but I'm not sure how to do this. I may have created a 'custom' user model back when I was learning the system, but I can't remember.
My files:
Project\register\forms.py
from django import forms
from SavBlock.models import * # <--- Contains User
''' Form for users to register '''
class RegisterForm(forms.ModelForm):
email = forms.EmailField(
initial='myemail#savagez.com'
)
uso_validate = forms.BooleanField(
label='Are you a PSMC member? (Chief, Uso, Anak)',
initial=False
)
class Meta:
model = User
widgets = {
'password': forms.PasswordInput(),
}
fields = '__all__'
Project\register\views.py
from django.http import request
from django.shortcuts import render, redirect
from .forms import RegisterForm
# Create your views here.
def register(response):
if response.method == "POST":
form = RegisterForm(response.POST or None)
if form.is_valid():
form.save()
return redirect('/dashboard/')
else:
form = RegisterForm()
return render(response, 'register/register.html', {'form': form})
Project\SavBlock\models.py
from django.db import models
class User(models.Model):
username = models.CharField("user name", max_length=50, default='')
email = models.EmailField("email address", unique=True, default='DEFAULT VALUE')
first_name = models.CharField("first name", max_length=50)
last_name = models.CharField("last name", max_length=50)
password = models.CharField("password", unique=True, max_length=50, default='')
rank = {
0: 'Supporter',
1: 'Anak',
2: 'Uso',
3: 'Chief'
}
#TODO: FIT __INIT__
'''
def __init__(self, first_name, last_name, *args, **kwargs):
super().__init__(*args, **kwargs)
self.first_name = first_name.title()
self.last_name = last_name.title()
'''
# Magic method returns string of self
def __str__(self):
return f"User {self.first_name} {self.last_name} rank {self.rank}".strip()
#property
def get_full_name(self):
return f"{self.first_name} {self.last_name}".strip()
class Anak(User):
def __init__(self, first_name, last_name, tribe):
super().__init__(first_name, last_name)
self.tribe = tribe.title()
self.rank = User.rank[1]
class Uso(User):
def __init__(self, first_name, last_name, tribe):
super().__init__(first_name, last_name)
self.tribe = tribe.title()
self.rank = User.rank[2]
----EDIT----
I fixed the different user tables and basically reset the migrations. Now, all users are showing up under a single user table SavBlock_user. However, the login issue is still there.
Admin was created using the terminal manage.py createsuperuser command. I am able to login on the webpage using this account.
testing123 was created using the registration form. It pulls up a message that says "Please enter a correct username and password".
Anyone have any ideas?

How to add users to a dictionary and they don't overwrite each other in python

I'm trying to make so that I can just add users to the dictionary but they just overwrite each other. Have looked around but can't seem to find a solution.
accounts = {}
class Program():
def __init__(self, user, username, password):
self.user = user
self.username = username
self.password = password
accounts['User'] = self.user
accounts['Username'] = self.username
accounts['Password'] = self.password
user1 = Program('xxxxx', 'xxxxx', 'xxxxx')
user2 = Program('xxxxx', 'xxxxx', 'xxxxx')
print(accounts)
Output:
{'User': 'xxxxx', 'Username': 'xxxxx', 'Password': 'xxxxx'}
How do I do if I want to make both 'user1' and 'user2' appear in the dictionary?
What if you do something like:
class Program():
def __init__(self, user, username, password):
self.user = user
self.username = username
self.password = password
def __repr__(self):
return "'User': {0} , 'Username': {1}, 'Password': {2}".format(self.user, self.username, self.password)
Then you could do something like:
user1 = Program(user='user1', username='username1', password='pass1')
user2 = Program(user='user2', username='username2', password='pass2')
accounts = dict()
accounts['user1'] = user1
accounts['user2'] = user2
>>> accounts
# {'user1': 'User': user1 , 'Username': username1, 'Password': pass1,
# 'user2': 'User': user2 , 'Username': username2, 'Password': pass2}
you need to use update method.
and the key should be unique.
If user is going to be unique
accounts[self.user] = {self.username,self.password}
Now your output would be like
{'user1' : {'user1name':'password'}, 'user2':{'user2name':'password'}}
I'm thinking you want to do something like this, although it's not 100% clear:
accounts = {}
class Program():
def __init__(self, user, username, password):
self.user = user
self.username = username
self.password = password
accounts['user1'] = Program('xxxxx', 'xxxxx', 'xxxxx')
accounts['user2'] = Program('xxxxx', 'xxxxx', 'xxxxx')
print(accounts)
When you instantiate the Program class, you can assign its value to a key in your accounts dictionary.
In your global variable "accounts", the key value "User' is getting overwritten each time you instantiate the Program class. If you want the dictionary to hold each of the users, perhaps you can store users as a list against the key value. This is one way to achieve what you want, I think.
accounts={'User':[],'Username':[],'Password':[]}
class Program():
def __init__(self, user, username, password):
self.user = user
self.username = username
self.password = password
accounts['User'].append(self.user)
accounts['Username'].append(self.username)
accounts['Password'].append(self.password)
user1 = Program('xxxxx', 'xxxxx', 'xxxxx')
user2 = Program('xxxxx', 'xxxxx', 'xxxxx')
print(accounts)
This should result in the output you want with both users and (their details) in the dictionary.
You also ask "How do I do if I want to make both 'user1' and 'user2' appear in the dictionary?" If you also want the Program instances user1 and user2 in the dictionary, you could have one key more than the three already in it, for the instances (you could call it 'user_objects') and append as before.
accounts={'User':[],'Username':[],'Password':[],'user_objects':[]}
....
accounts['Password'].append(self.password)
accounts['user_objects'].append(self)
user1 = Program('xxxxx', 'xxxxx', 'xxxxx')
....
Your problem is one of data modelling, rather than Python programming. You've chosen to make your program object-oriented, which can be a good choice for this scenario. You've defined a Program class and you have conceived of named users that would need to use this program, with their personal username and password.
From an OO-perspective, it would then make sense to make the User into a class by itself and to link these users to the program (or maybe even programs) they can access.
class User:
def __init__(self, name, username, password):
self.name = name
self.username = username
self.password = password
def __repr__(self):
return f'User({self.name}, {self.username}, {self.password})'
class Program:
def __init__(self, users=None):
if users is None:
users = []
self.users = users
def add_user(self, user):
self.users.append(user)
def __repr__(self):
return f'Program({", ".join(map(str, self.users))})'
my_program = Program()
my_program.add_user(User('John Smith', 'jsmith', 'ninja'))
my_program.add_user(User('David Jones', 'djones', 'pass1234'))
print(my_program)
I found a solution that worked for me. Thanks for all the help really appreciate it!
accounts={'User':[],'Username':[],'Password':[]}
class Program():
def __init__(self, user, username, password):
self.user = user
self.username = username
self.password = password
accounts['User'].append(self.user)
accounts['Username'].append(self.username)
accounts['Password'].append(self.password)
user1 = Program('Dante', 'Neelo', 'PassWord123')
user2 = Program('John', 'Randddd', '123PassWord')
print('User: ' + str(accounts['User']))
print('Username: ' + str(accounts['Username']))
print('Password: ' + str(accounts['Password']) + '\n')
print(accounts)
Output:
User: ['Dante', 'John']
Username: ['Neelo', 'Randddd']
Password: ['PassWord123', '123PassWord']
{'User': ['Dante', 'John'], 'Username': ['Neelo', 'Randddd'], 'Password': ['PassWord123', '123PassWord']}

pyqt5 QThread with SOAP Zeep Client

I am working on a simple application with GUI which connect to a server via SOAP and request some data, this data is returned in XML format
I was able to run in my application successfully but due to threading, GUI is freezes till the complete SOAP request is finished and returned its value
now I am trying to run my application into threading, I created a Thread which to first check and verify the SOAP connection if it is successful or not
Connection Verification
class WorkerThread(QThread):
def __init__(self, parent=None):
super(WorkerThread, self).__init__(parent)
def run(self):
self.session = Session()
self.session.verify = False
self.cucmurl = 'https://URL'
self.session.auth = HTTPBasicAuth(user, pass)
self.cache = SqliteCache(path='/tmp/sqlite.db', timeout=10)
self.trself.clientansport = Transport(session=self.session, cache=self.cache)
self.client = Client(wsdl, transport=self.transport, strict=False)
the above work fine to verify the connection, but I want to use the self.client later in my code in order to start initiating SOAP connection to severs
class MainAPP(QTabWidget, UI_File):
def __init__(self, parent=None):
def getinfor(self):
output_2 = self.client.getinfor('')
the function getinfor should be able to use the self.client from the WorkerThread.
any idea how to accomplish this
You can emit the client through a signal from the worker thread and set it in the main window.
class WorkerThread(QThread):
client_signal = pyqtSignal(object)
def __init__(self, parent=None):
super(WorkerThread, self).__init__(parent)
def run(self):
# code here
self.client = Client(wsdl, transport=self.transport, strict=False)
self.client_signal.emit(self.client)
class MainApp(QTabWidget, UI_File):
def __init__(self):
self.client = None
def set_client(self, client):
self.client = client
def setup_thread(self):
self.worker_thread = WorkerThread()
self.worker_thread.client_signal.connect(self.set_client)

Why isn't my current_user authenticated in flask-login?

My goal is to make my home view (/) a login page. Once the user logs in, a different page is render depending on its role. When I login (/auth), I see that the username and password are correctly entered. It then attempts to render /, where it tells me that my user is not authenticated and renders /login. Here are the views that describe this:
Views
#app.route("/login")
def login():
return flask.render_template('login.html')
#app.route("/", methods=["GET"])
def home():
if current_user.is_authenticated:
if current_user.is_admin():
return flask.render_template('admin_index.html')
return flask.render_template('user_index.html')
logger.info("Not authenticated. Going back to login.")
return flask.render_template('login.html')
#app.route("/auth", methods=["POST"])
def auth():
username = request.form['username']
password = request.form['password']
user = db.session.query(User).filter(User.username == username).first()
logger.info(user)
logger.info("{0}: {1}".format(username, password))
print("user exists? {0}".format(str(user != None)))
print("password is correct? " + str(user.check_password(password)))
if user and user.check_password(password):
user.is_authenticated = True
login_user(user)
return flask.redirect(url_for('home'))
return flask.redirect(url_for('login'))
The problem is that flask-login's current_user.is_authenticated is always returning False after I attempt to login. My created user is correctly created and committed to the database. Below is my User model with the necessary methods as per flask-login:
User model
class User(db.Model):
"""
A user. More later.
"""
__tablename__ = 'User'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(128), unique=True)
hashed_password = db.Column(db.String(160))
admin = db.Column(db.Boolean)
def __init__(self, username, password="changeme123", admin=False):
self.username = username
self.set_password(password)
self.admin = admin
self.is_authenticated = False
def is_active(self):
return True
def is_authenticated(self):
return self.is_authenticated
def is_anonymous(self):
return False
def is_admin(self):
return self.admin
def get_id(self):
return self.id
def __repr__(self):
return '<User {0}>'.format(self.username)
def set_password(self, password):
self.hashed_password = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.hashed_password, password)
Here is the load_user function:
load_user
#login_manager.user_loader
def load_user(user_id):
try:
return User.query.get(User.id==user_id)
except:
return None
Why is current_user.is_authenticated returning False? I presumed that login_user(user) would make current_user == user, i.e., the one who is being authenticated in /auth, but it seems this is not the case.
You have a method named User.is_authenticated. Inside User.__init__, though, you set an attribute with the same name.
self.is_authenticated = False
This overrides the method. Then, whenever you check current_user.is_authenticated, you are accessing the attribute that's always false.
You should remove the assignment from __init__ and change is_authenticated to the following:
def is_authenticated(self):
return True
If you need it to be dynamic for some reason, rename the attribute so it doesn't shadow the method.
def is_authenticated(self):
return self._authenticated
Another problem is with your load_user function.
Instead of filtering for User.id==user_id, you are getting it. The user wasn't being returned because load_user is returning User.query.get(True) instead of User.query.get(user_id).
If you make the following change, it will work:
#login_manager.user_loader
def load_user(user_id):
try:
return User.query.get(user_id)
except:
return None
You don't have to create is_authenticated field in Database
Flask-Login will take care of that

Resources