{ "info": { "author": "mattbennett", "author_email": "", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "Operating System :: MacOS :: MacOS X", "Operating System :: POSIX", "Programming Language :: Python", "Programming Language :: Python :: 3", "Topic :: Internet", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "# nameko-worker-postmortem\n\nHave you ever been frustrated with the behaviour of a Nameko service in pytest using the ``--pdb`` flag?\n\nIf your Nameko service throws a worker exception, ``--pdb`` won't interrupt with a breakpoint until the exception is serialised back to the caller of the entrypoint.\n\n`nameko-worker-postmortem` is a pytest plugin that inserts the tracepoint earlier, so you can see a more useful stack trace.\n\n### Example\n\nHere's an example test that will fail:\n\n```python\n# test.py\n\nfrom nameko.web.handlers import http\n\nclass BadRequest(Exception):\n pass\n\nclass Service:\n name = \"service\"\n\n @http(\"GET\", \"/resource\")\n def resource(self, request):\n param = request.args.get('param')\n if param == \"good\":\n return 200, \"OK\"\n raise BadRequest()\n\n\ndef test_service(container_factory, web_config, web_session):\n container = container_factory(Service, web_config)\n container.start()\n\n res = web_session.get('/resource?param=bad')\n assert res.status_code == 200\n```\n\n#### With `--pdb`\n\n\nUsing the `--pdb` flag, the breakpoint is set where the assertion fails, which isn't very helpful if you want to see the exception that the worker raised instead:\n\n```pycon\n$ py.test test.py\n============================= test session starts ==============================\nplatform darwin -- Python 3.4.6, pytest-3.7.4, py-1.6.0, pluggy-0.7.1\nrootdir: /private/tmp, inifile:\nplugins: nameko-2.11.0, nameko-worker-postmortem-0.0.1\ncollected 1 item\n\ntest.py F\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> captured log >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\ncontainers.py 399 ERROR error handling worker :\nTraceback (most recent call last):\n File \"/Users/mattbennett/.virtualenvs/tmp-302905cac73c0a2/lib/python3.4/site-packages/nameko/containers.py\", line 391, in _run_worker\n result = method(*worker_ctx.args, **worker_ctx.kwargs)\n File \"/private/tmp/test.py\", line 14, in resource\n raise BadRequest()\ntest.BadRequest\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> traceback >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\ncontainer_factory = .make_container at 0x11022f620>\nweb_config = {'WEB_SERVER_ADDRESS': '127.0.0.1:55934'}\nweb_session = .WebSession object at 0x11047ac18>\n\n def test_service(container_factory, web_config, web_session):\n container = container_factory(Service, web_config)\n container.start()\n\n res = web_session.get('/resource?param=bad')\n> assert res.status_code == 200\nE assert 500 == 200\nE + where 500 = .status_code\n\ntest.py:22: AssertionError\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> entering PDB >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n[11] > /private/tmp/test.py(22)test_service()\n-> assert res.status_code == 200\n 6 frames hidden (try 'help hidden_frames')\n> /private/tmp/test.py(22)\n\n 17 def test_service(container_factory, web_config, web_session):\n 18 container = container_factory(Service, web_config)\n 19 container.start()\n 20\n 21 res = web_session.get('/resource?param=bad')\n 22 -> assert res.status_code == 200\n```\n\n#### With `--worker-postmortem`\n\nReplacing `--pdb` with `--worker-postmortem` (or `--worker-pdb`) the breakpoint is inserted at where the worker exception is raised instead.\n\nNote that `-s` must also be passed to disable output capturing.\n\n```\n$ py.test test.py --worker-postmortem -s\n============================= test session starts ==============================\nplatform darwin -- Python 3.4.6, pytest-3.7.4, py-1.6.0, pluggy-0.7.1\nrootdir: /private/tmp, inifile:\nplugins: nameko-2.11.0, nameko-worker-postmortem-0.0.1\ncollected 1 item\n\ntest.py [1] > /private/tmp/test.py(14)resource()\n-> raise BadRequest()\n> /private/tmp/test.py(14)\n\n 9 @http(\"GET\", \"/resource\")\n 10 def resource(self, request):\n 11 param = request.args.get('param')\n 12 if param == \"good\":\n 13 return 200, \"OK\"\n 14 -> raise BadRequest()\n(Pdb++)\n```\n\n### TODO\n\n* Fix coverage collection\n* Add pre-commit hooks\n* Automatically disable capturing so you don't have to specify `-s` every time\n* Attempt to make navigation `up` and `down` the stack trace work as they would with a `pdb.set_trace()` (at the moment, `up` doesn't take you up the stack but into the `nameko-worker-postmortem` code that inserts the breakpoint.)\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/mattbennett/nameko-worker-postmortem", "keywords": "", "license": "Apache License, Version 2.0", "maintainer": "", "maintainer_email": "", "name": "nameko-worker-postmortem", "package_url": "https://pypi.org/project/nameko-worker-postmortem/", "platform": "", "project_url": "https://pypi.org/project/nameko-worker-postmortem/", "project_urls": { "Homepage": "http://github.com/mattbennett/nameko-worker-postmortem" }, "release_url": "https://pypi.org/project/nameko-worker-postmortem/1.0.0/", "requires_dist": [ "nameko", "pytest", "coverage (==4.4.1); extra == 'dev'" ], "requires_python": "", "summary": "Drop into PDB post mortem on Nameko worker exceptions", "version": "1.0.0" }, "last_serial": 4238420, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "4e41fc0eb6df0771d865ab5b57d0697e", "sha256": "dd2d13e260774a5a653f4f894c2b92bbb4c382c3f28499b2e09009abc13e040d" }, "downloads": -1, "filename": "nameko_worker_postmortem-1.0.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "4e41fc0eb6df0771d865ab5b57d0697e", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 4150, "upload_time": "2018-09-04T16:53:13", "url": "https://files.pythonhosted.org/packages/e2/63/40a900c572498177e5d5dba19fc2323a913596bef9b574b37839a05f8e0c/nameko_worker_postmortem-1.0.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e9d28b0f71ec67c2d9647cec59b48f03", "sha256": "a68defd6dad873b8f3ccab8ca6f036e39994911c2922375271b27f5881c703e6" }, "downloads": -1, "filename": "nameko_worker_postmortem-1.0.0.tar.gz", "has_sig": false, "md5_digest": "e9d28b0f71ec67c2d9647cec59b48f03", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3729, "upload_time": "2018-09-04T16:53:15", "url": "https://files.pythonhosted.org/packages/f1/8d/8c164d0bb160c95989f5e8f389cc7d64d4ab381a4d710ba738f98bd16677/nameko_worker_postmortem-1.0.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "4e41fc0eb6df0771d865ab5b57d0697e", "sha256": "dd2d13e260774a5a653f4f894c2b92bbb4c382c3f28499b2e09009abc13e040d" }, "downloads": -1, "filename": "nameko_worker_postmortem-1.0.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "4e41fc0eb6df0771d865ab5b57d0697e", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 4150, "upload_time": "2018-09-04T16:53:13", "url": "https://files.pythonhosted.org/packages/e2/63/40a900c572498177e5d5dba19fc2323a913596bef9b574b37839a05f8e0c/nameko_worker_postmortem-1.0.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e9d28b0f71ec67c2d9647cec59b48f03", "sha256": "a68defd6dad873b8f3ccab8ca6f036e39994911c2922375271b27f5881c703e6" }, "downloads": -1, "filename": "nameko_worker_postmortem-1.0.0.tar.gz", "has_sig": false, "md5_digest": "e9d28b0f71ec67c2d9647cec59b48f03", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3729, "upload_time": "2018-09-04T16:53:15", "url": "https://files.pythonhosted.org/packages/f1/8d/8c164d0bb160c95989f5e8f389cc7d64d4ab381a4d710ba738f98bd16677/nameko_worker_postmortem-1.0.0.tar.gz" } ] }