diff options
Diffstat (limited to '')
| -rw-r--r-- | 2025/captions/emacsconf-2025-swanky--swanky-python-interactive-development-for-python--scott-zimmermann--main.vtt | 1108 |
1 files changed, 1108 insertions, 0 deletions
diff --git a/2025/captions/emacsconf-2025-swanky--swanky-python-interactive-development-for-python--scott-zimmermann--main.vtt b/2025/captions/emacsconf-2025-swanky--swanky-python-interactive-development-for-python--scott-zimmermann--main.vtt new file mode 100644 index 00000000..35eb7ce7 --- /dev/null +++ b/2025/captions/emacsconf-2025-swanky--swanky-python-interactive-development-for-python--scott-zimmermann--main.vtt @@ -0,0 +1,1108 @@ +WEBVTT captioned by sachac + +00:00:00.880 --> 00:00:02.439 +Hello everyone, I'm Scott + +00:00:02.440 --> 00:00:04.239 +and I'll be talking about Swanky Python, + +00:00:04.240 --> 00:00:06.199 +which is a development environment for Python + +00:00:06.200 --> 00:00:08.319 +based on Emacs' Slime package. + +00:00:08.320 --> 00:00:11.679 +So what is that and why might you find it interesting? + +00:00:11.680 --> 00:00:15.279 +SLIME is the Superior Lisp Interaction Mode for Emacs. + +00:00:15.280 --> 00:00:17.999 +It's an Emacs package for developing Common Lisp, + +00:00:18.000 --> 00:00:20.679 +and it's a bit different from the way we develop most languages + +00:00:20.680 --> 00:00:22.599 +in that you're always connected + +00:00:22.600 --> 00:00:25.399 +to a running instance of your application, + +00:00:25.400 --> 00:00:27.959 +and you kind of build up your application, piece by piece, + +00:00:27.960 --> 00:00:30.399 +modifying one expression at a time + +00:00:30.400 --> 00:00:34.559 +without ever having to restart your application. + +00:00:34.560 --> 00:00:36.679 +So why might you want to develop this way? + +00:00:36.680 --> 00:00:40.039 +One advantage is that you can get a faster feedback loop. + +00:00:40.040 --> 00:00:42.599 +For some kinds of software, it doesn't make a big difference. + +00:00:42.600 --> 00:00:43.919 +Like, if you're developing a web backend + +00:00:43.920 --> 00:00:48.039 +where all state is stored externally in a database, + +00:00:48.040 --> 00:00:50.279 +then you can have a file watcher + +00:00:50.280 --> 00:00:52.799 +that just restarts the whole Python process + +00:00:52.800 --> 00:00:54.639 +whenever you make any edit, + +00:00:54.640 --> 00:00:56.159 +and you're not really losing anything, + +00:00:56.160 --> 00:00:59.679 +because all the state is stored outside the Python process + +00:00:59.680 --> 00:01:01.719 +in a database. So it works great. + +00:01:01.720 --> 00:01:03.559 +But for other kinds of software, like + +00:01:03.560 --> 00:01:05.559 +let's say you're developing an Emacs package + +00:01:05.560 --> 00:01:07.279 +or a video game, + +00:01:07.280 --> 00:01:10.319 +then it can be a real pain to restart the application + +00:01:10.320 --> 00:01:12.679 +and recreate the state it was in before + +00:01:12.680 --> 00:01:17.279 +just to test the effect of each edit you want to make. + +00:01:17.280 --> 00:01:21.359 +Another advantage is the runtime introspection you have available. + +00:01:21.360 --> 00:01:22.679 +So since you're always connected + +00:01:22.680 --> 00:01:24.999 +to a running instance of your application, + +00:01:25.000 --> 00:01:27.799 +you can inspect the values of variables, + +00:01:27.800 --> 00:01:30.959 +you can trace functions, and all sorts of other information + +00:01:30.960 --> 00:01:36.279 +to help you understand your application better. + +00:01:36.280 --> 00:01:39.919 +And lastly, it's just a lot of fun to develop this way, + +00:01:39.920 --> 00:01:43.519 +or at least I find it fun developing with SLIME, + +00:01:43.520 --> 00:01:45.759 +so I wrote a SLIME backend for Python + +00:01:45.760 --> 00:01:48.799 +so I could have more fun when I'm coding in Python. + +00:01:48.800 --> 00:01:52.599 +As for the name swanky-python, within SLIME, + +00:01:52.600 --> 00:01:56.279 +swank is the name of the Common Lisp backend + +00:01:56.280 --> 00:01:59.199 +that runs within your Common Lisp application + +00:01:59.200 --> 00:02:02.919 +and connects to Emacs. So I'm not too creative. + +00:02:02.920 --> 00:02:07.999 +swanky-python is just a swank implementation in Python. + +NOTE Demo + +00:02:08.000 --> 00:02:15.279 +So let's see it in action. So we started up with M-x slime. + +00:02:15.280 --> 00:02:19.639 +And what that does is it starts a Python process, + +00:02:19.640 --> 00:02:25.039 +starts swanky-python within it, and connects to it from Emacs. + +00:02:25.040 --> 00:02:29.039 +And you can configure how exactly it runs Python. + +00:02:29.040 --> 00:02:32.479 +Or you can start swanky python manually + +00:02:32.480 --> 00:02:35.119 +within a Python application running on a remote server + +00:02:35.120 --> 00:02:36.313 +and forward the port locally + +00:02:36.614 --> 00:02:40.919 +and connect to it in Emacs, from Emacs remotely. + +00:02:40.920 --> 00:02:43.239 +Within the README, there's more documentation + +00:02:43.240 --> 00:02:45.519 +on other ways to start it. + +00:02:45.520 --> 00:02:52.159 +But just M-x slime is the basic way that works most of the time. + +00:02:52.160 --> 00:02:55.759 +So within the REPL, the first thing you'll notice is that + +00:02:55.760 --> 00:02:58.839 +REPL outputs are clickable buttons, + +00:02:58.840 --> 00:03:02.119 +what SLIME calls presentations. + +00:03:02.120 --> 00:03:04.759 +So you can do things like inspect them. + +00:03:04.760 --> 00:03:09.759 +And for each presentation, in the Python backend, + +00:03:09.760 --> 00:03:12.479 +it holds on to the reference to the object. + +00:03:12.480 --> 00:03:14.559 +So for an int, it's not too interesting, + +00:03:14.560 --> 00:03:20.239 +but let's do a more complex object like a file. + +00:03:20.240 --> 00:03:22.519 +Then we can inspect the file. + +00:03:22.520 --> 00:03:26.599 +We can describe it, which will bring up documentation + +00:03:26.600 --> 00:03:33.759 +on that class. We can use it in further expressions + +00:03:33.760 --> 00:03:39.431 +like if we copy it, it will use the actual Python object + +00:03:39.432 --> 00:03:43.399 +in this expression. + +00:03:43.400 --> 00:03:48.319 +We can assign it to a variable. + +00:03:48.320 --> 00:03:50.999 +SLIME uses presentations everywhere + +00:03:51.000 --> 00:03:53.239 +that a Python object would be displayed. + +00:03:53.240 --> 00:03:56.559 +So instead of just their string representation, + +00:03:56.560 --> 00:04:00.239 +when you have a backtrace on an exception, + +00:04:00.240 --> 00:04:03.965 +or you... within the inspector or anywhere else really, + +00:04:03.966 --> 00:04:06.019 +anywhere that the string representation + +00:04:06.020 --> 00:04:07.940 +of an object would be displayed, + +00:04:07.941 --> 00:04:10.740 +it displays a presentation that you can go on to + +00:04:10.741 --> 00:04:14.960 +inspect, reuse, or send to the REPL and so on. + +00:04:14.961 --> 00:04:23.039 +One useful utility function is pp for print presentation. + +00:04:23.040 --> 00:04:25.119 +We haven't imported it yet. + +00:04:25.120 --> 00:04:29.159 +So when we get a name error exception + +00:04:29.160 --> 00:04:33.879 +and SLIME sees that that name is available for import somewhere, + +00:04:33.880 --> 00:04:38.279 +it'll give us the option of importing it. + +00:04:38.280 --> 00:04:40.599 +Since it's available for import from multiple modules, + +00:04:40.600 --> 00:04:43.919 +it'll prompt us for which one we want to import it from. + +00:04:43.920 --> 00:04:45.519 +We want to import it from swanky-python, + +00:04:45.520 --> 00:04:48.479 +not from the standard library. + +00:04:48.480 --> 00:04:52.599 +Then it will print a presentation of that object. + +00:04:52.600 --> 00:04:55.559 +Within the REPL, this is not really useful + +00:04:55.560 --> 00:04:58.919 +because all REPL outputs are already presentations. + +00:04:58.920 --> 00:05:02.799 +But I use this now whenever I would use print debugging, + +00:05:02.800 --> 00:05:05.639 +just whenever I would use insert print statements in my program + +00:05:05.640 --> 00:05:08.399 +to see what's going on, I have it print a presentation + +00:05:08.400 --> 00:05:11.199 +because that way I can go back and inspect it later, + +00:05:11.200 --> 00:05:16.599 +copy it to the REPL and further manipulate it and so on. + +NOTE Inspector + +00:05:16.600 --> 00:05:20.119 +Next up, let's look at the inspector more. + +00:05:20.120 --> 00:05:25.579 +If we go back and inspect the file object, + +00:05:25.580 --> 00:05:27.239 +you can write custom inspector views + +00:05:27.240 --> 00:05:28.839 +for different kinds of objects. + +00:05:28.840 --> 00:05:32.519 +So far, I just have a couple. One for sequences, + +00:05:32.520 --> 00:05:36.919 +one for mappings, and one for every other kind of object. + +00:05:36.920 --> 00:05:45.979 +Like if we inspect a mapping, there's a shortcut + +00:05:45.980 --> 00:05:48.639 +inspect last result, which is what I normally use + +00:05:48.640 --> 00:05:52.379 +to open the inspector. Then we see the values, + +00:05:52.380 --> 00:05:56.319 +and each value in the inspector is a presentation + +00:05:56.320 --> 00:05:58.419 +that we can go on to inspect, and so on. + +00:05:58.420 --> 00:06:03.979 +Let's go back to inspecting the file object. + +00:06:03.980 --> 00:06:06.039 +Again, we can inspect each of the values, + +00:06:06.040 --> 00:06:10.239 +we can copy them back to the REPL and so on. + +00:06:10.240 --> 00:06:13.839 +It just displays all the attributes for the class + +00:06:13.840 --> 00:06:15.399 +and their values. + +00:06:15.400 --> 00:06:18.119 +We can configure what attributes we want to show. + +00:06:18.120 --> 00:06:21.119 +There's a transient menu where we can toggle + +00:06:21.120 --> 00:06:23.359 +if we want to show private attributes, dunder attributes, + +00:06:23.360 --> 00:06:26.439 +doc strings, so on, or everything, + +00:06:26.440 --> 00:06:28.519 +which is a bit much to show by default. + +00:06:28.520 --> 00:06:33.719 +So we'll reset it to the default. + +00:06:33.720 --> 00:06:37.839 +In the future, I want to add graphical inspector views + +00:06:37.840 --> 00:06:40.679 +for different kinds of objects, and also support + +00:06:40.680 --> 00:06:42.999 +showing plots in both the inspector and the REPL, + +00:06:43.000 --> 00:06:47.719 +but that's future work I haven't started on yet. + +NOTE Evaluating Python + +00:06:47.720 --> 00:06:51.999 +Let's look at the different options for evaluating Python. + +00:06:52.000 --> 00:06:59.099 +So we can evaluate a whole file. + +00:06:59.100 --> 00:07:00.639 +We can evaluate just a class. + +00:07:00.640 --> 00:07:03.479 +We can evaluate just the method we're working on. + +00:07:03.480 --> 00:07:06.359 +We can evaluate a Python statement, + +00:07:06.360 --> 00:07:11.839 +and it will show the result in an overlay next to the cursor. + +00:07:11.840 --> 00:07:17.919 +We can select some code and just evaluate the highlighted region. + +00:07:17.920 --> 00:07:24.799 +We can sync the REPL to the active file. + +00:07:24.800 --> 00:07:27.319 +So now everything we evaluate in the REPL will be in the + +00:07:27.320 --> 00:07:29.639 +context of the eval_demo module. + +00:07:29.640 --> 00:07:35.399 +We can also set the module that the REPL is in. + +00:07:35.400 --> 00:07:38.279 +We can go back to main. + +00:07:38.280 --> 00:07:43.679 +But let's go back to the eval_demo module for now. + +NOTE Updating + +00:07:43.680 --> 00:07:49.799 +One useful thing is when you update a class or a function, + +00:07:49.800 --> 00:07:54.539 +it updates old instances of that class or function. + +00:07:54.540 --> 00:07:58.479 +So right now, f.bar is foobar. + +00:07:58.480 --> 00:08:03.719 +But if we edit that class, it will actually edit the code + +00:08:03.720 --> 00:08:05.239 +for the old instance of that class. + +00:08:05.240 --> 00:08:07.599 +And that's provided by code I copied + +00:08:07.600 --> 00:08:12.079 +from IPython's autoreload extension. + +00:08:12.080 --> 00:08:14.639 +It helps when you're trying to develop in Python + +00:08:14.640 --> 00:08:16.498 +without having to restart the Python process + +00:08:16.499 --> 00:08:20.039 +whenever you make a change. + +00:08:20.040 --> 00:08:22.599 +Auto reload in Python is a big topic + +00:08:22.600 --> 00:08:26.519 +that I don't really have time to go into here, + +00:08:26.520 --> 00:08:29.479 +but right now it is more limited + +00:08:29.480 --> 00:08:32.559 +than what is done in Common Lisp. + +00:08:32.560 --> 00:08:35.759 +Like for example, if you have a data class in Python + +00:08:35.760 --> 00:08:37.619 +and you add a new field to the data class, + +00:08:37.620 --> 00:08:41.039 +it won't automatically update old instances + +00:08:41.040 --> 00:08:43.399 +of the data class with a new field. + +00:08:43.400 --> 00:08:46.599 +So there's more that needs to be done with that, + +00:08:46.600 --> 00:08:50.359 +but I am perhaps naively optimistic + +00:08:50.360 --> 00:08:54.279 +that Python's runtime is quite dynamic and flexible, + +00:08:54.280 --> 00:08:59.799 +and that I can fully implement autoreload in Python, + +00:08:59.800 --> 00:09:02.119 +but there's still work to be done, + +00:09:02.120 --> 00:09:05.419 +and it's a big topic to go into. + +00:09:05.420 --> 00:09:08.959 +Next up, let's look at the backtrace buffer. + +00:09:08.960 --> 00:09:12.839 +But as it is right now, autoreload is actually useful. + +00:09:12.840 --> 00:09:16.959 +I mostly develop in Python without having to restart the process + +00:09:16.960 --> 00:09:19.599 +and without running into issues from old state + +00:09:19.600 --> 00:09:22.899 +that hasn't been updated properly. + +NOTE Backtraces + +00:09:22.900 --> 00:09:25.999 +So if we go on to look at the backtrace buffer, + +00:09:26.000 --> 00:09:32.819 +whenever we get an exception in Python... + +00:09:32.820 --> 00:09:37.079 +Let's go back to it. + +00:09:37.080 --> 00:09:41.419 +Whenever we get an exception, it will... + +00:09:41.420 --> 00:09:43.698 +let's change the code so that it actually + +00:09:43.699 --> 00:09:49.965 +gets an exception... + +00:09:49.966 --> 00:09:52.519 +we will get an interactive backtrace buffer + +00:09:52.520 --> 00:09:57.599 +where we can browse the source code for the different stack frames + +00:09:57.600 --> 00:10:00.199 +and the local variables within the stack frames, + +00:10:00.200 --> 00:10:03.439 +which are all presentations that we can inspect and so on. + +00:10:04.340 --> 00:10:10.619 +We can also open a REPL in the context of any stack frame. + +00:10:10.620 --> 00:10:16.439 +Or we can, when we go to the source for a given stack frame, + +00:10:16.440 --> 00:10:20.359 +we can select some Python code and evaluate it + +00:10:20.360 --> 00:10:25.959 +within the context of that stack frame. + +00:10:25.960 --> 00:10:30.699 +One major limitation compared to SLIME for Common Lisp + +00:10:30.700 --> 00:10:33.759 +is that in Common Lisp, you have the option to + +00:10:33.760 --> 00:10:38.159 +restart or resume execution from a given stack frame + +00:10:38.160 --> 00:10:42.439 +after an exception happens, where in Python, + +00:10:42.440 --> 00:10:45.799 +what we have right now is pretty much equivalent to + +00:10:45.800 --> 00:10:47.159 +the postmortem debugger. + +00:10:47.160 --> 00:10:50.839 +You can view the state that the call stack was in + +00:10:50.840 --> 00:10:51.959 +at the time of the exception, + +00:10:51.960 --> 00:10:55.659 +but you can't actually resume execution, + +00:10:55.660 --> 00:10:57.559 +which you often might want to do, + +00:10:57.560 --> 00:10:59.919 +because when you're coding in a dynamic language, + +00:10:59.920 --> 00:11:01.479 +you're going to get runtime errors. + +00:11:01.480 --> 00:11:04.119 +So if you're writing a script that does like some sort of + +00:11:04.120 --> 00:11:07.999 +long-running computation or processes a ton of files + +00:11:08.000 --> 00:11:11.939 +and gets an exception parsing one file halfway through, + +00:11:11.940 --> 00:11:16.919 +normally you'd have to fix the script, and then rerun it + +00:11:16.920 --> 00:11:19.759 +and have it process all the same files all over again, + +00:11:19.760 --> 00:11:23.839 +and lose a bunch of time for every bug you run into + +00:11:23.840 --> 00:11:24.879 +and fix you have to make. + +00:11:24.880 --> 00:11:28.679 +So right now we've got a kind of mediocre workaround + +00:11:28.680 --> 00:11:34.019 +which is you can add the restart decorator to a function + +00:11:34.020 --> 00:11:37.239 +and then... where in the case of a script + +00:11:37.240 --> 00:11:38.879 +processing a bunch of files, + +00:11:38.880 --> 00:11:41.799 +you would add the restart decorator to the function + +00:11:41.800 --> 00:11:43.599 +that processes a single file. + +00:11:43.600 --> 00:11:45.439 +You'd add it to the function + +00:11:45.440 --> 00:11:47.879 +that represents kind of the smallest unit of work + +00:11:47.880 --> 00:11:50.219 +that might fail with an exception, + +00:11:50.220 --> 00:11:54.359 +Then, when you get an exception, + +00:11:54.360 --> 00:11:57.479 +you can actually edit the function. + +00:11:57.480 --> 00:12:01.019 +Like, if we edit it so it doesn't throw an error, + +00:12:01.020 --> 00:12:07.199 +and then we can resume execution, + +00:12:07.200 --> 00:12:12.799 +then it will return from foo using the + +00:12:12.800 --> 00:12:15.040 +the new version of baz, + +00:12:15.041 --> 00:12:18.559 +without having to run the script from the beginning again. + +00:12:18.560 --> 00:12:22.379 +So in the example of a script that processes a bunch of files, + +00:12:22.380 --> 00:12:24.299 +that would let you, + +00:12:24.300 --> 00:12:27.619 +as you run into files that cause an exception, + +00:12:27.620 --> 00:12:29.079 +fix your code to deal with it + +00:12:29.080 --> 00:12:31.880 +and resume execution without having to restart the script + +00:12:31.881 --> 00:12:33.080 +from the beginning. + +00:12:33.081 --> 00:12:36.120 +But this is obviously a pretty terrible hack, + +00:12:36.121 --> 00:12:38.840 +having to add the restart decorator to the function. + +00:12:38.841 --> 00:12:46.739 +I would like it to be able to restart from any function. + +00:12:46.740 --> 00:12:49.631 +without needing the decorator, as you can in Common Lisp, + +00:12:49.632 --> 00:12:54.031 +but I think that will require patching CPython + +00:12:54.032 --> 00:12:56.579 +and I really have no idea how to do that. + +00:12:56.580 --> 00:13:00.531 +So if you do know anything about CPython internals + +00:13:00.532 --> 00:13:03.720 +and are interested in helping, please reach out. + +NOTE pydumpling + +00:13:03.721 --> 00:13:07.119 +Another feature we have with the backtrace buffer is + +00:13:07.120 --> 00:13:09.079 +there's this library called PyDumpling + +00:13:09.080 --> 00:13:14.659 +which can serialize a traceback and store it to a file. + +00:13:14.660 --> 00:13:17.859 +So you can use PyDumpling with your applications running in + +00:13:17.860 --> 00:13:21.239 +production to serialize a traceback + +00:13:21.240 --> 00:13:24.899 +whenever they have an exception and save it to a file. + +00:13:24.900 --> 00:13:28.599 +Then you can transfer the file locally + +00:13:28.600 --> 00:13:38.859 +and load it into your local Emacs with slime-py-load-pydumpling. + +00:13:38.860 --> 00:13:41.839 +This will load the same backtrace buffer, + +00:13:41.840 --> 00:13:44.559 +and you see all the same local variables + +00:13:44.560 --> 00:13:45.759 +at the time of the exception. + +00:13:45.760 --> 00:13:48.199 +You can inspect them and get a REPL + +00:13:48.200 --> 00:13:50.999 +in the context of the stack frame. + +00:13:51.000 --> 00:13:54.199 +Well, this will only work for variables + +00:13:54.200 --> 00:13:57.619 +that can be serialized with pickle. + +00:13:57.620 --> 00:13:59.519 +Or actually, the library uses dill, + +00:13:59.520 --> 00:14:03.039 +which can serialize a bit more than pickle can. + +00:14:03.040 --> 00:14:10.200 +But yeah so this can help you inspect and debug errors + +00:14:10.201 --> 00:14:12.880 +for applications running in production remotely + +00:14:12.881 --> 00:14:20.059 +that you don't want to have SLIME connected to 24-7. + +NOTE Documentation browser + +00:14:20.060 --> 00:14:24.859 +Next up, let's look at the documentation browser. + +00:14:24.860 --> 00:14:29.919 +We can bring up documentation for any module, + +00:14:29.920 --> 00:14:33.079 +and all this information is generated + +00:14:33.080 --> 00:14:34.999 +from runtime introspection, + +00:14:35.000 --> 00:14:37.079 +from the doc strings for the module + +00:14:37.080 --> 00:14:39.159 +and the classes and so on. + +00:14:39.160 --> 00:14:41.879 +So you won't see documentation for libraries + +00:14:41.880 --> 00:14:43.159 +that you don't have actually loaded + +00:14:43.160 --> 00:14:45.939 +into your running Python process. + +00:14:45.940 --> 00:14:50.119 +Then you can go browse to classes. + +00:14:50.120 --> 00:14:54.719 +It'll show all the attributes, their methods, and so on. + +00:14:54.720 --> 00:14:57.239 +By each method to the right, it will show + +00:14:57.240 --> 00:15:02.599 +the base class where the method was originally inherited from. + +00:15:02.600 --> 00:15:09.079 +You can also bring up a screen with all the Python packages + +00:15:09.080 --> 00:15:14.439 +that are installed, and browse that with imenu, + +00:15:14.440 --> 00:15:20.359 +and bring up information on any package and so on. + +NOTE Thread view + +00:15:20.360 --> 00:15:28.499 +Next up, let's take a look at the thread view. + +00:15:28.500 --> 00:15:31.839 +So let's run this and then bring up the thread view + +00:15:31.840 --> 00:15:35.559 +and this will show information on all running threads. + +00:15:35.560 --> 00:15:38.799 +You can configure it to refresh after a given interval, + +00:15:38.800 --> 00:15:41.959 +like every second, but I don't have that set up right now, + +00:15:41.960 --> 00:15:45.659 +so I have to manually refresh it. + +00:15:45.660 --> 00:15:47.639 +Probably the most useful thing is that + +00:15:47.640 --> 00:15:49.739 +you can bring up a backtrace for any thread + +00:15:49.740 --> 00:15:51.759 +which won't pause the thread or anything, + +00:15:51.760 --> 00:15:53.879 +but will just give you the call stack + +00:15:53.880 --> 00:15:55.879 +at the time you requested the backtrace. + +00:15:55.880 --> 00:15:59.199 +You can again view the stack frames, local variables, + +00:15:59.200 --> 00:16:04.139 +open a REPL in the context of the thread, and so on. + +00:16:04.140 --> 00:16:07.839 +There's also a viewer for async tasks, + +00:16:07.840 --> 00:16:09.999 +but I'm not going to demo that right now, + +00:16:10.000 --> 00:16:14.159 +because for that to work, you have to start swanky-python + +00:16:14.160 --> 00:16:16.599 +after the async event loop has started, + +00:16:16.600 --> 00:16:18.519 +from within the same thread. + +00:16:18.520 --> 00:16:20.279 +If you go to the project readme, + +00:16:20.280 --> 00:16:23.919 +there's a demo of how to use the async task viewer + +00:16:23.920 --> 00:16:27.439 +with a fastapi project. + +NOTE Tracing functions + +00:16:27.440 --> 00:16:33.879 +Next up, let's look at tracing functions. + +00:16:33.880 --> 00:16:36.279 +So here we got some random error, + +00:16:36.280 --> 00:16:39.879 +because this is still very much a work in progress. + +00:16:39.880 --> 00:16:42.359 +But it looks like it executed + +00:16:42.360 --> 00:16:43.199 +correctly this time. + +00:16:43.200 --> 00:16:47.565 +So now let's mark the fibonacci function + +00:16:47.566 --> 00:16:50.239 +for tracing and execute it. + +00:16:50.240 --> 00:16:56.079 +We can see, every time the function is called, + +00:16:56.080 --> 00:16:58.239 +all its arguments and return values. + +00:16:58.240 --> 00:17:02.899 +Again, there are presentations that we can inspect and so on. + +00:17:02.900 --> 00:17:06.079 +But let's inspect a more complex object, like a file object. + +00:17:06.080 --> 00:17:11.339 +If we trace the count_lines function and run that code, + +00:17:11.340 --> 00:17:15.319 +then we can inspect the file it was passed, or the file object. + +00:17:15.320 --> 00:17:21.039 +One pitfall is that in Python, objects are mutable. + +00:17:21.040 --> 00:17:25.559 +So in the trace buffer, the string representation + +00:17:25.560 --> 00:17:27.879 +that's printed is the string representation + +00:17:27.880 --> 00:17:31.219 +at the time it was passed to the function. + +00:17:31.220 --> 00:17:32.639 +But when we go to inspect it, + +00:17:32.640 --> 00:17:34.919 +we're inspecting the object as it is right now, + +00:17:34.920 --> 00:17:37.639 +which can be different than it was at the time + +00:17:37.640 --> 00:17:41.559 +the function saw it. So for this file object, for example, + +00:17:41.560 --> 00:17:44.279 +it's closed now, when it was open at the time + +00:17:44.280 --> 00:17:47.799 +the function used it. + +NOTE AI integrations + +00:17:47.800 --> 00:17:50.479 +Next up, let's look at AI integrations. + +00:17:50.480 --> 00:17:54.519 +So if you're used to SLIME with Common Lisp, + +00:17:54.520 --> 00:18:09.479 +Emacs actually has a built-in AI that can help with the transition. + +00:18:09.480 --> 00:18:14.559 +So it's just a joke, I actually really like Python. + +00:18:14.560 --> 00:18:18.119 +And for more serious AI integrations, + +00:18:18.120 --> 00:18:19.959 +I have some ideas for the future + +00:18:19.960 --> 00:18:21.919 +but I haven't implemented anything yet. + +00:18:21.920 --> 00:18:27.319 +I think right now, people are mostly passing source code to LLMs + +00:18:27.320 --> 00:18:32.679 +but since we're embedded in the Python process at runtime, + +00:18:32.680 --> 00:18:35.639 +we have a lot of more information available, + +00:18:35.640 --> 00:18:39.439 +like maybe we can trace all calls to functions, + +00:18:39.440 --> 00:18:41.799 +and when we have a bug, + +00:18:41.800 --> 00:18:46.479 +we can feed the trace to the LLM, + +00:18:46.480 --> 00:18:48.719 +and the LLM can point out maybe + +00:18:48.720 --> 00:18:51.959 +when this function was called with these arguments, + +00:18:51.960 --> 00:18:53.879 +its return value doesn't make sense, + +00:18:53.880 --> 00:18:55.679 +so maybe that's the root cause of your bug. + +00:18:55.680 --> 00:19:02.359 +If you have any ideas of potential LLM or AI integrations, + +00:19:02.360 --> 00:19:05.999 +let me know. I'm happy to discuss. + +NOTE LSP-type features + +00:19:06.000 --> 00:19:09.919 +Next up, let's look at standard LSP-type features. + +00:19:09.920 --> 00:19:14.439 +So we've got completions. It's fuzzy completions right now, + +00:19:14.440 --> 00:19:16.319 +so it's showing everything with a PR in the name. + +00:19:16.320 --> 00:19:21.779 +We can bring up documentation for each one. + +00:19:21.780 --> 00:19:26.759 +When we start calling a method in the minibuffer at the bottom + +00:19:26.760 --> 00:19:28.859 +it'll show the signature. + +00:19:28.860 --> 00:19:33.719 +There's some refactoring available. + +00:19:33.720 --> 00:19:37.399 +We can extract a function or variable, + +00:19:37.400 --> 00:19:39.499 +or rename something, + +00:19:39.500 --> 00:19:42.919 +like, let's rename fib to fib2, + +00:19:42.920 --> 00:19:47.479 +and it will rename all the uses of it. + +00:19:47.480 --> 00:19:49.759 +All these features are based on Jedi, + +00:19:49.760 --> 00:19:55.399 +which is the Python library used by IPython. + +00:19:55.400 --> 00:19:56.999 +But as it is right now, + +00:19:57.000 --> 00:20:02.039 +if you want the most complete Python development experience + +00:20:02.040 --> 00:20:05.579 +in Emacs, I'd probably recommend using LSP + +00:20:05.580 --> 00:20:10.439 +for everything LSP can do, and then just using swanky-python + +00:20:10.440 --> 00:20:13.679 +for the object inspector and backtrace buffer, + +00:20:13.680 --> 00:20:15.359 +and the interactive features it has + +00:20:15.360 --> 00:20:18.031 +that an LSP can't provide. + +NOTE Wrapping up + +00:20:18.032 --> 00:20:23.339 +And that's it really. + +00:20:23.340 --> 00:20:25.865 +Shortly we'll have questions and answers + +00:20:25.866 --> 00:20:28.799 +as part of EmacsConf, and later on, + +00:20:28.800 --> 00:20:31.199 +if you have any questions, ideas, or issues + +00:20:31.200 --> 00:20:34.639 +feel free to reach out over email + +00:20:34.640 --> 00:20:37.999 +or create an issue on the repository. + +00:20:38.000 --> 00:20:39.331 +I should probably warn you, + +00:20:39.332 --> 00:20:41.119 +if you want to try out the project: + +00:20:41.120 --> 00:20:45.279 +so far I'm probably the only user of it + +00:20:45.280 --> 00:20:48.279 +and I've only tested it on my own Emacs setup, + +00:20:48.280 --> 00:20:50.839 +so it's quite likely you'll run into issues + +00:20:50.840 --> 00:20:53.479 +trying to get it installed and working. + +00:20:53.480 --> 00:20:56.119 +But if you do run into problems, please reach out, + +00:20:56.120 --> 00:20:59.279 +let me know. I'm happy to help and try and fix them. + +00:20:59.280 --> 00:21:03.640 +So that's it. Thanks for listening. |
