Show Installed Package detail - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: General (https://python-forum.io/forum-1.html) +--- Forum: Code sharing (https://python-forum.io/forum-5.html) +--- Thread: Show Installed Package detail (/thread-1812.html) Pages:
1
2
|
Show Installed Package detail - Larz60+ - Jan-27-2017 I have created a ShowInstalledPackages.py program on GitHub (and below). Works on-line and offline, showing all python packages installed by user, and detailed information about each. https://github.com/Larz60p/ShowInstalledPackages/blob/master/ShowInstalledPackages.py Checks if Internet present, if so gets a fresh copy of package info from pip, otherwise loads the last version obtained from a file. Must be run from the internet first time. Single click on package name will show summary description on bottom frame of GUI. Double click shows detailed information on the package. ** Note ** The installed version and most recent version are shown at the top of the Detail information. If there is a difference, you should get the updated version. # Copyright <2016> <Larz60+> # # Permission is hereby granted, free of charge, to any person obtaining a copy of # this software and associated documentation files (the "Software"), to deal in the # Software without restriction, including without limitation the rights to use, # copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the # Software, and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # import tkinter as tk import tkinter.ttk as ttk import pip import requests import json import socket import getpass class ShowInstalledPackages: def __init__(self, root): self.s = ttk.Style() self.s.theme_use('classic') self.parent = root self.userid = getpass.getuser() self.package_name = None self.pkgs = None self.pkg_details = {} self.pkglist = None self.pkeys = [] self.pkglist_filename = 'pkglist.json' self.PackageData_filename = 'PackageData.json' root.title('Installed packages for {}'.format(self.userid)) self.internet_available = socket.gethostbyname(socket.gethostname()) != '127.0.0.1' # GUI prototypes self.fmain = tk.Frame self.bottom_frame = tk.Frame self.blabel = tk.Label self.blabeltxt = tk.StringVar() self.t1 = ttk.Treeview self.textframe = tk.Text self.txscroll = tk.Scrollbar # Geometry variables self.treeheight = 25 self.mfheight = self.treeheight + 5 self.bfheight = 5 self.mfrow = 0 self.mfcol = 0 self.trrow = 0 self.trcol = 0 self.txrow = 0 self.txcol = 0 self.build_gui() def build_gui(self): self.create_main_frame() self.create_bottom_frame() self.create_treeframe() self.create_textframe() self.create_treeframe() self.load_treeframe() def create_main_frame(self): self.fmain = tk.Frame(self.parent, bd=2, relief=tk.RAISED) self.fmain.grid(row=self.mfrow, rowspan=self.mfheight, column=self.mfcol, padx=2, pady=2, sticky='nsew') self.mfrow += self.mfheight def create_bottom_frame(self): self.bottom_frame = tk.Frame(self.parent, bd=2, relief=tk.RAISED) self.bottom_frame.grid(row=self.mfrow, rowspan=self.bfheight, column=self.mfcol, padx=2, pady=2, sticky='nsew') self.mfrow += self.bfheight self.blabel = tk.Label(self.bottom_frame, textvariable=self.blabeltxt, bd=2, relief=tk.SUNKEN) self.blabel.grid(row=0, rowspan=self.bfheight, column=0, sticky='nsew') def create_treeframe(self): treestyle = ttk.Style() treestyle.configure("Treeview.Heading", foreground='white', background='SteelBlue', height=3) self.t1 = ttk.Treeview(self.fmain, height=self.treeheight, padding=(2, 2, 2, 2), columns='Version', style='Treeview', selectmode="extended") self.t1.heading('#0', text='Package', anchor=tk.CENTER) self.t1.heading('#1', text='Version', anchor=tk.CENTER) self.t1.column('#0', stretch=tk.YES, minwidth=20, width=150) self.t1.column('#1', stretch=tk.YES, minwidth=10, width=70) self.t1.grid(row=0, rowspan=self.treeheight, column=0) treescrolly = tk.Scrollbar(self.fmain, orient=tk.VERTICAL, command=self.t1.yview) treescrolly.grid(row=0, rowspan=self.treeheight, column=1, sticky='ns') treescrollx = tk.Scrollbar(self.fmain, orient=tk.HORIZONTAL, command=self.t1.xview) treescrollx.grid(row=self.treeheight + 1, column=0, columnspan=2, sticky='ew') self.t1.configure(yscroll=treescrolly) self.t1.configure(xscroll=treescrollx) self.t1.bind('<Double-1>', self.pkg_selected) self.t1.bind('<ButtonRelease-1>', self.treeview_summary) def create_textframe(self): self.textframe = tk.Text(self.fmain, bd=2, bg='#CEF6EC', relief=tk.RAISED) self.txscroll = tk.Scrollbar(self.fmain, orient=tk.VERTICAL, command=self.textframe.yview) self.txscroll.grid(row=1, rowspan=self.treeheight, column=4, sticky='ns') self.textframe.configure(yscroll=self.txscroll.set) self.textframe.grid(row=0, rowspan=self.treeheight, column=3, padx=2, pady=2, sticky='nsew') def load_treeframe(self): self.get_pkgs_from_pip() self.get_pks_details() for key in self.pkeys: self.t1.insert('', 'end', text=key, values=self.pkglist[key]) def treeview_summary(self, event): curitem = self.t1.focus() x = self.t1.item(curitem) self.package_name = x['text'] sumdata = self.pkg_details[self.package_name]['summary'] self.blabeltxt.set(sumdata) @staticmethod def get_package_info(pkgname): pypi_info_url = 'https://pypi.python.org/pypi/{}/json'.format(pkgname) response = requests.get(pypi_info_url) if response.status_code == requests.codes.ok: jdata = json.loads(response.text.encode(response.encoding)) return jdata def get_pkgs_from_pip(self): if not self.internet_available: with open(self.pkglist_filename, 'r') as f: self.pkglist = json.load(f) else: self.pkgs = pip.get_installed_distributions(local_only=True, include_editables=True, editables_only=False, user_only=False) self.pkglist = dict() for item in self.pkgs: z = str(item).split() self.pkglist[z[0]] = z[1] if self.internet_available: with open(self.pkglist_filename, 'w') as f: json.dump(self.pkglist, f) def get_pks_details(self): if not self.internet_available: with open(self.PackageData_filename, 'r') as f: self.pkg_details = json.load(f) self.pkeys = list(self.pkglist.keys()) self.pkeys.sort() else: with open('ziggy1.txt', 'w') as fp: self.pkeys = list(self.pkglist.keys()) self.pkeys.sort() for key in self.pkeys: data = self.get_package_info(key) self.pkg_details[key] = data['info'] wpkg = str('self.pkg_details: {}\n'.format(self.pkg_details).encode('utf-8')) fp.write(wpkg) if self.internet_available: with open(self.PackageData_filename, 'w') as f: json.dump(self.pkg_details, f) def pkg_selected(self, event): curitem = self.t1.focus() x = self.t1.item(curitem) self.package_name = x['text'] pn = self.pkglist[self.package_name] data = self.pkg_details[self.package_name] dkeys = list(data.keys()) dkeys.sort() self.textframe.delete('1.0', tk.END) self.textframe.tag_configure('tag-center', justify='center') # Insert Title as first line self.textframe.insert('end', 'Package Name: {} -- Installed Version: {}\n' 'Latest Version: {}\n' .format(self.package_name, pn, data['version']), 'tag-center') self.display_data(data, dkeys) def display_data(self, data, dkeys): for key in dkeys: if key == 'version' or key == 'description': continue if isinstance(data[key], list): for element in data[key]: displ = ' {} -- {}\n'.format(key, element) self.textframe.insert(tk.END, displ) self.textframe.insert(tk.END, '\n') # print(f'Type List: {key} -- {data[key]}\n\n') elif isinstance(data[key], dict): for element in data[key].items(): displ = ' {} -- {}\n'.format(key, element) self.textframe.insert(tk.END, displ) self.textframe.insert(tk.END, '\n') # print(f'Type Dict: {key} -- {data[key]}\n\n') else: displ = '{} -- {}\n\n'.format(key, data[key]) self.textframe.insert(tk.END, displ) displ = '\n=========================================================\n' \ 'Description -- {}\n\n'.format(data['description']) self.textframe.insert(tk.END, displ) @staticmethod def show_widget_values(target_widget): wkeys = list(target_widget.keys()) wkeys.sort() for key in wkeys: print('key: {} value: {}'.format(key, target_widget[key])) def main(): root = tk.Tk() ShowInstalledPackages(root) root.mainloop() if __name__ == '__main__': main() RE: Show Installed Package detail - sparkz_alot - Jan-27-2017 Looks like a very useful and professional application. If I might ask, is it cross platform and which Python version(s) does one need? RE: Show Installed Package detail - Larz60+ - Jan-27-2017 I should have stated that. I have only tested it on windows 7 pro 64 bit. Also, I used python 3.6. I don't believe there are any system specific commands, but can't be sure. Would appreciate someone trying it on Linux and OS-X and let me know where problems (if any) are found. You may have to change the theme for it to look ok on another os. To do so, first run the following snippet to see what's available: import tkinter.ttk as ttk s = ttk.Style() print(s.theme_names())On windows 7 this returns: change the line (in __init__):self.s.theme_use('...') RE: Show Installed Package detail - snippsat - Jan-28-2017 Good job this @Larz60+. I have tested it and it work. You should look more into setup/packaging then it will be easier for end user to use. Could eg be pip install ShowInstalledPackages .Then your own program will show up in your in ShowInstalledPackages Here is my run with cmder. E:\1 λ git clone https://github.com/Larz60p/ShowInstalledPackages.git Cloning into 'ShowInstalledPackages'... remote: Counting objects: 16, done. remote: Compressing objects: 100% (16/16), done. remote: Total 16 (delta 7), reused 0 (delta 0), pack-reused 0 Unpacking objects: 100% (16/16), done. Checking connectivity... done. E:\1 λ cd ShowInstalledPackages E:\1\ShowInstalledPackages (master) λ ls InstalledPackages.png LICENSE README.md ShowInstalledPackages.py # Run ShowInstalledPackages E:\1\ShowInstalledPackages (master) λ python ShowInstalledPackages.py RE: Show Installed Package detail - Larz60+ - Jan-28-2017 Quote:You should look more into setup/packaging then it will be easier for end user to use. I have never gone through this process before. I guess it's time to learn how. I have never used cmder either. This is my task for tomorrow before I move on to my next project, which I haven't identified yet. I just noticed that there ate two calls to create_treeframe. I'll also make that change on github (and here tomorrow) One more error, 'ziggy.tst' was a text file name, and should be something eles. RE: Show Installed Package detail - snippsat - Jan-28-2017 You can at look this. Quote:I have never used cmder eitherI could have done the same in cmd, it's just a much better shell with color coding and more functionallty. So booth ls (give color to folders) and dir work.Look like this. RE: Show Installed Package detail - Larz60+ - Jan-28-2017 Downloaded and installed (into path) cmder and like it. RE: Show Installed Package detail - snippsat - Jan-28-2017 And follow also this. When run command .\cmder.exe /REGISTER ALL Then you can right click in file explorer,and cmder straight into that folder. RE: Show Installed Package detail - Larz60+ - Jan-29-2017 While trying to create a package for this module, got the following error (using cmder, and have .pypirc file setup I never got an email
RE: Show Installed Package detail - Larz60+ - Feb-01-2017 Have made pretty good progress in getting this thing published on PyPi. I am attempting to have a standalone executable in the package. I am able to create the .exe, but when I run it, i get the following error, which has something to do with expanding eggs. Perhaps tomorrow.Next project: either something to do with midi, or a big project -- yet another PDF library. |