Skip to content

Commit

Permalink
Preliminary attempt at extended Jupyter launcher
Browse files Browse the repository at this point in the history
that would allow for remembering the last 10
directories selected as well as selecting the
Anaconda environment to use.
  • Loading branch information
ColinTalbert committed Dec 12, 2017
1 parent 582bae4 commit c6089a9
Show file tree
Hide file tree
Showing 4 changed files with 557 additions and 44 deletions.
70 changes: 26 additions & 44 deletions pymdwizard/gui/MainWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
from pymdwizard.gui.Preview import Preview
from pymdwizard.gui.error_list import ErrorList
from pymdwizard.gui.wiz_widget import WizardWidget
from pymdwizard.gui.jupyterstarter import JupyterStarter

import sip

Expand Down Expand Up @@ -965,43 +966,35 @@ def launch_jupyter(self):
None
"""

jupyter_dialog = JupyterLocationDialog()
utils.set_window_icon(jupyter_dialog.msgBox)
jupyter_dialog.msgBox.setWindowTitle("Where do you want to launch Jupyter?")
ret = jupyter_dialog.msgBox.exec_()

install_dir = utils.get_install_dname()
if ret == 0:
jupyter_dname = os.path.join(install_dir, 'examples')
elif ret == 1:
settings = QSettings('USGS', 'pymdwizard')
last_jupyter_dname = settings.value('last_jupyter_dname')

if last_jupyter_dname is None:
last_jupyter_dname = os.path.join(install_dir, 'examples')
jupyter_dname = QFileDialog.getExistingDirectory(self, "Select Directory to launch Jupyter from",
last_jupyter_dname)
if jupyter_dname:
settings.setValue('last_jupyter_dname', jupyter_dname)
else:
return
else:
return

root_dir = utils.get_install_dname('root')
python_dir = utils.get_install_dname('python')
jupyterexe = os.path.join(python_dir, "scripts", "jupyter.exe")

if os.path.exists(jupyterexe) and os.path.exists(root_dir):

my_env = os.environ.copy()
my_env["PYTHONPATH"] = os.path.join(root_dir, "Python35_64")
settings = QSettings('USGS', 'pymdwizard')
last_kernel = settings.value('last_kernel', '')
jupyter_dnames = settings.value('jupyter_dnames', [])
if not jupyter_dnames:
install_dir = utils.get_install_dname()
jupyter_dnames = [os.path.join(install_dir, 'examples')]
settings.setValue('jupyter_dnames', jupyter_dnames)

self.jupyter_dialog = JupyterStarter(last_kernel=last_kernel,
previous_dnames=jupyter_dnames,
update_function=self.update_jupyter_dnames)
utils.set_window_icon(self.jupyter_dialog)
self.jupyter_dialog.show()

def update_jupyter_dnames(self, kernel, dname):
settings = QSettings('USGS', 'pymdwizard')
jupyter_dnames = settings.value('jupyter_dnames', [])

p = Popen([jupyterexe, 'notebook'], cwd=jupyter_dname, env=my_env)
try:
jupyter_dnames.remove(dname)
except ValueError:
pass

msg = 'Jupyter launching...\nJupyter will start momentarily in a new tab in your default internet browser.'
jupyter_dnames.insert(0, dname)
del jupyter_dnames[PyMdWizardMainForm.max_recent_files:]
settings.setValue('jupyter_dnames', jupyter_dnames)

QMessageBox.information(self, "Launching Jupyter", msg)
settings.setValue('last_kernel', kernel)

def about(self):

Expand Down Expand Up @@ -1066,17 +1059,6 @@ def update_from_github(self):
QMessageBox.information(self, "Update results", msg)


class JupyterLocationDialog(QDialog):
def __init__(self, parent=None):
super(JupyterLocationDialog, self).__init__(parent)

self.msgBox = QMessageBox()
self.msgBox.setText('Choose option below:')
self.msgBox.addButton(QPushButton('Default (MetadataWizard examples folder)'), QMessageBox.YesRole)
self.msgBox.addButton(QPushButton('Browse to different folder'), QMessageBox.NoRole)
self.msgBox.addButton(QPushButton('Cancel'), QMessageBox.RejectRole)


def launch_main(xml_fname=None, introspect_fname=None):
app = QApplication(sys.argv)

Expand Down
202 changes: 202 additions & 0 deletions pymdwizard/gui/jupyterstarter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
#!/usr/bin/env python
# -*- coding: utf8 -*-
"""
The MetadataWizard(pymdwizard) software was developed by the
U.S. Geological Survey Fort Collins Science Center.
See: https://github.com/usgs/fort-pymdwizard for current project source code
See: https://usgs.github.io/fort-pymdwizard/ for current user documentation
See: https://github.com/usgs/fort-pymdwizard/tree/master/examples
for examples of use in other scripts
License: Creative Commons Attribution 4.0 International (CC BY 4.0)
http://creativecommons.org/licenses/by/4.0/
PURPOSE
------------------------------------------------------------------------------
Provide a pyqt widget for the FGDC component with a shortname matching this
file's name.
SCRIPT DEPENDENCIES
------------------------------------------------------------------------------
This script is part of the pymdwizard package and is not intented to be
used independently. All pymdwizard package requirements are needed.
See imports section for external packages used in this script as well as
inter-package dependencies
U.S. GEOLOGICAL SURVEY DISCLAIMER
------------------------------------------------------------------------------
This software has been approved for release by the U.S. Geological Survey
(USGS). Although the software has been subjected to rigorous review,
the USGS reserves the right to update the software as needed pursuant to
further analysis and review. No warranty, expressed or implied, is made by
the USGS or the U.S. Government as to the functionality of the software and
related material nor shall the fact of release constitute any such warranty.
Furthermore, the software is released on condition that neither the USGS nor
the U.S. Government shall be held liable for any damages resulting from
its authorized or unauthorized use.
Any use of trade, product or firm names is for descriptive purposes only and
does not imply endorsement by the U.S. Geological Survey.
Although this information product, for the most part, is in the public domain,
it also contains copyrighted material as noted in the text. Permission to
reproduce copyrighted items for other than personal use must be secured from
the copyright owner.
------------------------------------------------------------------------------
"""

import os
import subprocess
from subprocess import Popen

from PyQt5.QtWidgets import QFileDialog
from PyQt5.QtWidgets import QDialog
from PyQt5.QtWidgets import QMessageBox

from pymdwizard.core import utils
from pymdwizard.gui import wiz_widget

from pymdwizard.gui.ui_files import UI_jupyterstarter


class JupyterStarter(QDialog):

def __init__(self, previous_dnames=[], last_kernel='',
default_kernel = 'pymdwizard <<default>>',
update_function=None, parent=None):
super(self.__class__, self).__init__(parent=parent)

self.build_ui()
self.connect_events()

self.kernels = []
self.previous_dnames = previous_dnames
if previous_dnames:
self.ui.dname.setCurrentText(previous_dnames[0])

self.default_kernel = default_kernel
self.populate_kernels()
self.update_function = update_function

for dname in self.previous_dnames:
self.ui.dname.addItem(dname)

if last_kernel and last_kernel in self.kernels:
index = self.ui.kernel.findText(last_kernel)
if index >= 0:
self.ui.kernel.setCurrentIndex(index)

utils.set_window_icon(self)
self.setStyleSheet(wiz_widget.NORMAL_STYLE)

def build_ui(self):
"""
Build and modify this widget's GUI
Returns
-------
None
"""
self.ui = UI_jupyterstarter.Ui_Form()
self.ui.setupUi(self)

def populate_kernels(self):
self.ui.kernel.addItem('pymdwizard <<default>>')
self.kernels.append('pymdwizard <<default>>')

kernels = subprocess.check_output(['conda', 'env', 'list'])
for line in kernels.split(b'\n'):
if line and not line.strip().startswith(b'#'):
try:
name, path = line.split()
self.ui.kernel.addItem(str(name)[2:-1])
self.kernels.append(str(name)[2:-1])
except ValueError:
pass

def connect_events(self):
"""
Connect the appropriate GUI components with the corresponding functions
Returns
-------
None
"""
self.ui.btn_browse.clicked.connect(self.browse)
self.ui.btn_cancel.clicked.connect(self.close_form)
self.ui.btn_launch.clicked.connect(self.launch)

def browse(self):
if not self.previous_dnames:
dname = ''
else:
dname = self.previous_dnames[0]

jupyter_dname = QFileDialog.getExistingDirectory(self, "Select Directory to launch Jupyter from",
dname)
if jupyter_dname:
self.ui.dname.setCurrentText(jupyter_dname)

def get_conda_root(self):
conda_info = subprocess.check_output(['conda', 'info']).decode("utf-8")
info = {}
for line in conda_info.split('\n')[1:]:
try:
key, value = line.strip().split(' : ')
info[key] = value
except ValueError:
pass

envs_dname = info['envs directories']
root_dname = info["root environment"].replace('(writable)', '').strip()
return str(root_dname), str(envs_dname)

def launch(self):
jupyter_dname = self.ui.dname.currentText()
if not os.path.exists(jupyter_dname):
msg = 'The selected directory to lauch jupyter in does not exists.'
msg += '\nPlease check the location before launching Jupyter.'
QMessageBox.information(self, "Missing Directory", msg)

if self.ui.kernel.currentText() == self.default_kernel:
# this is pymdwizard specific
# TODO:refactor to make this widget more generalizable
root_dir = utils.get_install_dname('root')
python_dir = utils.get_install_dname('python')
jupyterexe = os.path.join(python_dir, "scripts", "jupyter.exe")

my_env = os.environ.copy()
my_env["PYTHONPATH"] = os.path.join(root_dir, "Python36_64")

p = Popen([jupyterexe, 'notebook'], cwd=jupyter_dname, env=my_env)

else:
root_dname, envs_dname = self.get_conda_root()
activate_fname = os.path.join(root_dname, 'Scripts', 'activate.bat')
jupyter_exe_name = os.path.join(envs_dname, self.ui.kernel.currentText(), 'Scripts', 'jupyter.exe')
if not os.path.exists(jupyter_dname):
jupyter_exe_name = os.path.join(root_dname, 'Scripts', 'jupyter.exe')

cmds = ['"{}"'.format(activate_fname), self.ui.kernel.currentText(),
'&&', '"{}"'.format(jupyter_exe_name), 'notebook']
Popen(" ".join(cmds), cwd=jupyter_dname)

msg = 'Jupyter launching...\nJupyter will start momentarily in a new tab in your default internet browser.'
QMessageBox.information(self, "Launching Jupyter", msg)

self.update_function(self.ui.kernel.currentText(),
self.ui.dname.currentText())
self.close()

def close_form(self):
self.parent = None
self.deleteLater()
self.close()


if __name__ == '__main__':
utils.launch_widget(JupyterStarter, "JupyterStarter", previous_dnames=[r"c:\temp", r"c:\temp\junk"])

Loading

0 comments on commit c6089a9

Please sign in to comment.