Skip to content

Commit

Permalink
Refactoring the startup logic
Browse files Browse the repository at this point in the history
  • Loading branch information
jkarns275 committed May 29, 2019
1 parent 73a7de9 commit af5a46c
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 159 deletions.
95 changes: 6 additions & 89 deletions src/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,101 +2,18 @@
This is the main module. It basically checks that there is a hapi api key, asks for one if there
is not one, and launches the main GUI. Thats about it.
"""
import os
import sys
from multiprocessing import freeze_support
import sys

from PyQt5 import QtCore, QtWidgets

from metadata.config import Config
# This should be imported first: it verifies the correct python version is running, and moves the
# current working directory to wherever it ought to be. Importing things for their side-effects
# is probably bad practice, but so is using python.
from startup import verify_internet_connection_and_obtain_api_key
from utils.log import TextReceiver
from windows.main_window import MainWindow
from worker.hapi_thread import HapiThread
from worker.hapi_worker import HapiWorker
from worker.work_request import WorkRequest


# Create the data folder if it doesn't exist.
if not os.path.exists(Config.data_folder):
os.makedirs(Config.data_folder)


# This is not necessary right now but will be helpful of the behavior of
# the QApplication needs to be modified.
# class App(QtWidgets.QApplication):
# def __init__(self, *args):
# QtWidgets.QApplication.__init__(self, *args)

def main():
"""
The main method starts the GUI after asking for an api key if necessary.
"""
if len(sys.argv) > 1 and sys.argv[1] == 'test':
import test

test.run_tests()
return 0

if Config.high_dpi:
# Enable High DPI display with PyQt5
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)

# Fix for mac-based systems...
os.environ['no_proxy'] = '*'

##
# The following blocks of code verify the hapi API key is in place, and it
# is valid. If it is not valid or in place the user will we prompted for
# one. This code also checks for a working internet connection, as hapi
# needs one to download data. In the future, if there is no internet
# connection the GUI should simply disable the features that require it,
# and there could be a periodic check for internet connection that will
# re-enable them.

if not verify_internet_connection_and_obtain_api_key():
return 0

from metadata.molecule_meta import MoleculeMeta

WorkRequest.start_work_process()

# Hapi is now started automatically in the work process
# start = HapiWorker(WorkRequest.START_HAPI, {})
# start.start() # When a start_hapi request is sent, it starts automatically.

_ = MoleculeMeta(0)
from metadata.xsc_meta import CrossSectionMeta

# If the cache is expired, download a list of the cross section meta file.
# This also populates the CrossSectionMeta.molecule_metas field.
_ = CrossSectionMeta(0)

app = QtWidgets.QApplication(sys.argv)

window = MainWindow()
window.gui.adjustSize()

TextReceiver.init(window)

_qt_result = app.exec_()

TextReceiver.redirect_close()
close = HapiWorker(WorkRequest.END_WORK_PROCESS, { }, callback = None)
close.safe_exit()
WorkRequest.WORKER.process.join()
HapiThread.kill_all()
sys.exit(0)
return 0
from startup import fix_cwd, check_version
from app import run

check_version()
fix_cwd()

if __name__ == '__main__':
freeze_support()
# try:
# main()
# except Exception as error:
# debug(error)
main()
sys.exit(run())
141 changes: 141 additions & 0 deletions src/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
"""
This module launches the main GUI, which should only be ran after all setup is finished
"""

import os
import sys
from urllib.error import HTTPError, URLError

from PyQt5 import QtCore, QtWidgets

from utils.log import TextReceiver
from windows.main_window import MainWindow
from worker.hapi_thread import HapiThread
from worker.hapi_worker import HapiWorker
from worker.work_request import WorkRequest
from metadata.config import Config


def obtain_apikey():
"""
Attempts to obtain an API key from the user if there is not one in the user Config already.
If there is no valid API key when this function is called, the user will be prompted for one
and the program will exit.
"""
Config.hapi_api_key = Config.hapi_api_key.strip().lower()

from widgets.apikey_help_widget import ApiKeyHelpWidget, ApiKeyValidator

if Config.hapi_api_key == '0000' or \
ApiKeyValidator.APIKEY_REGEX.match(Config.hapi_api_key) is None:
app = QtWidgets.QApplication(sys.argv)
_ = ApiKeyHelpWidget()
app.exec_()


def verify_internet_connection_and_obtain_api_key():
"""
This function also verifies that the supplied hapi api key is valid. If the api key is not
valid, then the value in the config (in memory and on disk) is overwritten and the
obtain_apikey function is called, which will prompt the user for a valid API key and close the
program.
:return: True if there is an internet connection, false otherwise.
"""
import urllib.request
from utils.hapi_api import CrossSectionApi

try:
with urllib.request.urlopen(
f"{CrossSectionApi.BASE_URL}/{CrossSectionApi.API_ROUTE}/{Config.hapi_api_key}" \
f"{CrossSectionApi.XSC_META_ROUTE}"):
pass
return True
except HTTPError as _:
# An HTTP error code was given the response. This means the APIKEY was invalid
err_msg = """
Your HAPI API key is invalid, or you did not enter one. Hapiest will close after you hit Ok, and
will prompt you for your hapi API key upon the next launch. If you think your HAPI is valid,
please file a bug report at https://github.com/hitranonline/hapiest
"""
Config.hapi_api_key = '0000'
obtain_apikey()
Config.rewrite_config()
except URLError as _:
# URL Lookup failed. Probably means there is no internet connection
err_msg = """
You do not have a working internet connection. A working internet connection
is needed in order to use hapiest.
"""

from widgets.error_msg_widget import ErrorMsgWidget

app = QtWidgets.QApplication(sys.argv)
_ = ErrorMsgWidget(err_msg)
app.exec_()
sys.exit(0)


def run():
"""
The main method starts the GUI after asking for an api key if necessary.
"""

# Create the data folder if it doesn't exist.
if not os.path.exists(Config.data_folder):
os.makedirs(Config.data_folder)

if len(sys.argv) > 1 and sys.argv[1] == 'test':
import test

test.run_tests()
return 0

if Config.high_dpi:
# Enable High DPI display with PyQt5
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)

# Fix for mac-based systems...
os.environ['no_proxy'] = '*'

##
# The following blocks of code verify the hapi API key is in place, and it
# is valid. If it is not valid or in place the user will we prompted for
# one. This code also checks for a working internet connection, as hapi
# needs one to download data. In the future, if there is no internet
# connection the GUI should simply disable the features that require it,
# and there could be a periodic check for internet connection that will
# re-enable them.

if not verify_internet_connection_and_obtain_api_key():
return 0

from metadata.molecule_meta import MoleculeMeta

WorkRequest.start_work_process()

# Hapi is now started automatically in the work process
# start = HapiWorker(WorkRequest.START_HAPI, {})
# start.start() # When a start_hapi request is sent, it starts automatically.

_ = MoleculeMeta(0)
from metadata.xsc_meta import CrossSectionMeta

# If the cache is expired, download a list of the cross section meta file.
# This also populates the CrossSectionMeta.molecule_metas field.
_ = CrossSectionMeta(0)

app = QtWidgets.QApplication(sys.argv)

window = MainWindow()
window.gui.adjustSize()

TextReceiver.init(window)

_qt_result = app.exec_()

TextReceiver.redirect_close()
close = HapiWorker(WorkRequest.END_WORK_PROCESS, {}, callback=None)
close.safe_exit()
WorkRequest.WORKER.process.join()
HapiThread.kill_all()
return 0
85 changes: 15 additions & 70 deletions src/startup.py
Original file line number Diff line number Diff line change
@@ -1,83 +1,28 @@
"""
This is the startup module. It has the utility function
verify_internet_connection_and_obtain_api_key. When this package is imported, it moves the
current working directory to the proper place, if necessary.
This is the startup module. All of the functions here should be ran before the main app
is started.
"""
import os
import re
import sys
from urllib.error import HTTPError, URLError

from PyQt5 import QtWidgets


if sys.version_info < (3, 6):
print(f"You must have Python 3 installed to use hapiest, current version is {str(sys.version)}")
sys.exit(0)

# If someone launches the program through the command 'python3 __main__.py'
# this moves the current working directory to the proper place
SRC_REGEX = re.compile('.+src\\Z')
if SRC_REGEX.match(os.getcwd()):
os.chdir('..')

from metadata.config import Config


def obtain_apikey():
def check_version():
"""
Attempts to obtain an API key from the user if there is not one in the user Config already.
If there is no valid API key when this function is called, the user will be prompted for one
and the program will exit.
Ensures the version is at least python 3.6. The program exits if the wrong version of
python is used.
"""
Config.hapi_api_key = Config.hapi_api_key.strip().lower()

from widgets.apikey_help_widget import ApiKeyHelpWidget, ApiKeyValidator
if sys.version_info < (3, 6):
print(f"You must have Python 3 installed to use hapiest, current version is"
f"{str(sys.version)}")
sys.exit(0)

if Config.hapi_api_key == '0000' or \
ApiKeyValidator.APIKEY_REGEX.match(Config.hapi_api_key) is None:
app = QtWidgets.QApplication(sys.argv)
_ = ApiKeyHelpWidget()
app.exec_()


def verify_internet_connection_and_obtain_api_key():
def fix_cwd():
"""
This function also verifies that the supplied hapi api key is valid. If the api key is not
valid, then the value in the config (in memory and on disk) is overwritten and the
obtain_apikey function is called, which will prompt the user for a valid API key and close the
program.
:return: True if there is an internet connection, false otherwise.
If someone launches the program through the command 'python3 __main__.py', the current working
directory is in the wrong place. This moves it to where it should be.
"""
import urllib.request
from utils.hapi_api import CrossSectionApi

try:
with urllib.request.urlopen(
f"{CrossSectionApi.BASE_URL}/{CrossSectionApi.API_ROUTE}/{Config.hapi_api_key}" \
f"{CrossSectionApi.XSC_META_ROUTE}"):
pass
return True
except HTTPError as _:
# An HTTP error code was given the response. This means the APIKEY was invalid
err_msg = """
Your HAPI API key is invalid, or you did not enter one. Hapiest will close after you hit Ok, and
will prompt you for your hapi API key upon the next launch. If you think your HAPI is valid,
please file a bug report at https://github.com/hitranonline/hapiest
"""
Config.hapi_api_key = '0000'
obtain_apikey()
Config.rewrite_config()
except URLError as _:
# URL Lookup failed. Probably means there is no internet connection
err_msg = """
You do not have a working internet connection. A working internet connection
is needed in order to use hapiest.
"""

from widgets.error_msg_widget import ErrorMsgWidget

app = QtWidgets.QApplication(sys.argv)
_ = ErrorMsgWidget(err_msg)
app.exec_()
sys.exit(0)
src_regex = re.compile('.+src\\Z')
if src_regex.match(os.getcwd()):
os.chdir('..')

0 comments on commit af5a46c

Please sign in to comment.