PyQt event handlers snarf exceptions - exception

Here's the code that illustrates the problem:
from PyQt4 import QtGui
app = QtGui.QApplication([])
dialog = QtGui.QDialog()
button = QtGui.QPushButton('I crash')
layout = QtGui.QHBoxLayout()
layout.addWidget(button)
dialog.setLayout(layout)
def crash(): raise Exception('Crash!')
button.clicked.connect(crash)
button.click()
print 'I should not happen'
When I run that, PyQt4 handles the error for me. My console displays a stack trace with 'Crash!' etc. in it, and I see 'I should not happen'.
This is not useful, because I've been handed a large application with many handlers, and I need to force all their errors up into my face (and into my - ahem - automated tests). Each time I run, errors escape my nets, and they would require excessive and useless try:except blocks, inside every handler, just to catch them all.
Put another way, I want good code to be very good, and bad code to be very bad. Not whitewashed.
Apologies if this is already asked, but when I e-search for it, I naturally get thousands of newbies asking basic error handling questions (or, worse, I get newbies asking how to turn OFF their wayward exceptions!;)
How do I override PyQt4's default error handling, so I can propagate or log errors myself? And please don't answer sys.excepthook, either - it catches the errors that PyQt4 doesn't catch.

This is not the answer, you silly website. Stop forcing us to fit into a preconceived notion of an idealized thread template.
The un-answer is to use my test framework setUp() to hook in an exception handler:
def setUp(self):
self.no_exceptions = True
def testExceptionHook(type, value, tback):
self.no_exceptions = False
sys.__excepthook__(type, value, tback)
sys.excepthook = testExceptionHook
Where that says "self.no_exceptions = False", I would much rather simply say self.fail(''). However, because Python's unit test library insists on throwing exceptions just to register test failures, and because PyQt insists on snarfing all exceptions, we have a deadlock.
To fit into unittest.TestCase's silly preconceived notion of an idealized test case, I have to instead set a variable, then detect it in the teardown:
def tearDown(self):
self.assertTrue(self.no_exceptions)
This is still not ideal, but at least it will force me to spend more time paying attention to the errors, instead of spending that time complaining about them on technical websites.
The root question: How to turn off PyQt's magic error handler? - remains unanswered...

I think the answer is that this isn't a 'feature' of PyQt, but a consequence inherent to the design that lets signals/slots work (remember that the signal/slot communication is going through a c++ layer as well).
This is ugly, but does a bit of and end-run around your problem
from PyQt4 import QtGui
import time
app = QtGui.QApplication([])
class exception_munger(object):
def __init__(self):
self.flag = True
self.txt = ''
self.type = None
def indicate_fail(self,etype=None, txt=None):
self.flag = False
if txt is not None:
self.txt = txt
self.type = etype
def reset(self):
tmp_txt = self.txt
tmp_type = self.type
tmp_flag = self.flag
self.flag = True
self.txt = ''
self.type = None
return tmp_flag, tmp_type, tmp_txt
class e_manager():
def __init__(self):
self.old_hook = None
def __enter__(self):
em = exception_munger()
def my_hook(type, value, tback):
em.indicate_fail(type, value)
sys.__excepthook__(type, value, tback)
self.old_hook = sys.excepthook
sys.excepthook = my_hook
self.em = em
return self
def __exit__(self,*args,**kwargs):
sys.excepthook = self.old_hook
def mang_fac():
return e_manager()
def assert_dec(original_fun):
def new_fun(*args,**kwargs):
with mang_fac() as mf:
res = original_fun(*args, **kwargs)
flag, etype, txt = mf.em.reset()
if not flag:
raise etype(txt)
return res
return new_fun
#assert_dec
def my_test_fun():
dialog = QtGui.QDialog()
button = QtGui.QPushButton('I crash')
layout = QtGui.QHBoxLayout()
layout.addWidget(button)
dialog.setLayout(layout)
def crash():
time.sleep(1)
raise Exception('Crash!')
button.clicked.connect(crash)
button.click()
my_test_fun()
print 'should not happen'
This will not print 'should not happen' and gives you something to catch with your automated tests (with the correct exception type).
In [11]: Traceback (most recent call last):
File "/tmp/ipython2-3426rwB.py", line 68, in crash
Exception: Crash!
---------------------------------------------------------------------------
Exception Traceback (most recent call last)
<ipython-input-11-6ef4090ab3de> in <module>()
----> 1 execfile(r'/tmp/ipython2-3426rwB.py') # PYTHON-MODE
/tmp/ipython2-3426rwB.py in <module>()
/tmp/ipython2-3426rwB.py in new_fun(*args, **kwargs)
Exception: Crash!
In [12]:
The stack trace is jacked up, but you can still read the first one that was printed out.

