{"id":13501663,"url":"https://github.com/hchasestevens/astpath","last_synced_at":"2025-04-04T13:09:17.617Z","repository":{"id":12739966,"uuid":"72683933","full_name":"hchasestevens/astpath","owner":"hchasestevens","description":"A command-line search utility for Python ASTs using XPath syntax.","archived":false,"fork":false,"pushed_at":"2022-04-20T07:45:37.000Z","size":37,"stargazers_count":240,"open_issues_count":14,"forks_count":56,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-05-22T14:32:33.737Z","etag":null,"topics":["ast","command-line-tool","metaprogramming","python","python-ast","search","xpath","xpath-syntax"],"latest_commit_sha":null,"homepage":"https://pypi.python.org/pypi/astpath","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hchasestevens.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-11-02T21:43:14.000Z","updated_at":"2024-05-12T13:05:42.000Z","dependencies_parsed_at":"2022-08-07T07:00:41.279Z","dependency_job_id":null,"html_url":"https://github.com/hchasestevens/astpath","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hchasestevens%2Fastpath","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hchasestevens%2Fastpath/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hchasestevens%2Fastpath/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hchasestevens%2Fastpath/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hchasestevens","download_url":"https://codeload.github.com/hchasestevens/astpath/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247181641,"owners_count":20897370,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ast","command-line-tool","metaprogramming","python","python-ast","search","xpath","xpath-syntax"],"created_at":"2024-07-31T22:01:45.364Z","updated_at":"2025-04-04T13:09:17.598Z","avatar_url":"https://github.com/hchasestevens.png","language":"Python","funding_links":[],"categories":["Python","Tools"],"sub_categories":[],"readme":"# astpath\n[![PyPI version](https://badge.fury.io/py/astpath.svg)](https://badge.fury.io/py/astpath)\n\n[e ɛs ti pæθ] _n_.\n\nⅠ. A command-line utility for querying Python ASTs using XPath syntax.\n\nⅠⅠ. A better way of searching through your codebase.\n\n## Example usage\n_Finding all usages of the_ `eval` _builtin:_\n```bash\n$ astpath \".//Call/func/Name[@id='eval']\" | head -5\n./rlcompleter.py:136    \u003e            thisobject = eval(expr, self.namespace)\n./warnings.py:176       \u003e            cat = eval(category)\n./rexec.py:328  \u003e        return eval(code, m.__dict__)\n./pdb.py:387    \u003e                    func = eval(arg,\n./pdb.py:760    \u003e            return eval(arg, self.curframe.f_globals,\n```\n\n_Finding all numbers:_\n```bash\n$ astpath \".//Num\" | head -5\n./DocXMLRPCServer.py:31 \u003e        here = 0\n./DocXMLRPCServer.py:41 \u003e        while 1:\n./DocXMLRPCServer.py:57 \u003e            elif text[end:end+1] == '(':\n./DocXMLRPCServer.py:82 \u003e                    args[1:],\n./DocXMLRPCServer.py:96 \u003e            argspec = object[0] or argspec\n```\n\n_... that are never assigned to a variable:_\n```bash\n$ astpath \".//Num[not(ancestor::Assign)]\" | head -5\n./DocXMLRPCServer.py:41 \u003e        while 1:\n./DocXMLRPCServer.py:57 \u003e            elif text[end:end+1] == '(':\n./DocXMLRPCServer.py:201        \u003e                assert 0, \"Could not find method in self.functions and no \"\\\n./DocXMLRPCServer.py:237        \u003e        self.send_response(200)\n./DocXMLRPCServer.py:252        \u003e                 logRequests=1, allow_none=False, encoding=None,\n```\n\n_... and are greater than 1000:_\n```bash\n$ astpath \".//Num[not(ancestor::Assign) and number(@n) \u003e 1000]\" | head -5\n./decimal.py:959      \u003e                    return 314159\n./fractions.py:206    \u003e    def limit_denominator(self, max_denominator=1000000):\n./pty.py:138  \u003e    return os.read(fd, 1024)\n./whichdb.py:94       \u003e    if magic in (0x13579ace, 0x13579acd, 0x13579acf):\n./whichdb.py:94       \u003e    if magic in (0x13579ace, 0x13579acd, 0x13579acf):\n```\n\n_Finding names longer than 42 characters:_\n```bash\n$ astpath \"//Name[string-length(@id) \u003e 42]\"\n./site-packages/setuptools/dist.py:59   \u003e_patch_distribution_metadata_write_pkg_info()\n./site-packages/setuptools/command/easy_install.py:1759 \u003e        updater=clear_and_remove_cached_zip_archive_directory_data)\n./test/test_reprlib.py:268      \u003e        module = areallylongpackageandmodulenametotestreprtruncation\n./test/test_argparse.py:2744    \u003e    MEPBase, TestMutuallyExclusiveOptionalsAndPositionalsMixed):\n```\n\n_Finding_ `except` _clauses that raise a different exception class than they catch:_\n```bash\n$ astpath \"//ExceptHandler[body//Raise/exc//Name and not(contains(body//Raise/exc//Name/@id, type/Name/@id))]\" | head -5\n./hashlib.py:144        \u003eexcept ImportError:\n./plistlib.py:89        \u003e        except KeyError:\n./plistlib.py:103       \u003e        except KeyError:\n./nntplib.py:868        \u003e        except ValueError:\n./argparse.py:1116      \u003e        except KeyError:\n```\n\n_Finding beginnings of unreachable code blocks:_\n```bash\n$ astpath \"//body/*[preceding-sibling::Return or preceding-sibling::Raise][1]\"\n./unittest/test/testmock/testhelpers.py:381     \u003e        class Foo(object):\n./test/test_deque.py:16 \u003e    yield 1\n./test/test_posix.py:728        \u003e            def _create_and_do_getcwd(dirname, current_path_length = 0):\n```\n\n_Finding candidates for replacement with_ `sum`_:_\n```bash\n$ astpath -A 1 \"//For/body[AugAssign/op/Add and count(child::*)=1]\" | head -6\n./functools.py:374      \u003e        for item in sorted_items:\n./functools.py:375                   key += item\n./statistics.py:177     \u003e    for d, n in sorted(partials.items()):\n./statistics.py:178              total += Fraction(n, d)\n./pstats.py:512 \u003e    for calls in callers.values():\n./pstats.py:513          nc += calls\n```\n\n_Finding classes matching a regular expression:_\n```bash\n$ astpath \"//ClassDef[re:match('.*Var', @name)]\" | head -5\n./typing.py:452  \u003e      class TypeVar(_TypingBase, _root=True):\n./typing.py:1366 \u003e      class _ClassVar(_FinalTypingBase, _root=True):\n./tkinter/__init__.py:287  \u003e    class Variable:\n./tkinter/__init__.py:463  \u003e    class StringVar(Variable):\n./tkinter/__init__.py:485  \u003e    class IntVar(Variable):\n```\n\n`astpath` can also be imported and used programmatically:\n```python\n\u003e\u003e\u003e from astpath import search\n\u003e\u003e\u003e len(search('.', '//Print', print_matches=False))  # number of print statements in the codebase\n751\n```\n\n## Installation\nIt is recommended that `astpath` be installed with the optional `lxml` dependency, to allow full use of the XPath query language. \nTo do so,\n```\npip install astpath[xpath]\n```\n\nAlternatively, a no-dependency version using Python's builtin XPath subset can be installed via\n```\npip install astpath\n```\n\n`astpath` supports both Python 2.7 and 3.x.\n\n## Links\n* [Green tree snakes](https://greentreesnakes.readthedocs.io/en/latest/) - a very readable overview of Python ASTs.\n* Official `ast` module documentation for [Python 2.7](https://docs.python.org/2.7/library/ast.html) and [Python 3.X](https://docs.python.org/3/library/ast.html).\n* [Python AST Explorer](https://python-ast-explorer.com/) for worked examples of ASTs.\n* A [brief guide to XPath](http://www.w3schools.com/xml/xpath_syntax.asp).\n* [`bellybutton`](https://github.com/hchasestevens/bellybutton), a fully-featured linting engine built on `astpath`.\n\n## Contacts\n\n* Name: [H. Chase Stevens](http://www.chasestevens.com)\n* Twitter: [@hchasestevens](https://twitter.com/hchasestevens)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhchasestevens%2Fastpath","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhchasestevens%2Fastpath","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhchasestevens%2Fastpath/lists"}