Forum Archive

Issue with sys.Argv (BETA 160033)

wradcliffe

When running a script - clipboard.get() appears to be returning the full path to the current file opened in the editor instead of the contents of the clipboard. It also seems to cause a "cut" operation to be performed in the editor.

Note - clipboard.get() issued from the interactive prompt work fine. Running a script and using the function from a script shows the problem.

Note - I know the FileDownloader script was running fine in the release before BETA 160033

REPRO - switch out of Pythonista and copy a URL into the clipboard. Switch back and load the FileDownloader script and run it. You should see the path to the source code in the editor instead of the URL. Cancel the dialog box and see that the editor window is now empty. Switch over to the console again and execute "print clipboard.get() and the source code for the script should be displayed. For reference - here is the code for FileDownloader I am using (some slight mods from the original).

# Python file downloader for Pythonista by OMZ Software
# By: EJM Software ---- http://ejm.cloudvent.net
# Source: https://gist.github.com/89edf288a15fde45682a
# *****************************************
# This simple script uses the requests module to download files
# and the ui module to show a progress bar
# You can use this bookmarklet to download files from Safari:
# javascript:window.location='pythonista://filedownloader?action=run&argv='+encodeURIComponent(document.location.href);

import ui, console, clipboard, sys, requests, zipfile

class FileDownloader(ui.View):
    def __init__(self,width=600,height=100):
        #Setup the view
        self.name = 'File Downloader'
        self.background_color = 'white'
        self.frame = (0,0,width,height)
        self.flex = "WH"
        #Setup the ui elements
        self.url_input = ui.TextField(frame = (0, 0, self.width, 50), flex='W', background_color='white')
        self.url_input.placeholder = 'URL'
        self.start_button = ui.Button(flex='LR', title='Download')
        self.start_button.center = (self.width * 0.5, 70)
        self.start_button.action = self.start_download
        self.loading_bar = ui.Label(frame=(0,0,0,50), flex='', background_color=(0.00, 0.50, 1.00, 0.5))
        self.activity_indicator = ui.ActivityIndicator(frame=(50,25,0,0), flex='W', alignment=ui.ALIGN_CENTER)
        #Add subviews to main view and 'present' ui
        self.add_subview(self.url_input)
        self.add_subview(self.start_button)
        self.add_subview(self.loading_bar)
        self.add_subview(self.activity_indicator)
        self.present('sheet')

    def setprogress(self, progress=0):
        self.loading_bar.width = self.width*progress/100

    @ui.in_background
    def start_download(self, sender):
        self.download_file(self.url_input.text)

    def download_file(self, url) :
        self.start_button.enabled = False
        self.activity_indicator.start()
        localFilename = url.split('/')[-1]
        if localFilename == '': localFilename = 'download'
        with open(localFilename, 'wb') as f:
            r = requests.get(url, stream=True)
            total_length = r.headers.get('content-length')
            if not total_length:
                f.write(r.content)
            else:
                dl = 0
                total_length = float(total_length)
                for chunk in r.iter_content(1024):
                    dl += len(chunk)
                    f.write(chunk)
                    self.setprogress(dl/total_length*100.0)
        self.start_button.enabled = True
        self.activity_indicator.stop()
        self.process_file(localFilename)
        self.close()

    def process_file(self, path):
        if zipfile.is_zipfile(path):
            if console.alert('Extract File?', '', 'OK'):
                zipfile.ZipFile(path).extractall()

if __name__=='__main__':
    w, h = ui.get_screen_size()
    view = FileDownloader(width=int(.9*w),height=100)
    if len(sys.argv) > 1:
        view.url_input.text = sys.argv[1]
        view.download_file(sys.argv[1])
    elif '://' in clipboard.get():
        view.url_input.text = clipboard.get()
omz

Thanks! The problem doesn't seem to be with clipboard.get() but with sys.argv. For some reason, it contains the script path twice instead of just once, and the File Downloader blindly treats the second argument as a URL to download (without checking that it actually is a URL). Since it uses the last part of the URL's path as the destination filename, the current script gets overwritten by empty data (because downloading the "URL" fails of course)...

I don't know exactly why the argument is doubled right now, but it seems like this should be easy to fix. It's probably a bug that slipped through when I changed the way globals are cleared.

wradcliffe

Now it makes sense. I was also seeing issues with other scripts but without the apparent data loss issue and jumped to the wrong conclusion. Glad you were able to repro it easily and figure it out.