{ "info": { "author": "Christy O'Reilly", "author_email": "christy@oreills.co.uk", "bugtrack_url": null, "classifiers": [ "Development Status :: 1 - Planning", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 2.7" ], "description": "before_after\n============\n\nbefore_after provides utilities to help test race conditions.\n\nWhen testing Python programs that run in multiple threads or processes it's useful to simulate race conditions to ensure you handle them properly. before_after provides two functions, ``before`` and ``after``, that allow you to insert pre or post functions to be called before/after a function you want to test.\n\nSee this `blog post `_ for a practical example of using before_after in tests.\n\n\nPatching\n--------\n\nbefore_after is sugar over the `Mock library `_. It's recommended that you read the docs before using before_after, especially `Where to patch `_.\n\n\nExample usage\n-------------\n\n`Practical example of testing race conditions `_\n\n.. code:: python\n\n def before_fn(*a, **k):\n print 'before_fn called with', a, k\n\n def after_fn(*a, **k):\n print 'after_fn called with', a, k\n\n def hello(name, greeting='Hello'):\n print '{greeting} {name}!'.format(\n greeting=greeting, name=name)\n\n with before_after.before('__main__.hello', before_fn):\n hello('World')\n\n # before_fn called with ('World',) {}\n # Hello World!\n\n with before_after.after('__main__.hello', after_fn):\n hello('everybody', greeting='Hi there')\n\n # Hi there everybody!\n # after_fn called with ('everybody',) {'greeting': 'Hi there'}\n\n\nUse with recursive functions\n----------------------------\n\nBy default, before_after only calls the before_fn/after_fn function once. This is useful if you're calling the original function within the before_fn/after_fn, since otherwise you'll blow the stack. This behaviour can be disabled by passing ``once=False``.\n\n.. code:: python\n\n my_list = []\n\n def before_fn(*a, **k):\n print 'calling my_append in before_fn'\n my_append(1)\n\n def my_append(item):\n print 'appending', item, 'to my_list'\n my_list.append(item)\n print 'my_list is now', my_list\n\n with before_after.before('__main__.my_append', before_fn):\n my_append(2)\n\n # calling my_append in before_fn\n # appending 1 to my_list\n # my_list is now [1]\n # appending 2 to my_list\n # my_list is now [1, 2]\n\n with before_after.before('__main__.my_append', before_fn, once=False):\n my_append(2)\n\n # calling my_append in before_fn\n # calling my_append in before_fn\n # calling my_append in before_fn\n # ...\n # RuntimeError: maximum recursion depth exceeded while calling a Python object\n\nIt's recommended that if you're passing ``once=False`` that you make sure your program will exit cleanly!\n\n\nUse with methods\n----------------\n\nSince v1.0.0 before_after can be used on function methods. Make sure your before_fn/after_fn accepts a ``self`` argument.\n\n.. code:: python\n\n class Greeter(object):\n def __init__(self):\n self.greeted = []\n\n def greet(self, name):\n print 'Hi there', name\n self.greeted.append(name)\n print 'This is now a party of', len(self.greeted)\n\n def after_fn(self, name):\n self.greet(\"{name}'s guest\".format(name=name))\n\n greeter = Greeter()\n\n with before_after.after('__main__.Greeter.greet', after_fn):\n greeter.greet('Alice')\n\n # Hi there Alice\n # This is now a party of 1\n # Hi there Alice's guest\n # This is now a party of 2", "description_content_type": null, "docs_url": null, "download_url": "https://github.com/c-oreills/before_after/tarball/1.0.1", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/c-oreills/before_after", "keywords": "testing,race conditions", "license": "GPLv2", "maintainer": null, "maintainer_email": null, "name": "before_after", "package_url": "https://pypi.org/project/before_after/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/before_after/", "project_urls": { "Download": "https://github.com/c-oreills/before_after/tarball/1.0.1", "Homepage": "https://github.com/c-oreills/before_after" }, "release_url": "https://pypi.org/project/before_after/1.0.1/", "requires_dist": null, "requires_python": null, "summary": "before_after provides utilities for testing race conditions", "version": "1.0.1" }, "last_serial": 2708700, "releases": { "0.1.3": [ { "comment_text": "", "digests": { "md5": "77a8ef0887695d277cf134f60f563678", "sha256": "3290bda2d6c721cf407c1358721c1f02fdc5ceb7de528508f36924a791f02a63" }, "downloads": -1, "filename": "before_after-0.1.3.tar.gz", "has_sig": false, "md5_digest": "77a8ef0887695d277cf134f60f563678", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3832, "upload_time": "2015-03-01T22:29:34", "url": "https://files.pythonhosted.org/packages/bd/05/ee7c4131e2e9a89d019507bc95862057be2a49ec53abd48e8ec78a1f1849/before_after-0.1.3.tar.gz" } ], "1.0.0": [ { "comment_text": "", "digests": { "md5": "b21be1b33b637303f41e929dd71e6e4c", "sha256": "ab5beb942d17c9a0c03cc96c0cf6a6a67da39c05d663e4c0ebfe96c78cbf193b" }, "downloads": -1, "filename": "before_after-1.0.0.tar.gz", "has_sig": false, "md5_digest": "b21be1b33b637303f41e929dd71e6e4c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4185, "upload_time": "2016-10-30T12:17:30", "url": "https://files.pythonhosted.org/packages/55/29/8e115f043c44e162b6eba7fbc48c13ceb3fe06409084480ee7771d483ffc/before_after-1.0.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "3fbd12075b1024c29c74e7c1606cc86e", "sha256": "c7d4f9b8b8bb52095da14c4b9c59ea6b3f5b9ea9fdce8a7bfc72ecae0f5a3f85" }, "downloads": -1, "filename": "before_after-1.0.1.tar.gz", "has_sig": false, "md5_digest": "3fbd12075b1024c29c74e7c1606cc86e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3950, "upload_time": "2017-03-15T22:26:38", "url": "https://files.pythonhosted.org/packages/9a/72/d530e57aef0de092dc7ce626f52812f38dd65a4bfeafd6216fb868b15119/before_after-1.0.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "3fbd12075b1024c29c74e7c1606cc86e", "sha256": "c7d4f9b8b8bb52095da14c4b9c59ea6b3f5b9ea9fdce8a7bfc72ecae0f5a3f85" }, "downloads": -1, "filename": "before_after-1.0.1.tar.gz", "has_sig": false, "md5_digest": "3fbd12075b1024c29c74e7c1606cc86e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3950, "upload_time": "2017-03-15T22:26:38", "url": "https://files.pythonhosted.org/packages/9a/72/d530e57aef0de092dc7ce626f52812f38dd65a4bfeafd6216fb868b15119/before_after-1.0.1.tar.gz" } ] }