Monday, November 10, 2008

NetBeans Screenshot of the Week #32: Python Import Management

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


We're about to release an early access release of Python support for NetBeans. We have ambitious goals for the Python support: NetBeans should be the best IDE for Python development, bar none!



Over the next couple of weeks I'll post screenshots of a bunch of editor related features for Python. Today I'll start with a feature near and dear to my heart: Import Management.



I used to be a die hard XEmacs user. When I started coding in Java, I continued using emacs for a couple of years. And the feature which finally made me abandon emacs for a Java IDE? You guessed it -- import management. If I wanted to use for example the List class, I could just press a keystroke to choose which List class I had in mind, and the import statement was added for it at the top of the file while I could continue working in the middle of the file somewhere.



To be sure, this is not rocket science, and Emacs support for Java has improved a lot over the years. But at the time, this was a huge productivity boost and coupled with other code-intelligence and navigation features was enough to lure my away from my comfort zone in the IDE to what was a less powerful plain text editor, but a more powerful Java coding tool.



Anyway, Python shares some similarities with Java. There are lots of libraries, and you need to import modules before you can use them. And this is where NetBeans' Python support can help.



Let's say I've tried calling the cmp method to compare files. I ran the code and realized I need to import cmp before I can use it. To get the IDE to import the symbol for me, I can just pull up the context menu and select Fast Import (or more realistically, just use the keybinding Alt-Shift-I):



This brings up an import dialog like this:



This tells us there are two definitions of a function named cmp - one in filecmp and one in functions. I'm interested in the first one. The label below the list tells me that I can hold the Alt key or the Shift key when I select the list entry to change the import statement. And below that, there is a preview of the import statement that will be generate. As soon as I press the Alt key, the window changes to this:



Here, the bottom line is showing that we will be doing a wildcard import of all symbols instead of just the target symbol. And finally, let's press Shift:



This will not just import the cmp symbol, it will instead import the whole module and change my current call to use the imported module symbol. When I press Enter my editor looks like this:




This is the import facility I ditched Emacs for ten years ago. But it's not how I manage imports for Java anymore. Instead, there is the Fix Imports action (it's also there in the menu -- Ctrl-Shift-I for short). Unlike Fast Import, which looks at the identifier under the editor caret, Fix Imports will look at all your imports in the file, and, well, fix them! This means sorting them, removing duplicates, even removing unused imports. And obviously, resolving imports automatically using the machinery I showed above. Here's how this works.

Here I've opened the SocketServer.py file, and then I've commented out all the imports:



The file is now broken - it has various references to functions that are not defined/imported anymore. Let's see what happens if I press Ctrl-Shift-I:



Tadaaa! It has figured out the missing imports and has inserted them. This is confirmed by a message in the lower left hand corner:



This just happened automatically because NetBeans could figure out, unambiguously, what the missing imports must be. Let's make it less clear-cut. I'm going to insert a call to get(). Now let's try again:



This time we get a dialog. You can see that it has figured out the sys and os imports - but it is not certain to do about the call to get(). There are two modules defining this function - unicodedata and webbrowser:



The corresponding function signatures are listed to help me decide which one I'm interested in. I can choose one of them, and when I press Ok, the imports are applied.



In some cases it may not find the symbol at all. Let's put in a bogus call:



Here the import manager can't figure out what to do - there is no known matching function. Only when NetBeans is certain about the imports does it proceed to clean up the imports without any user intervention.



This facility can also help find bugs! When I was testing this feature, I happened to invoke it in the datetime.py file which ships with Jython. Here's what it said:



That's right - the code is referencing nonexistent class ValuError. This clearly should be ValueError!
NetBeans has additional facilities for tracking down these types of bugs which I'll cover in another post.



So far I've focused on using the import facility to import new symbols. If you're writing code using the editor you may not need it, since when you use code completion to insert calls, it also automatically inserts import statements as needed.
However, another useful aspect of Fix Imports is cleaning up your imports: removing duplicates, sorting alphabetically (configurable), and even deleting unused imports.



If you open up a file with unused imports, NetBeans will show you that immediately:



There are quickfixes here, so if you click on the lightbulbs or press Alt-Enter, you can see the import actions:



The integration with quickfixes means that if you look in the tasklist, it will show files containing unused imports. But when you're editing, you can just press Ctrl-Shift-I to clean up the imports - it will do everything we've covered so far: Add missing imports, remove duplicates, remove unused, and sort the remaining imports.



Import management is also tied into source formatting. If you format your source, you can optionally have it clean up formats. Here are the formatting options for Python:



You can play with the checkboxes and the preview will show you the effect. Here's what happens if we enable sorting system libraries to the top. Note also that removing unused imports is not done by default during formatting (whereas Fix Imports will perform it automatically). You can change that in this formatting preference panel:




As I mentioned, we'll have an early access version out very soon. If you're feeling adventurous, you can always download builds from the continuous build server - http://deadlock.netbeans.org/hudson/job/python/. Please file bugs and ideas here.


No comments:

Post a Comment