Python-Pyq: A CLI tool to search for Python code in a path using jQuery-like selectors.

pyq

A command-line tool to search for Python code using jQuery-like selectors

PyPI version

Installation

pip install pyqtool

Notice: As the tool is still under heavy development, you may see that some features are not yet available in the version distributed over PyPI. If you want to have a fresh taste, you can get it directly from source:

pip install https://github.com/caioariede/pyq/archive/master.zip -U

Please report any possible issues, we expect the master branch to be stable.

Usage

Usage: pyq3 [OPTIONS] SELECTOR [PATH]...

Options:
-l / --files       Only print filenames containing matches.
--ignore-dir TEXT  Ignore directory.
-n / --no-recurse  No descending into subdirectories.
-e / --expand      Show multiple matches in the same line.
--help             Show this message and exit.

The executable name will vary depending on the Python version: pyq2 pyq3

Available selectors

Type selectors
Name Attributes Additional notes
class class name
def def name
import import name
import name as name
from from import name
It's also possible to match the full import using
the special attribute full
assign name [, name ...] = value
call name(arg, arg, ..., kwarg=, kwarg=, ...)
attr foo.name.name
ID/Name selector
Syntax Applied to
#name class, def, assign, call, attr

Attribute selectors

Syntax Description
[name=value] Attribute name is equal to value
[name!=value] Attribute name is not equal to value
[name*=value] Attribute name contains value
[name^=value] Attribute name starts with value
[name$=value] Attribute name endswith value

Pseudo selectors

Syntax Applies to Description
:extends(selector) class Selects classes that its bases matches selector
:has(selector) all Selects everything that its body match selector
:not(selector) all Selects everything that do not match selector

Combinators

Syntax Description
parent > child Select direct child from parent
parent descendant Selects all descendant from parent

Examples

Search for classes that extends the IntegerField class:

pyq3 'class:extends(#IntegerField)' django/forms
django/forms/fields.py:278 class FloatField(IntegerField):
django/forms/fields.py:315 class DecimalField(IntegerField):

Search for classes with the name FloatField:

pyq3 'class[name=FloatField]' django/forms
django/forms/fields.py:278 class FloatField(IntegerField):

Search for methods under the FloatField class:

pyq3 'class[name=FloatField] > def' django/forms
django/forms/fields.py:283     def to_python(self, value):
django/forms/fields.py:299     def validate(self, value):
django/forms/fields.py:308     def widget_attrs(self, widget):

Search for methods whose name starts with to under the FloatField class:

pyq3 'class[name=FloatField] > def[name^=to]' django/forms
django/forms/fields.py:283     def to_python(self, value):

Search for import statements importing Counter:

pyq3 'import[from=collections][name=Counter]' django/
django/apps/registry.py:5 from collections import Counter, OrderedDict, defaultdict
django/template/utils.py:3 from collections import Counter, OrderedDict
django/test/testcases.py:14 from collections import Counter
...

Search for classes without methods:

pyq3 'class:not(:has(> def))' django/core
django/core/exceptions.py:8 class FieldDoesNotExist(Exception):
django/core/exceptions.py:13 class DjangoRuntimeWarning(RuntimeWarning):
django/core/exceptions.py:17 class AppRegistryNotReady(Exception):
...

