Source code for schrodinger.utils.license

"""
Contains a class `License` that allows easy licensing of Python scripts

It is a violation of your software license agreement to modify the code in this
module in any way.

Copyright Schrodinger, LLC. All rights reserved.
"""

import os

import schrodinger.infra.licensing as licensing
from schrodinger.infra import mm
"""
Documentation of the schrodinger.infra.licensing class:
license = licensing.License(licensing.BIOLUMINATE_MAIN, 93)

 The equivalent docstrings for the License object would be something like
 this:

 class License:
    ""
    This class checks out a license at instantiation and will check in the
    license when it is garbage collected.

    ""

    def __init__(product_feature, product_version, num_tokens=-1):
        ""
        Check out a license.

        :param product_feature:
            A module-level constant value indicating the product feature.

        :param product_version:
            An integer value representing the product version. This is ten
            times the decimal value with the tenths digit, i.e. 93 for version
            9.3.

        :param num_tokens:
            The number of tokens to check out. A value of -1 indicates that
            the default number of tokens for the feature should be used.

        ""
        ...

    def checkin(self):
        ""
        Check in the license.

        ""
        ...

 Please note that since this is a SWIG wrapper you can't actually use a
 keyword
 argument for num_tokens; just specify it as a positional argument.
"""

# The following steps are recommended for adding a new token
# 1) Add a module level constant pointing to the token in licensing - required
# 2) Add the license to the LICENSE_NAMES dictionary for more informative string
# representation of the license token
# 3) Provide a default version number in the DEFAULT_VERSIONS dictionary for
# ease of updating version numbers with new releases.

# Any license added here must also be added to LICENSE_NAMES
BIOLUMINATE_MAIN = licensing.BIOLUMINATE_MAIN
BIOLUMINATE_SHARED = licensing.BIOLUMINATE_SHARED
BIOLUMINATE_PROTEIN_DOCKING = licensing.BIOLUMINATE_PROTEIN_DOCKING
BIOLUMINATE_PEPTIDE_DESC = licensing.BIOLUMINATE_PEPTIDE_DESC
GPUSIMILARITY = licensing.GPUSIMILARITY
MATERIALSCIENCE_MAIN = licensing.MATERIALSCIENCE_MAIN
EPIK_MAIN = licensing.EPIK_MAIN
MATERIALSCIENCE_GA = licensing.MATERIALSCIENCE_GA
MATERIALSCIENCE_CG = licensing.MATERIALSCIENCE_CG
MATERIALSCIENCE_QE = licensing.MATERIALSCIENCE_QE
MATERIALSCIENCE_DIELECTRIC = licensing.MATERIALSCIENCE_DIELECTRIC
MATERIALSCIENCE_DIFFUSION = licensing.MATERIALSCIENCE_DIFFUSION
MATERIALSCIENCE_INFORMATICS = licensing.MATERIALSCIENCE_INFORMATICS
MATERIALSCIENCE_PENETRANT = licensing.MATERIALSCIENCE_PENETRANT
MATERIALSCIENCE_REACTIVITY = licensing.MATERIALSCIENCE_REACTIVITY
MATERIALSCIENCE_MOBILITY = licensing.MATERIALSCIENCE_MOBILITY
MATERIALSCIENCE_MORPH = licensing.MATERIALSCIENCE_MORPH
DESMOND_GPGPU = licensing.DESMOND_GPGPU
FEP_GPGPU = licensing.FEP_GPGPU
FEP_COMPLETED_COMPOUND = licensing.FEP_COMPLETED_COMPOUND
JAGUAR_TS_SEARCH = licensing.JAGUAR_TS_SEARCH
JAGUAR_MACRO_PKA = licensing.JAGUAR_MACRO_PKA
PSP_PLOP = licensing.PSP_PLOP
IMPACT_MAIN = licensing.IMPACT_MAIN
LIGPREP_MAIN = licensing.LIGPREP_MAIN
GLIDE_MAIN = licensing.GLIDE_MAIN
SHAPE_SCREEN = licensing.SHAPE_SCREEN
WSCORE_MAIN = licensing.WSCORE_MAIN
AUTODESIGNER = licensing.AUTODESIGNER
GLIDE_SP_DOCKING = licensing.GLIDE_SP_DOCKING
GLIDE_XP_DOCKING = licensing.GLIDE_XP_DOCKING
ACTIVE_LEARN = licensing.ACTIVE_LEARN
PHASE_FEATURE = licensing.PHASE_FEATURE
PHASE_DBSEARCH = licensing.PHASE_DBSEARCH

