return a FaultObject on purpose from pyamf - python

I am currently migrating from RubyAMF to PyAMF. In RubyAMF you can return a FaultObject deliberately like so:
render :amf => FaultObject.new("Thats not your pie!")
Is there comparable functionality in PyAMF? I've searched the docs and can't find any mention of it.

coulix is right (but due to reputation restrictions I cannot upvote! :)
From within your service method, raise an exception as you would normally and PyAMF will trap that and convert it to an appropriate fault object for consumption by the requestor (e.g. using Flex Messaging this will be an ErrorMessage instance).
class HandsOffThatPie(Exception):
pass
def get_pie(please=False):
if not please:
raise HandsOffThatPie('Say please!')

raise Exception, "ur message" can do.

Related

Continue after Try has failed

I have a function:
def save_to_models(all_item_tags):
from article.models import Articles
for item in all_item_tags:
newobj = Articles()
try:
newobj.pub_date =item.contents[9].contents[0]
except:
continue
try:
newobj.title =item.contents[1].contents[0]
except:
continue
try:
newobj.description =item.contents[5].contents[0]
except:
continue
try:
newobj.image =get_the_picture(item.contents[7])
except:
continue
newobj.save()
each model has unique=True so I'm using try, except to skip over the error I get when its trying to input a data that's already in the database. How can I condense this code? I feel like its a lot of unnecessary lines of code.
Django is smart: like stated in one of the comments, it's only gonna raise an error when the save() method is called. Until then, Article is a normal Python object. What you should would look more like this :
from psycopg2 import IntegrityError # this is the actual error raised by psycopg2 (the postgres python driver)
from article.models import Articles
for item in all_item_tags:
try:
new_article = Articles(
pub_date=item.contents[9].contents[0],
title=item.contents[1].contents[0],
description=item.contents[5].contents[0],
image=get_the_picture(item.contents[7])
new_article.save() # this is where the actual save happens
except IntegrityError:
# Handle the exception here
Another (more advanced) option is to override the save() method and put your logic there.
That said, you could also use get_or_created to do that. It looks like this:
for item in all_item_tags:
# this methods returns a boolean True of False if the object is already in the DB.
# use your unique identifier here
article, created = Article.objects.get_or_create(unique_id=...)
# You can then do a classic if-else without handling any errors...
if created:
# Great! The object a
else:
# the object exist, do something with it or not...
However, there are a few things I would suggest. My feeling is that you are diving into Django without really knowing Python. Django is a big beast that makes a lot of things really convenient (almost magical) but it's still Python. If you dive too deep and something breaks, it will be very hard for you to know what's going on. I would suggest furthering your knowledge of Python (it's an amazing language so it's gonna be fun) and then go back to Django or maybe start with a smaller framework like Flask which does less magic! For now, here's a link to the official doc on error handling so you can learn a bit more about it. Also, Django has really good doc so I would first look there if a problem arises.
Cheers and happy coding!

What's the most pythonic way to get name of the field when an exception related to IntegrityError is thrown?

I'm developing an API with DRF and I want to generate and return proper custom error messages when an exception related to IntegrityError is thrown.
To do this, I've implemented a custom exception handler. Inside the custom exception handler, I want to get the name of the field that causes the error from the Exception instance and then I'll generate and return proper message in the response.
Currently, I can do this by parsing the message attribute of the Exception instance but I'm not sure this is the best possible solution.
So, is there any pythonic way to get the name of the field from the Exception instance when an exception related to IntegrityError is thrown?
Thanks!
According to source it seems IntergityError is no more than an Exception so the only way is to parsing exception.message or exception.args.
You always can check what gives you print(dir(exception)) but I'm pretty sure only message and args will be helpful.
IMHO "parsing the message" is perfectly pythonic: simple, readable, you can do the same/similar solution in any other similar situation. I've seen something like this before:
# in a custom Serializer's create() method
try:
return super().create(validated_data)
except IntegrityError as e:
raise APIException(detail=e.args[0].split('DETAIL: ')[1])
It simple, it works and getting the extra data in any other way will likely involve something significantly more complicated.

Django exists() versus DoesNotExist

I have some questions about django exists() and DoesNotExist exception.
Example code:
id = 1
# first
if User.objects.get(pk=id).exists():
# my logic
pass
# second
try:
User.objects.get(pk=id)
# my logic
pass
except User.DoesNotExist:
return 0
I often use get() method. Which practice is better? Which code is better? The first or second?
if User.objects.get(pk=id).exists()
This won't work, so the question is pretty easy to answer: This way is inferior to the ways which do work :-)
I guess you actually didn't make a Minimal Complete Verifiable Example and so missed the error when you posted un-verified code.
So instead, I suppose you are asking about the difference between:
QuerySet.exists() when you have a QuerySet (e.g. from a filter operation).
For example:
if User.objects.filter(pk=id).exists():
# ... do the things that need that user to exist
Model.objects.get(…) and catching the Model.DoesNotExist exception type (or, if you want to be more general, the parent type ObjectDoesNotExist).
For example:
try:
user = User.objects.get(pk=id)
except User.DoesNotExist:
# ... handle the case of that user not existing
The difference is:
The QuerySet.exists method is on a queryset, meaning you ask it about a query (“are there any instances matching this query?”), and you're not yet attempting to retrieve any specific instance.
The DoesNotExist exception for a model is raised when you actually attempted to retrieve one instance, and it didn't exist.
Use whichever one correctly expresses your intention.
You can find more info in docs:
about exists(),but exists() works only for QuerySet
Returns True if the QuerySet contains any results, and False if not. This tries to perform the query in the simplest and fastest way possible, but it does execute nearly the same query as a normal QuerySet query.
exists() is useful for searches relating to both object membership in a QuerySet and to the existence of any objects in a QuerySet, particularly in the context of a large QuerySet.
But ObjectDoesNotExist works only with get().
Also you can try another approach:
user = User.objects.filter(id=2)
if user:
# put your logic
pass
Since we are in Django, we'll try to catch the error with Django functionality instead of the common way(which is using Exceptions with Python).
id = 1
def a_query(id):
qs = User.objects.filter(pk=id)
if qs.exists():
return qs.first()
return None
In here, the method exists() helps you catching the error(if there's any).
ref: https://docs.djangoproject.com/en/3.0/ref/models/querysets/#django.db.models.query.QuerySet.exists
in django model,
if you gonna use model.objects.get() if it wasn't exist it raise an error. in that case you can use DoesNotExist along with except:
try:
val = Model.objects.get(pk=val) # if nothing found it will raise an exception
exception:
you can trace an exception without mentioning anything on top.
(or)
exception ObjectDoesNotExist:
# it will come here if exception is DoesNotExist
For Django version 2.0.6, you can do the following, and it will work:
if Model.objects.filter(my_id=objectid).exists():
myobject = get_object_or_404(Model, my_id=objectid)
context = {'myobject': myobject}
return render(request, self.template_name, context)
You can get more info here: https://docs.djangoproject.com/en/2.1/ref/models/querysets/
It's my understanding that you're asking whether to use if statements or try catch on your code. I personally prefer to avoid using try catch, a think it's an ugly syntax, when I do want to raise an exception, I use a python keyword raise, to me, it makes the code cleaner.
Code example:
user = User.objects.filter(id=2)
if not user:
raise ObjectDoesNotExist

Exception Value field is blank when throwing custom exceptions in django

I have custom exceptions in my django project that look like this:
class CustomFooError(Exception):
def __init__(self, msg="Something went wrong with Foo."):
self.msg = msg
def __str__(self):
return repr(self.msg)
At various points in my code I will raise exceptions like this:
raise CustomFooError("Things are going badly")
When Django catches these errors, in debug mode I get django's standard pretty stack-trace page. But I never see my error messages -- "Things are going badly" never shows up in the debug error page.
It seems they should show up as the Exception Value on the error page. I walked back through the django source far enough to find out that this is the value field from sys.exc_info() which is consistently tersely documented as "[the exception's] associated value or the second argument to raise, which is always a class instance if the exception type is a class object." Unfortunately, I don't know what to do with this information.
So my question is: How should I be writing and raising my custom exceptions to get more useful data to show up in places like the django error screen?
I would just use super and let the constructor of Exception handle assigning the msg attribute:
class CustomFooError(Exception):
def __init__(self, msg=None):
if msg is None:
msg = 'Something went wrong with Foo.'
super(CustomFooError, self).__init__(msg)
I just tested this from within a Django environment and it correctly displayed the message I passed to the exception constructor or the default one if None was passed.
#AdmiralNemo is right: let the base class do the work.
But to dig into your code a little deeper, the problem is that you don't tie into the Exception implementation at all. Exception(s) stores s in the .message attribute, not .msg. It also stores it as (s,) in the .args attribute. Your code doesn't set either of these attributes, which is probably why Django can't find a message to display.
Also, your __str__ method is odd. It should return self.msg, not repr(self.msg), which would add quotes around the string, and potentially escapes inside the text.

How to handle conditional-imports-dependent exceptions?

I'm wondering what is the most elegant way to handle exceptions that depend on a conditional import.
For example:
import ldap
try:
...
l = ldap.open(...)
l.simple_bind_s(...)
...
except ldap.INVALID_CREDENTIALS, e:
pass
except ldap.SERVER_DOWN, e:
pass
In the real-world scenario (the one that made me think of this), we have a cherrypy server with a 'login' page. And the login method does a lot of stuff - one of them is authentication.
However, I can use something else than LDAP to do authentication, in which case I do not want to import ldap at all.
But if I make the 'import ldap' statement conditional (e.g. it only gets imported when USE_LDAP value is True in a config file), I have to do something with the 'except's too. The question is: what?
Catch a generic Exception, use an if statement to check whether we use LDAP (i.e., ldap is imported) and then use isinstance to check, whether the Exception is the correct type (ldap.INVALID_CREDENTIALS)?
Try to concentrate the code that depends on ldap at one place and re-raise a user defined exception that finally gets caught in the login method?
What would you suggest as the most pythonic?
Probably somewhere there should be a configuration option in your program that is used to decide which kind of authentication should be used. The imports should be done depending on this option.
If you put all the ldap related authentication functions into their own module, like auth_ldap and do the same for your other methods of authentication, you could do the login check like this:
if config.auth_method == 'ldap':
import ldap_auth as auth
elif config.auth_method == 'db':
import db_auth as auth
else:
raise Exception("No valid authentication module configured")
auth.check_login(user, password)
The check_login method in each module would here provide a uniform interface that internally does whatever is necessary to perform the specific login. This function could also translate specific Ldap exceptions into a generic LoginFailure or just return True or False depending on the success of the user check.
This will be easier to handle if you write a set of abstraction modules for authn (Strategy Pattern). Each module will catch its specific authn exceptions, and in place raise generic exceptions defined by the application.

Categories