mirror of
https://github.com/python/cpython.git
synced 2025-07-25 20:24:11 +00:00

(with one small bugfix in bgen/bgen/scantools.py) This replaces string module functions with string methods for the stuff in the Tools directory. Several uses of string.letters etc. are still remaining.
242 lines
6.9 KiB
Python
Executable file
242 lines
6.9 KiB
Python
Executable file
#! /usr/bin/env python
|
|
|
|
"""Tkinter-based GUI for websucker.
|
|
|
|
Easy use: type or paste source URL and destination directory in
|
|
their respective text boxes, click GO or hit return, and presto.
|
|
"""
|
|
|
|
from Tkinter import *
|
|
import Tkinter
|
|
import websucker
|
|
import sys
|
|
import os
|
|
import threading
|
|
import Queue
|
|
import time
|
|
|
|
VERBOSE = 2
|
|
|
|
|
|
try:
|
|
class Canceled(Exception):
|
|
"Exception used to cancel run()."
|
|
except (NameError, TypeError):
|
|
Canceled = __name__ + ".Canceled"
|
|
|
|
|
|
class SuckerThread(websucker.Sucker):
|
|
|
|
stopit = 0
|
|
savedir = None
|
|
rootdir = None
|
|
|
|
def __init__(self, msgq):
|
|
self.msgq = msgq
|
|
websucker.Sucker.__init__(self)
|
|
self.setflags(verbose=VERBOSE)
|
|
self.urlopener.addheaders = [
|
|
('User-agent', 'websucker/%s' % websucker.__version__),
|
|
]
|
|
|
|
def message(self, format, *args):
|
|
if args:
|
|
format = format%args
|
|
##print format
|
|
self.msgq.put(format)
|
|
|
|
def run1(self, url):
|
|
try:
|
|
try:
|
|
self.reset()
|
|
self.addroot(url)
|
|
self.run()
|
|
except Canceled:
|
|
self.message("[canceled]")
|
|
else:
|
|
self.message("[done]")
|
|
finally:
|
|
self.msgq.put(None)
|
|
|
|
def savefile(self, text, path):
|
|
if self.stopit:
|
|
raise Canceled
|
|
websucker.Sucker.savefile(self, text, path)
|
|
|
|
def getpage(self, url):
|
|
if self.stopit:
|
|
raise Canceled
|
|
return websucker.Sucker.getpage(self, url)
|
|
|
|
def savefilename(self, url):
|
|
path = websucker.Sucker.savefilename(self, url)
|
|
if self.savedir:
|
|
n = len(self.rootdir)
|
|
if path[:n] == self.rootdir:
|
|
path = path[n:]
|
|
while path[:1] == os.sep:
|
|
path = path[1:]
|
|
path = os.path.join(self.savedir, path)
|
|
return path
|
|
|
|
def XXXaddrobot(self, *args):
|
|
pass
|
|
|
|
def XXXisallowed(self, *args):
|
|
return 1
|
|
|
|
|
|
class App:
|
|
|
|
sucker = None
|
|
msgq = None
|
|
|
|
def __init__(self, top):
|
|
self.top = top
|
|
top.columnconfigure(99, weight=1)
|
|
self.url_label = Label(top, text="URL:")
|
|
self.url_label.grid(row=0, column=0, sticky='e')
|
|
self.url_entry = Entry(top, width=60, exportselection=0)
|
|
self.url_entry.grid(row=0, column=1, sticky='we',
|
|
columnspan=99)
|
|
self.url_entry.focus_set()
|
|
self.url_entry.bind("<Key-Return>", self.go)
|
|
self.dir_label = Label(top, text="Directory:")
|
|
self.dir_label.grid(row=1, column=0, sticky='e')
|
|
self.dir_entry = Entry(top)
|
|
self.dir_entry.grid(row=1, column=1, sticky='we',
|
|
columnspan=99)
|
|
self.go_button = Button(top, text="Go", command=self.go)
|
|
self.go_button.grid(row=2, column=1, sticky='w')
|
|
self.cancel_button = Button(top, text="Cancel",
|
|
command=self.cancel,
|
|
state=DISABLED)
|
|
self.cancel_button.grid(row=2, column=2, sticky='w')
|
|
self.auto_button = Button(top, text="Paste+Go",
|
|
command=self.auto)
|
|
self.auto_button.grid(row=2, column=3, sticky='w')
|
|
self.status_label = Label(top, text="[idle]")
|
|
self.status_label.grid(row=2, column=4, sticky='w')
|
|
self.top.update_idletasks()
|
|
self.top.grid_propagate(0)
|
|
|
|
def message(self, text, *args):
|
|
if args:
|
|
text = text % args
|
|
self.status_label.config(text=text)
|
|
|
|
def check_msgq(self):
|
|
while not self.msgq.empty():
|
|
msg = self.msgq.get()
|
|
if msg is None:
|
|
self.go_button.configure(state=NORMAL)
|
|
self.auto_button.configure(state=NORMAL)
|
|
self.cancel_button.configure(state=DISABLED)
|
|
if self.sucker:
|
|
self.sucker.stopit = 0
|
|
self.top.bell()
|
|
else:
|
|
self.message(msg)
|
|
self.top.after(100, self.check_msgq)
|
|
|
|
def go(self, event=None):
|
|
if not self.msgq:
|
|
self.msgq = Queue.Queue(0)
|
|
self.check_msgq()
|
|
if not self.sucker:
|
|
self.sucker = SuckerThread(self.msgq)
|
|
if self.sucker.stopit:
|
|
return
|
|
self.url_entry.selection_range(0, END)
|
|
url = self.url_entry.get()
|
|
url = url.strip()
|
|
if not url:
|
|
self.top.bell()
|
|
self.message("[Error: No URL entered]")
|
|
return
|
|
self.rooturl = url
|
|
dir = self.dir_entry.get().strip()
|
|
if not dir:
|
|
self.sucker.savedir = None
|
|
else:
|
|
self.sucker.savedir = dir
|
|
self.sucker.rootdir = os.path.dirname(
|
|
websucker.Sucker.savefilename(self, url))
|
|
self.go_button.configure(state=DISABLED)
|
|
self.auto_button.configure(state=DISABLED)
|
|
self.cancel_button.configure(state=NORMAL)
|
|
self.message( '[running...]')
|
|
self.sucker.stopit = 0
|
|
t = threading.Thread(target=self.sucker.run1, args=(url,))
|
|
t.start()
|
|
|
|
def cancel(self):
|
|
if self.sucker:
|
|
self.sucker.stopit = 1
|
|
self.message("[canceling...]")
|
|
|
|
def auto(self):
|
|
tries = ['PRIMARY', 'CLIPBOARD']
|
|
text = ""
|
|
for t in tries:
|
|
try:
|
|
text = self.top.selection_get(selection=t)
|
|
except TclError:
|
|
continue
|
|
text = text.strip()
|
|
if text:
|
|
break
|
|
if not text:
|
|
self.top.bell()
|
|
self.message("[Error: clipboard is empty]")
|
|
return
|
|
self.url_entry.delete(0, END)
|
|
self.url_entry.insert(0, text)
|
|
self.go()
|
|
|
|
|
|
class AppArray:
|
|
|
|
def __init__(self, top=None):
|
|
if not top:
|
|
top = Tk()
|
|
top.title("websucker GUI")
|
|
top.iconname("wsgui")
|
|
top.wm_protocol('WM_DELETE_WINDOW', self.exit)
|
|
self.top = top
|
|
self.appframe = Frame(self.top)
|
|
self.appframe.pack(fill='both')
|
|
self.applist = []
|
|
self.exit_button = Button(top, text="Exit", command=self.exit)
|
|
self.exit_button.pack(side=RIGHT)
|
|
self.new_button = Button(top, text="New", command=self.addsucker)
|
|
self.new_button.pack(side=LEFT)
|
|
self.addsucker()
|
|
##self.applist[0].url_entry.insert(END, "http://www.python.org/doc/essays/")
|
|
|
|
def addsucker(self):
|
|
self.top.geometry("")
|
|
frame = Frame(self.appframe, borderwidth=2, relief=GROOVE)
|
|
frame.pack(fill='x')
|
|
app = App(frame)
|
|
self.applist.append(app)
|
|
|
|
done = 0
|
|
|
|
def mainloop(self):
|
|
while not self.done:
|
|
time.sleep(0.1)
|
|
self.top.update()
|
|
|
|
def exit(self):
|
|
for app in self.applist:
|
|
app.cancel()
|
|
app.message("[exiting...]")
|
|
self.done = 1
|
|
|
|
|
|
def main():
|
|
AppArray().mainloop()
|
|
|
|
if __name__ == '__main__':
|
|
main()
|