from io import StringIO from pip import main import sys from tkinter import * from tkinter import messagebox, ttk from tkinter.scrolledtext import ScrolledText sysout = StringIO() syserr = StringIO() class redirect: """Context manager for temporarily redirecting stdout/err. Simplified and generalize from contextlib.redirect_stdout. """ def __init__(self, stdfile, new_target): self._stdfile = stdfile # 'stdout' or 'stderr' self._new_target = new_target def __enter__(self): self._old = getattr(sys, self._stdfile) setattr(sys, self._stdfile, self._new_target) return self._new_target def __exit__(self, exctype, excinst, exctb): setattr(sys, self._stdfile, self._old) # For GUI version, redirects would be here, done once. # Put in runpip for prototype testing in text mode, so can print. def runpip(argstring): '''Run pip with argument string containing command and options. Argstring is quoted version of what would follow 'pip' on command line. ''' with redirect('stdout', sysout) as f1, redirect('stderr', syserr) as f2: status = main(argstring.split()) out = sysout.getvalue() err = syserr.getvalue() sysout.seek(0); sysout.truncate(0) syserr.seek(0); syserr.truncate(0) return status, out, err class pip_gui(Frame): def __init__(self, parent): """Set the parent of the current frame""" Frame.__init__(self, parent) self.parent = parent self.initialize() self.load_settings() self.parent.protocol('WM_DELETE_WINDOW', self.onExit) def initialize(self): """Set the contents of the GUI for pip package manager""" self.parent.title('PIP package manager') self.adjustWindow() self.nb = ttk.Notebook(self.parent) self.installed_tab = ttk.Frame(self.nb) self.search_tab = ttk.Frame(self.nb) self.update_installed_tab() self.nb.add(self.installed_tab, text='Installed Packages') self.nb.add(self.search_tab, text='Search and Install Packages') self.nb.pack(expand=1, fill='both') def update_installed_tab(self): """Update the installed tab by getting the list of installed packages""" #Get list of all installed PyPI packages status, out, err = runpip('list') all_instt_packages = out.split("\n") #Create a Listbox to show the list of installed packages self.instt_package_list = Listbox( self.installed_tab, activestyle='none', cursor='hand2', selectmode=EXTENDED, width=40, height=36, bg='#99ccff') self.instt_package_list.config(width=50) self.instt_package_list.grid(row=0, column=0, sticky=N+S+E) self.scrollbar1 = Scrollbar(self.installed_tab) self.scrollbar1.grid(row=0, column=1, sticky=N+S) self.instt_package_list.config(yscrollcommand=self.scrollbar1.set) self.scrollbar1.config(command=self.instt_package_list.yview) for i in range(len(all_instt_packages)): self.instt_package_list.insert(END, all_instt_packages[i]) self.instt_package_details=StringVar() self.instt_package_details.set(' ') self.package_subwindow = Label( self.installed_tab, textvariable=self.instt_package_details) self.package_subwindow.config(width=(self.parent.winfo_width()//2)) self.package_subwindow.grid(row=0, column=2, sticky=N+S+W) self.instt_package_list.bind( "",self.show_details) def show_details(self, event=None): """ Show further details of the selected package""" try: selected_id = int(self.instt_package_list.curselection()[0]) #print(selected_id) selected_name = self.instt_package_list.get(selected_id) #print(selected_name) if selected_name: stat, out, err = runpip('show '+selected_name) #print(out) self.instt_package_details.set(out) self.package_subwindow.config( textvariable=self.instt_package_details) except: self.instt_package_details.set('No package selected') self.package_subwindow.config( textvariable=self.instt_package_details) def update_search_tab(self, search_tab): """Provide functionality for searching and installing packages""" # Here I will use runpip('search '+package_name). Then user will be #presented with a list of similar packages which can be selected for #installation #To implement the installation, I will use runpip('install #'+package_name) def adjustWindow(self): """Set the window at center position of the screen""" #Get the screen width and screen height screen_width = self.parent.winfo_screenwidth() screen_height = self.parent.winfo_screenheight() #Calculate the appropriate window width and height window_width = int(0.75*screen_width); window_height = int(0.75*screen_height); #Determine the position of the window x = (screen_width - window_width)//2 y = (screen_height - window_height)//2 self.parent.geometry( str(window_width)+'x'+str(window_height)+'+'+str(x)+'+'+str(y)) def load_settings(self): """Load the saved settings for the application""" def onExit(self): """Manage the close event of the window""" result = messagebox.askyesno( 'Quit', 'Do you want to quit?', icon='question') if result: self.parent.destroy() # example usage if __name__=='__main__': #print (sys.argv[0]) #package = sys.argv[1] #stat, out, err = runpip('show %s', package) #print('stat: {}\n\n{}\nerr: {}'.format(stat, out, err)) root = Tk() root.resizable(width=FALSE, height=FALSE) pip_window = pip_gui(root) root.mainloop() #prints ##stat: 0 ## ##--- ##Metadata-Version: 2.0 ##Name: pip ##Version: 7.1.2 ##Summary: The PyPA recommended tool for installing Python packages. ##Home-page: https://pip.pypa.io/ ##Author: The pip developers ##Author-email: python-virtualenv@groups.google.com ##License: MIT ##Location: c:\programs\python34\lib\site-packages ##Requires: ## ##err: