Quickies: Telnet in Cygwin 1.7

Windows’ cmd.exe is pretty anemic and just doesn’t have the feel of a real command line. (It isn’t.) PowerShell is cute and has its uses for poking around with COM objects and the likes, but for common tasks it seems ridiculously verbose and unnecessary. Cygwin alleviates much of this in an Windows environment and grants those of us who use proper shells a method of interfacing with Windows. Well, kind of!

Unfortunately, Cygwin 1.7 has moved a few things around. Geeks like me tend to use telnet to verify connectivity to other hosts, communicate directly with certain services (hey, HTTP isn’t that difficult), and troubleshoot. However…

[gridlock-x:~]$ which telnet
/cygdrive/c/WINDOWS/system32/telnet

Hmmmm… this isn’t good. Windows’ telnet is terrible. More importantly, it doesn’t work in Cygwin. After some exploration, it would seem that the Cygwin folks have consolidated telnet and a few other useful utilities into a single package.

cygwin_17-01

If your distribution doesn’t have telnet available, make sure to run the setup utility again and select the “inetutils” package. Once you’ve finished up the installation (again), it’ll install only the changed package, and you’ll have access to telnet again. Horray!

Although Cygwin 1.7 is still in beta, the developers are encouraging everyone to give it a try. What can I say? It has a lot of nice improvements over the 1.5 branch. Heck, it even finally comes with a decent icon for a pre-configured rxvt shortcut! Now that’s classy.

Try it out!

No comments.
***

wxPython Menu Status Text

wxPython isn’t quite as easy to develop for as some other GUI toolkits but the greatest benefit is that it uses native widgets in Windows. I believe the PyQT bindings also support native widgets and have since QT 4, but I personally find that certain simple layouts behave slightly faster in wxPython than PyQT. Perhaps I’ll test this theory and be surprised whenever I put together a QT-based project next!

One of the unfortunate problems with wx is that the toolkit’s documentation requires a significant amount of introspection, some knowledge of what subject in particular is sought after, and a little bit of experimentation. The examples that ship with wxPython are absolutely fantastic and make up for what the documentation lacks. However, some things aren’t very obvious. Here’s a good example.

If you open Windows Explorer (this is the XP version–Vista and Seven both do something similar) and mouse-over each of the menu items, you’ll notice brief snippets of help text on the status bar. Here’s a shot of the status bar before:

screenshot_01

And here’s a shot while leaving the mouse over “File”:

screenshot_02

Something like this is pretty easy to accomplish in .NET and merely requires attaching a method to the appropriate handler. This isn’t so obvious in wxPython (and I’d imagine the wx toolkit in general) and requires a bit of work.

Your first inclination might be to do something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class MyFrame (wx.Frame):
    def __init__ (self):
        wx.Frame.__init__(self, None, -1, "My App", pos=wx.DefaultPosition,
                          size=(300, 300), style=wx.DEFAULT_FRAME_STYLE)
        # In whatever part of your code you're adding the file menu...
        menu = wx.MenuBar()
        file = wx.Menu()
        file.Append(100, "&New\tCtrl+N")
        file.Append(101, "E&xit\tAlt+F4")
        menu.Append(file, "&File")
 
        ##
        # Add some bindings...
 
        # This only works AFTER the menu has been opened
        # and only when we highlight a menu ITEM... oops
        self.Bind(wx.EVT_MENU_HIGHLIGHT, self.OnMenuHighlight)
 
        # Close, but not quite--you'll see why in a minute
        self.Bind(wx.EVT_MENU_OPEN, self.OnMenuOpen)
 
    def OnMenuHighlight (self, event):
        # Do highlight
        pass
 
    def OnMenuOpen (self, event):
        # Process opening a menu
        pass

At first blush it would seem that the wx.EVT_MENU_HIGHLIGHT gives us exactly the event we want. However, once we run our application we’ll be surprised to note that this doesn’t work as expected. The wx.EVT_MENU_HIGHLIGHT is triggered only when a menu item is highlighted. wx.EVT_MENU_OPEN is much closer to what we want, but there’s one small problem. Before I can explain the issue, let’s look into some object introspection.

First, let’s assume that we have the following in our OnMenuOpen() function:

1
2
3
4
5
    def OnMenuOpen (self, event):
        print "event.GetMenu()\n"
        print dir(event.GetMenu())
        print "\nevent.GetMenu().GetMenuBar()\n"
        print dir(event.GetMenu().GetMenuBar())

This will yield something like the following (I’ve snipped out the irrelevant parts):

event.Menu:

['FindItem', 'FindItemById', 'FindItemByPosition', 'GetClassName', 'GetEventHandler',
'GetEvtHandlerEnabled', 'GetHelpString', 'GetInvokingWindow', 'GetLabel', 'GetLabelText',
'GetMenuBar', 'GetMenuItemCount', 'GetMenuItems', 'GetNextHandler', 'GetParent',
'GetPreviousHandler', 'GetStyle', 'GetTitle', 'HelpString']

event.Menu.MenuBar:

