PyQt QMessageBox acting funny - sqlite

I have somewhat strange issue with my QMessageBox answers. This function is used to remove a row from an SQLite database. Before deletion, a message box pops and asks for confirmation. Query executes fine, except it ALWAYS deletes, whether I answer with YES or NO.
here is the code:
def deleteFromDB(self):
name = (str(self.ui.searchName.text()).upper())
if name:
with con:
cur = con.cursor()
cur.execute('SELECT name FROM cases WHERE name =?',[name])
tempname = str(cur.fetchone())
if len(tempname) != 4 :
reply = QtGui.QMessageBox.question(self, 'Removal',
"Are you sure ", QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
cur.execute('DELETE FROM cases where name =?',[name])

Related

What should I learn to code a bot in Telegram?

I want to code and creat a bot for telegram that does these things:
1 - shows a massage to the person that hit start button
2 - then it gets a name as an input
3 - then again shows a massage
4 - getting an input
5 - at the end add the inputs to a defualt text and showing it;
for exampele:
-start
+Hi What is your name?
-X
+How old are you?
-Y
+Your name is X and you are Y years old.
My second Question is that how can I Connect to bots together, for example imagine I want to pass some input from this bot to make a poll(voting massage), in order to do that I should send the name to let's say #vote, how is that possible and what should I learn to do such things with my bot?
First you're gonna have to explore telegram bot API documentation here.
Then you should choose your programming language and the library you want to use.
There are different libraries for each language, I'm gonna name a few:
Go: https://github.com/aliforever/go-telegram-bot-api (DISCLAIMER: I wrote and maintain it)
Python: https://github.com/eternnoir/pyTelegramBotAPI
NodeJS: https://github.com/telegraf/telegraf
I'm gonna give you an example for what you want in python using pyTelegramBotAPI:
First install the library using pip:
pip install git+https://github.com/eternnoir/pyTelegramBotAPI.git
Then run this script:
import telebot
API_TOKEN = 'PLACE_BOT_TOKEN_HERE'
bot = telebot.TeleBot(API_TOKEN)
user_info = {}
def set_user_state(user_id, state):
if user_id not in user_info:
user_info[user_id] = {}
user_info[user_id]["state"] = state
def get_user_state(user_id):
if user_id in user_info:
if "state" in user_info[user_id]:
return user_info[user_id]["state"]
return "Welcome"
def set_user_info(user_id, name=None, age=None):
if name is None and age is None:
return
if name is not None:
user_info[user_id]["name"] = name
if age is not None:
user_info[user_id]["age"] = age
def get_user_info(user_id):
return user_info[user_id]
#bot.message_handler()
def echo_all(message):
user_id = message.from_user.id
if message.text == "/start":
bot.reply_to(message, "Hi What is your name?")
set_user_state(user_id, "EnterName")
return
user_state = get_user_state(user_id)
if user_state == "EnterName":
set_user_info(user_id, name=message.text)
bot.reply_to(message, "How old are you?")
set_user_state(user_id, "EnterAge")
return
if user_state == "EnterAge":
set_user_info(user_id, age=message.text)
info = get_user_info(user_id)
bot.reply_to(message, "Your name is %s and you are %s years old." %(info["name"], info["age"]))
set_user_state(user_id, "Welcome")
return
bot.reply_to(message, "To restart please send /start")
bot.infinity_polling()
Here we use a dictionary to place user state and info, you can place them anywhere like databases or json files.
Then we update a user's state based on their interactions with the bot.
For your second question, bots cannot communicate with each other so you should look for other solutions. In the case of your question where you want to create a poll, you should check sendPoll method as well as PollAnswer object which you receive when a user votes in a poll.

SQLite3 with Flask Insert only allowing 1 character

I'm using Flask and trying to insert names (text) into an SQLite3 DB. The DB has one table (guests) and one column (name). However, it will only accept 1 character during the insert; anything more is failing.
If I hardcode 'nm' as a value, it still fails, so I don't think it's the Html template. I can manually add a value of varying length to the DB with the 'DB Browser' app, so I'm really at a loss here. Here's a code snippet.
#app.route('/addrec', methods=['POST', 'GET'])
def addrec():
msg = "msg"
if request.method == 'POST':
try:
nm = request.form['nm']
with sqlite3.connect("database.db") as con:
cur = con.cursor()
cur.execute('''Insert into guests values (?)''', nm)
con.commit()
msg = "Record successfully added"
Second argument to cur.execute should be a tuple:
cur.execute('''Insert into guests values (?)''', (nm,))
Why? If, for example, you call that argument arg then arg[0] is the string value you require (nm): the first item in that tuple.
Otherwise (when passing nm instead of the tuple) it will read nm[0] which is the first character of the string nm.

How to make this function where I can give it an argument or not

So I made this very small function. it is a bonehead easy function but frankly borderline my capabilities.. Im learning. The function works as expected, but I would like to go further. I would like to make it so I can either give it an argument (a username) and just get the information for that single user, or default to reporting all users. is this possible w/o starting over from what I have so far?
I have just poked around and seen some examples but nothing that I can fit into my script. that I can understand at least.
import boto3
iam = boto3.client('iam')
def user_group():
for myusers in iam.list_users()['Users']:
Group = iam.list_groups_for_user(UserName=myusers['UserName'])
print("User: " + myusers['UserName'])
for groupName in Group['Groups']:
print("Group: " + groupName['GroupName'])
print("----------------------------")
user_group()
I would like to have the ability to run this script in two fashions.
1) add an argument(s) of 'username' so I can get the response for a particular user
2) default to getting response for all users if no argument is given.
This can be done by using an argument with a default value:
def user_group(user = None):
if user is None:
print("No user")
else:
print(user)
user_group()
user_group('some user')
prints
No user
some user
In your case you may want to write
def user_group(user = None):
users_to_list = iam.list_users()['Users'] if user is None else [user]
for myusers in user_to_list:
...

