{ "info": { "author": "thg", "author_email": "", "bugtrack_url": null, "classifiers": [], "description": "# InspectorTiger\n![CI](https://github.com/thg-consulting/inspectortiger/workflows/CI/badge.svg)\n![codecov.io](http://codecov.io/github/thg-consulting/inspectortiger/coverage.svg?branch=master)\n![PyPI version](https://badge.fury.io/py/inspectortiger.svg)\n![black](https://img.shields.io/badge/code%20style-black-000000.svg)\n![Python 3.7+](https://img.shields.io/badge/python-3.7+-blue.svg)\n![Dependicy Free](https://img.shields.io/static/v1?label=dependicy&message=free&color=success)\n\nInspectorTiger is a modern python code review tool / framework. It comes with bunch of pre-defined handlers which warns you about improvements and possible bugs. Beside these handlers, you can write your own or use community ones.\n\n## Example\n```py\nALPHABET = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n\n\nclass Foo(SomeObjects):\n def bar(self, x=[], y: Union[int, None] = None):\n x.append(1)\n for _ in range(3):\n try:\n super(bla, bla).foo_baz()\n except Exception:\n print(\"An exception\")\n except AttributeError:\n print(\"An attribute error\")\n finally:\n continue\n\n my_iterable = list(token[0] for token in tokens)\n for a in my_iterable:\n yield a\n\n my_other_iterable = list(map(itemgetter(0), tokens))\n for a in range(len(my_other_iterable)):\n print(a, \"=>\", my_other_iterable[a])\n\n```\nThink about this piece of code, you see some bugs or improvements, don't you? But what if there were hundreds of lines code in this form inside your big codebase. How would you find these patterns? By writing regex queries? LOL, of course not.\n```console\n$ inspectortiger ../t.py\n[Inspector Tiger] INFO - InspectorTiger inspected \ud83d\udd0e and found these problems;\n[Inspector Tiger] INFO - \n[upgradeable]\n - ../t.py:1:0 => ALPHABET_CONSTANT\n - ../t.py:4:29 => OPTIONAL\n - ../t.py:8:16 => SUPER_ARGS\n - ../t.py:16:22 => USE_COMPREHENSION\n - ../t.py:17:8 => YIELD_FROM\n - ../t.py:20:28 => MAP_USE_COMPREHENSION\n - ../t.py:21:8 => BUILTIN_ENUMERATE\n[misc]\n - ../t.py:4:4 => DEFAULT_MUTABLE_ARG\n - ../t.py:7:12 => CONTROL_FLOW_INSIDE_FINALLY\n - ../t.py:7:12 => UNREACHABLE_EXCEPT\n```\n\nBuutt, what if i want something more specific? Like what if i want to find all calls to `xyz` function with 2 arguments only inside of a class inside of a class, can you implement this feature? Nop, but you can.\n\n```py\nxyz()\nxyz(1, 2)\ndef yyy():\n xyz()\n xyz(1, 2)\n\nclass PamPam:\n xyz(1, 2)\n\n class FooFoo:\n xyz(1, 2) # this one\n\ndef papa():\n class Papa:\n xyz(1, 2)\n class FoFo:\n xyz(1, 2) # this one\n```\n\nTo write a handler, you'll need a python package. Let's create a `setup.py` (or `setup.cfg`);\n```py\nfrom setuptools import setup, find_packages\n\nsetup(\n name=\"xyzintro\",\n packages=find_packages()\n)\n```\nThis would work (just for tutorial). Then we need an actual package which would contain a `__init__.py` and as many modules as we want.\n```\n\u251c\u2500\u2500 xyzintro\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 handlers.py\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 __init__.py\n```\nThe only module in that example is the module that contains our handler. Let's take a look to that.\n```py\nfrom inspectortiger import Inspector\n```\n`Inspector` is the base of all the things. It controls workflow by handlers etc.\n```py\nfrom inspectortiger.utils import name_check\n```\n`name_check` is a small utility that compares given `ast.Name`'s `id` attribute.\n```py\nfrom inspectortiger.plugins.context import Contexts\n```\nThe `Contexts` is an `enum` which contain context states.\n\n\nAfter import a decorator comes in,\n```py\n@Inspector.register(ast.Call)\n```\nWhich registers our function (below that) to the `Inspector` with an AST node. When the `InspectorTiger` encounters with that node, it'll call our function.\n```py\ndef xyzinspector(node, db):\n \"\"\"Finds all `xyz()` calls with 2 arguments inside of 2-level-depth class context.\"\"\"\n```\nThe first thing we need to do is to find what the current context is and what the previous context was. If both of these are classes, we can proceed.\n```py\n prev = db[\"context\"][\"previous_contexts\"]\n depth_one = db[\"context\"][\"context\"].context is Contexts.CLASS\n if len(prev) > 0:\n depth_two = prev[-1].context is Contexts.CLASS\n else:\n depth_two = False\n```\nLuckily Inspector Tiger has a core plugin for deciding our context, `inspectortiger.plugins.context`. First thing we did was accessing the hook database (`db`) which allows hooks to share data between them. Then we got our current context (`depth_one`). We performed a check because we could be in the global scope and if that's the case, `prev[-1]` will raise an error. After deciding the status of the our contexts,\n```py\n return (\n depth_one\n and depth_two\n and name_check(node.func, \"xyz\")\n and len(node.args)== 2\n )\n```\nwe are ready to return a value. If the value is `True`, `Inspector` will put this investigaton code to report. If it's `False`, then inspector will pass.\n\n\nLast thing we need to do is to activate our plugin by creating/modifiying the `~/.inspector.rc` file;\n```json\n{\n ...\n \"plugins\": {\n \"\": [\"\", \"\", \"\", \"\"],\n \"xyzintro\": [\"handlers\"]\n }\n ...\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": "https://github.com/thg-consulting/inspectortiger", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "inspectortiger", "package_url": "https://pypi.org/project/inspectortiger/", "platform": "", "project_url": "https://pypi.org/project/inspectortiger/", "project_urls": { "Homepage": "https://github.com/thg-consulting/inspectortiger" }, "release_url": "https://pypi.org/project/inspectortiger/0.7.0/", "requires_dist": null, "requires_python": "", "summary": "Modern python code review tool / framework", "version": "0.7.0" }, "last_serial": 5955852, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "d5c62a4002f1311410ce427d937d7614", "sha256": "a69485922e67d7558aeef265628a88256b3359e26e7b19607f4c8352e22cf81b" }, "downloads": -1, "filename": "inspectortiger-0.1.0.tar.gz", "has_sig": false, "md5_digest": "d5c62a4002f1311410ce427d937d7614", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2745, "upload_time": "2019-08-04T12:50:41", "url": "https://files.pythonhosted.org/packages/68/de/8a86af5b306e7af16105b184bcef052022a9fa562bbc223a6ba91553c342/inspectortiger-0.1.0.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "ff02c6ba9c3c2a0ea8ceff8922dc4366", "sha256": "9a15b390fea26af00fcbfdbbc0135a2d26d9d19b02794ffe340eb79baff50900" }, "downloads": -1, "filename": "inspectortiger-0.2.0.tar.gz", "has_sig": false, "md5_digest": "ff02c6ba9c3c2a0ea8ceff8922dc4366", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3094, "upload_time": "2019-08-05T09:37:41", "url": "https://files.pythonhosted.org/packages/0f/a4/c9d0d1f725f92d2698217914a6cbce58289b5d8fdad5cbe4d4a6e11ebed9/inspectortiger-0.2.0.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "06c0368693602a398f3dcdb147a18e4b", "sha256": "979a16ad772e7345fd196a625cb3469a0cba8ed899935e30336e9a901f9378f4" }, "downloads": -1, "filename": "inspectortiger-0.3.0.tar.gz", "has_sig": false, "md5_digest": "06c0368693602a398f3dcdb147a18e4b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3293, "upload_time": "2019-08-05T10:49:10", "url": "https://files.pythonhosted.org/packages/8a/3b/352e30744f9ea93366e797428341d33788eb07e63bf58c82953233ab0a57/inspectortiger-0.3.0.tar.gz" } ], "0.3.1": [ { "comment_text": "", "digests": { "md5": "0c89ae2daf3029857dc006c6644ba55d", "sha256": "e54faecd9cb73e0acea7efb3771806af6c2312c63ca77b5553ecd355d3ba5552" }, "downloads": -1, "filename": "inspectortiger-0.3.1.tar.gz", "has_sig": false, "md5_digest": "0c89ae2daf3029857dc006c6644ba55d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3897, "upload_time": "2019-08-06T09:20:00", "url": "https://files.pythonhosted.org/packages/e0/34/30a559adad2fbd4ad3d1698acdcad7b5147bb29696dcae6da3d239a073b1/inspectortiger-0.3.1.tar.gz" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "472e3bba9176e039dafd4db0fa037ffb", "sha256": "76ab567bc0675eb40b816b41b96ca3d1dc462029306fd0360ba4005c695471fd" }, "downloads": -1, "filename": "inspectortiger-0.4.0.tar.gz", "has_sig": false, "md5_digest": "472e3bba9176e039dafd4db0fa037ffb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4117, "upload_time": "2019-09-22T15:46:49", "url": "https://files.pythonhosted.org/packages/c5/84/e05c1497e1cc5133be905fe718afbdf586b87a4cf8cff40408b6b14ebeff/inspectortiger-0.4.0.tar.gz" } ], "0.4.5": [ { "comment_text": "", "digests": { "md5": "35b4771081dacacdb776a0b239a955e2", "sha256": "a36bd86ee2366ddb5064eb59a1a3d055625ec325af2c80b1d78f9bd8ea4096bb" }, "downloads": -1, "filename": "inspectortiger-0.4.5.tar.gz", "has_sig": false, "md5_digest": "35b4771081dacacdb776a0b239a955e2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6460, "upload_time": "2019-09-23T15:13:57", "url": "https://files.pythonhosted.org/packages/60/b5/6a3e8fd2117795c075adf5033f4dd8a6801aab68aeca4a7713d508ef6f41/inspectortiger-0.4.5.tar.gz" } ], "0.5.0": [ { "comment_text": "", "digests": { "md5": "ec10d838922d40a63c23c629f372d254", "sha256": "7636e148ca9fbcbbcb836962cb18524a099ada2e62afae154dbe866383f6f91a" }, "downloads": -1, "filename": "inspectortiger-0.5.0.tar.gz", "has_sig": false, "md5_digest": "ec10d838922d40a63c23c629f372d254", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9471, "upload_time": "2019-09-26T17:54:53", "url": "https://files.pythonhosted.org/packages/2c/55/4e2b91ee32a9190a6a15bef3c594ad8378438ed5314a03b4e13456f0a12b/inspectortiger-0.5.0.tar.gz" } ], "0.6.0": [ { "comment_text": "", "digests": { "md5": "7d6507655992dd172981dcf059a7e52e", "sha256": "cea392594f82a190158eb6660f4064f0ad5563a3f973e8ccb58e5896a4cf5ed2" }, "downloads": -1, "filename": "inspectortiger-0.6.0.tar.gz", "has_sig": false, "md5_digest": "7d6507655992dd172981dcf059a7e52e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10255, "upload_time": "2019-10-02T17:13:08", "url": "https://files.pythonhosted.org/packages/56/52/8416c18fb991970fa08f4fa6bcaa86dda80568b8336ded51c7c5c54cd811/inspectortiger-0.6.0.tar.gz" } ], "0.6.1": [ { "comment_text": "", "digests": { "md5": "c57aa1c39809ba63311b1b0c9d5be7e0", "sha256": "0b7ac2556811038d026e2d33134f371e14521e3c4ce28e580238c78c32805e59" }, "downloads": -1, "filename": "inspectortiger-0.6.1.tar.gz", "has_sig": false, "md5_digest": "c57aa1c39809ba63311b1b0c9d5be7e0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10206, "upload_time": "2019-10-02T17:41:12", "url": "https://files.pythonhosted.org/packages/d6/46/c11e9b1f163124f012f0ecfefda9b8889abf18d0c307f9fb28b9f852c085/inspectortiger-0.6.1.tar.gz" } ], "0.7.0": [ { "comment_text": "", "digests": { "md5": "a608e9207b5602a5d5ef1e4a210f10f4", "sha256": "f64c5350fbc0ce0bd70db09f4a3be11444d9dc96ec2afc144d6339d9bc84e8e0" }, "downloads": -1, "filename": "inspectortiger-0.7.0.tar.gz", "has_sig": false, "md5_digest": "a608e9207b5602a5d5ef1e4a210f10f4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14985, "upload_time": "2019-10-10T16:35:43", "url": "https://files.pythonhosted.org/packages/9d/e9/ccd8ed2c219367cbda11c29526ca46b2ed90b260e508a6dbe2a142d93278/inspectortiger-0.7.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "a608e9207b5602a5d5ef1e4a210f10f4", "sha256": "f64c5350fbc0ce0bd70db09f4a3be11444d9dc96ec2afc144d6339d9bc84e8e0" }, "downloads": -1, "filename": "inspectortiger-0.7.0.tar.gz", "has_sig": false, "md5_digest": "a608e9207b5602a5d5ef1e4a210f10f4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14985, "upload_time": "2019-10-10T16:35:43", "url": "https://files.pythonhosted.org/packages/9d/e9/ccd8ed2c219367cbda11c29526ca46b2ed90b260e508a6dbe2a142d93278/inspectortiger-0.7.0.tar.gz" } ] }