[Tutor] flag to call methods on objects?

Dave Angel davea at ieee.org
Sat Aug 1 13:28:33 CEST 2009


(You replied off-list, so I'm copying your email, plus my response, to 
the list)

prasad rao wrote:
>   >I still see four problems.
>
>
> Hello Dave.I made modification as suggested by you.
>
>
>   
You made the first three.  But the problem of zlib.compress() producing 
a string with an embedded (0a) still hasn't been addressed.  And I 
suspect this is your next problem.  If you don't give the whole string 
that zlib.compress() produced to zlib.uncompress(), then it'll fail as 
you saw here.

>>>> import mcript
>>>>         
>
> Traceback (most recent call last):
>   File "<pyshell#13>", line 1, in <module>
>     import mcript
>   File "C:\Python26\mcript.py", line 84, in <module>
>     a.main()
>   File "C:\Python26\mcript.py", line 65, in main
>     nl= self.__shorten(self.__undigi(self.__decompress(line.strip())))+'\n'
>   File "C:\Python26\mcript.py", line 47, in __decompress
>     astring=zlib.decompress(astring)
>  error: Error -5 while decompressing data
>
> on interactive mode it is(decompress())working well.
>
> What should I do to rectifi this error?
>
> I dont know java,know basics of c++
>
> I started to lear python hardly onyear back.
>
> This is my 1st program using classes.
>
> Thanks for your time.
>
>
>
> #! usr/bin/env python
>
> import ast,random,os,zlib,string
> key=5
> class Cripto(object):
>     def __init__(self,afile):
>         self.afile=afile
>     def __digi(self,astring):
>         y=[]
>         for x in astring:
>             y.append(ord(x))
>         y=str(y)
>
>         return y
>     def __undigi(self,astring):
>
>         alist=ast.literal_eval(astring)
>         y=[]
>         for x in alist:
>             y.append(chr(x))
>         astring=''.join(y)
>         return astring
>     def __gen_string(self):
>         s=''
>         nl=random.sample(string.ascii_letters,key)
>         for x in nl:s+=x
>         return s
>
>     def __lengthen(self,astring):
>          s=list(astring)
>          ns=''
>          for x in s:
>          ns+=x
>          ns+=self.__gen_string()
>          return ns
>     def __shorten(self,astring):
>
>          s=list(astring)
>          ns=''
>          for x in range(0,len(s),key+1):
>          ns+=s[x]
>          return ns
>     def __compress(self,astring):
>         astring=zlib.compress(astring)
>         return astring
>     def __decompress(self,astring):
>         astring=zlib.decompress(astring)
>         return astring
>     def main(self):
>         sorce=open(self.afile,'r')
>         data=(sorce.readlines())
>         dest=open((os.path.split(self.afile)[0]+os.sep+'temp'),'w')
>         if (data[0]).strip()=='flag1':
>
>             ns='flag0\n'
>             data=data[1:]
>             for line in data:
>                nl=
> self.__compress(self.__digi(self.__lengthen(line.strip())))+'\n'
>                ns+=nl
>             dest.write(ns)
>         elif data[0].strip()=='flag0':
>             ns='flag1\n'
>             data=data[1:]
>             for line in data:
>                 nl=
> self.__shorten(self.__undigi(self.__decompress(line.strip())))+'\n'
>                 ns+=nl
>             dest.write(ns)
>         else:
>             print 'File does not begin with the flag'
>             sorce.close()
>             dest.close()
>             os.remove(os.path.split(self.afile)[0]+os.sep+'temp')
>             return
>
>         sorce.close()
>         dest.close()
>
>         os.remove(self.afile)
>         os.rename((os.path.split(self.afile)[0]+os.sep+'temp'),self.afile)
>
>
> #========
> a=Cripto('C:/pp.txt')
> a.main()
>
>   
There are a couple of places where indentation has been broken.  For 
example, in method __shorten(), the for loop body isn't indented.  Are 
you retyping these, or are you using tabs in your source, or is paste 
broken on your system?

What Python version are you using?  It's clear that you're using 
Windows, so you will need to store the encoded file as binary.   
Furthermore, something I didn't spot before is that strip() isn't safe 
on the compressed data.

You said you tested the lower-level functions manually.  But they're not 
correct, so clearly it's past time to put in place some form of test 
harness.

To properly test the code, you'll need to remove most of those 
double-underscores.  And I'd suggest factoring out two methods, encode() 
and decode(), as follows:

    def encode(self, unencoded):
        nl= 
self.__compress(self.digi(self.lengthen(unencoded.strip())))+'\n'
        return nl
    def decode(self, encoded):
        nl= 
self.shorten(self.undigi(self.__decompress(encoded.strip())))+'\n'
        return nl


I don't have your data file to test with, so I may not get exactly the 
same errors.  In fact, multiple runs with the same data give different 
results.  Sometimes I get bad data, and sometimes an exception like 
yours. Probably that's because of the random string you append in 
lengthen().  But the crash itself is probably caused by the bug I 
described in #4 of my previous message.  zlib.compress() produces binary 
data, and you're assuming leading and trailing whitespace is irrelevant, 
and that there are no embedded 0a codes.

So the first test I wrote was:

def test_lengthen(line):
    xx = a.lengthen(line)
    yy = a.shorten(xx)
    if yy != line:
        print "shorten did not reproduce original data for ", line
    #else:
        #test_digi(xx, line)         #this will be the next level of 
testing.

Make up a few strings, and call this function.  It fails every time.

Your shorten() and lengthen() methods are not inverses.  shorten() does 
not recreate the original text passed to lengthen.   You'll have to fix 
that before you can do anything else.




More information about the Tutor mailing list