skip to navigation
skip to content

Not Logged In

pycheck 0.1

Type checking tools for debugging and developing Python code

checked is a function decorator that uses function annotations as type declarations
and verifies that the function has been passed, and is returning, the
correct types of values.

Yes, yes, I know, this is python and we're not supposed to have to have
type checking. Before you pound your keyboard angrily telling me what an
idiot I am, please at least read the "Motivation" section below. Thank you.


def function(parameter:<type declaration="">) -> <type declaration="">

"function" may be a function, a method, or a generator*.

* For generators the actual return type is type <generator> however
@checked will check that the values yielded by the generator are
of the specified type.

<type declaration=""> may be any of the following:

* a class or type object (int, str, MyClass, etc.)

``def f( x:int ): # f() only accepts int``

* A tuple (or any iterable) of type objects, indicating that the value may be an instance of
any of those types.

``def f( x: (int, str) ): # f() must return a str OR None``

* The literal None, to indicate that only None is an acceptable value
(usually used for declaring that a function does not return a value)

``def f( x ) -> None: # f() has no return value``

* A tuple (or any other iterable) containing type objects and the value None, indicating that
the value may be any of the indicated types or the special value None.

``def f( x ) -> (str, None) # f() must return a str or None``

* Dict (or other mapping type) object which maps a collection type to an element type,
{<collection type=""> : <element type="">}.

This usage means that the function ruturns a collection of type <collection type="">
(e.g. set, list, tuple, etc.), which contains only elements of type <element type="">.

``def f(x) -> {set:int}: # f() must return a set of integers``

* A callable object which accepts one parameter and returns true or false. The callable
object is treated as a pre-condition when annotating function parameters and a
post-condition when annotating the return value. The value passed or returned will be
passed to the callable and an error will be raised if the result is not true.

``def f( x: lambda x: x > 0 ): # f() only accepting values greater than zero``

``def g(x) -> lambda y: y >= 0: # g() must return a value >= 0``

Parameters with default values, as well as *arg and **kwd arguments can also have
their types declared:

def function(x:<type declaration="">, y:<type declaration="">=1, *args:<type declaration="">, **kwds:<type declaration):="" debug="" mode:="" -----------------------------="" @checked="" is="" intended="" to="" be="" used="" as="" a="" tool="" during="" development="" and="" testing="" to="" help="" identify="" errors="" more="" quickly.="" for="" this="" reason="" ``@checked``="" is="" only="" functional="" in="" debug="" mode="" (i.e.="" when="" ``__debug__="=" true``).="" if="" not="" in="" debug="" mode="" it="" is="" defined="" simply="" as,="" def="" checked(f):="" return="" f="" motivation:="" -----------="" the="" original="" motivation="" for="" this="" function="" was="" my="" attempt="" to="" apply="" the="" excercises="" outlined="" in="" ben="" nadel's="" whitepaper,="" "object="" calisthenics"="" (http:="""" resources="" uploads="" 2012="" objectcalisthenics.pdf).="" one="" of="" nadel's="" excercises="" is="" to,="" "wrap="" all="" primitives="" and="" strings."="" what="" he="" means="" is="" that="" instead="" of="" passing="" simple="" ints,="" floats,="" and="" strings="" to="" a="" function,="" you'd="" create="" simple="" subclasses="" of="" int,="" float="" and="" str="" to="" represent="" the="" type="" of="" data="" the="" parameter="" actually="" represents="" and="" to="" protect="" you="" from="" accidently="" passing="" an="" integer="" that="" represents="" hours="" to="" a="" function="" that="" is="" intended="" to="" work="" with="" dollar="" ammounts,="" for="" example.="" of="" course,="" nadel="" wrote="" his="" paper="" with="" java="" in="" mind,="" so="" the="" java="" compiler="" would="" actually="" catch="" an="" error="" like="" that.="" in="" attempting="" to="" apply="" that="" recommendation="" to="" python="" something="" was="" needed="" in="" order="" implement="" type="" checking.="" not="" finding="" a="" suitable="" package="" after="" an="" exhaustive="" five="" minute="" search="" of="" the="" internet="" i="" decided="" to="" try="" to="" implement="" my="" one="" on="" my="" own="" (okay,="" i="" really="" wanted="" to="" see="" if="" i="" could="" do="" it="" or="" not).="" limitations="" -----------="" *="" there's="" currently="" no="" way="" to="" verify="" if="" the="" default="" value="" specified="" for="" a="" parameter="" violates="" the="" type="" declaration="" for="" that="" parameter.="" example:="" def="" f(="" x:int="bad default value" ):="" ....="" hopefully="" the="" fact="" that="" the="" type="" declaration="" is="" right="" there="" in="" front="" of="" you="" will="" be="" enough="" to="" get="" you="" to="" use="" the="" right="" type.="" this="" actually="" has="" at="" least="" one="" legitamate="" use,="" actually,="" in="" the="" case="" where="" the="" default="" value="" is="" a="" magic="" value="" (typically="" none)="" which="" indicates="" that="" the="" user="" didn't="" supply="" a="" value:="" def="" f(="" x:int="None" )="" #="" user="" is="" never="" intended="" to="" specify="" a="" value="" of="" none.="" user="" is="" expected="" #="" to="" either="" supply="" an="" int="" or="" no="" value="" at="" all.="" if="" x="" is="" none:="""" something="" special...="" *="" if="" the="" annotations="" are="" callable="" objects,="" they="" can="" only="" operate="" on="" a="" single="" parameter,="" or="" the="" return,="" value.="" the="" validation="" cannot="" evaluate="" all="" of="" the="" parameters="" --="" for="" example="" you="" can't="" write="" a="" pre-condition="" that="" checks="" that="" the="" parameters="" are="" ordered="" from="" least="" to="" greatest.="" known="" issues:="" -------------="" although="" an="" error="" is="" raised="" as="" it="" should="" be,="" the="" text="" of="" the="" error="" message="" for="" a="" container="" containing="" and="" element="" of="" the="" wrong="" type="" is="" not="" clear="" type_proxy(typename)="" type_proxy(typename)="" is="" used="" when="" an="" actual="" typename="" cannot="" be="" used="" because="" it="" is="" not="" yet="" defined="" in="" the="" namespace="" and="" cannot="" be.="" the="" two="" typical="" causes="" are,="" 1.="" using="" a="" class="" in="" an="" annotation="" of="" a="" method="" of="" that="" same="" class.="" example:="" class="" a:="" @checked="" @classmethod="" def="" factory(cls,="" ...)="" -=""> A: # Error, when the annotation is processed, A has not yet been defined
class A:
def factory(cls, ...) -> type_proxy('A') # valid

2. Trying to create an annotation which refers to a class not yet defined, which itself uses an annotation
that refers back to _this_ class (i.e. circular references). Because the two classes refer to each other
the solution is not so simple as to just move the second class definition before the first.

class A:
def to_b(self) -> B : # Error: B not yet defined
return B(self)

class B:
def to_a(self) -> A : # A refers to B and B refers to A, so it doesn't matter
return A(self) # which class is defined first, there's going to be an error.

class A:
def to_b(self) -> type_proxy("B") : # Fixed
return B(self)

class B:
File Type Py Version Uploaded on Size
pycheck-0.1.tar.gz (md5) Source 2013-01-22 12KB (md5) Source 2013-01-22 16KB
  • Downloads (All Versions):
  • 17 downloads in the last day
  • 73 downloads in the last week
  • 258 downloads in the last month