[Python-Dev] Re: Proposal: get rid of compilerlike.py

Gordon McMillan gmcm@hypernet.com
Sat, 1 Sep 2001 19:53:20 -0400


[Eric]
> Right...one of which completely misses the point by suggesting
> that this is a filter framework, 

True. It's a tad more general than just a filter. How about 
UnixishTextfileTransformFramework
since that captures it's most distinguishing feature (the fact 
that it follows a popular unix convention). Also hints that it 
would chew the hell out of a binary file on Windows.

[Guido]
> > - A framework like this should be structured as a class or set
> > of
> >   related classes, not a bunch of functions with function
> >   arguments. 

[Eric]
> Yes, I thought of this.  There's a reason I didn't do it that
> way. Method override would work just fine as a way to pass in the
> filename transformer, but not the data transformer.
> 
> The problem is this: the driver or "go do it" method of your
> hypothetical class (the one you'd pass sys.argv[1:]) can't know
> which overriden method to call in advance, because which one is
> right would depend on the argument signature of the hook function

Who cares about signatures? Try the attached.

- Gordon



-------------- Enclosure number 1 ----------------
import sys, os

class UnixishFileTransformer:
    def transformFile(self, infp, outfp):
        raise NotImplementedError
    def transformData(self, data):
        raise NotImplementedError
    def transformLine(self, line):
        raise NotImplementedError
    def transformFilename(self, nm):
        raise NotImplementedError
    def run(self, args):
        if not args:
            self.fnm = "stdin"
            self._do_one(sys.stdin, sys.stdout)
        else:
            for fnm in args:
                if fnm == '-':
                    infp = sys.stdin
                    self.fnm = "stdin"
                else:
                    infp = open(fnm, 'r')
                    self.fnm = fnm
                tempfile = file + ".~%s-%d~" % (name, os.getpid())
                outfp = open(tempfile, "w")
                try:
                    self._do_one(infp, outfp)
                except:
                    os.remove(tempfile)
                    raise
                infp.close()
                outfp.close()
                try:
                    newnm = self.transformFilename(self.fnm)
                except NotImplementedError:
                    if filecmp.cmp(file, tempfile):
                        continue
                    newnm = self.fnm
                    os.remove(self.fnm)
                os.rename(tempfile, newnm)
                
    def _do_one(self, infp, outfp):
        try:
            self.transformFile(infp, outfp)
        except NotImplementedError:
            try:
                while 1:
                    line = infp.readline()
                    if not line:
                        break
                    outfp.write(self.transformLine(line))
            except NotImplementedError:
                try:
                    lump = line + infp.read()
                    outfp.write(self.transformData(lump))
                except NotImplementedError:
                    raise NotImplementedError, "no implementation of a transform method provided"

if __name__ == '__main__':
    import getopt
    class T1(UnixishFileTransformer):
        def transformFilename(self, fnm):
            return fnm+'.out'
        def transformFile(self, infp, outfp):
            while 1:
                line = infp.readline()
                if not line:
                    break
                if line == "\n":
                    outfp.write("------------------------------------------\n")
                outfp.write(line)
    class T2(UnixishFileTransformer):
        def transformFilename(self, fnm):
            return fnm+'.out2'
        def transformLine(self, line):
            return "<" + line[:-1] + ">\n"
    class T3(UnixishFileTransformer):
        def transformFilename(self, fnm):
            return fnm+'.foo'
        def transformData(self, data):
            lines = data.split("\n")
            lines.reverse()
            return "\n".join(lines)
    
    (options, arguments) = getopt.getopt(sys.argv[1:], "fls")
    for (switch, val) in options:
        if switch == '-f':
            t = T1()
            t.run(arguments)
        elif switch == '-l':
            t = T2()
            t.run(arguments)
        elif switch == '-s':
            t = T3()
            t.run(arguments)
        else:
            print "Unknown option."