Example #1
0
def test_dl_dry_cancel():
    bdl = bd.BulkDownloader('https://feeds.radiokawa.com/podcast_nawak.xml',
                            './dl')
    assert len(bdl.list_mp3()) > 0
    cb = Callback()
    cb.cancel()
    bdl.download_mp3(dry_run=True, cb=cb)
Example #2
0
class PDBApp(Frame):
    def __init__(self, master):
        Frame.__init__(self, master)
        master.title('Podcast Bulk Downloader v{}'.format(pbd_version))
        # master.geometry('500x800')
        style = ttk.Style()
        self._style = StringVar()
        if 'vista' in style.theme_names():
            self._style.set('vista')
        else:
            self._style.set('default')
        style.theme_use(self._style.get())

        # Layout configuration
        columns = 0
        while columns < 10:
            master.columnconfigure(columns, weight=1)
            columns += 1
        rows = 0
        while rows < 5:
            w = 1 if rows != 3 else 5
            master.rowconfigure(rows, weight=w)
            rows += 1

        # First line
        self._label_rss = ttk.Label(master, text='Feed')
        self._label_rss.grid(row=0, column=0, padx=2, pady=2, sticky=W + E)
        self._entry_rss = ttk.Entry(master)
        self._entry_rss.grid(row=0,
                             column=1,
                             padx=2,
                             pady=2,
                             columnspan=9,
                             sticky=W + E)

        # Second line
        self._label_folder = ttk.Label(master, text='Folder')
        self._label_folder.grid(row=1, column=0, padx=2, sticky=W + E)
        self._entry_folder = ttk.Entry(master)
        self._entry_folder.grid(row=1,
                                column=1,
                                padx=2,
                                columnspan=8,
                                sticky=W + E)
        self._btn_nav = ttk.Button(master,
                                   text='...',
                                   command=self.browse_directory)
        self._btn_nav.grid(row=1, column=9, padx=2, pady=2, sticky=W + E)

        # Third line
        self._overwrite = IntVar()
        self._cb_overwrite = ttk.Checkbutton(master,
                                             text='Overwrite existing files',
                                             variable=self._overwrite,
                                             onvalue=1,
                                             offvalue=0)
        self._cb_overwrite.grid(row=2,
                                column=0,
                                columnspan=2,
                                sticky=W + E,
                                padx=2,
                                pady=2)
        self._btn_fetch = ttk.Button(master, text='Fetch', command=self.fetch)
        self._btn_fetch.grid(row=2,
                             column=7,
                             columnspan=1,
                             sticky=W + E,
                             padx=2,
                             pady=2)
        self._btn_download = ttk.Button(master,
                                        text='Download',
                                        command=self.download)
        self._btn_download.grid(row=2,
                                column=8,
                                columnspan=1,
                                sticky=W + E,
                                padx=2,
                                pady=2)
        self._btn_cancel = ttk.Button(master,
                                      text='Cancel',
                                      command=self.cancel)
        self._btn_cancel.grid(row=2,
                              column=9,
                              columnspan=1,
                              sticky=W + E,
                              padx=2,
                              pady=2)

        # Fourth line
        self._progress_bar = ttk.Progressbar(master,
                                             orient='horizontal',
                                             mode='determinate')
        self._progress_bar.grid(row=3,
                                column=0,
                                columnspan=10,
                                sticky=W + E + N + S,
                                padx=2,
                                pady=2)
        self._progress_bar["maximum"] = 100

        # Fifth line
        self._text = Text(master)
        self._text.grid(row=4,
                        column=0,
                        columnspan=10,
                        sticky=W + E + N + S,
                        padx=2,
                        pady=2)
        self._text.configure(state=DISABLED)

        self._logger = Log2Text(self._text)
        logging.getLogger().setLevel(logging.INFO)
        logging.getLogger().addHandler(self._logger)

        # Utilities
        self._dl = BulkDownloader(self._entry_rss.get(),
                                  self._entry_folder.get())
        self._dl_thread = Thread(target=None)
        self._fetch_thread = Thread(target=None)
        self._callback = Callback(self._progress_bar)

        # Launch background task
        self.reset_buttons()

    def reset_buttons(self):
        if not self._fetch_thread.is_alive() and not self._dl_thread.is_alive(
        ):
            self._switch_action(False)
            self._callback.reset()
        self.after(100, self.reset_buttons)

    def browse_directory(self):
        cur_dir = self._entry_folder.get()
        initial_dir = cur_dir if os.path.exists(
            cur_dir) else os.path.expanduser('~')
        directory = filedialog.askdirectory(title='Select directory',
                                            initialdir=initial_dir)
        if directory:
            self._entry_folder.delete(0, END)
            self._entry_folder.insert(0, directory)

    def _clean_text_box(self):
        try:
            self._text.configure(state=NORMAL)
            self._text.delete('1.0', END)
            self._text.configure(state=DISABLED)
        except TclError as exc:
            logging.warning('Can\'t clean text ({})'.format(exc))

    def _update_dl_with_fields(self):
        self._dl._url = self._entry_rss.get()
        self._dl.folder(self._entry_folder.get())
        self._dl.overwrite(self._overwrite.get() == 1)

    def _switch_action(self, action: bool):
        state_f_dl = DISABLED if action else NORMAL
        state_cancel = NORMAL if action else DISABLED
        self._btn_download.configure(state=state_f_dl)
        self._btn_fetch.configure(state=state_f_dl)
        self._btn_cancel.configure(state=state_cancel)

    def download(self):
        self._clean_text_box()
        self._update_dl_with_fields()
        logging.info("Start download")
        self._dl_thread = Thread(target=self._dl.download_mp3,
                                 kwargs={'cb': self._callback})
        self._switch_action(True)
        self._dl_thread.start()

    def fetch(self):
        self._clean_text_box()
        self._update_dl_with_fields()
        logging.info("Fetch info")
        self._fetch_thread = Thread(target=self._dl.list_mp3,
                                    kwargs={
                                        'verbose': True,
                                        'cb': self._callback
                                    })
        self._switch_action(True)
        self._fetch_thread.start()

    def cancel(self):
        self._callback.cancel()
        logging.info('Action cancelled by user, waiting for threads to end...')
        if self._fetch_thread.is_alive():
            self._fetch_thread.join()
        if self._dl_thread.is_alive():
            self._dl_thread.join()
        self._callback.reset()
        self._switch_action(False)
        logging.info('Threads have ended')
Example #3
0
def test_try_download_cancel(tmp_directory):
    cb = Callback()
    cb.cancel()
    assert not bd.try_download('https://feeds.radiokawa.com/podcast_nawak.xml',
                               os.path.join(tmp_directory, 't.xml'), 1, 1, cb)