Python: Make line number paths with inspect

Some kind of inspection device.

Many terminals and text editors support what I’ll call “line number paths” of the form <filename>:<lineno>. Opening that path, whether by clicking or passing to a CLI, opens the given file at that line.

Python’s inspect module has a couple of functions that can be combined to make such paths, for a given class or function. Here’s the recipe:

from inspect import getsourcefile, getsourcelines

print(f"{getsourcefile(obj)}:{getsourcelines(obj)[1]}")

getsourcefile() returns the file the object is defined in. getsourcelines() returns a tuple, containing the list of source code lines and the first line number, hence the [1] to select just the line number.

For example, to make a path for a function in Django:

In [1]: from django.utils.html import format_html

In [2]: from inspect import getsourcefile, getsourcelines
   ...: print(f"{getsourcefile(obj)}:{getsourcelines(obj)[1]}")
/.../.venv/site-packages/django/utils/html.py:95

I have found this recipe handy a couple of times for batch edits. For example, I recently upgraded django-import-export on a project. Due to an upstream change, I needed to check every subclass of django-import-export’s ModelResource class in the project. I could have searched the code for all such classes, but that can be complicated due to inheritance. Instead, I used class.__subclasses__() to find all subclasses and made “line number paths” for each:

In [1]: from inspect import getsourcefile, getsourcelines

In [2]: from import_export.resources import ModelResource

In [3]: for cls in ModelResource.__subclasses__():
   ...:     init = cls.__init__
   ...:     if init is not ModelResource.__init__:
   ...:         print(f"{getsourcefile(init)}:{getsourcelines(init)[1]}")
   ...:
/.../example/apples/resources.py:1136
/.../example/apples/resources.py:1239
/.../example/bananas/resources.py:351
/.../example/bananas/resources.py:502
/.../example/bananas/resources.py:1874
/.../example/cherries/resources.py:297
...

I was then free to edit each link in turn.

Fin

May you find more creative ways to use Python’s inspection features,

—Adam


Learn how to make your tests run quickly in my book Speed Up Your Django Tests.


Subscribe via RSS, Twitter, Mastodon, or email:

One summary email a week, no spam, I pinky promise.

Related posts:

Tags: ,