['FindFocus', 'FindItemById', 'FindMenu', 'FindMenuItem', 'FindWindowById', 'FindWindowByLabel',
'FindWindowByName', 'Fit', 'FitInside', 'Font', 'ForegroundColour', 'Frame', 'Freeze',
'GetAcceleratorTable', 'GetAdjustedBestSize', 'GetAutoLayout', 'GetAutoWindowMenu',
'GetBackgroundColour', 'GetBackgroundStyle', 'GetBestFittingSize', 'GetBestSize',
'GetBestSizeTuple', 'GetBestVirtualSize', 'GetBorder', 'GetCapture', 'GetCaret', 'GetCharHeight',
'GetCharWidth', 'GetChildren', 'GetClassDefaultAttributes', 'GetClassName','GetClientAreaOrigin',
'GetClientRect', 'GetClientSize', 'GetClientSizeTuple', 'GetConstraints', 'GetContainingSizer',
'GetCursor', 'GetDefaultAttributes', 'GetDefaultBorder', 'GetDropTarget', 'GetEffectiveMinSize',
'GetEventHandler', 'GetEvtHandlerEnabled', 'GetExtraStyle', 'GetFont', 'GetForegroundColour',
'GetFrame', 'GetFullTextExtent', 'GetGrandParent', 'GetGtkWidget', 'GetHandle', 'GetHelpString',
'GetHelpText', 'GetHelpTextAtPoint', 'GetId', 'GetLabel', 'GetLabelTop', 'GetLayoutDirection',
'GetMaxHeight', 'GetMaxSize', 'GetMaxWidth', 'GetMenu', 'GetMenuCount', 'GetMenuLabel',
'GetMenuLabelText', 'GetMenus', 'GetMinHeight', 'GetMinSize', 'GetMinWidth', 'GetName',
'GetNextHandler', 'GetParent', 'GetPosition', 'GetPositionTuple', 'GetPreviousHandler', 'GetRect',
'GetScreenPosition', 'GetScreenPositionTuple', 'GetScreenRect', 'GetScrollPos', 'GetScrollRange',
'GetScrollThumb', 'GetSize', 'GetSizeTuple', 'GetSizer', 'GetSizerProps', 'GetTextExtent',
'GetThemeEnabled', 'GetToolTip', 'GetTopLevelParent', 'GetUpdateClientRect', 'GetUpdateRegion',
'GetValidator', 'GetVirtualSize', 'GetVirtualSizeTuple', 'GetWindowBorderSize', 'GetWindowStyle',
'GetWindowStyleFlag', 'GetWindowVariant']

The answer seems obvious–at first. All we need to do is add event.GetMenu() to our OnMenuOpen() function and… wait. How are we going to know which menu was opened? There’s no identifier we can use. Maybe if we use event.GetMenu().GetLabelText() we can examine the string for “File” or whichever menu the user has opened…

Traceback (most recent call last):
  File "ui.py", line 37, in OnMenuOpen
    print event.GetMenu().GetLabelText()
  File "D:\Python25\Lib\site-packages\wx-2.8-msw-unicode\wx\_core.py", line 1126
8, in GetLabelText
    return _core_.Menu_GetLabelText(*args, **kwargs)
TypeError: Menu_GetLabelText() takes exactly 2 arguments (1 given)

Damn.

We then try various incantations of this code. We might even wind up with something embarrassingly convoluted like event.GetMen().GetMenuBar().Get… Ugh. I think I’ve lost myself after that one.

Fortunately, the solution isn’t terribly difficult. You can even add some additional features yourself, if you like. But here’s the catch: There isn’t anything in the documentation that indicates if it’s even possible using the existing classes to figure out which menu someone has opened. So, if you’ve got “File,” “Edit,” “View,” and “Help” menus, you’re out of luck–at least with the stock wx classes.

Here’s the quick and dirty solution that worked for me. It may not be optimal, but it sure beats screwing around with object introspection and trying to Get() a clue. (See that pun I did there?)

Simply extend wx.Menu:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#########
# Menu
class Menu (wx.Menu):
    '''Menu
Overrides the default wx.Menu object to provide offset and status text
monitoring.'''
    offset = -1
    statusText = ""
    def __init__ (self, offset=-1, status=""):
        '''constructor
Create a new menu item.
 
``offset`` indicates what offset this menu item lives at in the menu but can
be any ID you prefer.
 
``Status`` indicates the status text you wish to use with this menu item for
retrieval by the status bar.'''
        wx.Menu.__init__(self)
        self.offset = offset
        self.statusText = status
 
    def GetOffset (self):
        '''GetOffset()
Returns the user-defined offset to identify this menu item's position in the
menu bar.'''
        return self.offset
 
    def GetStatusText (self):
        '''GetStatusText()
Returns text associated with this control for shuttling to the status bar.'''
        return self.statusText
## end Menu

And then modify your OnMenuOpen() function to read:

1
2
3
4
5
6
    def OnMenuOpen (self, event):
        '''OnMenuOpen (event)
Triggered whenever a menu itme is opened. Sets the default status text.'''
        print event.GetMenu().GetLabel(1)
        if hasattr(event.GetMenu(), "GetStatusText"):
            self.statusBar.SetStatusText(event.GetMenu().GetStatusText(), 0)

Then when you create a new menu item, just simply pass the offset and the text to your new class:

1
2
3
4
5
        menu = wx.MenuBar()
        file = wx.Menu(0, "Contains file operations")
        file.Append(100, "&New\tCtrl+N")
        file.Append(101, "E&xit\tAlt+F4")
        menu.Append(file, "&File")

The hasattr() call is needed for submenu items otherwise OnMenuOpen() will trigger an exception whenever the user mouses over a submenu. If you don’t have submenus, you probably don’t need to worry about this. In this example, I assume that we’ve added a wx.StatusBar to our initial class.

Combining this trick with the wx.EVT_MENU_CLOSE event will yield a fairly painless method of altering (and resetting) the status bar text whenever the user opens a menu item.

No comments.
***

Links June 17th

It’s an uninteresting week but there’s a few nifty things out there tech-wise.

Shaking the world of browsing? Okay, maybe not…

Opera 10’s beta seems to be attracting a lot of attention. I still wish they had done something like a P2P network to work around routing issues.

Imagine the following situation: Person A lives in California. Person B lives in Texas. Person A and B share the same favorite site. It may be a social network or perhaps their favorite new aggregator. Person A can get to the site but Person B is running into a “local” routing issue which allows them to communicate with Person A but Mr. B can’t access this particular site. If Opera included a P2P web sharing mechanism, Person A’s browser could fetch the data for Person B.

There’d be a number of security implications, of course (passwords could be easily sniffed!) but for simply accessing a site, particularly if you really need to read it, this could be a workaround for local connectivity issues. I’d imagine the security concerns could be worked around by prohibiting form submission via the P2P connection in addition to disabling cookie access to the site.

Is HTML 5 the death knell of Flash, Silverlight, and Java Applets (JavaFX?)

It is interesting to say the least. It sounds a little idealistic to me, and the web doesn’t traditionally fare well with massive, wide-sweeping changes. Instead, many of the technological changes we’ve seen have largely been delivered piecemeal with the more interesting or useful features considered for early adoption. Those of us who have been using Firefox, Opera, and WebKit (as far as I know) have been able to enjoy limited Canvas features for at least two years. AJAX-related technologies adopt some parts of the HTML 5 spec from–once again–years ago.

Local storage and background processing seems a little far-fetched for the time being. However, it’s feasible the Internet could evolve into a distributed “operating system.” All it’d take would be merging the concepts of P2P networks (hello, Opera) and HTML 5 proposals.

We’ll see what happens. I’m not going to wager any guesses, but the HTML 5 spec sounds increasingly revolutionary. Revolutionary insofar as the Internet is concerned usually breeds half a dozen incompatible implementations–even if there is an accepted standard in place. What’s this mean for the consumer? Well, not much. Don’t expect to see any significant changes for another couple of years at best. At worst, we might see a few of the neater ideas being integrated into your favorite browser while everything else fades into vaporware.

Eclipse Galileo RC4 is out

You can read about it here. I noticed the other day while running some updates that Eclipse Galileo is due to be out in about two weeks. I’m really excited about this. From what I’ve been hearing they’re introducing a number of performance boosts and have given SWT a bit of a face lift. I really like Eclipse for general purpose coding but it’s pretty cumbersome for incredibly simple tasks. (Quick scripts get written in a simple text editor or maybe a very basic syntax highlighting-capable editor like Notepad++.) Maybe this next version will change that?

DZone has been banging around some more D language propaganda

Actually, I’ll confess. This article is really quite good. It’s actually giving me an itch to try D, and I might have to go about scratching it soon. I’ve been watching the language for a few years off and on (probably since 2002-2003 when I first heard about it from a friend), but I always assumed it was going to fade away into obscurity. It hasn’t yet, and it’s been at least six years and growing albeit rather slowly.

That said, it might be worth a look.

Internet censorship to rise in Germany

This article may be a little sensationalistic, but I think it’s worth a read. The unfortunate thing is that many do-good politicians are pushing strongly both here in the US and abroad (but most especially abroad) to censor Internet services in the name of protecting children. Sure, it sounds like a great idea–but the Aussies are already well aware of what a move like this does to the utility of the Internet. Late last year, there was talk about the Aussie filters being too ambitious, and they were. If I recall correctly, many sites (including Wikipedia) were affected due to simply mentioning a banned term.

People like their freedoms, and when they’re afraid a government initiative could potentially be used to stifle their freedoms, it doesn’t matter if it’s pushed under the guise of protecting the children. Things like this sound great–initially–but when they can be extended to squelch anything else that could be construed as “unlawful” (I see you’re saying something bad about the party in power! Ahhh, what a shame you won’t be able to have your dose of Internets today…), people get worried.

And rightfully so, I might add.

No comments.
***