Source code for schrodinger.utils.documentation

import os
from urllib.parse import urlparse

import pyhelp
import requests

from schrodinger.infra import mm
from schrodinger.Qt import QtCore
from schrodinger.Qt import QtGui
from schrodinger.Qt import QtWidgets
from schrodinger.utils import fileutils
from schrodinger.utils import log
from schrodinger.utils.config import get_knime_workflows_url
from schrodinger.utils.env import swap_ld_library_path

logger = log.get_output_logger("documentation")
return_if_url_fails = True

BASE_SCHRODINGER_DOCUMENTATION_URL_FOR_CURRENT_RELEASE = "https://www.schrodinger.com/sites/default/files/s3/release/{}/".format(
    mm.mmfile_get_release_name())

# dictionary to store links fragments for help action items.
DOCUMENTATION_LINKS = {
    "maestro_tutorials": ("smdd?f%5B0%5D=type%3Atraining", ""),
    "material_science_tutorials":
        ("materials-science?f%5B0%5D=type%3Atraining", ""),
    "bioluminate_tutorials": ("biologics?f%5B0%5D=type%3Atraining", "")
}


[docs]def get_topic_fragment(topic_name: str) -> str: """ Returns topic fragment (relative path of topic file) Raise RuntimeError if docs folder is not present. :param topic_name: is help topic ID. :return: relative path of topic file. """ if not pyhelp.is_docs_installed(): raise RuntimeError("Docs folder is not found") return pyhelp.mmpyhelp_get_relative_topic_url(topic_name)
[docs]def show_local_doc(relative_file_path: str): """ Shows help topic webpage from local docs ($SCHRODINGER/docs). Raises RuntimeError if help topic file is not found. :param relative_file_path: is path to help topic webpage. """ docsdir = pyhelp.mmpyhelp_get_docs_dir() topic_fp = os.path.normpath( os.path.join(docsdir, urlparse(relative_file_path).path)) if not os.path.isfile(topic_fp): raise RuntimeError("Topic file not found") doc_base_path = os.path.join(docsdir, 'Documentation.htm') if not os.path.isfile(doc_base_path): raise RuntimeError("Documentation file not found") if not open_url( doc_base_path, fragment=relative_file_path, show_warning=False): raise RuntimeError("Couldn't show help topic")
[docs]def is_internet_available() -> bool: """ Returns True if access to www.schrodinger.com is available False otherwise """ try: response = requests.get("https://www.schrodinger.com", timeout=10) return response.status_code == requests.codes.ok except requests.exceptions.RequestException: return False
[docs]def show_topic(topic_name: str) -> str: """ Opens a window to display the help topic. It will try to look for online docs, if not able to show then fallback to search for local docs present inside $SCHRODINGER/docs. In case both are not available warns user. :param topic_name Name of help topic """ try: relative_topic_fp = get_topic_fragment(topic_name) documentation_url = BASE_SCHRODINGER_DOCUMENTATION_URL_FOR_CURRENT_RELEASE + "Documentation/html/Documentation.htm" if is_internet_available() and open_url(documentation_url, fragment=relative_topic_fp, show_warning=False): return show_local_doc(relative_topic_fp) except RuntimeError: message = ( "Schr&ouml;dinger documentation is now online at <a href='https://www.schrodinger.com/documentation'>schrodinger.com/documentation</a>." " Please check your internet access." "<br>If online access is not available, download a local copy of the documentation <a href='https://www.schrodinger.com/downloads/releases'>here</a>." "<br>Once you've downloaded the zip file, un-zip and move the contents into the 'docs' folder in the Schr&ouml;dinger software installation." ) show_message(message, title="Documentation Not Found")
[docs]def show_python_api(): """ Opens a browser to display local python API. """ url = ("http://www.schrodinger.com/docs/suite{}/python_api/api" "/frames.html".format(mm.mmfile_get_release_name())) status = open_url(url, return_if_url_fails) if not status: url = os.path.join(pyhelp.mmpyhelp_get_docs_dir(), "python_api", "api", "frames.html") open_url(url)
[docs]def show_python_overview(): url = ("http://www.schrodinger.com/docs/suite{}/python_api/overview." "html".format(mm.mmfile_get_release_name())) status = open_url(url, return_if_url_fails) if not status: url = os.path.join(pyhelp.mmpyhelp_get_docs_dir(), "python_api", "overview.html") open_url(url)
[docs]def show_contact_info(): url = "https://www.schrodinger.com/supportcenter/" open_url(url)
[docs]def show_manuals_index(): help_dir = pyhelp.mmpyhelp_get_docs_dir() url = os.path.join(help_dir, "Documentation.htm") open_url(url)
[docs]def show_knowledge_base(context=""): url = "http://www.schrodinger.com/kb_redirect.php%s" % context open_url(url)
[docs]def show_new_features(context=""): url = "http://www.schrodinger.com/new_features_general_redirect.php%s" % context open_url(url)
[docs]def show_new_maestro_features(context=""): url = "http://www.schrodinger.com/new_features_maestro_redirect.php%s" % context open_url(url)
[docs]def show_known_issues(context=""): url = "http://www.schrodinger.com/Known_Issues.html%s" % context open_url(url)
[docs]def show_canvas_user_manual(): help_dir = pyhelp.mmpyhelp_get_docs_dir() url = os.path.join(help_dir, "canvas_user_manual", "canvas_user_manualTOC.htm") open_url(url)
# Maestro URLS
[docs]def show_elements_visualization_tutorial(): url = os.path.join(pyhelp.mmpyhelp_get_docs_dir(), "maestro_elements", 'maestro_elements_tutorial_vis.pdf') open_url(url)
[docs]def show_elements_task_tutorial(): url = os.path.join(pyhelp.mmpyhelp_get_docs_dir(), "maestro_elements", 'maestro_elements_tutorial_tasks.pdf') open_url(url)
[docs]def show_about_utilities(): help_dir = pyhelp.mmpyhelp_get_docs_dir() url = os.path.join(help_dir, "quick_reference", "schrodinger_utilities.htm") open_url(url)
[docs]def show_knime_workflows(): open_url(get_knime_workflows_url())
[docs]def show_online_tutorials(key): """ Shows online tutorials according to profile key value present in DOCUMENTATION_LINKS dictionary. :param key: is key for help action. :type key: str """ try: link, fragment = DOCUMENTATION_LINKS[key] base_url = "https://www.schrodinger.com/learn/training/" url = base_url + link open_url(url=url, show_warning=True, fragment=fragment) except KeyError: pass
[docs]@swap_ld_library_path() def open_url(url, show_warning=True, fragment=None): if os.path.isfile(url): #normalizes path separators qurl = QtCore.QUrl.fromLocalFile(url) else: qurl = QtCore.QUrl(url) qurl.setFragment(fragment) status = openTempURL(qurl) if not status: if show_warning: warn_msg = ( "WARNING Please check if the given path - {} is okay and has a " "valid associated application to open it.").format(url) show_message(warn_msg) return status
[docs]def openTempURL(qurl): """ Create a temporary file containing HTML and open it in browser The HTML redirects the browser to the appropriate url. This circumvents a bug in Windows and MacOS that chops off the anchor of a URL if the URL points to a local file. :param qurl: The QUrl to redirect to :type qurl: QtCore.QUrl :return: Success of opening the temp URL :rtype: bool """ url = qurl.toString() temp_dir = fileutils.get_directory_path(fileutils.TEMP) redir_file = os.path.join(temp_dir, "redir.html") html = ("<html><head>" "<meta http-equiv=\"refresh\" " "content=\"0;url={}\" />" "</head></html>").format(url) with open(redir_file, mode="w") as fh: fh.write(html) redir_qurl = QtCore.QUrl.fromLocalFile(redir_file) status = QtGui.QDesktopServices.openUrl(redir_qurl) return status
[docs]def show_message(message, title="Warning"): if not QtWidgets.QApplication.instance(): logger.error(message) else: QtWidgets.QMessageBox.warning(None, title, message)