1.1.3.3 Differences Between protocols.adapt() and PEP 246
Description: Differences Between protocols.adapt() and PEP 246
Keywords: ref

### 1.1.3.3 Differences Between `protocols.adapt()` and PEP 246

If you have read PEP 246 or are looking for an exact implementation of it, you should know that there are a few differences between the `protocols` implementation of `adapt()` and the PEP 246 specification. If you don't care about these differences, you can skip this mini-appendix and proceed directly to section 1.1.4, ``Defining and Subclassing Interfaces''.

The first difference is that `TypeError` is treated differently in each implementation. PEP 246 says that if a `__conform__` or `__adapt__` method raises a `TypeError`, it should be treated in the same way as if the method returned `None`. This was a workaround for the issue of accidentally calling an unbound class method, in the case where a component or protocol supplied to `adapt()` was a class.

The `protocols` implementation of `adapt()` attempts to catch such errors also, but will reraise any exception that appears to come from within the execution of the `__conform__` or `__adapt__` method. So if these methods raise a `TypeError`, it will be passed through to the caller of `adapt`. Thus, if you are writing one of these methods, you should not raise a `TypeError` to signal the lack of an adaptation. Rather, you should return `None`.

Second, `protocols.AdaptationFailure` is raised when no adaptation is found, and no default is supplied, rather than the `TypeError` specified by PEP 246. (Note: `protocols.AdaptationFailure` is a subclass of `TypeError` and `NotImplementedError`, so code written to catch either of these errors will work.)

These differences are the result of experience using the `protocols` package with PEAK, and advances in the Python state-of-the-art since PEP 246 was written (over two years ago). We believe that they make the adaptation protocol more robust, more predictable, and easier to use for its most common applications.