kilrey.decoratosライブラリです。 便利なデコレータ、メタクラスを提供します。 (download)
- kilrey.decorators.mimic
-
デコレータ 'mimic' は関数のメタ情報をコピーした関数を生成します。 他の類似デコレータと比べてコピーするメタ情報が多いのが特徴です。 例えば、標準で付属している functools.wraps では __module__, __name__, __doc__ といった 書き換え可能な属性をラッパーに設定するだけですが、 kilrey.decoratos.mimic.mimic では func_code やトレースバックまで書き換えます。
- kilrey.decorators.docassert
-
デコレータ 'docassert', メタクラス 'DocAssert' は python にて Design by Contract(DbC) を実現します。 すでにある DbC ライブラリとの最大の違いは docstring 中に条件を端的に書くので pydoc などのドキュメントシステムと相性が良い点です。 以前のdocassertから細かい点が変わっていますが、 基本的な使い方は変わっていません。
今、自分で使いながら少しずつ機能を追加しているところです。 あまりドキュメントを書いていないので その代わりに pydoc の出力を載せておきます。 機能の追加や日本語の解説などへの要望は id:kilrey へお願いします。
- kilrey.decorators.mimic
-
Help on module mimic: NAME mimic - kilrey.decorators.mimic FILE kilrey/decorators/mimic.py DESCRIPTION The decorator 'mimic' builds a wrapper function with the meta informations of another function. The advantage over the others is that the overwritten meta informations are not only of the function itself but of the func_code. The overwritten meta informations are following. - __module__ - func_name and __name__ - func_doc and __doc__ - func_defaults - func_globals - func_code.co_argcount - func_code.co_filename - func_code.co_firstlineno - func_code.co_name - func_code.co_nlocals - func_code.co_varnames - The tracebacks in the raised exception. FUNCTIONS metainfo(_func, _file, _line, _fname, _spec, _assigned, _updated) Decorate a function(_func) with metainfos. mimic(_orig) >>> from kilrey.decorators.mimic import mimic >>> def test(_args0, _args1=1, *_args, **_dict): ... 'This is the docstring of test.' ... raise SyntaxError >>> @mimic(test) ... def dummy(*_args, **_dict): ... return test(*_args, **_dict) >>> dummy == test False >>> dummy.__name__ 'test' >>> dummy.__doc__ 'This is the docstring of test.' >>> dummy.func_name == test.func_name True >>> dummy.func_doc == test.func_doc True >>> dummy.func_defaults == test.func_defaults True >>> dummy.func_globals == test.func_globals True >>> dummy.func_code.co_argcount == test.func_code.co_argcount True >>> dummy.func_code.co_filename == test.func_code.co_filename True >>> dummy.func_code.co_firstlineno == test.func_code.co_firstlineno True >>> dummy.func_code.co_name == test.func_code.co_name True >>> dummy.func_code.co_nlocals == test.func_code.co_nlocals True >>> dummy.func_code.co_varnames == test.func_code.co_varnames True >>> import sys >>> import traceback >>> try:#doctest:+ELLIPSIS ... test(0) ... except: ... traceback.print_exception(file=sys.stdout, *sys.exc_info()) ... pass Traceback (most recent call last): File "<doctest __main__.mimic[...]>", line 2, in <module> test(0) File "<doctest __main__.mimic[1]>", line 3, in test raise SyntaxError SyntaxError: None >>> try:#doctest:+ELLIPSIS ... dummy(0) ... except: ... traceback.print_exception(file=sys.stdout, *sys.exc_info()) ... pass Traceback (most recent call last): File "<doctest __main__.mimic[...]>", line 2, in <module> dummy(0) File "<doctest __main__.mimic[1]>", line 3, in test raise SyntaxError SyntaxError: None DATA __author__ = 'kilrey@kilrey.com' __date__ = '2008/11/30' __licence__ = 'The MIT License\n\nCopyright (c) 2008 kilrey@kilre...RE... DATE 2008/11/30 AUTHOR kilrey@kilrey.com - kilrey.decorators.docassert
-
Help on module docassert: NAME docassert - kilrey.decorators.docassert FILE kilrey/decorators/docassert.py DESCRIPTION The decorator 'docassert' and metaclass 'DocAssert' are for the Design by Contract in python using assertions written in docstrings. The contracts for classes are enforced recursively. Only if __debug__ is true, the contracts will weaved into the functions. Write contract expressions with tags in docstrings. For functions, decorate them with @docassert. For classes, set DocAssert as __metaclass__. Examples are written in docassert.__doc__. Write such as '@setup <statements>' or '@invariant <expression>' In contract expressions, you should know some additional rules. - The arguments can be used as their own identifiers. - The function itself is called '__func'. - The return value can be used as '__retval'. - The exception value can be used as '__except'. - The decorators need '@@' not '@'. Description: 1) The defined tags. 1-1) @setup @setup is statements working before the function. 1-2) @teardown @teardown is statements working after the function. 1-3) @invariant @invariant is a contract for invariant-conditions. 1-4) @precond @precond is a contract expression for pre-conditions. 1-5) @postcond @postcond is a contract expression for post-conditions. 1-6) @return @return is a contract expression for post-conditions asserting in returning normally. 1-7) @except @except is a contract expression for post-conditions asserting in raising exceptions. 2) The evaluating sequence. 2-1) Execute @setup of the class. 2-2) Assert @invariant of the class. 2-3) Assert @precond of the class. 2-4) Execute @setup of the function. 2-5) Assert @invariant of the function. 2-6) Assert @precond of the function. 2-7) Call the function itself. 2-8) Assert @return or @except of the function. 2-9) Assert @postcond of the function. 2-10) Assert @invariant of the function. 2-11) Execute @teardown of the function. 2-12) Assert @return or @except of the class. 2-13) Assert @postcond of the class. 2-14) Assert @invariant of the class. 2-15) Execute @teardown of the class. 3) The notices. 3-1) In executing or asserting a contract, any contracts are ignored. 3-2) The guard conditions are sometimes needed, such as 'not hasattr(self, 'x') or self.x == 0'. CLASSES __builtin__.type(__builtin__.object) DocAssert class DocAssert(__builtin__.type) | Wrap the all methods of the class(_class) | with the contracts in the docstring(_doc). | >>> from kilrey.decorators.docassert import * | >>> class Test: | ... """ | ... @setup print "setup" | ... @teardown print "teardown" | ... @invariant not hasattr(self, 'x') or self.x == 0 | ... """ | ... __metaclass__ = DocAssert | ... def __init__(self, x): | ... self.x = x | ... pass | ... def test(self): | ... self.x += 1 | ... pass | ... pass | >>> _t = Test(0) | setup | setup | teardown | teardown | >>> _t.x | setup | teardown | 0 | >>> _t.test() | Traceback (most recent call last): | ... | AssertionError: @invariant not hasattr(self, 'x') or self.x == 0 | >>> _t.x = 1 | Traceback (most recent call last): | ... | AssertionError: @invariant not hasattr(self, 'x') or self.x == 0 | >>> _t.x | Traceback (most recent call last): | ... | AssertionError: @invariant not hasattr(self, 'x') or self.x == 0 | | Method resolution order: | DocAssert | __builtin__.type | __builtin__.object | | Static methods defined here: | | __new__(mcs, _clsname, _clsbases, _clsdict) | | ---------------------------------------------------------------------- | Methods inherited from __builtin__.type: | | __call__(...) | x.__call__(...) <==> x(...) | | __cmp__(...) | x.__cmp__(y) <==> cmp(x,y) | | __delattr__(...) | x.__delattr__('name') <==> del x.name | | __getattribute__(...) | x.__getattribute__('name') <==> x.name | | __hash__(...) | x.__hash__() <==> hash(x) | | __repr__(...) | x.__repr__() <==> repr(x) | | __setattr__(...) | x.__setattr__('name', value) <==> x.name = value | | __subclasses__(...) | __subclasses__() -> list of immediate subclasses | | mro(...) | mro() -> list | return a type's method resolution order | | ---------------------------------------------------------------------- | Data descriptors inherited from __builtin__.type: | | __base__ | | __bases__ | | __basicsize__ | | __dict__ | | __dictoffset__ | | __flags__ | | __itemsize__ | | __mro__ | | __weakrefoffset__ FUNCTIONS docassert(_func) Wrap the function(_func) with the contracts in the docstring(_doc). >>> from kilrey.decorators.docassert import * >>> @docassert ... def test(_arg0): ... """ ... @setup print "setup" ... @teardown print "teardown" ... @invariant _arg0 == 0 ... @precond _arg0 == 0 ... @postcond _arg0 == 0 ... @return __retval == 1 ... @except __except.message == 'ERROR' ... """ ... return _arg0+1 >>> test(0) setup teardown 1 >>> test(1) Traceback (most recent call last): ... AssertionError: @invariant _arg0 == 0 DATA __author__ = 'kilrey@kilrey.com' __date__ = '2008/11/30' __licence__ = 'The MIT License\n\nCopyright (c) 2008 kilrey@kilre...RE... DATE 2008/11/30 AUTHOR kilrey@kilrey.com