Related

Python objects in dealloc in cython

In the docs it is written, that "Any C data that you explicitly allocated (e.g. via malloc) in your __cinit__() method should be freed in your __dealloc__() method."
This is not my case. I have following extension class:
cdef class SomeClass:
cdef dict data
cdef void * u_data
def __init__(self, data_len):
self.data = {'columns': []}
if data_len > 0:
self.data.update({'data': deque(maxlen=data_len)})
else:
self.data.update({'data': []})
self.u_data = <void *>self.data
#property
def data(self):
return self.data
#data.setter
def data(self, new_val: dict):
self.data = new_val
Some c function has an access to this class and it appends some data to SomeClass().data dict. What should I write in __dealloc__, when I want to delete the instance of the SomeClass()?
Maybe something like:
def __dealloc__(self):
self.data = None
free(self.u_data)
Or there is no need to dealloc anything at all?
No you don't need to and no you shouldn't. From the documentation
You need to be careful what you do in a __dealloc__() method. By the time your __dealloc__() method is called, the object may already have been partially destroyed and may not be in a valid state as far as Python is concerned, so you should avoid invoking any Python operations which might touch the object. In particular, don’t call any other methods of the object or do anything which might cause the object to be resurrected. It’s best if you stick to just deallocating C data.
You don’t need to worry about deallocating Python attributes of your object, because that will be done for you by Cython after your __dealloc__() method returns.
You can confirm this by inspecting the C code (you need to look at the full code, not just the annotated HTML). There's an autogenerated function __pyx_tp_dealloc_9someclass_SomeClass (name may vary slightly depending on what you called your module) does a range of things including:
__pyx_pw_9someclass_9SomeClass_3__dealloc__(o);
/* some other code */
Py_CLEAR(p->data);
where the function __pyx_pw_9someclass_9SomeClass_3__dealloc__ is (a wrapper for) your user-defined __dealloc__. Py_CLEAR will ensure that data is appropriately reference-counted then set to NULL.
It's a little hard to follow because it all goes through several layers of wrappers, but you can confirm that it does what the documentation says.

How to store data from python/kivy app