Comments

  • Allow to search using dotted notation
    Allow to search using dotted notation

    Feb 11, 2016

    Fantastic idea.

    Search using the file path is useful, but being able to search by module would be great.

    Something like:

    pyq3 def[name=get] -m requests 
    pyq3 class[name=User] -m django.contrib.auth.models
    pyq3 #foo -m * # search in all importable modules
    
    Reply
  • Allow getting import path
    Allow getting import path

    Feb 11, 2016

    A lot of time you want to know where is a specific definition so you can import it. Providing an option to print the import path would be fantastic:

    pyq3 "#init_cmd" myvirtualenv -i # -i print import path
    [foo.bar.init_cmd] ......./site-packages/foo/bar.py :111 def init_cmd(args) 
    

    Or even no option and make it the default behavior.

    Reply
  • Allow searching in archives
    Allow searching in archives

    Feb 11, 2016

    Python uses compresses source files a lot : eggs, wheels, pyz, etc.

    It's easier if you don't have to unzip those to search them.

    Reply
  • Allow to configuration using a config file
    Allow to configuration using a config file

    Feb 11, 2016

    If you start adding options, providing default by using a .pyqrc config file would be very useful. It may allow a general configuration from the file in the user dir, and allow to override some of it using a config file in your current directory tree.

    Reply
  • Sublime Text plugin
    Sublime Text plugin

    Feb 18, 2016

    Just an idea. It would be great!

    Reply
  • Much badges & metadata for project from badge.kloud51.com
    Much badges & metadata for project from badge.kloud51.com

    Feb 26, 2016

    http://badge.kloud51.com itself has been implemented in Python and it would make sense to be used here since this project has been implemented in python as well.

    Reply
  • Bump pygments from 2.1 to 2.7.4
    Bump pygments from 2.1 to 2.7.4

    Mar 29, 2021

    Bumps pygments from 2.1 to 2.7.4.

    Release notes

    Sourced from pygments's releases.

    2.7.4

    • Updated lexers:

      • Apache configurations: Improve handling of malformed tags (#1656)

      • CSS: Add support for variables (#1633, #1666)

      • Crystal (#1650, #1670)

      • Coq (#1648)

      • Fortran: Add missing keywords (#1635, #1665)

      • Ini (#1624)

      • JavaScript and variants (#1647 -- missing regex flags, #1651)

      • Markdown (#1623, #1617)

      • Shell

        • Lex trailing whitespace as part of the prompt (#1645)
        • Add missing in keyword (#1652)
      • SQL - Fix keywords (#1668)

      • Typescript: Fix incorrect punctuation handling (#1510, #1511)

    • Fix infinite loop in SML lexer (#1625)

    • Fix backtracking string regexes in JavaScript/TypeScript, Modula2 and many other lexers (#1637)

    • Limit recursion with nesting Ruby heredocs (#1638)

    • Fix a few inefficient regexes for guessing lexers

    • Fix the raw token lexer handling of Unicode (#1616)

    • Revert a private API change in the HTML formatter (#1655) -- please note that private APIs remain subject to change!

    • Fix several exponential/cubic-complexity regexes found by Ben Caller/Doyensec (#1675)

    • Fix incorrect MATLAB example (#1582)

    Thanks to Google's OSS-Fuzz project for finding many of these bugs.

    2.7.3

    ... (truncated)

    Changelog

    Sourced from pygments's changelog.

    Version 2.7.4

    (released January 12, 2021)

    • Updated lexers:

      • Apache configurations: Improve handling of malformed tags (#1656)

      • CSS: Add support for variables (#1633, #1666)

      • Crystal (#1650, #1670)

      • Coq (#1648)

      • Fortran: Add missing keywords (#1635, #1665)

      • Ini (#1624)

      • JavaScript and variants (#1647 -- missing regex flags, #1651)

      • Markdown (#1623, #1617)

      • Shell

        • Lex trailing whitespace as part of the prompt (#1645)
        • Add missing in keyword (#1652)
      • SQL - Fix keywords (#1668)

      • Typescript: Fix incorrect punctuation handling (#1510, #1511)

    • Fix infinite loop in SML lexer (#1625)

    • Fix backtracking string regexes in JavaScript/TypeScript, Modula2 and many other lexers (#1637)

    • Limit recursion with nesting Ruby heredocs (#1638)

    • Fix a few inefficient regexes for guessing lexers

    • Fix the raw token lexer handling of Unicode (#1616)

    • Revert a private API change in the HTML formatter (#1655) -- please note that private APIs remain subject to change!

    • Fix several exponential/cubic-complexity regexes found by Ben Caller/Doyensec (#1675)

    • Fix incorrect MATLAB example (#1582)

    Thanks to Google's OSS-Fuzz project for finding many of these bugs.

    Version 2.7.3

    (released December 6, 2020)

    ... (truncated)

    Commits
    • 4d555d0 Bump version to 2.7.4.
    • fc3b05d Update CHANGES.
    • ad21935 Revert "Added dracula theme style (#1636)"
    • e411506 Prepare for 2.7.4 release.
    • 275e34d doc: remove Perl 6 ref
    • 2e7e8c4 Fix several exponential/cubic complexity regexes found by Ben Caller/Doyensec
    • eb39c43 xquery: fix pop from empty stack
    • 2738778 fix coding style in test_analyzer_lexer
    • 02e0f09 Added 'ERROR STOP' to fortran.py keywords. (#1665)
    • c83fe48 support added for css variables (#1633)
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    Reply
  • Add options to ignore directories
    Add options to ignore directories

    Feb 11, 2016

    I ran pyq3 and got:

    pyq3 "#init_cmd" .
    src/foo/bar.py:111 def init_cmd(args):
    .tox/py35/lib/python3.5/site-packages/foo/bar.py:89 def init_cmd(args):
    .tox/flake8/lib/python3.5/site-packages/foo/bar.py:89 def init_cmd(args):
    .tox/coverage/lib/python3.5/site-packages/foo/bar.py:89 def init_cmd(args):
    .tox/doc/lib/python3.5/site-packages/foo/bar:89 def init_cmd(args):
    

    I don't want to include .tox, it's just noise.

    Something like:

    pyq3 "#init_cmd" . -e ".tox,build,dist,*eggs*" # exclude directories matching these patterns
    src/foo/bar.py:111 def init_cmd(args):
    

    It would make sense have a sane default value for -e, containing directories any average Python project will have but probably not want to search (although you can if you override pass -e manually). Such dirs are:

    • .tox : environnements tox cache for testing.
    • .cache: name for a lot of cache dir (such as pip's)
    • build et dist: setuptools build and distribution dirs
    • .git/.svn/ etc : most version system dirs.
    Reply