I'm also really appreciating the base64 exec hack. All my years in Python I never thought of or came across it until now. I'll totally be using it for some things :).
[0] https://github.com/gabrielcnr/python-ls [1] https://pypi.org/project/snoop/
Surprised there isn't more innovation and new tools like this around python's interactive shell given it's one of the real strong points the language has.
In [1]: int?
Init signature: int(self, /, *args, **kwargs)
Docstring:
int([x]) -> integer
int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments
are given. If x is a number, return x.__int__(). For floating point
numbers, this truncates towards zero.
[...]
1. Write the program skeleton
2. Put an import pdb; pdb.set_trace() whereever I need to fill out next
3. Once I hit the breakpoint, type 'interact'
4. Start coding in the debugger.
4a. For small functions write in a scratch pad, test against another python console, then paste into the current debugger.
4b. For network calls, save the inputs and outputs. Toss a decorator on some functions to log the inputs and outputs to files, and cool we already have some proto test data.
4c. For documentation, call help() on the variable or method or module.
If you never heard about it, scroll to the bottom to https://github.com/gruns/icecream#icecream-in-other-language...
Twenty years ago I wrote an object introspector for Zope ;)
Nowadays, I'm using devtools daily, and icecream and q occasionally. I'll give wat a try.
Given the cool nature of this project, I'm surprised they don't offer simply "import wat" with identical usage syntax. Thus inviting curious users to wat/wat in order to discover the trick...
Edit: Oh, you don't mean in the importing module's globals, you mean `sys.modules`. Yeah that works!
why do you say it's wonky? it's just
sys.modules[__name__] = wat
According to the official python documentation [0] of sys.modules:> This is a dictionary that maps module names to modules which have already been loaded. This can be manipulated to force reloading of modules and other tricks.
Thus, the modules dictionary is being used as intended, and it has the desired effect. Nothing wonky about that.
Of course, a __call__ method would be better because you could still keep the other functions inside the module. But for a single-function import like "wat" it seems quite natural and sane.
import sys
def wat(): print("wat")
def bar(): print("bar")
wat.wat = wat
wat.bar = bar
sys.modules[__name__] = wat
... >>> import wat
>>> wat()
wat
>>> from wat import bar
>>> bar()
bar
Edit: I think a better way would be to instead add __call__ to the current module somehow though. try:
from wat import wat
except ImportError:
pass
to your $PYTHONSTARTUP file to avoid the cumbersome import.But I eventually printed that output, and put it in a dir I point my PYTHONPATH to so that I will always have it available.
Let's see if it sticks.
Instead I just installed pry and became a rabid ruby fanboy, but this might get me to give it another go.
see inspection.py in the wat module.
it has this on line 2:
import inspect as std_inspect
> Load it on the fly by pasting this snippet to your Python interpreter
The idea of having a project's readme include a full copy of the project itself as base64'd compressed data is pretty ingenious!
especially for a project like this where you may not have had the foresight to preload it into the environment where you most need it
--
1: https://github.com/Textualize/rich?tab=readme-ov-file#rich-p...
Doesn't the repr() built-in function do what you want?
It can also be customized by defining the __repr__() method of a class, IIRC.
Commonly done.
Read about repr() here:
https://docs.python.org/3/library/functions.html
and dunder repr, i.e. __repr__() here:
https://docs.python.org/3/reference/datamodel.html#object.__...
For node you it’s possible to hook it up with the browser inspector as well
Hooking devtools with Node is possible but could be a lot nicer.
I mean the number of times I've bumped on json not being able to dump the content of an object is just infuriating given how flexible Python is.
I'm definitely giving this a whirl.
Somthing like that does exist, and has, from Python 2.x; the inspect module, apart from help() and dir():
It is somewhat lower-level than wat, which builds upon it. But it is powerful.
https://news.ycombinator.com/item?id=41072878
Or did you mean the inspect module itself?
Please don't do this. Exec'ing arbitrary, obfuscated code you just copied from the internet directly in a running environment is such a bad idea it shouldn't even be suggested.
At the very lease please put huge warnings around this section to let people know that it is a horrendously bad idea and they do it at their own peril.
That idea of exec'ing arbitrary obfuscated (compressed) shell code that's easy to copy-paste into a python shell is very helpful, mind.
I've had to debug issues in production with silently hanging I/O threads and my only access is via `kubectl exec`.
This wat tool and that "insta-load" idea pairs nicely with pyrasite for that very useful !!!DO NOT DO THIS, YOUR CONTAINERS SHOULD BE LOCKED DOWN SO YOU CANNOT DO THIS!!! step of copying gdb and the pyrasite library into a running container when all you have is a python shell to play with.
(This almost feels like an exploit, running shellcode after getting RCE :))
And some may not want it actually installed for whatever reason. Such as when there's no proper separation between dev and prod deps. (I'm mostly just guessing at this point though...)
In a previous company I set things up so that when there's an uncaught exception it will automatically start a VSCode debug session and connect to it.
Here's the extension: https://github.com/Timmmm/autodebug/
Unfortunately the Python part of that is not open source but it was only a few lines of code - should be easy to recreate. That repo does contain a C library that does a similar thing.
You might just say "why not just run your program directly with the debugger?" and yeah that is better when you can do it, but I'm working with complicated silicon verification flows that are often several layers of Python and Make, followed by a simulator (e.g. Questa or VCS) that itself loads the library you want to debug. Very difficult to make debugging work through all those layers, but it's quite easy to write some code at the bottom of the stack that says to a debugger "I'm here, debug me!".
print(name.__doc__)
works for many kinds of names in Python.Same reason jupyter notebooks allow you to prepend '?' or '??' to inspect a variable (though not expressions, in that respect this syntax is better)
I believe it should be equally possible to overload the bitwise OR operator (|), which, for people used to piping in Unix, is probably more intuitive.
One thing I'd like to note, though, is that most engineers (at least around and including myself) would be triggered by the "Insta-load" example of executing base64 encoded (and thus obfuscated) code.
the author has encoded the wat module's source code into base64. the snippet shown decodes that back into python code, and then executes it on the fly, thus having the same effect as importing the wat module in the normal python way?
with open('wat_source.py', 'w') as f: f.write(zlib.decompress(base64.b64decode(code.encode())).decode())
> wat object can quickly inspect things by using the division operator (to avoid typing parentheses). A short, no-parentheses syntax wat / object is equivalent to wat(object).