Exception classes - how to instantiate?

#1

Question about exceptions: I’ve written my own wrapper class around the CB Python SDK, and am trying to write unit & functional tests for it. One of the things I’m testing is the retry logic I’ve implemented to handle transient/network errors. The exceptions I’m catching are CouchbaseNetworkError, CouchbaseTransientError, TemporaryFailError. I also attempted to check the is_transient and is_network attributes of the raised exceptions, because the documentation (http://docs.couchbase.com/sdk-api/couchbase-python-client-2.5.0/api/exceptions.html) does not make it clear what exceptions may have these attributes. For example, it’s only implied that CouchbaseTransientError will have is_transient set to (some value that evaluates to True) - it doesn’t state it explicitly, nor does it state whether or not any other exceptions might set this attr. The same goes for CouchbaseNetworkError and the is_network attr.

So, can someone please provide concrete info on how these attrs map to exceptions?

Additional, and more involved question:

What is the proper method for instantiating a CouchbaseError exception? I’ve tried instantiating them with no constructor parameters, and I get an error:

def __init__(self, params=None):
    if isinstance(params, str):
        params = {'message': params}
    elif isinstance(params, CouchbaseError):
        self.__dict__.update(params.__dict__)
        return

>       self.rc = params.get('rc', self.CODE)
E       AttributeError: 'NoneType' object has no attribute 'get'

…The hack I’ve used thus far is to pass a[ny] string to the constructor, a la error = CouchbaseNetworkError('blah'). This is obviously not the correct way to do this. What I’m guessing IS the correct way is to use CouchbaseError.rc_to_exctype(int), but I cannot figure out exactly what integer value to use for CouchbaseTransientError itself, as opposed to its subclasses. For example, I see in error.h that 0x02 == LCB_AUTH_ERROR, and rc_to_exctype(2) returns an AuthError, but I don’t see what hex code I’m supposed to use in order to instantiate CouchbaseTransientError.

Also: I see that when I instantiate a CouchbaseTransientError, the is_transient attr == 8. I’m guessing this is because of:
LCB_ERRTYPE_TRANSIENT = 1 << 3
…but why?

Apologies in advance for incoherence, this is all just very confusing to me.

#2

Updates: after reading the source, I do see and acknowledge that the purpose of passing a string to the CouchbaseError constructor is to convey the reason for the exception, e.g. raise couchbase.exceptions.CouchbaseError("Decryption failed"). But this isn’t documented, thus my confusion.

Furthermore - when I raise a CouchbaseNetworkError, and check the is_network attr, it’s 0. Why is this the case? The documentation implies it should evaluate to True:

`is_network`

True if errors were received during TCP transport. See [ `CouchbaseNetworkError` ](http://docs.couchbase.com/sdk-api/couchbase-python-client-2.5.0/api/exceptions.html#couchbase.exceptions.CouchbaseNetworkError)
#3

Hi @gnarlium,
I’ll try to dig up some more detailed info on errors. As a wrapper for libcouchbase, Python Couchbase Client’s exceptions wrap the standard error codes returned from the server. There is now a system for retrieving a description of each error code from the server using KV Error Map - this is accessible from Python via a connection string setting, as far as I am aware.

Please look here for an up-to-date account:

With respect to raising CouchbaseErrors as an end-user, this is not something that we cater for normally, as they are intended to be emitted by the SDK only. Do you need these for tests? I guess you can map the exceptions you are expecting to handle to something else for that purpose.

Thanks,
Ellis

#4

Thanks for your reply - the KV Error map looks very useful for handling retries, etc - I like the corrective-action-oriented classification. Can you help me locate where in the Python SDK this is exposed? I haven’t been able to find anything on it when searching the docs.
Regarding my use case for instantiating my own exceptions - yes, I need this for testing. My wrapper wraps the SDK, so to test it, I must raise the SDK’s exceptions. Mapping them to my own exception classes could certainly work…but then I’d still have to raise SDK exceptions in order to test the code that performs those mappings - same problem, different location.

#5

Hi, any update on this? I haven’t been able to find anything on the KV error map as it relates to the python SDK.

#6

Bumping this post, still looking for answers, and a way to test my code.