How to error check a function containing a SQL query with the placeholder %s

I am working on a project for school and run into a crossroad. I have a bunch of queries in a python script that a user can search when running the script. A couple of these function are using %s as a placeholder so that the user can enter a value.
However, I want to check that what they enter is actually in my database. For instance, if you ask a user for a movie genre, it should produce an error if they enter something that is not in my tables.
I have spent a few days trying to find a way to do it, with no luck. I am not the greatest with functions, and I get things mixed up some times.
To simplify things I copied one of my queries requiring user input for testing. I thought I had come up with a solution on how to error check, but no luck. I have pasted the code below. If you know what I am missing, your help would be much appreciated.
#!/usr/bin/python36
#Modules
############################
import psycopg2
import sys
import os
#Open Database
############################
global cursor
#def OpenDatabase():
try:
connection = psycopg2.connect(database='Blockbuster36', user='dbadmin')
cursor = connection.cursor()
except psycopg2.DatabaseError:
print("No connection to database.")
sys.exit(1)
#Functions
###########################
def Show_Tuples():
tuple = cursor.fetchone()
while tuple != None:
print(tuple)
tuple = cursor.fetchone()
#3) Display all films of a certain genre
def Qry3_Film_of_Genre(Genre_Choice):
Qry3 = '''select Film_Title, Genre_Name from Film
join Film_Genre
on Film.Film_ID = Film_Genre.Film_ID
join Genre
on Film_Genre.Genre_ID = Genre.Genre_ID
where Genre_Name = %s;'''
cursor.execute(Qry3, (Genre_Choice,))
Show_Tuples()
def Qry3_Error_Check(Genre_Choice):
try:
Qry3_ec = "select Genre_ID, Genre_Name from Genre where Genre_Name = %s;"
cursor.execute(Qry3_ec, (Genre_Choice,))
results = cursor.fetchone()
if results[0] > 0:
print()
Qry3_Film_of_Genre(Genre_Choice)
# else:
elif results[0] == None:
print("This Genre does not exist")
Genre_Choice = input("Please enter the Genre name to filter movies by: ")
except psycopg2.Error as query_issue:
print("Something wrong with the query", query_issue)
except Exception as unkown:
print("Error: Something else went wrong")
print("Here is the issue: ", unkown)
#Main Code
##########################
Genre_Choice = input("Please enter the Genre name to filter movies by: ")
Check_Genre = Qry3_Error_Check(Genre_Choice)
#print("Function Return: ", Check_Genre)
#print()
#print(Check_Genre)
#if Check_Genre == None:
# print("This Genre does not exist")
# Genre_Choice = input("Please enter the Genre name to filter movies by: ")
# Check_Genre = Qry3_Error_Check(Genre_Choice)
#elif Check_Genre != None:
# Qry3_Film_of_Genre(Genre_Choice)
#while Check_Genre != Genre_Choice:
# print("This Genre does not exist")
# Genre_Choice = input("Please enter the Genre name to filter movies by: ")
# Check_Genre = Qry3_Error_Check(Genre_Choice)
#if Check_Genre == None:
# Qry3_Film_of_Genre(Genre_Choice)
#Close Cursor and Database
###################################
cursor.close()
connection.close()
Essentially I want the error message to keep printing, along with entering another genre name, until a valid genre is entered. Right now it keeps saying it is wrong even if enter a valid genre name and get output with the Qry3_Error_Check function.
Once the user has entered a valid genre name, based on the error-checking function query, then the original query will appear.
I have made some progress, entering a valid genre now works. However, when entering an invalid genre name it jumps to the general except and prints the error "NoneType object is not subscriptable." Obviously, there are no rows that match, thus the NoneType error. However, it should re-prompt the user in the elif statement above. What do enter as an elif statement so that the user is re-prompted for a valid genre name?
Note: I commented out the bulk of my main code for now.
If you want to check specifically for SQL errors, you can have a separate except block for them. Also, its usually (but not always) a bad idea to use exceptions for control flow.
Something like below (I have not tested this) is probably close to what you need.
try:
Qry3_ec = "select Genre_ID, Genre_Name from Genre where Genre_Name = %s;"
cursor.execute(Qry3_ec, (Genre_Choice,))
results = cursor.fetchall()
if results.count > 0:
print(results)
else:
print("Nothing found!")
except psycopg2.Error as e:
print("Something wrong with the query")
print(e)
except Exception as e
print("Something else went wrong")
print(e)
Good luck with your project. :)