MATERIALSCIENCE = 'MATERIALSCIENCE'

# Any license added here should also be a module-level constant.  Values should
# be the string-ified module constant for informative user output
LICENSE_NAMES = {}
LICENSE_NAMES[BIOLUMINATE_MAIN] = 'BIOLUMINATE_MAIN'
LICENSE_NAMES[BIOLUMINATE_SHARED] = 'BIOLUMINATE_SHARED'
LICENSE_NAMES[BIOLUMINATE_PROTEIN_DOCKING] = 'BIOLUMINATE_PROTEIN_DOCKING'
LICENSE_NAMES[BIOLUMINATE_PEPTIDE_DESC] = 'BIOLUMINATE_PEPTIDE_DESC'
LICENSE_NAMES[GPUSIMILARITY] = 'GPUSIMILARITY'
LICENSE_NAMES[MATERIALSCIENCE_MAIN] = f'{MATERIALSCIENCE}_MAIN'
LICENSE_NAMES[EPIK_MAIN] = 'EPIK_MAIN'
LICENSE_NAMES[MATERIALSCIENCE_GA] = f'{MATERIALSCIENCE}_GA'
LICENSE_NAMES[MATERIALSCIENCE_CG] = f'{MATERIALSCIENCE}_CG'
LICENSE_NAMES[MATERIALSCIENCE_QE] = f'{MATERIALSCIENCE}_QE'
LICENSE_NAMES[MATERIALSCIENCE_DIFFUSION] = f'{MATERIALSCIENCE}_DIFFUSION'
LICENSE_NAMES[MATERIALSCIENCE_DIELECTRIC] = f'{MATERIALSCIENCE}_DIELECTRIC'
LICENSE_NAMES[MATERIALSCIENCE_INFORMATICS] = f'{MATERIALSCIENCE}_INFORMATICS'
LICENSE_NAMES[MATERIALSCIENCE_PENETRANT] = f'{MATERIALSCIENCE}_PENETRANT'
LICENSE_NAMES[MATERIALSCIENCE_REACTIVITY] = f'{MATERIALSCIENCE}_REACTIVITY'
LICENSE_NAMES[MATERIALSCIENCE_MOBILITY] = f'{MATERIALSCIENCE}_MOBILITY'
LICENSE_NAMES[MATERIALSCIENCE_MORPH] = f'{MATERIALSCIENCE}_MORPH'
LICENSE_NAMES[DESMOND_GPGPU] = 'DESMOND_GPGPU'
LICENSE_NAMES[FEP_GPGPU] = 'FEP_GPGPU'
LICENSE_NAMES[FEP_COMPLETED_COMPOUND] = 'FEP_COMPLETED_COMPOUND'
LICENSE_NAMES[JAGUAR_TS_SEARCH] = 'JAGUAR_TS_SEARCH'
LICENSE_NAMES[PSP_PLOP] = 'PSP_PLOP'
LICENSE_NAMES[IMPACT_MAIN] = 'IMPACT_MAIN'
LICENSE_NAMES[GLIDE_MAIN] = 'GLIDE_MAIN'
LICENSE_NAMES[LIGPREP_MAIN] = 'LIGPREP_MAIN'
LICENSE_NAMES[SHAPE_SCREEN] = 'SHAPE_SCREEN'
LICENSE_NAMES[WSCORE_MAIN] = 'WSCORE_MAIN'
LICENSE_NAMES[AUTODESIGNER] = 'AUTODESIGNER'
LICENSE_NAMES[GLIDE_SP_DOCKING] = 'GLIDE_SP_DOCKING'
LICENSE_NAMES[GLIDE_XP_DOCKING] = 'GLIDE_XP_DOCKING'
LICENSE_NAMES[ACTIVE_LEARN] = 'ACTIVE_LEARN'
LICENSE_NAMES[PHASE_FEATURE] = 'PHASE_FEATURE'
LICENSE_NAMES[PHASE_DBSEARCH] = 'PHASE_DBSEARCH'
LICENSE_NAMES[JAGUAR_MACRO_PKA] = 'JAGUAR_MACRO_PKA'

LICENSE_BY_NAME = {v: k for k, v in LICENSE_NAMES.items()}


[docs]class License: """ Class to allow easy licensing of Python scripts It is a violation of your software license to modify this class in any way. """
[docs] def __init__(self, license_type, num_tokens=1, version=None, force=False): """ Create a License object. License objects should be assigned to a variable that stays in scope for the duration the license token should be held. The accepted way to return a license token is by calling the `checkin` method of the license object, but the token will also be returned when the object is garbage collected. :type license_type: module-level constant :param license_type: Module-level constant such as `BIOLUMINATE_MAIN`, `BIOLUMINATE_SHARED`, `BIOLUMINATE_PROTEIN_DOCKING`, `MATERIALSCIENCE_MAIN` :type num_tokens: int :param num_tokens: The number of tokens to check out :type version: int :param version: An integer value representing the product version. This is ten times the decimal value with the tenths digit, i.e. 93 for version 9.3. If not provided, the license type is looked up in the module constant DEFAULT_VERSIONS dictionary and that version is used. If license_type is not found in DEFAULT_VERSIONS, the module constant DEFAULT_GENERIC_VERSION is used. :type force: bool :param force: For the attempted checkout of the license even if license_type is not recognized by this class. If checkout is unsuccessful, no error will be raised, but self.license will be None """ self.license_type = license_type if license_type not in LICENSE_NAMES and not force: self.license = None raise ValueError('License must be a module constant\n' + '\n'.join(list(LICENSE_NAMES.values()))) # Get the version number if necessary if version is None: version = mm.mmcommon_get_license_feature_version(license_type) self.version = version try: self.license = licensing.License(license_type, version, num_tokens) except RuntimeError: self.license = None
def __str__(self): """ Create an informative string to print in debugging messages """ try: mystring = 'Schrodinger license of type ' + \ LICENSE_NAMES[self.license_type] except KeyError: mystring = 'Schrodinger license of type <UNKNOWN> ' if self.license: mystring = mystring + ' (Valid)' else: mystring = mystring + ' (Invalid)' return mystring
[docs] def isValid(self): """ Check if the license is currently valid """ return bool(self.license)
[docs] def checkin(self): """ Return the license token. After calling this method, the License object will report itself as invalid. """ if self.isValid(): self.license.checkin() self.license = None
def __enter__(self): return self def __exit__(self, etype, evalue, etrace): """ Return the license token when leaving a 'with' statement """ self.checkin()
[docs]class LicenseStatus: """ Simple class to store license availability status. Meant to be returned by is_license_available(), for which __bool__() has been defined. """
[docs] def __init__(self, error_code): """ :ivar error_code: The error code of a particular license type. Error codes defined in mmlic3.h :vartype error_code: int """ self._error_code = error_code
@property def error_code(self): return self._error_code def __bool__(self): return self._error_code == licensing.MMLIC3_SUCCESS
[docs]def is_license_available(license_type): """ :return: The license status :rtype: LicenseStatus """ licensing.mmlic3_initialize(0) license_status = LicenseStatus( licensing.mmlic3_feature_exists(license_type)) licensing.mmlic3_terminate() return license_status
[docs]def is_opls2_available(): """ Returns TRUE if S-OPLS is available. Note that OPLS2, OPLS3, OPLS3e, and OPLS4 are all now called S-OPLS (as of 01 June 2021). This function does not actually check for OPLS2 specifically, but rather it checks for S-OPLS. """ _lazy_import_libs() if 'MAESTRO_EXEC' in os.environ: # S-OPLS is now the term used for any Schrodinger-developed OPLS beyond # OPLS2005. Some functions like this `*_display_opls2` are holdovers # from when S-OPLS was called OPLS2. return mm.mmcommon_display_opls2() else: return (mm.mmffld_license_ok(16) == mm.TRUE)
def _lazy_import_libs(): """ Do a lazy import of schrodinger.infra.mm to avoid dependency on a large library for only one function. """ global mm from schrodinger.infra import mm
[docs]def is_matsci(token=None, name=None): """ Return True if the given license token or name is for the MATERIALSCIENCE product, False otherwise. :type token: int or None :param token: the license token, if None use name :type name: str or None :param name: the license name, if None use token :rtype: bool :return: whether the license token or name is for the MATERIALSCIENCE product """ assert bool(token) ^ bool(name) if token: name = LICENSE_NAMES[token] return name.startswith(MATERIALSCIENCE)