 Thank you, Lais. Thank you to the organization of EuroPython for accepting this talk. And OK, I am Ramon Cromina's accessibility consultant because I have a retinitis pigmentosa. It is a retinal disease, and I am losing my vision. So since some years, I use a screen reader to use my computer. My screen reader is this. Let me. OK. Excuse me? Yeah, OK. This is my screen reader. If I pass the slides, you will see that my screen reader reads allow the text in the slide. Obviously, I usually have it here. But now I have changed the output so you can hear it. Obviously, you probably need a little slower. One, the problem is that you plug a screen reader while using a screen reader. OK. So this is my screen reader. I will switch to my earphone. OK, so the presentation is about this problem. Is how can I debug a screen reader if I am using a screen reader? Because one of the problems is that if I try to debug my screen reader, I go step by step in my screen reader so my screen reader is frozen and I cannot hear anything. So I cannot use my computer because the screen reader is frozen. OK, so the talk is about debugging. So first, I will try to debug something more simple than the screen reader. And I have prepared a little game that is the typical guess the number. We will generate a random number. Then we have a main loop where I have to ask the user for a bet and then compare with the secret number. If they match, I run the winner block and exit. If they don't match, I give another opportunity with the high or low indication. And if the match tries are reached, then it is loser and game over. OK, so this is the code in Python. It is very simple code. The main code, the main program is just the settings and the code to the main function. I have also some modules for the UI and for the audio player. And then the function is just the comparisons and they run in the different blocks, OK? So let me, oh, sorry. OK, this is the play game function that you see. It's very simple. I will not go here more deeply. OK, so debugging the program. I need some steps to debug a program. First, I will create a virtual environment to isolate the libraries that I need for the project. In this case, I am using Pygame for the audio player. We have to install those dependencies, in this case, Pygame. I have to open the project as a folder in the workspace in Visual Studio Code. So I can establish some settings in Visual Studio Code. Then we have to select the Python interpreter and then set breakpoints. And after that, I can start debugging. So I will do that now so you can see what I pretend to do with my screen reader, with any package program. Because this is the aim of the talk that you will see that this works for other things too. OK, let me. So if I go to my first demo, I open this as workspace. And if I, OK, now I can create the virtual environment. This usually takes a bit of time, but it is just Python.mvm.vm. So now I have a virtual environment. I can activate it. And now that I have activated it, I can install the requirements in my virtual environment. And with that, I have everything I need. I can now run the game. You will see that the secret number is whatever. Low. OK, winner. Thank you, thank you. OK, but what I want to do is debug the program. So you see that I have here my virtual environment that I have just created. The other player is a package. The waves, the whatever files that I need to play the game. Here is my main program and the requirements and the UI.py where I have some little functions. OK, so I have here the gamify.py. I have already set a break point in the, if I think, in the first comparison. So if I now run the program, let me check the, OK. I have here the break point. You can hear that that is an audio queue that tells me that there is a break point. OK, so if I now run the program from Visual Studio Code with F5, you will see that the program. Oh, sorry. I have to, maybe I have to select the interpreter. OK, it is already selected. So, OK, if I run the active file, OK, now it is running. If I go to the terminal, I can type there my bit and I can now go step by step. OK, so for example, now I'm here and I know that it is low before it hits the thing. I will inspect this variable. So now I know that the second number is 11. So in the next try, I can put directly 11 and run the program until the end. So I win again. OK, so that is the bugging. So this is the purpose of this talk. OK, so in the minute, OK, I forgot to create the launch.json. But anyway, this is very easy. If I go again to my demos folder again, I don't know why it is not. OK, now, if I open it again with code, I open again there. OK, I open this. And if I go to the run and debug panel, I can go to create a launch.json. And it will ask me what kind of launch. So the Python file. So I have my first launch.json that is just a request launch that is to launch the program from Visual Studio Code. And this will be saved here in the UBS code folder. I suppose you can see where I am when I move the keyboard and so forth. Because if not, I can highlight it. OK, so OK, this is the example of launch.json just for the you have it in the presentation. I will upload the slides later. So I will introduce you my screen reader. And that's the reason of this talk. My screen reader is the main program is in Python. It's an application created with Py2X. It is packet. And the core of the program and parts of the standard library are packet in a zip file that is library.zip. This is because of the configuration of Py2X. But the interesting thing is that NVDA has also some add-ons that are in plain text that we can program in plain text and load them from the running Py2X program. So I will simulate this more or less with the game that I program it. So you can see how I will debug NVDA using this example. NVDA has also some C++ libraries that are extensions for performance and system access. But I have the first problem that the main entry point of NVDA is inside the executable file. I cannot run it from VS Code. OK, NVDA is open source. So maybe I can run the code from the source. And you can, of course. But you have to install a lot of things. First, you have to install Git. This is usually installed if you are a developer. So this is not a problem. You have to install the exact version of Python that needs NVDA because it is attached to this version. They are planning to upgrade. But for the moment, it is this version. We have to install the Visual Studio build tools because we have to compile all the C++ extension. And this is about 20 gigabytes of space to install these build tools. And the final step is to build everything that it is not an easy task, I must say. So there are many problems in this approach of trying to run from the source code. Because building from source is not easy. You have to install a lot of things. You need a lot of this space. And the main problem of this is that debugging may interfere with the running program. Because, for example, NVDA is always reading keystrokes is reading the focus, where is the focus, which window is open, and so on. So if I am in the debugger, obviously, I cannot debug other windows or other things. And probably the keystrokes that I press in the debugger will interfere with NVDA and so on. And this is common to many other programs that are not necessarily a screen reader. OK, anyway, if we develop an addon, we need to check that everything works when we pack the program. So we cannot bypass this step. But OK, if we don't have the main source, because maybe the project is not an open source, they let us to develop addons in plain text or something like that, but they don't give us the source code of the main program. But also, if the host language of Python is not Python, for example, if we use C++ or C-SARP to pack or to embed Python application, we cannot launch it from VS Code the normal way. Or maybe if the application is running in another operating system, for example, in Raspberry Pi, where we don't have even Visual Studio Code, or even in a Mac, or maybe in Linux, or in a Docker container, for example. So the idea is to run the screen reader, in this case, the screen reader, in another computer. So the goal is to run a second copy of the screen reader that I can stop and post and continue and so on. I will not interfere with my debugger, because the debugger is in the local computer. So my local computer will be the debugger tool, will be the computer that has Visual Studio Code, and the remote computer will have the program running, and I will connect to the program running through a debug adapter. That is what the talk is about. Debug Pi is an implementation of the debug adapter protocol. The debug adapter protocol basically communicates the debugging tool that is Visual Studio Code, or maybe PyCharm, unless PyCharm doesn't work the same way. But anyway, the debugging tool, it is a bridge between the debugging tool and the debugger itself, or the running process that is in the remote matching. It works with the classical stream of requests, responses, and events in JSON format. So the idea is that the debug adapter will send messages to the debugger tool from the debugger and vice versa, OK? And for example, these kind of things. If I set a breakpoint, this is a request from the debugger tool to the debugger in the remote matching to set a breakpoint in a file in the remote matching. And it will respond with an answer or a response that says, OK, breakpoint established, or maybe breakpoint cannot be set because the file doesn't exist, for example. And also other events, like threads, like exceptions, they are all communicated between the two machines, OK? So the basic uses of debugpy is, OK, sorry, because, OK, I have the code here. And obviously, we have to install debugpy in the debug by in the virtual environment. Then we have the import debug guy. And this line, if not debugpy, is client-connected, is to avoid that the adapter tries to listen twice in the same port, OK, because the port is being used. So if you try to launch the process a second time, it will give an exception, OK? I don't mean it. We have also some lines to save logs to the hard disk. So we can search there if we have some problems debugging. Then we have the listen with the port number. This would be for a local debugging, OK? It would be remote in the sense that we will connect to the process from the debug tool. But in this case, we are opening the port locally. By default, the host is localhost, OK? And finally, we have the debugpy wait for client. That this means that when this line is hit, the debugger will stop here so we can debug our program from the first line of code, OK? Because if not, we have to wait to a natural stop in the program. For example, in our game, it would be the input. Asking the input to the user, there is a natural stop. And then we can connect there. But maybe the program is running without the stops. So we need this kind of things to stop the program in that line. So we have to change the launch.json. So we connect instead of launch, OK? This is just going to the menu and select Remote Attach instead of debug this file. So now we will see how to run the remote debugger in the remote computer. So reminder of the goal. It is just to run the program in the remote computer and to debug from the local computer with the debugpy in the middle. So in the remote computer where the program will run, we need the full code of the program and the virtual environment and dependencies because the program needs to run, OK? So this is the basic needs. It is the program and the dependencies. We have to change the line of debugpy.listen to include also the host. So it is a pair of values with the host and port. We have to allow the program through firewall in the remote computer because we are trying to open a port. And visual studio code or any debugging tool is not required because we only need to run the program there. So in the remote computer, we only need to change the line with the host and port. And in the local computer, I go very fast, or is it OK? In the local computer, in the debugging computer, I will need to mirror the code that I want to debug. Maybe I don't need the full code. Only the code that I need to debug. I will show you this later. The virtual environment and dependencies are not required because I don't need to run the program. The program will not run in my local computer. I need the developer tool, the debugging tool, in this case, visual studio code. And OK. And I need to change the host in the launch.json because I need to connect to the remote computer. In this case, if you showed before, in the listen, I put 0.0.0.0.0.0. That is the full interface. So it will listen in any IP that is connected to this computer, to the remote computer. But for the connection from the launch.json, I have to establish the exact IP or host name to the remote computer. And we don't need the same Python version, or even we don't need any Python version in the local computer because the program, again, is not running in the local computer but in the remote computer. This could be good for other things but later. So this is the launch.json here. Let me check. OK, 24 minutes, I think I'm in time. So number two. OK. So I have a remote computer because you see only one remote computer, but if I have another machine, I have a virtual machine here with VMware workstation. So this is my remote computer. And I can switch to it because I am using a remote add-on in NVIDIA. That lets me connect to another computer. So if you see the Earth and the floor is the moon, it's because I am in the remote computer. And if you see the moon, it's because I am in the local computer. So if I switch to the remote computer now, obviously you don't see that, but I hear it here. OK, if I switch here, I can go to the demos in the remote. You see that the remote is white because the moon is more or less white. So if I go to the remote, I have my demo number two. And I have, let me check. OK, I can open it with code just to show you how this works. I don't need visual studio code in the remote computer, but to show you this, it is better to have it. So here I have the virtual environment already created. I have my modules. I have the backlogs of another session that I made. I have the waves, the resources that I need to run the program in the remote computer and everything else. But I don't need visual studio code at all. I can just go, let me check. If I go to the demos remote, if I go here and open a CMD here, OK, I am in the right place. Do you see the backslash? I don't know why I cannot. Let me check. OK, now the keyboard was not working. I don't know what. OK, so I said I don't need visual studio code to run the program. I can run it from here. OK, let me. OK, you will see. Now I have the debugger connected. It is waiting for another computer to connect. It is waiting for the local computer, in this case, to connect. If I go again to my local computer, let me go to my demos. If I open the folder in my local computer, remember. I don't know what happened. It's not changing. OK, I think I've closed the presentation. OK, open with code. Wait a minute. OK, I have my code here. OK. And if I go to the launch to the Gamify Pi, I can establish a breakpoint here. So I have it already, but I will put it again. Add it to the breakpoint. And my launch.json is already set up. So it will connect to the remote computer. I have the remote computer there in the left side. So you will see that if I now go. Excuse me, ah, the presentation. Sorry, sorry. It is just OK. Now you have the remote computer. I was in it white, so I suppose that it was the remote computer. OK, so I have now my local computer prepared to connect to the debugging session that is already launched in the remote computer. So if I press now F5, you see that probably in the remote computer there is some text. I don't know, I suppose. I know, because I put another breakpoint in the first line of code. So you can see that the wait for client is awaiting for my, OK, you see where is my cursor, isn't it? You see that I am reading the different lines here, OK. So if I run to the next breakpoint with F5 again, OK, now you have seen that in the remote computer, it is already asking for the number, OK. So if I switch to the remote computer, and I write there three, I am a bit stupid, so. OK, I go there. But you see that the computer, the local has posted again, because it has hit again a breakpoint in the local computer. So if I go to my local computer, I can now do again the trick that, oh, I was very far. It's 19, OK. And of course I can go through my code and I can go with F11, for example, I can go to the inner here. So I can go to the function. It is opening the different files that I have in my local computer. So I can debug the full program, OK. So my bed is too low, OK, OK, OK. OK, I win, again. OK, so this is the typical setup of a debugging or far remote debugging, OK. This is more or less easy, but we go again to the presentation, OK. OK, you know that in my local setup, I have the launch.json with the connection. Oh, OK, I didn't show that, but this is a minute. So if I go to the launch.json, you see that there is the IP of my remote computer. In this case, it is a local network, because the virtual machine is sharing the same network with the normal computer. OK, you know that this is just a virtual machine. And I can connect from one to the other. OK, let me go back to. Sometimes it does strange things. I don't know why. OK, this is not. OK, what happens here? Maybe it is that I am going very fast. OK, I lost my presentation. Oh, OK, I was in the remote computer. So I cannot control my remote, my local computer if I am in the other. OK, I don't know what happens here. OK, I opened them again. So it is in full screen. Excuse me? But it's in full screen. OK, OK, OK, OK, OK, OK, OK, simplifying. So that's the typical debugging session. But we don't need the full code of the program in our local environment. Because in our local computer, we only need the code that we are really going to debug. In this case, I have a main program that calls another program. I mean, it is loading the play game function. So I can separate that play game function. So I can separate it to another package, for example. So the main program will look like this. From games.game, guest game, I import the play game. So now it is in another package outside the main program. And the game, the guest game.py file will look like this. This is just all that we need to set up the play game function and the play game function itself. OK. So in the local computer, we don't need the full code. So we can change the past mappings in our local computer to match the way that its side sees the code. OK. You will understand this later, probably. The point here is, in my local computer, I will open the games folder where the guest game.py is. Only that folder, the games folder, that is the folder of the package. But in the remote computer, I will have the full program with all the main program, the packages, like the audio player, the UI, or something like that. So from the local side, the guest game.py is in the root folder, because it is the root of the workspace. But in the remote computer, the games folder is a subfolder of the root folder for the remote program. Do you understand what I said? More or less, we will see it later, probably. When we connect to the remote computer, we can check if the breakpoints are set. Because if there is an error, a mistake with these paths, the breakpoint will not be set, because the file will not exist. If the debug adapter cannot match the file in the local computer with the file in the remote computer, they will not be able to establish any breakpoints. And there is another option in the launch.json file. That is just my code. This is useful if I want to go outside my program. If I put it in true, then the debugger will only debug the program that is loaded in the debugger. In this case, the guest game.py would be. But if I put it in false, I can go to other libraries, maybe other dependencies of the program. For example, I can debug through PyGain, or I can debug through the standard library, going inside the functions of the standard library, and so on. OK, the code for this is this one. You see that the path mappings say, OK, for the local computer, I have that it is the workspace. It is my current folder. If I open this folder, if I open the games folder, the workspace is the document root, the workspace root. And from the other side, in the remote, the program sees that folder as a subfolder of the root. So it is dot slash games. And just my code in false. So OK, this is very nice. But what happens when I pack the program? Because until now, I have the source code of the program. And I said that this has a lot of problems, because maybe I don't have the source code, maybe it is another host, maybe another language host. That means maybe we don't want to build the full environment of the program, because we don't have 20 gigabytes free in our hard disk. So when we pack, OK, first, how we pack a program with Py2XA, OK? What we need is, first, Py2XA, probably it will work also with Py2 installer, OK? But in this case, I am using this, because it is the tool that uses NVIDIA. Obviously, I have to install it in the dependencies of the virtual environment. I need setup.py with the modules and packages that I want to pack in my library.zip. Maybe we have to monkey patch some code. For example, for this demo, I have to patch the PyGame package, because it doesn't work packet. It doesn't work well in Python versions 3.8 or more, or above. So in this case, I am using now 3.10 for the game. So I have to patch the PyGame module. I will upload a repository with all of these maybe tomorrow or next week, OK, but for the moment, just to say that it will be there. In my GitHub, it is in Ramon Corominas, and it will be slash EuroPython 2023, OK? OK. But we have another problem that debug.py cannot be packet. This is a problem, because debug.py uses some modules in the standard library that are bounded in Py2X that are not included in Py2X, even if you try to include them. For example, site.py is not packaged. Maybe we can patch Py2X. I have not tried yet to do that, but for the moment, I have not managed to debug Py inside the packet executable. So what can we do with that? I have the setup.py. This is the typical minimal setup.py. I have some includes with my UI module and packages with my audio player packets. And you see also the data files that we have to copy all the waves to the corresponding folder in the packet program. And I have to copy also the plain text file that I want to debug. Because in this case, I want to debug it in plain text, OK? So it is not inside the packet program, but it is in the external folder gains. And it is copied just as a plain text file, OK? So if we want to import that file, we need to change the way we import it from the main program. Because if we try to import it with the normal from games.guest game import play game, it will not import or worse. It will import it from the packet version. And we will not be able to include all the debug.py stuff that we need there, OK? So we changed that. So even in the packet program, the import will work, because it is importing from a folder and not exactly from a package, OK? I hope this is understandable. Another thing here. And there are some lines. Because in the packet version, we don't have the double underscore file, double underscore, the double under dot file, the file variable. We don't have that variable, so we have to test our directory from the executable itself, OK? OK, so how can we load the debug by if we cannot pack into the executable file? So we can create an empty environment. We can install the bug be there in the virtual environment that we just create for this, OK? We create an empty environment. That should be the same version as the Python version that we are using in the main program. Then we install there the debug by package. Then we can create a directory in our hard disk and move the debug be and all its dependencies. For example, debug by and debug by this in for something like that. We have to copy that to our folder. We can add that folder to the sys.pass variable. So we can now import from that folder instead of our virtual environment or whatever that we wanted to import from. For example, I usually have a folder in my hard disk that is only for the backers of the different versions of Python. So I can load always the debug be from there, OK? And we have to fix that because if we try to import that, you can try. I will not do it here because I don't have time. Whoa, I have 13 minutes. I think it's enough for the last demo, OK? So OK, we have to fix this installation because the debug by needs some modules of the standard library. I mentioned site.py. For example, also the underscore site buildings.py, also JSON, the package JSON, and the XML RPC package, OK? All of that can be copied to this folder. With these debuggers, so I will show you that in my local computer, for example, I have moved them to the root, OK? So in the debuggers, I have the debug adapter for Python 3.7. That is the one that I use for MVDA. And I have the debug adapter for Python 3.10. So here I have, OK, this is not needed. I have debug.py. These are copied directly from the virtual environment that I created explicitly for that. This is copied from the Python version, from the installed Python version that I have here, from Python 3.10, in this case. This is also copied from there. And these two, they are also copied from there, OK? So with that, if I put that in the sys.path variable, I can import from that folder, OK? So now I can import debugg.py there. OK, but there is a problem, because if I try to spawn the adapter from debugg.py just this way, there are some problems, because debugg.py uses a subprocessor to launch the adapter, to spawn the adapter to listen, OK? To launch the debug server. It uses a subprocessor that tries to use the same executable as the program that is running the main thread, OK? So if I run the program with Python, with Py, gamify.py, and so on, the main program is Python. But if I am in a packet program, the sys.executable, that is what debugg.py uses, is not Python, is the executable of the packet program, OK? So it will try to launch the server, but it will not be able to do that. So how can we fix that? With this line, debugg.py.configure, we set the argument Python to our local copy of Python.exe, OK? OK, local in the sense that it is the local copy of Python in the computer that will run debug.py. That is the remote computer, OK? Remember that the remote computer is the running computer, and the local computer is just for debugging, OK? So we have to add this line, the debug.py.configure. And we have another problem. I will show you now the full code of how this ends. We have a second problem that if we have managed to do all these things, we will receive a warning because the debugger is trying to use the os.path.apps path or something like that, or relative path or something like that. But we are inside a zip file, the library.zip. I will show you this in the remote computer. OK, in the remote computer. I have, OK, this is the packet version of the program, OK? So you see that here I only have, in the packet version, I only have the games folder with the temporary files that are not useful now, OK? In this folder, I only have the guessgame.py with all the needs for debugging. The waves, of course, that are the resources that I need for the packet program. And I have the gamify.exe. This is the packet version of gamify.py. And the DLLs, and a zip file that contains the standard library, the many things of the standard library. It has also, for example, our UI.py. Obviously, it is compiled, OK? It is compiled code. We have also the audio player, OK? So it is a packet version of our things. It is compiled and packaged in the library.zip. So what I wanted to say here is that we don't have absolute paths because, or relative paths. I don't remember what is the extra problem. But we don't have that because we are in the library.zip. We are not in a real folder, OK? So it cannot read it in the same way. This is because there are frozen leaves, the compiled leaves inside the library.zip, OK? So this is solved. When you receive this warning, you see the solution. They say, directly in the warning. So it is just to put this environment variable. You can do it through the system settings of Windows, in this case. Or maybe if you are running the program in, OK, in this case, maybe with Py2App, for example, in MacOS, maybe you can put it in the system variables in MacOS, OK? Or we can do this directly in our program before running the adapter, OK? We can just set the variable from our code, OK? So the final result is like this. I think it is OK. I'm not sure because I think this didn't work very well with the OS environment. But I think it is because of the order. Because maybe it has to be, OK. If you put it in the first line or the second after importing OS, it will work, OK? Anyway, I will check and I will put it the right way in the slides, OK? So the final result, OK. So for the final result, what we have here is I have to go to my remote computer. I have already in the remote, isn't it? You see the Earth, OK? So if I go to my remote computer and I open here the, oh, sorry, I am 0, 3, 8. OK, if I, sorry, I will open here. I will open it so you can see that I am doing it from the command line, OK? So if I run here the gamify.exe, you will see that now it is loading the back view from the external, from the debuggers folder, the folder that I made with all the libraries of Debugpy and so on. And if I go again to my local computer and I open here the demo version, I have four minutes, OK? OK, in the final result, OK. I have here, I have only, let me open this with code, OK. And this is my remote and this is Visual Studio Code, isn't it? Oh, sorry, wait. OK, this is my remote computer and this is Visual Studio Code, isn't it? OK, now, OK, now I have the screen split, isn't it? OK, so now I here only have the, you see, I only have the guess game.py, OK? I don't need anything else. I only need this file and I only need the launch.json prepared to connect to the remote computer, OK? So I will show you now that even if I don't open, let me check, I will put the breakpoint as always here, OK? OK, I can even close this file. I have my workspace open and the debugger, the debug adapter is waiting for our connection. So if I now press F5, it will run the program in the other side. I can go there and when I type here and the breakpoint is rich, it opens directly in our local version, OK? Have you seen that? I hope so. I did not see. OK, so it is now running and we can go here. We can go again here and say, OK, this is three. Again, to the local computer, I am switching between both. For you, it is not clear, maybe. OK, if I put this here, you will see. OK, you will see how I am doing all of this, OK? If I go to, I am in the local. OK, it has hit another breakpoint. I go to the remote. Here I can put six. OK, I am still in the remote computer. OK, it is in Spanish, but it says controlando el equipo remoto. Controlando el equipo local. I mean, I think it has said that. OK. OK, so you see that this is my way of doing things. I will switch again. OK, to my earphones. And finally, let me, OK, in Spanish again. And, OK, this is a typical debugging session, OK? I stopped the debugging session. And I will now open a different thing. This is the five minutes, OK? For the second demo. OK, I have in the B option, I have the open with code. Again, I close that. OK, here I have the full code. I have the games here, the guest game, and the library.zip. But this is not a zip file. This is a folder that I have copied here what I need to debug here, OK? I have the UI. And I have the audio player and the gamify.py that I have the source code of this file. So I have copied them in the library.zip. So if I now run in the remote computer. OK, sorry. If I go to the remote computer, I close this. OK, if I go now and do it again. It is already waiting for my connection. And if I go, excuse me. Oh, again. I will close this presentation for a moment. OK, now you can see the waiting for client, isn't it? So if I now attach to that process. You see that I have my normal program that is waiting here. Or maybe it has not dampened. OK, now it has hit a breakpoint. But if I go now. OK, now I am in the play wave function. I press F11. OK, I can go to the function itself. Even if the remote has this library packet. OK, you see the thing. Because in the local computer, I have the library and packet. But in the remote computer, it is packet in the library.zip. And it is compiled. If you want to open the file in the library, in the real library.zip, you will not have the code of the library. OK, and we can do this also with the standard library. If we have Python installed in the local computer, then we can go through the standard library even if... OK, you know. OK, and that's all. If you want... I think... oh, OK. This is just... OK. I had another demo of how I debug the remote screen reader from my local screen reader. But I think it is not worth the time. And we don't have time. Let me just go to my slides. Because I have... let me check. Wait. OK, thanks, but I was just... OK. OK. OK, I will not go to that demo, but I have a final word here because you see that I have no time. But this is also working in C++. I have an example of this. I will put it in the repository when I upload it next week. OK, so now, yes, thank you. And enjoy debugging.