Xion/pyduck — Issue #9: General "examine arguments" decorator
Author: Xion
Created: 2011-10-30 18:49:59+00:00
State: open

@expects seems to be an example of a more general utilty decorator that we might call an 'argument examiner'. Such decorator goes through the argument list and does something to argument values - presumbly based on parameters passed earlier to decorator itself.

As an example, @expects checks whether argument implements particular interface or is instance of specific type. Other examples might include a specific transformation of arguments, such as transforming a database object primary key (ID) into an ORM object.

While such decorator is not hard to write, there are some issues related to handling positional (*args) and keyword (**kwargs) arguments. that could be addressed by writing a generalized arguments' examiner. The @expects decorator would be then using this decorator as a basis.

Below there is an example of implementing a decorator upon such argument examiner:

```python
class OrmCoerceDecorator(Examiner):
# 'spec' is argument value got in decorator initialization
# 'actual' comes from function call
def _process_argument(self, spec, actual):
if not isinstance(actual, spec): # assume 'spec' is ORM class
return db_session.get_by_primary_key(actual)

orm_coerce = OrmCoerceDecorator
```
The usage would be as follows:

```python
@orm_coerce(User)
def reset_password(user):
user.password = None # accessing object field
send_password_recovery_mail(user)

# somewhere in website request handler
current_user_id = session.get('user_id')
reset_password(user_id) # works with just an ID thanks to @orm_coerce
```