I'd like to know how to store data from my app so I can review the data when I re-run the app.
e.g. I type some info in a TextInput and then when I click the submit button, the info is pasted in a label, so I close the app and when I reopen it the info should be appearing in the label. I know that there are sqlite3 and mysql but I don't know how to apply it into my python/kivy code.
Please anyone suggest me how that can be done.
If possible show with an example, it would be perfect.
Thanks in advance,
My py code:
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from random import shuffle
from kivy.core.window import Window
Window.clearcolor = [1, 1, 1, 1]
Window.size = (550, 650)
Builder.load_file('builder.kv')
class MainScreen(ScreenManager):
pass
class Menu(Screen):
pass
class Levels(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def on_pre_enter(self):
Window.bind(on_keyboard=self.voltar)
def voltar(self, window, key, *args):
if key == 27:
App.get_running_app().root.current = 'menu'
return True
def on_pre_leave(self):
Window.unbind(on_keyboard=self.voltar)
class LvLogos(Screen):
def on_pre_enter(self):
Window.bind(on_keyboard=self.voltar)
def voltar(self, window, key, *args):
if key == 27:
App.get_running_app().root.current = 'menu'
return True
def on_pre_leave(self):
Window.unbind(on_keyboard=self.voltar)
class Logo(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def shuffle(self):
letter = self.letters
self.s = shuffle(letter)
return letter
def on_pre_enter(self):
Window.bind(on_keyboard=self.voltar)
def voltar(self, window, key, *args):
if key == 27:
App.get_running_app().root.current = 'menu'
return True
def on_pre_leave(self):
Window.unbind(on_keyboard=self.voltar)
class LvShields(Screen):
pass
class Shield(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def shuffle(self):
letter = self.letters
self.s = shuffle(letter)
return letter
class QuizZApp(App):
def build(self):
self.icon = 'C:\\Users\\gusta\\PycharmProjects\\QuizzApp\\Images\\QuizzLogo.png'
return MainScreen()
if __name__ == '__main__':
QuizZApp().run()
Of course you can use sqlite3, but the simplest way to store basic data for kivy app like your exaple would be to use json file with kivy's own JsonStore class.
It has the benefit of allocating your file in the right place depending on the platform it is deployed on, you won't need to care where exactly.
Here is a simple example using get(), put() and exists() methods to store typed text from TextInput and load it on a Label. (You won't need to create the file itself, just initialize the object and write (put()) in it).
from kivy.uix.boxlayout import BoxLayout
from kivy.storage.jsonstore import JsonStore
from kivy.base import runTouchApp
from kivy.lang import Builder
from kivy.properties import ObjectProperty
kv='''
RootWidget:
orientation: 'vertical'
BoxLayout:
TextInput:
id: txtinpt
Label:
id: lbl
text: root.stored_data.get('mydata')['text'] if root.stored_data.exists('mydata') else ''
Button:
size_hint_y: .3
text: 'Submit'
on_press:
root.stored_data.put('mydata', text=txtinpt.text)
lbl.text = txtinpt.text
'''
class RootWidget(BoxLayout):
stored_data = ObjectProperty(None)
def __init__(self, *args, **kwargs):
super(BoxLayout, self).__init__(*args, **kwargs)
self.stored_data = JsonStore('data.json')
runTouchApp(Builder.load_string(kv))
If you are new to Json, it is a file containing list of pairs, which's value by its own may be a new list of pair. pretty much like python's dict.
For kivy's JsonStore class, it assume you are working with a minimum of two levels, hence {"mydata": {"text": "What you have written last run"}}. It doesn't make much sense in this simple example to have a nested dict, but in general it will be exactly what you want for real applications, like if you wanted to take contacts data for multiple contacts, or you want to store various configurations for multiple widget for the app itself (in this case you may want to read (get()) the data prior of loading the widgets, probably in the App-class's build() method).
reference: https://kivy.org/docs/api-kivy.storage.html

Views.py processing the form data

My form.html
{{ form_field(task_form['execution_time']) }}
<input type="text" name="admin_time">
views.py
class CreateTaskView(LoginRequiredMixin, MyStaffUserRequiredMixin, generic.CreateView):
model = Task
form_class = TaskForm
template_name = 'tasks/form.html'
def get_context_data(self, *args, **kwargs):
ctx = super(CreateTaskView, self).get_context_data(*args, **kwargs)
ctx['task_form'] = ctx.get('form')
ctx['action'] = 'Add'
ctx['cancel_url'] = reverse('tasks.list')
return ctx
def form_valid(self, form):
form.save(self.request.user)
messages.success(self.request, _('Your task has been created.'))
return redirect('tasks.list')_url'] = reverse('tasks.list')
return ctx
When processing the form if admin_time has a value, then execution_time should be equal to admin_time.
How can I bring that about?
I want something like this- but it throws eror
def get_context_data(self, *args, **kwargs):
ctx = super(CreateTaskView, self).get_context_data(*args, **kwargs)
ctx['task_form'] = ctx.get('form')
if self.admin_time.is_valid():
task.execution_time=self.admin_time
else:
ctx['action'] = 'Add'
ctx['cancel_url'] = reverse('tasks.list')
return ctx
CreateView.get_context_data used to send additional context to your template (or override exist one) and it yields only when you have to render empty values request.GET
You can receive data on request.POST, so it yields methods in order (main of them) dispatch -> post -> form_valid or form_invalid -> redirect to success url. You can see there is no get_context_data so remove that weird code from get_context_data:
if self.admin_time.is_valid():
task.execution_time=self.admin_time
else:
I can see you override form_valid so if it runs - form already is valid and you can get "cleaned data" from it if you want perform some additional validation, put following code before form.save():
admin_time = form.cleaned_data['admin_time']
# check if it is not empty
if admin_time:
self.execution_time = admin_time
And you should not do this return ctx in your form_valid, because it never reach here after first return.
I also recommend you look at CreateView class implementation https://docs.djangoproject.com/en/1.7/ref/class-based-views/generic-editing/#createview and Django tutorials and docs if you want understand what you are doing https://docs.djangoproject.com/en/1.7/intro/tutorial01/ there ~ 6 tutorials, read and try it all and http://www.checkio.org/ for learning python. Because here we mainly don't loyal for such questions.

RESTful interface in Flask and issues serializing

I'm learning Backbone.js and Flask (and Flask-sqlalchemy). I chose Flask because I read that it plays well with Backbone implementing RESTful interfaces. I'm currently following a course that uses (more or less) this model:
class Tasks(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(80), unique=True)
completed = db.Column(db.Boolean, unique=False, default=False)
def __init__(self, title, completed):
self.title = title
self.completed = completed
def json_dump(self):
return dict(title=self.title, completed=self.completed)
def __repr__(self):
return '<Task %r>' % self.title
I had to add a json_dump method in order to send JSON to the browser. Otherwise, I would get errors like object is not JSON serializable, so my first question is:
Is there a better way to do serialization in Flask? It seems that some objects are serializable but others aren't, but in general, it's not as easy as I expected.
After a while, I ended up with the following views to take care of each type of request:
#app.route('/tasks')
def tasks():
tasks = Tasks.query.all()
serialized = json.dumps([c.json_dump() for c in tasks])
return serialized
#app.route('/tasks/<id>', methods=['GET'])
def get_task(id):
tasks = Tasks.query.get(int(id))
serialized = json.dumps(tasks.json_dump())
return serialized
#app.route('/tasks/<id>', methods=['PUT'])
def put_task(id):
task = Tasks.query.get(int(id))
task.title = request.json['title']
task.completed = request.json['completed']
db.session.add(task)
db.session.commit()
serialized = json.dumps(task.json_dump())
return serialized
#app.route('/tasks/<id>', methods=['DELETE'])
def delete_task(id):
task = Tasks.query.get(int(id))
db.session.delete(task)
db.session.commit()
serialized = json.dumps(task.json_dump())
return serialized
#app.route('/tasks', methods=['POST'])
def post_task():
task = Tasks(request.json['title'], request.json['completed'])
db.session.add(task)
db.session.commit()
serialized = json.dumps(task.json_dump())
return serialized
In my opinion, it seems a bit verbose. Again, what is the proper way to implement them? I have seen some extensions that offer RESTful interfaces in Flask but those look quite complex to me.
Thanks
I would use a module to do this, honestly. We've used Flask-Restless for some APIs, you might take a look at that:
https://flask-restless.readthedocs.org/en/latest/
However, if you want build your own, you can use SQLAlchemy's introspection to output your objects as key/value pairs.
http://docs.sqlalchemy.org/en/rel_0_7/core/schema.html#metadata-reflection
Something like this, although I always have to triple-check I got the syntax right, so take this as a guide more than working code.
#app.route('/tasks')
def tasks():
tasks = Tasks.query.all()
output = []
for task in tasks:
row = {}
for field in Tasks.__table__.c:
row[str(field)] = getattr(task, field, None)
output.append(row)
return jsonify(data=output)
I found this question which might help you more. I'm familiar with SQLAlchemy 0.7 and it looks like 0.8 added some nicer introspection techniques:
SQLAlchemy introspection
Flask provides jsonify function to do this. Check out its working here.
Your json_dump method is right though code can be made concise. See this code snippet
#app.route('/tasks')
def tasks():
tasks = Tasks.query.all()
return jsonify(data=[c.json_dump() for c in tasks])

Check if object is an sqlalchemy model instance

I want to know how to know, given an object, if it is an instance of an sqlalchemy mapped model.
Normally, I would use isinstance(obj, DeclarativeBase). However, in this scenario, I do not have the DeclarativeBase class used available (since it is in a dependency project).
I would like to know what is the best practice in this case.
class Person(DeclarativeBase):
__tablename__ = "Persons"
p = Person()
print isinstance(p, DeclarativeBase)
#prints True
#However in my scenario, I do not have the DeclarativeBase available
#since the DeclarativeBase will be constructed in the depending web app
#while my code will act as a library that will be imported into the web app
#what are my alternatives?
You can use class_mapper() and catch the exception.
Or you could use _is_mapped_class, but ideally you should not as it is not a public method.
from sqlalchemy.orm.util import class_mapper
def _is_sa_mapped(cls):
try:
class_mapper(cls)
return True
except:
return False
print _is_sa_mapped(MyClass)
# #note: use this at your own risk as might be removed/renamed in the future
from sqlalchemy.orm.util import _is_mapped_class
print bool(_is_mapped_class(MyClass))
for instances there is the object_mapper(), so:
from sqlalchemy.orm.base import object_mapper
def is_mapped(obj):
try:
object_mapper(obj)
except UnmappedInstanceError:
return False
return True
the complete mapper utilities are documented here: http://docs.sqlalchemy.org/en/rel_1_0/orm/mapping_api.html
Just a consideration: since specific errors are raised by SQLAlchemy (UnmappedClassError for calsses and UnmappedInstanceError for instances) why not catch them rather than a generic exception? ;)