REAL UGLY KLUDGE to replace and import modules (almost) transparently

Steven D. Majewski (sdm7g@elvis.med.virginia.edu)
Tue, 9 Nov 1993 19:08:03 -0500

A Real Ugly Kludge to overlay module namespace in python,
OR The Return of Obfuscated Python ...

A Long Story:

All of that old thread on overly-pedantic error checking, and
trying out pseudo-sequence classes has finally made clear to
me in a practical way the real differences between ADT's and
O-O.

I cross-posted an article in comp.{object,misc,compilers} about
reusing interfaces vs. inheritance, where I made the flame bait
statement that, given abstract data types with methods and/or
generic functions, inheritance didn't seem to gain me much other
than saving a little cutting and pasting with the editor.

So, when I needed to make this patch to the FTP class, I felt
an obligation to avoid my impulse to patch it in the ftplib.py
source, but to try using inheritance. ( just to be honest
and try to give myself a counterexample! ) BUT: I was unable to
import it as 'ftplib' and still use the distribution ftplib.

Renaming the distribution python/lib/ftplib.py didn't seem
acceptable - In that case, I might just as well have edited
the source. And changing all occurances of 'from ftplib import FTP'
to 'from myftplib import FTP' was not acceptable, either.

But, given a working Mac-friendly ftplib.cwd(), after a few
failed attempts, I gave up on the problem until I rasied the
question again in my recent post about library-file namespace.

So, I gave it another try, and here is the ugly kludge that
works - I haven't made the effort to make it portable - it
assumes it is in ftplib.py in the current working directory.
The trick is to remove the current directory from sys.path,
and 'ftplib' ( *THIS* ftplib ) from sys.modules. THEN import
ftplib, which brings in ANOTHER ftplib on the import path.
Then restore path and modules. Without restoring msaved to
sys.module, it will appear to work while importing this
module ( I stripped out all of my debug lines ) but the
name ftplib in the main program will NOT be interpreted
as a module name.

Oh! I wish I could be there to see Guido's expression as
he reads THIS! If you thought "obfuscated python" was bad ...
Try and top THIS, Tim! ;-)

- Steve

[ Anybody have any tips on how to make it position/name/path
independent ? ]

###### - file named './ftplib.py' #######
import sys
del sys.path[sys.path.index('.')] # remove '.' from sys.path
msaved=sys.modules['ftplib'] # remove and save module
del sys.modules['ftplib']

from ftplib import * # import the OTHER ftplib

sys.path.insert( 0, '.' ) # put the path pack
sys.modules['ftplib'] = msaved # put the module back

oldFTP = FTP # reference to original

# NCSA Telnet's ftpdaemon for the Mac ( and maybe for PC also )
# doesn't recognize 'CDUP' command, but it does some limited
# posix pathname to/from native conversion, so cwd('..') will work.
# ftplib.FTP().cwd translates cwd('..') into a CDUP operation.
# this cwd falls back on 'CWD ..' if CDUP fails.

class FTP( oldFTP ):
def cwd( self, dir ):
try:
oldFTP.cwd( self, dir )
except ( error_perm, ), why :
if why[:3] == '500' :
print 'CDUP did not work, trying CWD ..'
oldFTP.voidcmd( self, 'CWD ..' )
else: raise error_perm, why

def mactest( who ):
ftp = FTP().init(who)
ftp.login()
ftp.pwd()
ftp.cwd('..')
ftp.pwd()
ftp.cwd('..')
ftp.pwd()
ftp.quit()