Tuesday, December 1, 2015

Kivy Garden - Fixed to fertile land again

Kivy fascinates me when it comes to a python UI framework. However while I was installing the pre-requisites I was looking for a kivy-designer which is thankfully available on github.

https://github.com/kivy/kivy-designer

This chap requires the garden and filebrowser class from the kivy garden which is suppose to be downloaded by the garden script which is nothing but a python script. The moment I started setting up the bloke I get

$ garden install filebrowser
Downloading http://github.com/kivy-garden/garden.filebrowser/archive/master.zip ...
Traceback (most recent call last):
  File "/home/addy/workspace/kivyenv/bin/garden", line 190, in <module>
    GardenTool().main(sys.argv[1:])
  File "/home/addy/workspace/kivyenv/bin/garden", line 72, in main
    options.func()
  File "/home/addy/workspace/kivyenv/bin/garden", line 110, in cmd_install
    fd = self.download(opts.package)
  File "/home/addy/workspace/kivyenv/bin/garden", line 171, in download
    data += buf
TypeError: Can't convert 'bytes' object to str implicitly

The problem is with the download call. The initial data buffer is initialized as a str object. The 'r' is a variable which contains the request library's download request data which would a sequence of bytes.  Ultimately the goal is to pass the in-memory binary streams as a zipfile. However python 3 will not let us convert the bytes to str directly.  Observe the following code 

    def download(self, package):
        url = 'http://github.com/kivy-garden/{}/archive/master.zip'.format(
                package)

        print('Downloading {} ...'.format(url))
        r = requests.get(url)#, prefetch=False) # r is requests library's download content 
        if r.status_code != 200:
            print('Unable to found the garden package. (error={})'.format(
                r.status_code))
            sys.exit(1)

        animation = '\\|/-'
        index = 0
        count = 0
        data = '' # problem 1 
#the loop is basically re-assembling the binary stream 
        for buf in r.iter_content(1024):
            index += 1
            data += buf  ## this is what is throwing the exception 
            count += len(buf)
            print('Progression', count, animation[index % len(animation)], '\r')
            sys.stdout.flush()
        print('Download done ({} downloaded)'.format(count))
        
        return StringIO(data) ## why aren't we returning binary data 

Potential fix to the problem which finally worked 

# add the import to the top of the file. 
    from io import BytesIO

    def download(self, package):
        url = 'http://github.com/kivy-garden/{}/archive/master.zip'.format(
                package)

        print('Downloading {} ...'.format(url))
        r = requests.get(url)#, prefetch=False)
        if r.status_code != 200:
            print('Unable to found the garden package. (error={})'.format(
                r.status_code))
            sys.exit(1)

        animation = '\\|/-'
        index = 0
        count = 0
        data = b'' #this takes care of the string conversion
        for buf in r.iter_content(1024):
            index += 1
            data += buf  # no more error here 
            count += len(buf)
            print('Progression', count, animation[index % len(animation)], '\r')
            sys.stdout.flush()
        print('Download done ({} downloaded)'.format(count))
        
        return BytesIO(data) #return a byte stream than a string stream 

Wallah !! all works now !! 

$ garden install filebrowser
Downloading http://github.com/kivy-garden/garden.filebrowser/archive/master.zip ...
Progression 1024 | 
...... snppped ... 
Progression 206959 - 
Download done (206959 downloaded)
Extracting...
Installing new version...
Done! garden.filebrowser is installed at: /home/addy/.kivy/garden/garden.filebrowser
Cleaning...





No comments:

Post a Comment