How to solve a tkinter memory leak?

I have a dynamic table with a fixed row number (like a FIFO Queue), which updates continuously through tkinter's after() function. Inside the table is a Button, which text is editable.
To make the Button's text editable I used the solution of BrenBarn and reference a loop variable into a function call at the command-attribute.
When the function update_content_items() is cycled, I found, that the memory usage is increasing MB by MB per second. I can confirm that after commenting out the lambda expression, the memory leak was gone. (as seen live running 'top' in the terminal)
It seems I have to use the lambda, otherwise the Button will have a wrong index and the user edits the wrong row, when I just used self.list_items[i], though the user clicked the right one.
Is there a way to solve the problem? How can the user click the right button and edit it while having the right index and getting rid of the leak?
The corresponding code:
def update_content_items(self):
"""
Continuously fills and updates the Table with rows and content.
The size of the table rows is initially fixed by an external value at config.ini
:return: nothing
"""
if len(self.list_items) > self.queueMaxlen:
self.queueMaxlen = len(self.list_items)
self.build_table()
try:
for i in range(len(self.list_items)):
item = self.list_items[i]
self.barcodeImgList[i].image = item.plateimage
orig_image = Image.open(io.BytesIO(item.plateimage))
ein_image = ImageTk.PhotoImage(orig_image)
self.barcodeImgList[i].configure(image=ein_image)
# keeps a reference, because somehow tkinter forgets it...??? Bug of my implementation???
self.barcodeImgList[i].image = ein_image
orig_image = None
ein_image = None
#FIXME Memory LEAK?
self.numberList[i].configure(text=item.number,
command=lambda K=i: self.edit_barcode(self.list_items[K]))
self.timestampList[i].configure(text=item.timestamp)
self.search_hitlist[i].config(bg='white', cursor="xterm")
self.search_hitlist[i].unbind("<Button-1>")
if item.queryresult is not None:
if item.queryresult.gesamtstatus != 'Gruen':
self.search_hitlist[i].insert(tk.END, item.queryresult.barcode +
'\n' + item.queryresult.permitlevel)
self.search_hitlist[i].configure(bg='red', cursor="hand2")
self.search_hitlist[i].bind("<Button-1>", item.url_callback)
else:
self.search_hitlist[i].configure(bg='green', cursor="xterm")
self.search_hitlist[i].configure(state=tk.DISABLED)
self.on_frame_configure(None)
self.canvas.after(10, self.update_content_items)
except IndexError as ie:
for number, thing in enumerate(self.list_items):
print(number, thing)
raise ie
def edit_barcode(self, item=None):
"""
Opens the number plate edit dialogue and updates the corresponding list item.
:param item: as Hit DAO
:return: nothing
"""
if item is not None:
new_item_number = EditBarcodeEntry(self.master.master, item)
if new_item_number.mynumber != 0:
item.number = new_item_number.mynumber
self.list_items.request_work(item, 'update')
self.list_items.edit_hititem_by_id(item)
self.parent.master.queryQueue.put(item)
else:
print("You shouldn't get here at all. Please see edit_barcode function.")
EDIT: It seems there is indeed a deeper memory leak (python itself). The images won't get garbage collected. Memory is slowly leaking in Python 3.x and I do use PIL. Also here: Image loading by file name memory leak is not properly fixed
What can I do, because I have to cycle through a list with records and update Labels with images? Is there a workaround? PhotoImage has no explicit close() function, and if I call del, the reference is gc'ed and no configuring of the Label possible.
an example of my proposed changes, with indentation fixed:
def update_content_items(self):
"""
Continuously fills and updates the Table with rows and content.
The size of the table rows is initially fixed by an external value at config.ini
:return: nothing
"""
if len(self.list_items) > self.queueMaxlen:
self.queueMaxlen = len(self.list_items)
self.build_table()
try:
for i in range(len(self.list_items)):
item = self.list_items[i]
self.barcodeImgList[i].image = item.plateimage
orig_image = Image.open(io.BytesIO(item.plateimage))
ein_image = ImageTk.PhotoImage(orig_image)
self.barcodeImgList[i].configure(image=ein_image)
# keeps a reference, because somehow tkinter forgets it...??? Bug of my implementation???
self.barcodeImgList[i].image = ein_image
orig_image = None
ein_image = None
self.numberList[i].configure(text=item.number) # removed lambda
self.numberList[i].bind("<Button-1>", self.edit_barcode_binding) # added binding
self.timestampList[i].configure(text=item.timestamp)
self.search_hitlist[i].config(bg='white', cursor="xterm")
self.search_hitlist[i].unbind("<Button-1>")
if item.queryresult is not None:
if item.queryresult.gesamtstatus != 'Gruen':
self.search_hitlist[i].insert(tk.END, item.queryresult.barcode +
'\n' + item.queryresult.permitlevel)
self.search_hitlist[i].configure(bg='red', cursor="hand2")
self.search_hitlist[i].bind("<Button-1>", item.url_callback)
else:
self.search_hitlist[i].configure(bg='green', cursor="xterm")
self.search_hitlist[i].configure(state=tk.DISABLED)
self.on_frame_configure(None)
self.canvas.after(10, self.update_content_items)
except IndexError as ie:
for number, thing in enumerate(self.list_items):
print(number, thing)
raise ie
def edit_barcode_binding(self, event): # new wrapper for binding
K = self.numberList.index(event.widget) # get index from list
self.edit_barcode(self.list_items[K]) # call the original function
def edit_barcode(self, item=None):
"""
Opens the number plate edit dialogue and updates the corresponding list item.
:param item: as Hit DAO
:return: nothing
"""
if item is not None:
new_item_number = EditBarcodeEntry(self.master.master, item)
if new_item_number.mynumber != 0:
item.number = new_item_number.mynumber
self.list_items.request_work(item, 'update')
self.list_items.edit_hititem_by_id(item)
self.parent.master.queryQueue.put(item)
else:
print("You shouldn't get here at all. Please see edit_barcode function.")

Resources