pdb and pdbpp aliases and configs
~/.pdbrc gets read by both of them, and can import stuff and use aliases!
# ! makes it python code to be executed
!import rich
alias I rich.inspect(%1)
# # alternative if not !importing it above in one command
alias P !import rich; rich.print(%1)
print("Custom commands:")
print("\t I $thing — rich inspect $thing")
print("\t P $thing — rich pretty print $thing")
EDIT: the above works only if rich is already imported.
Better pretty printing
The above doesn’t do comprehensions well (+ needs imported rich in the running thing).
> [x for x in [2,4,5]]
[2, 4, 5]
> P [x for x in [2,4,5]]
*** SyntaxError: closing parenthesis ')' does not match opening parenthesis '['
Looking at:
- Sample pdbrc: pdbpp/pdbrc.py at master · pdbpp/pdbpp
- Pdbpp source: pdbpp/src/pdbpp.py at master · pdbpp/pdbpp
- Pdb source’s
self._getval(): https://github.com/python/cpython/blob/3.14/Lib/pdb.py#L2080
Instead of doing alias ... which uses %1 which fails, we can use pdbpp’s pdb’s _getval() fn which does this in a smarter way.
THEN, in our ~/.pdbrc.py (NOT ~/.pdbrc!), adapting the code for pdbpp’s do_pp():
import pdb
import rich
import os, sys, traceback
class Config(pdb.DefaultConfig):
def setup(self, pdb):
Pdb = pdb.__class__
# "do_xxx" methods automagically get parsed into commands
# make 'l' an alias to 'longlist' -> existing method
Pdb.do_l = Pdb.do_longlist
# new methods
Pdb.do_P = _do_P
# defining a method with self outside a class feels so _wrong_...
def _do_P(self, arg):
try:
val = self._getval(arg)
except:
return
try:
rich.print(val)
except:
exc_info = sys.exc_info()[:2]
self.error(traceback.format_exception_only(*exc_info)[-1].strip())
# [x for x in [2,4,5]]
Then it works!
Even better:
import pdb
import os, sys, traceback
from pprint import pprint
try:
# from rich import print as rprint
from rich import inspect
from rich.pretty import pprint
except ImportError:
print("rich is not available, falling back to pprint")
pass
class Config(pdb.DefaultConfig):
prompt = "> "
sticky_by_default = True
def setup(self, pdb):
Pdb = pdb.__class__
Pdb.do_P = _do_P
Pdb.do_I = _do_I
def do_with_arg(self, arg, func):
try:
val = self._getval(arg)
except:
return
try:
func(val)
except:
exc_info = sys.exc_info()[:2]
self.error(traceback.format_exception_only(*exc_info)[-1].strip())
def _do_P(self, arg):
do_with_arg(self, arg, pprint)
def _do_I(self, arg):
try:
do_with_arg(self, arg, inspect)
except NameError:
print("rich is not available, falling back to pprint")
do_with_arg(self, arg, pprint)
Nel mezzo del deserto posso dire tutto quello che voglio.
comments powered by Disqus