Python refactoring with Rope and Traad
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Part Number | 97 | |
Number of Parts | 119 | |
Author | ||
License | CC Attribution 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor. | |
Identifiers | 10.5446/19947 (DOI) | |
Publisher | ||
Release Date | ||
Language | ||
Production Place | Berlin |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
| |
Keywords |
EuroPython 201496 / 119
1
2
9
10
11
13
15
17
22
23
24
27
28
41
44
46
49
56
78
79
80
81
84
97
98
99
101
102
104
105
107
109
110
111
112
113
116
118
119
00:00
Right angleComputer animationLecture/ConferenceMeeting/Interview
00:27
Code refactoringComputer virusMereologyRight angleBitWeb 2.0Slide ruleGreatest elementDifferent (Kate Ryan album)GodRandomizationHookingResultantElectronic visual displayMixed realityDisk read-and-write headComputer animation
01:56
Code refactoringIntegrated development environmentCodeComplete metric spaceActive contour modelLibrary (computing)Code refactoringCodeProcess (computing)View (database)Source codeSelf-organizationIntegrated development environmentMereologyModule (mathematics)Element (mathematics)Functional (mathematics)Power (physics)Level (video gaming)Right angleComplete metric spaceEndliche ModelltheorieRoboticsGoodness of fitState of matterGroup actionFactory (trading post)Lecture/ConferenceComputer animation
02:59
Computer fileDirectory serviceCodeRootFingerprintProgrammable read-only memoryCode refactoringObject (grammar)Process (computing)Cue sportsProduct (business)Instance (computer science)MathematicsThread (computing)Server (computing)Client (computing)Formal languageComputer fileDirectory serviceMereologyProjective planeLevel (video gaming)Power (physics)Code refactoringConstructor (object-oriented programming)Point (geometry)Social classCASE <Informatik>Multiplication signTrailElectronic mailing listServer (computing)MultiplicationMathematicsEinbettung <Mathematik>MiniDiscQuicksortObject (grammar)Different (Kate Ryan album)Run time (program lifecycle phase)Network topologyProcess (computing)Thread (computing)InternetworkingDescriptive statisticsClient (computing)BitProxy serverAnalytic continuationData dictionaryData managementImplementationCodeKey (cryptography)Frame problemVisualization (computer graphics)Goodness of fitSet (mathematics)Integrated development environmentJava appletEnterprise architectureOperator (mathematics)WordRing (mathematics)INTEGRALLetterpress printingConfidence intervalSingle-precision floating-point formatFactory (trading post)WindowCuboidFlow separationInformation1 (number)Business modelFile systemTraffic reportingSchmelze <Betrieb>Figurate numberTouch typingArmRefractionProduct (business)Row (database)View (database)Context awarenessLine (geometry)GradientRight angleGodSlide ruleLikelihood functionState of matterCategory of beingExecution unitLecture/ConferenceComputer animation
11:49
Universe (mathematics)Computer programmingDisintegrationDependent and independent variablesVolumeRevision controlClient (computing)Time domainAbstractionProper mapLevel (video gaming)ArchitectureConcurrency (computer science)Task (computing)Texture mappingState of matterOperations researchSystem callContent (media)Host Identity ProtocolMessage passingInflection pointCurve fittingHoaxMessage passingInterpreter (computing)BitProcess (computing)Client (computing)CodeExpressionIntegrated development environmentParameter (computer programming)Code refactoringFunctional (mathematics)MiniDiscTask (computing)System callBuffer solutionINTEGRALLogicComputer fileState of matterText editorCondition numberTable (information)Right angleDemo (music)Term (mathematics)MultiplicationOperator (mathematics)Point (geometry)Interactive televisionView (database)Branch (computer science)DiagramLine (geometry)SynchronizationObject (grammar)Cursor (computers)Thread (computing)Endliche ModelltheorieMultiplication signComputer architectureMereologySource codeImplementationConcurrency (computer science)Military baseMappingTrailReal-time operating systemKeyboard shortcutGoodness of fitIntegerQuicksortDependent and independent variablesRevision controlAbstractionDirectory serviceoutputFreewareProjective planeTraffic reportingProper mapResponse time (technology)Maxima and minimaGroup actionSoftware developerComputer programmingCuboidFactory (trading post)Overhead (computing)MultilaterationModal logicData structureTheoryFigurate numberPatch (Unix)Product (business)Rule of inferenceService-oriented architectureLevel (video gaming)Open setFile systemStack (abstract data type)
20:24
Convex hullVacuumMaxima and minimaHost Identity ProtocolExecution unitSchmelze <Betrieb>Cellular automatonWorkloadState of matterLipschitz-StetigkeitEmailGraphical user interfaceMoment <Mathematik>Menu (computing)Pulse (signal processing)Point (geometry)Meta elementNormed vector spaceInformationUniform resource nameAirfoilRootCollisionCalculusComputer fontAreaScalable Coherent InterfaceTwin primeMathematicsMaizeSocial classBeer steinTerm (mathematics)Electronic mailing listNo free lunch in search and optimizationChemical polarityChi-squared distributionDensity of statesGradientBitMultiplication signMaxima and minimaMedical imagingWordDemo (music)Right angleService (economics)Directory serviceGame controllerProcess (computing)2 (number)InformationPoint (geometry)Execution unitSoftware testingScaling (geometry)QuicksortCollisionFunctional (mathematics)System callVector spaceRow (database)Collision detectionInclusion mapInheritance (object-oriented programming)ForceUnit testingComputer clusterCodeServer (computing)Semiconductor memoryMilitary baseHexagonComputer-assisted translationCode refactoringLecture/ConferenceSource code
23:54
Formal languageNP-hardComputer programmingLink (knot theory)Slide rulePresentation of a groupLecture/Conference
24:45
Link (knot theory)Link (knot theory)Lecture/Conference
Transcript: English(auto-generated)
00:15
Austin is going to tell us about refactoring, which is awesome and tricky in Python. So please welcome Austin.
00:27
All right. Thank you. Okay. That's all right. Again, my name is Austin Bingham and I'm going to talk to you about Python refactoring with Rope and Thrall. I'll explain what both of those are. They're two technologies that work together. I work for a company called 60 North.
00:41
Part own it as well. So hi. This wrong button there. Right. A little bit about myself. I'm originally from Austin, Texas, and my name is Austin, so I'm Austin from Austin. When I like to show this slide to give a sense of the differences in places I've lived, Austin has statues of Stevie Ray Vaughan downtown, a big guitar god.
01:01
And I went to the University of Texas, so hook them horns. About five years ago, I moved to Norway, Stavanger, Norway, there on the west coast. Our statues there are different. We have three swords rammed into the ground, so those are like 30-foot tall stone swords to commemorate the unification of the Norwegian kingdoms. And this is the most beautiful fjord in the world, I guarantee. Come visit Stavanger sometime.
01:20
It's really wonderful. And this is something I added at the last minute. I was in The Hague the other day, and we tend to think of Python as very much being used for web stuff and being used for a lot of science and engineering. But I saw an art exhibit. This is one of the most famous Mondrian paintings here rendered using Python. I saw this at the bottom of the display, and I had to get a picture, because you can't really read it, but it's import numpy, import tkenter, from import random
01:43
art parts. They're using Python to generate really interesting art for a very overpriced painting, but the Mondrian exhibit in The Hague is really worth seeing, and you get to see some Python, so a little side note. What is Rope? Rope is a Python library for doing Python refactorings.
02:01
It's that simple. That's why I have the snake eating itself. It's a Python module you can import, but then you can have it look at your source code, and it can do things like renames and pulling out of functions and all that kind of stuff. So at a very high level, that's all that Rope is. I didn't write Rope. Rope is something that exists independent of me. I've never met the people who do it, but they're very, very bright, because it does
02:21
a really hard job refactoring Python, because Python is so dynamic. Rope has a lot of very powerful IDE-oriented features like code completion, finding definitions and occurrences. These are things you'll note, by the way, which aren't actually refactoring. They're just things that Rope is also able to do. Organizing imports, a good refactoring, looking up docstrings, et cetera, et cetera.
02:41
It's really designed to be used from IDEs and not used as a module per se. It's not wise for you to import Rope and start trying to use it yourself, because there's a lot of ceremony involved in refactorings. You want your IDE to take care of all that for you. And that's kind of what I'm getting to with Trold later on. So what are the elements of Rope? I'm gonna take a pretty high level view of Rope, just to give you a sense of the parts
03:01
of it, how a refactoring looks and things like that. I'm not gonna get into too many details. The highest level concept is the project. A project is really just a directory with a bunch of stuff under it, a bunch of files and other directories containing even more files. And this is the tree of stuff that Rope is going to manipulate for you when you ask it to do a renaming or something along those lines.
03:21
So there's a project class, and you instantiate that with a directory, and that's the base of all the things you do. You create a project just like this. I think that's fairly readable, but it's that simple. There, that's created a project, and it creates a little file for you, and it's parsed a bunch of stuff, and it's ready to go. The kind of things you can do with projects, you can walk all of the resources.
03:42
Resources are files and directories, and you can get the children of resources and continue walking. So this is just, it's not important that you understand this, this is to show the kind of the flavor of the API. It's very straightforward, really easy to understand, if a bit under-documented. There is a prefs object that you can get, and this thing is basically a dictionary
04:02
of keys to values, and these values are all sorts of settings related to how much stuff should it keep in cache, or where, I forget all the different prefs, there's like hundreds of them. And this is, if you look in your Rope project on disk, you'll see a .Rope project file, that is essentially reflected directly in this prefs class. So this is something you can interrogate at runtime if you need to, if you end up doing
04:23
IDE embedding of some sort with Rope. Right, I just said all that. Resources, again, those are things like files and directories, and this is a lot of what you end up doing when you work with Rope, is walking these trees and finding specific things you want to work with, and then applying refactorings to specific resources.
04:44
Again, not a lot of detail, just something so you have a sense of how it all is put together. What's more interesting, from my point of view, sort of aesthetically and technically, is how refactoring is done. So you have these concepts of projects and resources and so forth, but how do you actually, what does it look like to do a refactoring with Rope, from the code point of view?
05:03
The first thing you do is create a, in this case, we're creating a rename refactoring. So I've imported the rename refactoring class and I've constructed one. This can fail, of course, if Rope says that that's not a resource that exists, or you've like gone off the end of the file, it can complain, and so it's possible for the
05:20
construction of this to fail immediately. You can see this is only partially bound, and what I mean is that we've created a rename, and we've told it which project to work against, and we've told it the resource to work against, in this case a file called state.py, and we've told it the offset at which I want to do the rename, but what's conspicuously missing from this, of course, is what you want to rename it to.
05:41
So Trod has this notion of these partially bound incomplete refactorings. It's figured out, if you then tell it to do the renaming, it's figured out all the places it has to touch. So interestingly, you can use the same refactoring multiple times if you want to, for some reason, rename something to six different things. So that's the first step in refactoring with Rope. The next thing you do is calculate the actual refactoring, what you would actually
06:03
do. In this case, I'm changing whatever was at .42 into the word taco-copter. If taco-copter doesn't ring a bell, it should, because it's one of the greatest business models in the world. It's drones delivering tacos to you. It's brilliant, and hopefully one of these days it will be a reality. I think it was denied by the FAA in the United States.
06:21
They couldn't do it. One of these days, the future will arrive. Once you've calculated the changes, you haven't actually done the changes. You've just figured out what you're going to do. You can print out things like the description of the change, the changed resources, which is an interesting bit of information if you have an IDE and you need to refresh frames or something like that. That's a good piece of information to get without actually having done the refactoring.
06:43
So changes represents a fully balanced change that you can then execute. You just say project.do. Changes is the refactoring you calculated, and then this is when things actually get changed on disk. So that is the sort of 10 cent tour of how to do a refactoring in Rope.
07:02
And this is sort of the full process here from creating a project to creating a refactoring, calculating changes and doing the changes. So really pretty straightforward, conceptually pretty easy, technically very difficult, but that's Rope's job to keep the technical part difficult and not have you worry about it too much. One important feature of Trot is this notion of history.
07:22
This is the most historically accurate picture I could find on the internet. It's Abe Lincoln with a machine gun on a bear freeing the slaves. So it's a joke. History keeps track of things in this history class. Every project has a history list, I think is what it is, or a list like, I forget the exact class. But it manages the changes that have been made and also the changes that have been
07:42
undone. So if I've made a change and I want to undo it, I can do it, but it also remembers the things I've undone and I can redo them. And this is, it's kind of fun sometimes to kind of shuffle back and forth between different refactorings to see which is the one that you like the best, which is the one that maybe is most aesthetically pleasing or whatnot. To undo changes, you can just say project.history.undo, very straightforward, or you can select
08:04
specific points in the past that you want to undo. So you can go maybe four refactorings back and undo that one or redo it, as the case may be. This is transitive, maybe transitive is the wrong word, but it will undo all dependent changes. So if I undo my most recent change, or if I undo my first change, it has to undo
08:23
all the ones that have come afterwards, so it will undo all of your changes. And the same with redo. Because if it didn't do that, of course, it would just kind of spam your code in all likelihood, or you wouldn't want that. Redoing changes is very similar. There's a thing called the redo list, you can look things up in that. And of course, you would never do this manually.
08:40
You don't want to be writing code to do this. You want your IDE, again, to be asking the history object what is there and then displaying it in a nice window so you can check boxes and stuff and decide what to undo and redo. But this is just the API at the Rope level. Another really interesting and very powerful feature is multi-project refactoring. You may decide that you have separate projects in different directories and different places,
09:00
but you know that they rely on each other. One depends on the other. And you want a refactoring that mostly applies to this project to also be performed in this project. And Rope can do that. At a very high level, it works like this. You create a multi-project refactoring and you give it the refactoring type, in this case, rename, that you want to do. I've just used rename for all of my examples here. There's many other refactorings.
09:22
You construct this multi-project refactoring and tell it the other projects, not your main project, but all the other projects you'd like this to operate on. And remember, these are just projects built on some other directory tree somewhere. And then you can use the MPR, the multi-project refactoring there to construct the unbound refactoring
09:40
just like we did earlier. Then you create the changes like we did earlier and change it. This is clearly somebody who likes Java because it's the enterprise proxy manager implementation factory factory. And then you would do multi-project perform on the changes. The multi-project API is a bit weird, and it took me basically a lot of experimentation to figure out how it worked.
10:01
But it does work. I can say that with good confidence. It works as well as Rope works on single projects, which is not perfect all the time. We talked a lot about refactoring things that Rope does. It has a lot of obviously non-refactoring related things like finding docstrings and finding definition points and so forth. These are great IDE tools as well.
10:22
Frankly, I use JEDI for a lot of that kind of stuff now, but I still use Rope and Traud for pure refactorings. I've said this many times, but Rope is not intended for manual operation. It's really tricky to get right and let your IDE do the heavy lifting for you. Let an integration tool do the heavy lifting for you. And that is where Traud comes in.
10:43
There's the definition of Traud. It's Norwegian for thread. I thought that was kind of witty. Yeah, Rope, thread, okay. Little pro tip, if you need to find names for your projects, learn a foreign language and just use the foreign language's word for that. I'm not Norwegian, obviously.
11:01
So I just picked Traud, and nobody in the world has used Traud for a project name. So it was wide open. So what is Traud? Traud is an HTTP JSON server wrapped around Rope. That's all it is. All it did is put an HTTP API on top of Rope so that you can call it easily. It also includes, I say, various clients for driving the server.
11:22
Right now it contains one, and that's for Emacs. So I use Emacs, and so I needed this tool, basically, is why I wrote this. So the idea is that your IDE, Vim, Emacs, Visual Studio, whatever, can send HTTP JSON requests to Traud, and it will work on the file system and do the work for you. It's great. The embedding is really, really easy. The embedding of a refactoring tool in Emacs is really simple, because it's just so simple.
11:44
So why Traud? Why did I go through the trouble of writing this? There are existing tools that wrap Rope for Emacs. One is simpler integration with editors. Everything in the world now, my watch probably, this table speaks HTTP JSON, right? So it's easy to send these messages back and forth.
12:00
So I didn't have to worry about embedding the Python interpreter in Emacs or something along those lines, which is technically feasible, and I know how to do it, but it's more complicated than it needs to be. HTTP is way more than fast enough for this kind of work. People will say, oh, but you're sending messages over HTTP. What about response times? No, no. HTTP is way faster than we can blink, so of course it's fast enough for this kind of work.
12:21
The real time involved in refactorings is the refactorings themselves, and so I don't have to worry about latency. This is really a great way for me to support multiple versions of Python in one Emacs. If I was embedding the Python interpreter in Emacs, I'd basically have to pick the one I wanted or jump through incredible hoops to have Python 3 and Python 2 embedded in Emacs. As it is, that's all separate processes.
12:42
It's really easy, and really Emacs knows very little about the distinction now between 2 and 3. It knows a little bit because I have to tell it, but very, very little, and this really simplifies 2-3 concurrent development, especially over multiple projects. It's an architectural win in many, many ways. It's the proper level of abstraction. The job of Trod is Python refactoring, not being embedded in an IDE, and so this
13:04
has allowed me to pull them apart and really work at the proper level of abstraction. You can see I've solved the most heinous religious war in the world now. Emacs now loves VI because they both use the same tools. If we all wrote our tools like this, we wouldn't have to complain. We'd all use the same tools really under the hood. We just had different key bindings.
13:21
Right. So it's that simple, believe me. So a little bit about the architecture. We're good on time here. This is where I get to talk about the Python goodness for the most part. I use Bottle for the HTTP handling, and Bottle is wonderful. Anybody here at Volvith Bottle? Thank you. It's brilliant.
13:40
It really is. I just copied Bottle.py, dropped it in my source directory. It's there. I don't have to worry about dependencies or anything like that. It just works, and it's awesomely, awesomely easy to use. Thank you very much. If you need to do HTTP handling, use Bottle. Or at least consider it. Another one. Pika or Pika. Who knows how to pronounce this? Pika.
14:00
Okay. He should know because he wrote it, I believe, right? Yeah. Okay. Thank him. Pika is an actor model implementation in Python, which is hence the award here. That's an Oscar. It is awesome as well. I started the implementation of Trod without that, and I had to handle my own concurrency because you need concurrent asynchronous handling of requests because some refactorings can
14:22
take a long time, especially on large code bases. Well, once I switched to actors, basically I didn't have to think about it anymore. This is another huge architectural win. I knew that my state in this actor was distinct from my state in this other actor, and I didn't have to worry about locks or anything. It just works. It just works. And the biggest win is not even concurrency, which I don't really get.
14:42
It's the conceptual clarity of the program itself. So if you've never used actors and you have concurrency nightmares or concurrency headaches, really make a branch for Pika on your project and try it out. I almost can guarantee that you're going to love it. Even not Pika. Any actor model. Stackless is essentially an actor model. Try that. Stackless is incredibly cool for many other reasons as well.
15:03
So this is another big win. So thank you. Thank you for that. The architectural diagram. If architecture has to have boxes and lines. So I was required by EuroPython to do this. You have a model at the front receiving all of the inputs and two actors. The project, which is the thing that kind of handles all of the actually talking
15:23
to rope. So it takes the requests for do a renaming, do an extraction of method, et cetera, and you can see that it works directly on the file system, which the editor is also looking at, by the way. Which is a bit of a trick sometimes. The other actor is the state, which basically is a thing that keeps track of the request
15:40
to the state of that request, and that can be queried through a bottle as well, hence the line, obviously. The task state, like I said, is just a mapping of integers, which are just increasing integers for every request, mapped to whatever the status of that thing happens to be. Failure or pending or success is sort of a free form thing. I don't use it much except to keep track of what's going on right now.
16:04
It's simple. The state actor, the state object, the task state object is an actor, and thus, call it thread safe. That's a reasonable term to use for this. Really just means it's asynchronous safe, and multiple asynchronous tasks can be accessed at any time, and I don't have to, again, think about locks or anything.
16:20
It just magically works, because there's serialized messages at every port. I've got enough time to talk about this. The important part here is for the asynchronous operations in TROS, so some request comes in for a rename. That's asynchronous, because it might take a long time. The request just spits back immediately a task ID, and then that's done from the client's point of view. The client can then come in later and ask for task 23 and get the status back,
16:44
but all the renaming actually happens asynchronously. Synchronous things happen in a much more simple way. Find definition. We want that to happen as fast as possible. There's no reason to continue without, there's no reason to come back to the IDE until it's completed, so this is a synchronous operation. There you go, UML.
17:01
There's a couple of asynchronous things, renames, extracts, organized imports, and there's a couple of synchronous things. Things like find definition, get history, find the call tip, that kind of stuff. Those are all synchronous. I love Emacs, so I had to sneak this in. Really, Emacs is the only place where I use TROD, the only place that I know that it's used at all, actually.
17:21
So the code for using TROD from Emacs is very simple, TROD open, and TROD rename. It's really that straightforward. Because Emacs knows where my cursor is, or VI for that matter, knows where your cursor is, TROD rename raging roid, which is from an Asteroids clone that I wrote, it works because you don't have to tell it where to do it from. Emacs figures it all out, and this is letting your IDE do the heavy lifting of figuring
17:44
out where to do the refactorings and stuff. I keep hitting that point over and over. This is what I mean. And this is what the HTTP messages look like as they come through. Probably all knew that anyway. Right. So how am I on time? I have about... Okay.
18:01
I could do demos or we could take questions. The demos are just me using Emacs doing some refactorings. So if there are questions, we can start with that, and I can do demos later if people want to see.
18:23
Yeah, I'll repeat the question. So the question fundamentally had to do with I have Rope doing work on files, and I also have Emacs looking at these files, potentially doing things at the same time. Right now, that interaction is very dirty and crude. I just... Let me pop the stack up a little bit here.
18:41
I'm the only person who uses TROD as far as I know, so it works for me. That's what I know. I have my Emacs set up to, once a second, refresh or revert any buffers that have changed on disk. So I know before I do a refactoring, I just save my file and do the refactoring. There are ways around this, of course, because one of the things I can ask Rope is, what are you about to change? And it can tell me, here's what I'm about to change, and then after the refactoring is
19:02
done, I can automatically revert all those buffers. I just haven't written the logic to do that. I'm accepting patches, so of course if you want to do something like that, I'm more than happy to consider it or build it in. But you do have to be a little bit careful about that kind of stuff. And you can, of course, get into weird situations where you've made your own edits
19:20
in Emacs, and then the file system's getting changed two or three times, and that's just a race condition. I'd say don't do it. Yeah. Other questions? Yes. What I've missed for a while is the go-to-format tool can take two expressions to a kind of mechanistic reformat, like to name all arguments in this one.
19:51
I don't fully understand what it is you're asking about, a mechanistic renaming of arguments. I don't know what that means.
20:02
The answer is maybe. I don't know. The question was about something I don't know. But Rope has a lot of functionality that I don't expose right now in Rope. So if you are missing some feature, we can explore whether or not it already exists in Rope or if it needs to be added or what the state is.
20:22
Any other questions? Okay. Well, we've got a little bit of time, so okay. You asked for it. All right. So this is Emacs. And I'm going to do a quick refactoring. So the first thing I need to do is start the trod server. So trod open, and I tell it the directory.
20:42
And you can see, of course, that, okay, Emacs is kind of managing this process, this trod server. It spits out some information. So that's trod running under Emacs's control. Now let me make that a bit bigger. If I can. You know, at my age, I should be able to do this.
21:01
I don't know how to make the font bigger. I'm sorry. Well, you can kind of see that. The point is, this on the right is my unit tests for my collision detection. Increase, hex scale, text scale, increase.
21:22
Hey, look at that. All right. I'll do it over here. Probably. Watch the Nyan cat. Oh, isn't that great? Does that make you feel better? Okay. Yeah, this is how I spend my time.
21:40
Okay. So we've got this function, calculate collision vector, which is defined in collision.py, collision detection stuff for my asteroids game. And over here is the unit test. And say I'm in my unit test, and I, for some reason, decide I don't like that name anymore. Right? So I can say control XTR, rename that to calc call back, and it will think about it for a few seconds. And this is kind of what you were getting at earlier in the second row about the timing.
22:04
But you can see, okay, now it's changed. Actually gave it the wrong name, but that's okay. It's changed it everywhere that you could find it. So it's changed it not only in the call here in the test, but also in the definition. One shortcoming, and I don't know if there's a great solution, is it does this. It leaves all these things incorrectly indented.
22:20
That seems like a rope shortcoming that I would like to get fixed. So if I don't like those, I can display the history now, and I can see I've got this one thing that I can undo, which was renaming calculate collision vector to calc call back. I do want to undo that, because that's actually not the name I wanted to give it. So I'm going to draw the undo.
22:43
And it will think about it for a few seconds. And then I promise it will. Now the history doesn't automatically update, so let's just ignore that for now. That's another fixable thing. But that's sort of the main things that it does.
23:01
It's just in memory. So if I kill off the trold server, it's gone. As far as I know, it might be serializable, but I've never tried, I've never looked into it. It's never been an issue for me, basically. One kind of cool thing that a lot of people might appreciate when they're starting to work with new code bases is it can clean up, rope can clean up your imports in certain ways. And so in trold, I've created the command trold imports super smackdown, and it just
23:24
runs all of the organizing and cleaning up of imports, and I tell it which file, and it does it, and a second later, it will boom. Okay, see? Isn't that much nicer than it? There's no leading import dot dot, all that kind of stuff. It's all done. And of course, I can undo that.
23:45
So that's it for the demo. If there's no more, oh, more questions, okay. Can you say that a bit louder?
24:04
Oh, renaming decorators. That's a really good question. I don't know. Like I said, I'm the only one who uses this, so if I've never had to do it, who knows if it works or not.
24:21
I would think so, because rope is pretty darn smart. Rope does incredible things, well beyond what I would have imagined would be doable with refactoring tools in a language as dynamic as Python. But we can try it out later. It shouldn't be hard. So, yeah. Anything else?
24:40
All right. I'll go to the last slide. There's some links to all this stuff. The presentation is on GitHub, github.com. You can find it. Links to everything else. And thank you very much.