Utility Classes :: Function

Function() is used to make assertions about functions and methods that get passed in and out of Python code.

Positional Parameters

Your garden variety assertions are going be something like, "does the function take X number of parameters of types Y and Z?" As a contrived example, say you wanted to make sure that a passed-in function takes three integers as arguments:

@accepts(Function(int, int, int))

Note that even if the passed-in function is defined like

def foo(a, b, c, d=6):
    ...

that is, three integers are valid -- but so are four -- the Function() will reject the callable. The callable signature must match maximally.

Keyword Parameters

If you'll be passing certain arguments by keyword, the Function() instance can be used to ensure that the function has parameters with certain names.

Function(int, int, c=int)

This will check to make sure that the function takes three integers and that one parameter is named c.

Excess Parameters

Let's say you want to assert that a function has either a *vargs or **kwargs parameter defined. Now, even though you use positional arguments to Function() to cover positional parameters and keyword arguments to make assertions about keyword parameters, you have to do something different for these excess parameters. To verify that a function has *vargs or **kwargs parameters, use the Function class's star() and double_star() methods, respectively.

A function like

def foo(a, b, *vargs, **kwargs):
    ...

can be covered by

@accepts(Function(int, int).star(int).double_star(int))

Note that star() and double_star() return the invocant instance so that they can be used "inside" the decorator (as illustrated above).

Return Types

Using a mechanism similar to that used to assert the presence of excess parameters, an invocant-returning method can be used to verify that a function returns objects of the proper type:

@accepts(Function(int, int).returns(int, int))

will ensure that the passed-in function takes two integers and returns a two integers.

Note that if you don't specify a return type, the Function instance won't just guess.

Non-typechecked Functions

Since Function objects work by analysis the type information from typecheck's accepts and returns decorators, the question naturally arises: what to do about non-typechecked callables? By default, passing in a callable with insufficient type information (no type information, or e.g. @returns wasn't applied and the Function expected that it was) will cause the Function instance to reject the callable. If this behaviour is undesirable, you can have non-typechecked functions automatically approved in one of two ways:

  1. It's possible to make all Function instances non-strict (i.e., they allow non-typechecked functions) by setting Function.is_strict to False. This applies to all Function instances created after this assignment.

  2. Function instances can also be made non-strict on an individual basis by passing False to the invocant-returning Function.strict() instance method. Since this method returns the invocant (like returns() and star()), it can be used "inside" the decorator.

Details

Valid XHTML 1.0 Transitional