Wxc
wxc is a command line tool to query source code from the environment. wxc is said as which. wxc serves similar purpose as man pages but for python source code.
Example usages
$poetry run wxc django.db.models.Q
/Users/user/Library/Caches/pypoetry/virtualenvs/code-census-Ypc4NYco-py3.9/lib
/python3.9/site-packages/django/db/models/query_utils.py:57
$poetry run wxc django.db.models.Q --help
usage: wxc [-h] [-v | -f] [-s] [--lines] name
positional arguments:
name target Python scope (package.module.submodule.class.method)
optional arguments:
-h, --help show this help message and exit
-v, --version print module version
-f, --full print a full report
-s, --source print the source code
--lines show source lines
Get the report of the name by passing the -f
flag.
$prun wxc django.db.models.Q -f
source =
/Users/user/Library/Caches/pypoetry/virtualenvs/code-census-Ypc4NYco-py3.9/lib
/python3.9/site-packages/django/db/models/query_utils.py:57
in_stdlib = False
name = django.db.models.Q
version = 3.2.7
Display the source code
$poetry run wxc django.db.models.Q --source
class Q(tree.Node):
"""
Encapsulate filters as objects that can then be combined logically (using
`&` and `|`).
"""
# Connection types
AND = 'AND'
OR = 'OR'
default = AND
conditional = True
def __init__(self, *args, _connector=None, _negated=False, **kwargs):
super().__init__(children=[*args, *sorted(kwargs.items())],
connector=_connector, negated=_negated)
def _combine(self, other, conn):
if not(isinstance(other, Q) or getattr(other, 'conditional', False) is True):
raise TypeError(other)
if not self:
return other.copy() if hasattr(other, 'copy') else copy.copy(other)
elif isinstance(other, Q) and not other:
_, args, kwargs = self.deconstruct()
return type(self)(*args, **kwargs)
obj = type(self)()
obj.connector = conn
obj.add(self, conn)
obj.add(other, conn)
return obj
def __or__(self, other):
return self._combine(other, self.OR)
def __and__(self, other):
return self._combine(other, self.AND)
def __invert__(self):
obj = type(self)()
obj.add(self, self.AND)
obj.negate()
return obj
def resolve_expression(self, query=None, allow_joins=True, reuse=None,
summarize=False, for_save=False):
# We must promote any new joins to left outer joins so that when Q is
# used as an expression, rows aren't filtered due to joins.
clause, joins = query._add_q(
self, reuse, allow_joins=allow_joins, split_subq=False,
check_filterable=False,
)
query.promote_joins(joins)
return clause
def deconstruct(self):
path = '%s.%s' % (self.__class__.__module__, self.__class__.__name__)
if path.startswith('django.db.models.query_utils'):
path = path.replace('django.db.models.query_utils',
'django.db.models')
args = tuple(self.children)
kwargs = {}
if self.connector != self.default:
kwargs['_connector'] = self.connector
if self.negated:
kwargs['_negated'] = True
return path, args, kwargs
/Users/user/Library/Caches/pypoetry/virtualenvs/code-census-Ypc4NYco-py3.9/lib
/python3.9/site-packages/django/db/models/query_utils.py:57
wxc works for the non-installed Python code as well. Here is example from the cli.py
$tail code_census/cli.py
def create_db(db_url: str):
engine = create_engine(db_url, echo=True)
cfg = Config("alembic.ini")
with engine.begin() as connection:
cfg.attributes["connection"] = connection
command.upgrade(cfg, "head", sql=True)
if __name__ == "__main__":
cli()
$poetry run wxc code_census.cli.create_db --source
@click.option(
"--db-url", type=str, required=True, envvar="DB_URL", help=HELP_TEXT["db_url"]
)
def create_db(db_url: str):
engine = create_engine(db_url, echo=True)
cfg = Config("alembic.ini")
with engine.begin() as connection:
cfg.attributes["connection"] = connection
command.upgrade(cfg, "head", sql=True)
/Users/user/code/personal/code_census/code_census/cli.py:197
When wxc doesn’t work?
-
Django project in a repository. Django expects to load the settings and app configs to load first. Hence, it doesn’t work.
$PYTHONPATH="." poetry run wxc customer.service.get_active_customers ... File "/Users/user/Library/Caches/pypoetry/virtualenvs/code-census-Ypc4NYco-py3.9/lib/python3.9/site-packages/django/apps/registry.py", line 136, in check_apps_ready raise AppRegistryNotReady("Apps aren't loaded yet.") django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
-
Compiled python source code and builtin object.
$ poetry run wxc print --source ERROR failed to locate source data. 'print' is a builtin object. $poetry run wxc os.listdir --source ERROR failed to locate source data. 'os.listdir' is a C-compiled function.