import tkinter as tk import re import json import xmlrpc.client as xmlrpclib from tkinter import ttk from tem_pip import runpip class Pip_interface(tk.Frame): def __init__(self, parent): tk.Frame.__init__(self, parent) self.parent = parent self.parent.title("PIP Package Manager") self.gui_height = parent.winfo_reqheight() self.gui_width = parent.winfo_reqwidth() # use for installed package tab self.installed_list = None self.lastest_version = None self.package_detail = None self.installed_and_lastest_list = [] self.installed_canvas_text_id = None # end for installed package tab # use for search tab self.list_package = None self.release_data = None self.search_canvas_text_id = None self.search_result = None # end for search tab self._create_panel() self.parent.resizable("false", "false") def _create_panel(self): nb = ttk.Notebook(self.parent) nb.pack(fill="both") self._create_search_tab(nb) self._create_installed_package_tab(nb) def _create_search_tab(self, nb): frame = ttk.Frame(nb) frame.pack() search_text = tk.StringVar() search_text_entry = ttk.Entry(frame, width=40, textvariable=search_text) search_button = ttk.Button(frame, text="Search") paned_window = ttk.PanedWindow(frame, orient="horizontal") install_button = ttk.Button(frame, text="Install") search_text_entry.grid(column=1, row=0, sticky="e") search_button.grid(column=2, row=0, sticky="w") paned_window.grid(column=0, row=1, columnspan=4, sticky="news") install_button.grid(column=3, row=2, sticky="e") # search frame package_frame = ttk.LabelFrame(paned_window, text="Pypi") search_treeview = ttk.Treeview(package_frame, columns=("Package"), show="headings", height=29) search_treeview.heading("Package", text="Package") search_treeview.column(0, width=300) treeview_v_scrollbar = ttk.Scrollbar(package_frame, orient="vertical", command=search_treeview.yview) search_treeview.configure(yscrollcommand=treeview_v_scrollbar.set) self.get_data_pypi("list_package") self.display_data("search_treeview", search_treeview) search_treeview.grid(sticky="news") treeview_v_scrollbar.grid(column=1, row=0, sticky="ns") # end search frame # description frame description_frame = ttk.LabelFrame(paned_window, text="Description") description_text = tk.Canvas(description_frame, height=540, width=915, scrollregion=(0, 0, 1200, 1400)) description_text.xview_moveto(0.0) description_text.yview_moveto(0.0) text_canvas_v_scrollbar = ttk.Scrollbar(description_frame, orient="vertical", command=description_text.yview) text_canvas_h_scrollbar = ttk.Scrollbar(description_frame, orient="horizontal", command=description_text.xview) description_text.configure(yscrollcommand=text_canvas_v_scrollbar.set, xscrollcommand=text_canvas_h_scrollbar.set) search_treeview.bind("", lambda x: self._get_and_display_package_detail ( "search_treeview", description_text, search_treeview ) ) description_text.grid(sticky="news") text_canvas_v_scrollbar.grid(column=1, row=0, sticky="ns") text_canvas_h_scrollbar.grid(column=0, row=1, sticky="ew") # end description frame paned_window.add(package_frame) paned_window.add(description_frame) nb.add(frame, text="Search") def _create_installed_package_tab(self, nb): frame = ttk.Frame(nb) frame.pack() paned_window = ttk.PanedWindow(frame, orient="horizontal") update_button = ttk.Button(frame, text="Update") uninstall_button = ttk.Button(frame, text="Uninstall") paned_window.pack(fill="both") update_button.pack(side="right") uninstall_button.pack(side="right") # installed package frame installed_package_frame = ttk.LabelFrame(paned_window, text="Installed Package") self._add_lastest_version_to_installed_list() installed_package_treeview = ttk.Treeview(installed_package_frame, columns=("Package", "Version", "Lastest"), show="headings", height=30) installed_package_treeview.heading("Package", text="Package") installed_package_treeview.heading("Version", text="Version") installed_package_treeview.heading("Lastest", text="Lastest") self.display_data("installed_treeview", installed_package_treeview) treeview_v_scrollbar = ttk.Scrollbar(installed_package_frame, orient="vertical", command=installed_package_treeview.yview) installed_package_treeview.configure(yscrollcommand=treeview_v_scrollbar.set) installed_package_treeview.grid(sticky="news") treeview_v_scrollbar.grid(column=1, row=0, sticky="ns") # end installed package frame # description frame description_frame = ttk.LabelFrame(paned_window, text="Description") description_text = tk.Canvas(description_frame, height=555, width=600, scrollregion=(0, 0, 1200, 1400)) description_text.xview_moveto(0.2) description_text.yview_moveto(0.3) text_canvas_v_scrollbar = ttk.Scrollbar(description_frame, orient="vertical", command=description_text.yview) text_canvas_h_scrollbar = ttk.Scrollbar(description_frame, orient="horizontal", command=description_text.xview) description_text.configure(yscrollcommand=text_canvas_v_scrollbar.set, xscrollcommand=text_canvas_h_scrollbar.set) installed_package_treeview.bind("", lambda x: self._get_and_display_package_detail ( "installed_treeview", description_text, installed_package_treeview ) ) description_text.grid(sticky="news") text_canvas_v_scrollbar.grid(column=1, row=0, sticky="ns") text_canvas_h_scrollbar.grid(column=0, row=1, sticky="ew") # end description frame paned_window.add(installed_package_frame) paned_window.add(description_frame) nb.add(frame, text="Installed Package") # to know more, read from this site https://wiki.python.org/moin/PyPIXmlRpc?action=show&redirect=PyPiXmlRpc def get_data_pypi(self, command_string): """ Function to get data from the pypi site """ try: command, option = command_string.split(" ") except ValueError: command = command_string option = None client = xmlrpclib.ServerProxy("https://pypi.python.org/pypi") if command == "list_package": self.list_package = client.list_packages() elif command == "release_data": try: version = client.package_releases(option)[0] except IndexError: self.release_data = "No information about this package" return data = client.release_data(option, version) self.release_data = "" self.release_data += "author: " + data['author'] + "\n" self.release_data += "author_email: " + data['author_email'] + "\n" self.release_data += "\n" + "description: " + data['description'] + "\n\n" # self.release_data += "docs_url: " + + "\n" self.release_data += "homepage: " + data['home_page'] + "\n" self.release_data += "summary: " + data['summary'] + "\n" self.release_data += "version: " + data['version'] def get_data(self, command_string): """ Function to get data only from the pip command """ try: command, option = command_string.split(" ") except ValueError: command = command_string option = None # if command == "search": # status, out, err = runpip("search {}".format(option)) # pattern = re.compile("(\w+.*?)\s\(([0-9a-z.]+)\)\s+-") # self.search_result = pattern.findall(out) if command == "list": if option is None: status, out, err = runpip("list") self.installed_list = out.split("\n") elif option == "--outdated": status, out, err = runpip("list --outdated") self.lastest_version = out.split("\n") elif command == "show": status, out, err = runpip("show {}".format(option)) self.package_detail = out def display_data(self, widget_type, widget_name): """ The type are: installed_treeview installed_canvas_text search_treeview search_canvas_text """ if widget_type == "installed_treeview" and self.installed_and_lastest_list is not None: for i in range(0, len(self.installed_and_lastest_list)): widget_name.insert("", "end", "", values=tuple(self.installed_and_lastest_list[i])) elif widget_type == "installed_canvas_text" and self.package_detail is not None: if self.installed_canvas_text_id is not None: widget_name.delete(self.installed_canvas_text_id) self.installed_canvas_text_id = widget_name.create_text(600, 700, text=self.package_detail) else: self.installed_canvas_text_id = widget_name.create_text(600, 700, text=self.package_detail) elif widget_type == "search_treeview" and self.list_package is not None: for i in range(0, len(self.list_package)): widget_name.insert("", "end", "", values=(self.list_package[i])) elif widget_type == "search_canvas_text" and self.release_data is not None: if self.search_canvas_text_id is not None: widget_name.delete(self.search_canvas_text_id) self.search_canvas_text_id = widget_name.create_text(0, 0, anchor="nw", text=self.release_data) else: self.search_canvas_text_id = widget_name.create_text(0, 0, anchor="nw", text=self.release_data) # from here is the function for installed package frame def _add_lastest_version_to_installed_list(self): self.get_data("list") self.get_data("list --outdated") self.installed_list.pop() # do not know why got last empty item in list self.lastest_version.pop() # below code is used to clean the above two list so I can compare for update version temp_installed_list = [] installed_pattern = re.compile("(\w+.*?)\s\(([0-9a-z.]+)\)") temp_lastest_list = [] lastest_pattern = pattern = re.compile("(\w+.*?)\s\(.*?\:\s([0-9a-z.]+)\s") for i in range(0, len(self.installed_list)): temp_installed_list.insert(i, list(installed_pattern.findall(self.installed_list[i])[0])) for i in range(0, len(self.lastest_version)): temp_lastest_list.insert(i, list(lastest_pattern.findall(self.lastest_version[i])[0])) num_list = [] for x in range(0, len(temp_lastest_list)): for y in range(0, len(temp_installed_list)): if temp_lastest_list[x][0] == temp_installed_list[y][0]: temp_list = [ temp_installed_list[y][0], temp_installed_list[y][1], temp_lastest_list[x][1] ] self.installed_and_lastest_list.append(temp_list) num_list.append(y) for i in range(0, len(temp_installed_list)): if i not in num_list: temp_list = [ temp_installed_list[i][0], temp_installed_list[i][1], temp_installed_list[i][1] ] self.installed_and_lastest_list.append(temp_list) # end here # end function for installed package frame # from here is the function for description frame def _get_and_display_package_detail(self, widget_type, widget_name, select): if widget_type == "installed_treeview": item = select.selection()[0] self.get_data("show {}".format(select.item(item)["values"][0])) self.display_data("installed_canvas_text", widget_name) elif widget_type == "search_treeview": item = select.selection()[0] self.get_data_pypi("release_data {}".format(select.item(item)["values"][0])) self.display_data("search_canvas_text", widget_name) # end function for description frame if __name__ == "__main__": root = tk.Tk() Pip_interface(root) root.mainloop()