From 97de5b0f92b658588b53582ae7d84dd21ed12ed4 Mon Sep 17 00:00:00 2001 From: Steve Barnes Date: Mon, 7 Aug 2017 06:26:53 +0100 Subject: [PATCH] Added wx/tools/wxget_docs_demo.py with script entry points of wxdemo and wxdocs --- setup.py | 5 +- wx/tools/wxget.py | 71 +++++++++------ wx/tools/wxget_docs_demo.py | 175 ++++++++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+), 28 deletions(-) create mode 100644 wx/tools/wxget_docs_demo.py diff --git a/setup.py b/setup.py index cda4511f..cf353d3e 100644 --- a/setup.py +++ b/setup.py @@ -59,7 +59,7 @@ the `Migration Guide <{docs_base}/MigrationGuide.html>`_, or the `wxPython API documentation <{docs_base}/index.html>`_. Archive files containing a copy of the wxPython documentation, the demo and -samples, and also a set of MSVC .pdb files for Windows are available +samples, and also a set of MSVC .pdb files for Windows are available `here `_. """.format(version=cfg.VERSION, docs_base=DOCS_BASE) @@ -314,6 +314,9 @@ ENTRY_POINTS = { "pywxrc = wx.tools.pywxrc:main", # ], # 'gui_scripts' : [ # TODO: Why was this done? + "wxget = wx.tools.wxget:main", # New wx wget + "wxdocs = wx.tools.wxget_docs_demo:docs_main", # Get/Launch Docs + "wxdemo = wx.tools.wxget_docs_demo:demo_main", # Get/Launch Demo "helpviewer = wx.tools.helpviewer:main", "pycrust = wx.py.PyCrust:main", "pyshell = wx.py.PyShell:main", diff --git a/wx/tools/wxget.py b/wx/tools/wxget.py index 8679a832..db7a0ae3 100644 --- a/wx/tools/wxget.py +++ b/wx/tools/wxget.py @@ -10,13 +10,20 @@ # Copyright: (c) 2017 by Steve Barnes # Licence: wxWindows license # Tags: phoenix-port, py3-port +# +# Module to allow cross platform downloads originally from answers to: +# https://stackoverflow.com/questions/22676/how-do-i-download-a-file-over-http-using-python +# by Stan and PabloG then converted to wx. #---------------------------------------------------------------------- -""" -wx Version of wget utility for platform that don't have it already. -Module to allow cross platform downloads originally from answers to: -https://stackoverflow.com/questions/22676/how-do-i-download-a-file-over-http-using-python -by Stan and PabloG then converted to wx. +""" +wxget.py -- wx Version of wget utility for platform that don't have it already. + +Usage: + wxget URL [DEST_DIR] + +Where URL is a file URL and the optional DEST_DIR is a destination directory to +download to, (default is to prompt the user). """ from __future__ import (division, absolute_import, print_function, unicode_literals) @@ -41,23 +48,31 @@ def get_docs_demo_url(demo=False): pkg = 'docs' base_url = "https://extras.wxpython.org/wxPython4/extras/%s/wxPython-%s-%s.tar.gz" ver = wx.version().split(' ')[0] + major = ver.split('.')[0] + if major != '4': + raise ValueError("wx Versions before 4 not supported!") return base_url % (ver, pkg, ver) def get_save_path(url, dest_dir, force=False): """ Get the file save location.""" + old_dir = os.getcwd() if not dest_dir: - dest = os.getcwd() + dest_dir = os.getcwd() + else: + if not os.path.exists(dest_dir): + os.makedirs(dest_dir) + os.chdir(dest_dir) filename = os.path.basename(urlparse.urlsplit(url)[2]) if not filename: filename = 'downloaded.file' if not force: dlg = wx.FileDialog( - None, message="Save As ...", defaultDir=dest, + None, message="Save As ...", defaultDir=dest_dir, defaultFile=filename, style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT ) if dlg.ShowModal() == wx.ID_OK: - dest, filename = os.path.split(dlg.GetPath()) + dest_dir, filename = os.path.split(dlg.GetPath()) else: url = None del dlg @@ -67,8 +82,9 @@ def get_save_path(url, dest_dir, force=False): elif not os.path.isdir(dest_dir): url = None - if dest: - filename = os.path.join(dest, filename) + if dest_dir: + filename = os.path.join(dest_dir, filename) + os.chdir(old_dir) return (url, filename) @@ -125,27 +141,28 @@ def download_file(url, dest=None, force=False): return filename -if __name__ == "__main__": # Only run if this file is called directly +def main(args=sys.argv): + """ Entry point for wxget.""" APP = wx.App() - MESSAGE = '\n'.join([ - "USAGE:\n\twxget URL [dest_dir]", - "Will get a file from a file URL and save it to the destinaton or ." - ]) - if len(sys.argv) > 2: - DEST_DIR = sys.argv[2] + + if len(args) > 2: + dest_dir = args[2] else: - DEST_DIR = None - if len(sys.argv) > 1: - URL = sys.argv[1] + dest_dir = None + if len(args) > 1: + url = args[1] else: - print(MESSAGE) - YES_NO = wx.MessageBox(MESSAGE+"\nRUN TEST?", "wxget", + print(__doc__) + yes_no = wx.MessageBox(__doc__+"\n\nRUN TEST?", "wxget", wx.YES_NO|wx.CENTER) - if YES_NO == wx.YES: + if yes_no == wx.YES: print("Testing with wxDemo") - URL = get_docs_demo_url(True) + url = get_docs_demo_url() else: - URL = None - if URL: - FILENAME = download_file(URL) + url = None + if url: + FILENAME = download_file(url) print(FILENAME) + +if __name__ == "__main__": # Only run if this file is called directly + main() diff --git a/wx/tools/wxget_docs_demo.py b/wx/tools/wxget_docs_demo.py new file mode 100644 index 00000000..31df5529 --- /dev/null +++ b/wx/tools/wxget_docs_demo.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +#---------------------------------------------------------------------- +# Name: wx.tools.wxget_docs_demo +# Purpose: wx fetch & launch demo or docs +# +# Author: Steve Barnes +# +# Created: 06-Aug-2017 +# Copyright: (c) 2017 by Steve Barnes +# Licence: wxWindows license +# Tags: phoenix-port, py3-port +# +# Module to allow the correct version of the documents &/or demos to be +# launched after, if necessarily being fetched. +#---------------------------------------------------------------------- + +""" +wxget_docs_demo.py -- Launch the appropriate wx Docs or Demo. + +Usage: + wxget_docs_demo [docs|demo] + +Will install if missing, the requested item for the current version and then +launch it. +""" +from __future__ import (division, absolute_import, print_function, unicode_literals) + +import sys +import os +import subprocess +import webbrowser +import tarfile +if sys.version_info >= (3,): + from urllib.error import HTTPError + import urllib.request as urllib2 + import urllib.parse as urlparse + from urllib.request import pathname2url +else: + import urllib2 + from urllib2 import HTTPError + import urlparse + from urllib import pathname2url + +import wx + +import wxget + +APP = None +WXVERSION = wx.version().split(' ')[0] +MAJOR = WXVERSION.split('.')[0] +if MAJOR != '4': + raise ValueError("wx Versions other than 4 not supported!") + +def endsure_wx_app(): + """ Ensure that there is a wx.App instance.""" + global APP + if APP is None and not wx.GetApp(): + APP = wx.App() + APP.SetAppName("wxPython") + return (APP is not None) + +def get_paths_dict(): + """ Get a dictionary of the required paths.""" + global APP + endsure_wx_app() + sp = wx.StandardPaths.Get() + pathdict = {} + pathdict['TempDir'] = sp.GetTempDir() + pathdict['Cache'] = os.path.join(sp.GetUserLocalDataDir(), 'wxDocsDemoCache', + WXVERSION) + pathdict['Docs_URL'] = wxget.get_docs_demo_url(False) + #pathdict['wxDocs'] = os.path.join(sp.GetAppDocumentsDir(), 'wxDocs', WXVERSION) + pathdict['wxDocs'] = sp.GetAppDocumentsDir() + pathdict['Docs_Name'] = "wxPython-docs-%s" % WXVERSION + pathdict['Demo_URL'] = wxget.get_docs_demo_url(True) + #pathdict['wxDemo'] = os.path.join(sp.GetUserLocalDataDir(), 'wxDemo', WXVERSION) + pathdict['wxDemo'] = sp.GetUserLocalDataDir() + pathdict['Demo_Name'] = "wxPython-demo-%s" % WXVERSION + pathdict['Ext'] = 'tar.gz' + return pathdict + +def unpack_cached(cached, dest_dir): + """ Unpack from the cache.""" + print('Unpack', cached, 'to', dest_dir) + tf = tarfile.open(cached, "r:*") + tf.extractall(dest_dir) + dest_dir = os.listdir(dest_dir)[0] + return dest_dir + +def get_item(final, url, cache, name, ext): + """ Get the item """ + print('Looking for', name, 'at', final) + fullpath = os.path.join(final, name) + if os.path.exists(fullpath): # Already exists + return fullpath + + cached = os.path.join(cache, name) + cached = os.path.extsep.join([cached, ext]) + print('Looking for cashed', cached) + if not os.path.exists(cached): # No cached copy + cached = wxget.download_file(url, cache, True) + + if os.path.exists(cached): # We now have a cached copy + unpack_cached(cached, final) + else: + fullpath = None + return fullpath + +def report_error(err_text): + """ Report a problem.""" + endsure_wx_app() + wx.MessageBox(err_text, caption='ERROR!', + style=wx.OK|wx.CENTRE|wx.ICON_ERROR) + +def done(result=0): + """ Tidy up and exit.""" + global APP + if APP: + print("Closing Launcher App!") # Debug + APP.Destroy() + print("Done!") + sys.exit(result) + +def docs_main(args=sys.argv): + """ Get/Launch Docs.""" + endsure_wx_app() + result = 0 + print("Launch Docs for wxPython V%s" % WXVERSION) + pd = get_paths_dict() + location = get_item(pd['wxDocs'], pd['Docs_URL'], pd['Cache'], + pd['Docs_Name'], pd['Ext']) + if location: + location = os.path.join(location, 'docs', 'html', 'index.html') + location_url = urlparse.urljoin('file:', pathname2url(location)) + print("Show Docs at:", location) + webbrowser.open(location_url) + else: + result = 'Unable to find wx.Docs' + report_error(result) + done(result) + +def demo_main(args=sys.argv): + """ Get/Launch Demo.""" + result = 0 + endsure_wx_app() + print("Launch Demo for wxPython V%s" % WXVERSION) + pd = get_paths_dict() + location = get_item(pd['wxDemo'], pd['Demo_URL'], pd['Cache'], + pd['Demo_Name'], pd['Ext']) + if location: + cmds = [sys.executable, os.path.join(location, "demo", "demo.py")] + print("Launching", cmds[1]) + pid = subprocess.Popen(cmds).pid + #subprocess.check_call(cmds) # Use instead for debug + print("Demo starting as PID %s - may take a few seconds!" % pid) + else: + result = 'Unable to find wx.Demo' + report_error(result) + done(result) + +def main(args=sys.argv): + """ Command line main.""" + if len(args) > 1: + if "demo" in args[1].lower(): + return demo_main() + elif "docs" in args[1].lower(): + return docs_main() + #else: + print(__doc__) + #else: + #APP = wx.App() + +if __name__ == "__main__": + main()