The first version should be preferred. This is true, not just for Python, but for other languages like C++/Java because its prone to error and per the Zen of Python Errors should never pass silently.
, which would be the case in your second version.
The Reason:
Consider, the instantiate of Client fails, which results in returning None
. Chaining the same object without checking for a success or proper error handling would result in errors unrelated to the actual problem AttributeError: 'NoneType' object has no attribute 'users'
.
So it is always better, to avoid chaining objects, as that would cause errors to pass silently.
Example
Consider the following modification to your first version
class EmailConfirmation():
@receiver(email_confirmed)
def confirmed(sender, **kwargs):
email = kwargs['email_address'].email
keystone_id = User.objects.get_by_natural_key(email).keystone_id
try:
client = Client(token=settings.KEYSTONE_TOKEN,
endpoint=settings.KEYSTONE_URL)
except CustomClientError as e:
# Your Error Handling Code goes here
raise CustomClientError("Your Error Message")
else:
if client.users:
client.users.update(keystone_id, enabled=True)
else:
raise CustomEmailError("Your Error Message")
finally:
# Cleanup code goes here