def create_grant(KeyId=None, GranteePrincipal=None, RetiringPrincipal=None,
    Operations=None, Constraints=None, GrantTokens=None, Name=None):
    """
    Adds a grant to a key to specify who can use the key and under what conditions. Grants are alternate permission mechanisms to key policies.
    For more information about grants, see Grants in the AWS Key Management Service Developer Guide .
    See also: AWS API Documentation

    Examples
    The following example creates a grant that allows the specified IAM role to encrypt data with the specified customer master key (CMK).
    Expected Output:

    :example: response = client.create_grant(
        KeyId='string',
        GranteePrincipal='string',
        RetiringPrincipal='string',
        Operations=[
            'Decrypt'|'Encrypt'|'GenerateDataKey'|'GenerateDataKeyWithoutPlaintext'|'ReEncryptFrom'|'ReEncryptTo'|'CreateGrant'|'RetireGrant'|'DescribeKey',
        ],
        Constraints={
            'EncryptionContextSubset': {
                'string': 'string'
            },
            'EncryptionContextEquals': {
                'string': 'string'
            }
        },
        GrantTokens=[
            'string',
        ],
        Name='string'
    )

    :type KeyId: string
    :param KeyId: [REQUIRED]
            The unique identifier for the customer master key (CMK) that the grant applies to.
            To specify this value, use the globally unique key ID or the Amazon Resource Name (ARN) of the key. Examples:
            Globally unique key ID: 12345678-1234-1234-1234-123456789012
            Key ARN: arn:aws:kms:us-west-2:123456789012:key/12345678-1234-1234-1234-123456789012

    :type GranteePrincipal: string
    :param GranteePrincipal: [REQUIRED]
            The principal that is given permission to perform the operations that the grant permits.
            To specify the principal, use the Amazon Resource Name (ARN) of an AWS principal. Valid AWS principals include AWS accounts (root), IAM users, IAM roles, federated users, and assumed role users. For examples of the ARN syntax to use for specifying a principal, see AWS Identity and Access Management (IAM) in the Example ARNs section of the AWS General Reference .

    :type RetiringPrincipal: string
    :param RetiringPrincipal: The principal that is given permission to retire the grant by using RetireGrant operation.
            To specify the principal, use the Amazon Resource Name (ARN) of an AWS principal. Valid AWS principals include AWS accounts (root), IAM users, federated users, and assumed role users. For examples of the ARN syntax to use for specifying a principal, see AWS Identity and Access Management (IAM) in the Example ARNs section of the AWS General Reference .

    :type Operations: list
    :param Operations: A list of operations that the grant permits.
            (string) --

    :type Constraints: dict
    :param Constraints: A structure that you can use to allow certain operations in the grant only when the desired encryption context is present. For more information about encryption context, see Encryption Context in the AWS Key Management Service Developer Guide .
            EncryptionContextSubset (dict) --A list of key-value pairs, all of which must be present in the encryption context of certain subsequent operations that the grant allows. When certain subsequent operations allowed by the grant include encryption context that matches this list or is a superset of this list, the grant allows the operation. Otherwise, the grant does not allow the operation.
            (string) --
            (string) --

            EncryptionContextEquals (dict) --A list of key-value pairs that must be present in the encryption context of certain subsequent operations that the grant allows. When certain subsequent operations allowed by the grant include encryption context that matches this list, the grant allows the operation. Otherwise, the grant does not allow the operation.
            (string) --
            (string) --

    :type GrantTokens: list
    :param GrantTokens: A list of grant tokens.
            For more information, see Grant Tokens in the AWS Key Management Service Developer Guide .
            (string) --

    :type Name: string
    :param Name: A friendly name for identifying the grant. Use this value to prevent unintended creation of duplicate grants when retrying this request.
            When this value is absent, all CreateGrant requests result in a new grant with a unique GrantId even if all the supplied parameters are identical. This can result in unintended duplicates when you retry the CreateGrant request.
            When this value is present, you can retry a CreateGrant request with identical parameters; if the grant already exists, the original GrantId is returned without creating a new grant. Note that the returned grant token is unique with every CreateGrant request, even when a duplicate GrantId is returned. All grant tokens obtained in this way can be used interchangeably.

    :rtype: dict
    :return: {
        'GrantToken': 'string',
        'GrantId': 'string'
    }

    """
    pass


def _ri2py(obj):
    """ Dummy function for ri2py.

    This function will convert Python objects into Python (presumably non-rpy2) objects.
    """
    raise NotImplementedError(
        "Conversion 'ri2py' not defined for objects of type '%s'" % str(
        type(obj)))


@classmethod
def has_archiving(cls):
    """Returns whether it supports archiving items on the fetch process.

        :returns: this backend supports items archive
        """
    return True


def readFastqBlock(file, n=1024):
    """
    Read textual input from the file object `file`, which is assumed
    to be in line-oriented FASTQ format (not full multi-line FASTQ).
    Yields a block of sequences at a time.
    """
    grps = []
    grp = [None, None, None, None]
    i = 0
    for l in file:
        l = l.strip()
        grp[i] = l
        i += 1
        if i == 4:
            grps.append(grp)
            if len(grps) == n:
                yield grps
                grps = []
            grp = [None, None, None, None]
            i = 0
    if i == 4:
        grps.append(grp)
    if len(grps) > 0:
        yield grps


def line_add_lazy_describe(line):
    """if describe has no arguments, default silently to <describe version>"""
    l = line.split()
    if 'describe' in line and len(l) == 1:
        return 'describe version'
    return line


def to_bool(val):
    """Convert value to bool

    Because bool('0') = true, so...

    :param val: value to convert
    :type val:
    :return: True if val == '1' or val == 'on' or val == 'true' or val == 'True', else False
    :rtype: bool
    """
    return val in ['1', 'on', 'true', 'True']


def grouper_list(l, n):
    """Evenly divide list into fixed-length piece, no filled value if chunk
    size smaller than fixed-length.

    Example::

        >>> list(grouper(range(10), n=3)
        [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]

    **中文文档**

    将一个列表按照尺寸n, 依次打包输出, 有多少输出多少, 并不强制填充包的大小到n。

    下列实现是按照性能从高到低进行排列的:

    - 方法1: 建立一个counter, 在向chunk中添加元素时, 同时将counter与n比较, 如果一致
      则yield。然后在最后将剩余的item视情况yield。
    - 方法2: 建立一个list, 每次添加一个元素, 并检查size。
    - 方法3: 调用grouper()函数, 然后对里面的None元素进行清理。
    """
    chunk = list()
    counter = 0
    for item in l:
        counter += 1
        chunk.append(item)
        if counter == n:
            yield chunk
            chunk = list()
            counter = 0
    if len(chunk) > 0:
        yield chunk


def sortMe(func):
    """ returns all the fields sorted first by alpabetical dimensions/filters, then alphabetical measures """
    return sorted(list(func), key=lambda field: field.identifier)


def extract_provider_location(provider_location, key):
    """Extracts value of the specified field from provider_location string.

    :param provider_location: provider_location string
    :param key: field name of the value that to be extracted
    :return: value of the specified field if it exists, otherwise,
             None is returned
    """
    if not provider_location:
        return None
    kvps = provider_location.split('|')
    for kvp in kvps:
        fields = kvp.split('^')
        if len(fields) == 2 and fields[0] == key:
            return fields[1]


def update_time_range(form_data):
    """Move since and until to time_range."""
    if 'since' in form_data or 'until' in form_data:
        form_data['time_range'] = '{} : {}'.format(form_data.pop('since',
            '') or '', form_data.pop('until', '') or '')


def flatten_timeline(report, context):
    """Flattens the timeline into a list of tuples as report['timeline'].

    Looks for the timeline in content['timeline'] and sets it in
    report['timeline'].
    """
    timeline = context.get('timeline')
    if timeline is None:
        return
    statements = []
    for action in timeline.actions:
        statements.append(action.logTuple())
    report['timeline'] = statements


def mod(divisor, remainder):
    """Test mod(<divisor>) is <remainder>.
    """
    return {'$mod': [divisor, remainder]}


def get_bit(byte, n):
    """Extract a single bit from a byte, with 0 referring to
       the least significant (last) bit and 7 referring to the most
       significant (first) bit."""
    if type(byte) in [str, bytes]:
        if len(byte) != 1:
            raise ValueError('Expected a single byte')
        if type(byte) is str:
            byte = ord(byte)
        else:
            byte = byte[0]
    elif type(byte) is int:
        if byte < 0 or byte > 255:
            raise ValueError('Expected a value between 0 and 255')
    else:
        raise TypeError('Expected a character or integer')
    if n < 0 or n > 7:
        raise ValueError('n must be between 0 and 7')
    return byte >> n & 1


def remove(key):
    """ remove the key from the storage """


def scan_setup_py():
    """Validate the contents of setup.py against Versioneer's expectations."""
    found = set()
    setters = False
    errors = 0
    with open('setup.py', 'r') as f:
        for line in f.readlines():
            if 'import versioneer' in line:
                found.add('import')
            if 'versioneer.get_cmdclass()' in line:
                found.add('cmdclass')
            if 'versioneer.get_version()' in line:
                found.add('get_version')
            if 'versioneer.VCS' in line:
                setters = True
            if 'versioneer.versionfile_source' in line:
                setters = True
    if len(found) != 3:
        print('')
        print('Your setup.py appears to be missing some important items')
        print('(but I might be wrong). Please make sure it has something')
        print('roughly like the following:')
        print('')
        print(' import versioneer')
        print(' setup( version=versioneer.get_version(),')
        print('        cmdclass=versioneer.get_cmdclass(),  ...)')
        print('')
        errors += 1
    if setters:
        print("You should remove lines like 'versioneer.VCS = ' and")
        print("'versioneer.versionfile_source = ' . This configuration")
        print('now lives in setup.cfg, and should be removed from setup.py')
        print('')
        errors += 1
    return errors


def open_boundaries(model):
    """
    Open all boundary reactions.

    Parameters
    ----------
    model : cobra.Model
        The metabolic model under investigation.

    """
    for boundary in model.boundary:
        boundary.bounds = -1000, 1000


@classmethod
def get_exchange_name(cls):
    """
        Get exchange name
        :return: Exchange name string
        """
    return 'Yunbi'


def calculate_absolute_position_replaced_height(node, context):
    """Implements S10.6.8"""
    raise NotImplementedError('Section 10.6.8')


def normalize_port_no(port_no):
    """Normalize port number value to int or string."""
    if isinstance(port_no, int):
        return port_no
    if isinstance(port_no, str):
        try:
            return int(port_no, 0)
        except ValueError:
            return port_no.upper()
    raise ValueError('Invalid port_no: %r' % port_no)


def _squeeze_output(out):
    """
    Remove single-dimensional entries from array and convert to scalar,
    if necessary.

    """
    out = out.squeeze()
    if out.ndim == 0:
        out = out[()]
    return out


def delay_denial(func):
    """
    Decorator to declare which methods should have any swift.authorize call
    delayed. This is so the method can load the Request object up with
    additional information that may be needed by the authorization system.

    :param func: function for which authorization will be delayed
    """
    func.delay_denial = True
    return func


@staticmethod
def format_unicode_to_right_format_string(invalid_format_unicode):
    """
        Convert unicode string to right format string
        :param invalid_format_unicode:
        :return:
        """
    return str(invalid_format_unicode.encode('ascii', 'ignore').decode('ascii')
        ).replace('\n', '')


def absModuleToDist(magApp, magAbs):
    """
    Convert apparent and absolute magnitude into distance.

    Parameters
    ----------
    magApp : float
        Apparent magnitude of object.
    magAbs : float
        Absolute magnitude of object.

    Returns
    -------
    Distance : float
        The distance resulting from the difference in
        apparent and absolute magnitude [pc].
    """
    d = 10.0 ** (-(magAbs - magApp) / 5.0 + 1.0)
    return d


def add_zero(number):
    """
    Add a zero if the value doesn't have
    2 digits behind it's decimal point
    """
    if number == '':
        return ''
    else:
        list_number = list(str(number))
        if len(list_number[list_number.index('.') + 1:]) < 2:
            list_number.append('0')
        return ''.join(list_number)


def wl_clearLocks():
    """ Deletes ALL locks on the object - should only be called
        by lock management machinery. """


def char_to_word_index(char_ind: int, sent: str) ->int:
    """
    Convert a character index to word index in the given sentence.
    """
    return sent[:char_ind].count(' ')


@classmethod
def from_string(cls, roman_as_string):
    """ Create a RomanNumeral object from an string

        """
    cls(roman_as_string)


def save():
    """Save the image with current name and settings

    """
    pass


@staticmethod
def density(r, rho0, e1=0, e2=0):
    """
        computes the density
        :param r: radius in angles
        :param rho0: density at angle=1
        :return: density at r
        """
    rho = rho0 / r ** 2
    return rho


def format_model_basefilename(segment_subject: str, traindata_id: int,
    architecture_id: int=0, trainparams_id: int=0) ->str:
    """
    Format the parameters into a model_filename.

    Args
        segment_subject: the segment subject
        traindata_id: the id of the data used to train the model
        architecture_id: the id of the model architecture used
        trainparams_id: the id of the hyper parameters used to train the model
    """
    filename = f'{segment_subject}_{traindata_id:02d}'
    if architecture_id > 0 or trainparams_id > 0:
        filename = f'{filename}.{architecture_id}.{trainparams_id}'
    return filename


def refresh():
    """ Tickles the locks modified time by setting it to the current
        time.time() value.  (As stated in the RFC, the timeout counter
        SHOULD be restarted for any HTTP method called by the lock owner
        on the locked object). """


def _add_doc(func, doc):
    """Add documentation to a function."""
    func.__doc__ = doc


def compute_cache_header(cache_config):
    """Compute the cache header for a given :class:`CacheConfigT`.

    :param cache_config: The :class:`CacheConfigT` defining the cache params
    :type cache_config: :class:`supercell.api.cache.CacheConfigT`
    :return: The computed `Cache-Control` header
    :rtype: str
    """
    params = []
    params.append('max-age=%s' % cache_config.max_age.seconds)
    if cache_config.s_max_age:
        params.append('s-max-age=%s' % cache_config.s_max_age.seconds)
    if cache_config.public:
        params.append('public')
    if cache_config.private:
        params.append('private')
    if cache_config.no_cache:
        params.append('no-cache')
    if cache_config.no_store:
        params.append('no-store')
    if cache_config.must_revalidate:
        params.append('must-revalidate')
    if cache_config.proxy_revalidate:
        params.append('proxy-revalidate')
    return ', '.join(params)


def autoincrement_tag(last_tag):
    """
    autoincrement_tag('1') => 2
    autoincrement_tag('1.2') => 1.3
    autoincrement_tag('1.2.3') => 1.2.4
    """
    tokens = last_tag.split('.')
    r = int(tokens[-1]) + 1
    if len(tokens) > 1:
        return '%s.%s' % ('.'.join(tokens[0:-1]), r)
    else:
        return str(r)


def render_git_describe(pieces):
    """TAG[-DISTANCE-gHEX][-dirty].

    Like 'git describe --tags --dirty --always'.

    Exceptions:
    1: no tags. HEX[-dirty]  (note: no 'g' prefix)
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        if pieces['distance']:
            rendered += '-%d-g%s' % (pieces['distance'], pieces['short'])
    else:
        rendered = pieces['short']
    if pieces['dirty']:
        rendered += '-dirty'
    return rendered


def depth_to_reduced_level(z, H=1.0, rlzero=None):
    """Convert normalised depth to reduced level, or non-normalised depth

    Parameters
    ----------
    z : float, or ndarray
        Normalised depth. Usually between 0 and 1.
    H : float, optional
        Height of soil layer.  Default H=1.0.
    rlzero : float, optional
        Reduced level of soil surface. Default rlzero=None.  If rlzero=None then
        function will return non normalised depth H*z, otherwise it will
        return rl = rlzero - H * z

    Returns
    -------
    out : float or ndarray
        Actual depth or reduced level.

    """
    if not rlzero is None:
        return rlzero - z * H
    else:
        return z * H


@staticmethod
def quit(session):
    """
        Stops the current shell session (raises a KeyboardInterrupt exception)
        """
    session.write_line('Raising KeyboardInterrupt to stop main thread')
    raise KeyboardInterrupt()


def _get_origins(type_):
    """Get all origins, includes passed type."""
    origins = [type_]
    if hasattr(type_, '__origin__'):
        while getattr(type_, '__origin__', None) is not None:
            type_ = type_.__origin__
            origins.append(type_)
    return origins


def enforce_cookiecutter_options(struct, opts):
    """Make sure options reflect the cookiecutter usage.

    Args:
        struct (dict): project representation as (possibly) nested
            :obj:`dict`.
        opts (dict): given options, see :obj:`create_project` for
            an extensive list.

    Returns:
        struct, opts: updated project representation and options
    """
    opts['force'] = True
    return struct, opts


def p_common_scalar_lnumber(p):
    """common_scalar : LNUMBER"""
    if p[1].startswith('0x'):
        p[0] = int(p[1], 16)
    elif p[1].startswith('0b'):
        p[0] = int(p[1], 2)
    elif p[1].startswith('0'):
        p[0] = int(p[1], 8)
    else:
        p[0] = int(p[1])


def _download_file(url, outfile):
    """Downloads the MCEq database from github"""
    from tqdm import tqdm
    import requests
    import math
    r = requests.get(url, stream=True)
    total_size = int(r.headers.get('content-length', 0))
    block_size = 1024 * 1024
    wrote = 0
    with open(outfile, 'wb') as f:
        for data in tqdm(r.iter_content(block_size), total=math.ceil(
            total_size // block_size), unit='MB', unit_scale=True):
            wrote = wrote + len(data)
            f.write(data)
    if total_size != 0 and wrote != total_size:
        raise Exception('ERROR, something went wrong')


def sldDump(sldObj):
    """
    Creates valid SldStyle string from an object.
    """
    sld_type = sldObj.get('type', None)
    extended = str(sldObj.get('extended', 'false')).lower()
    items = sldObj.get('items', None)
    sld_attr = {'color': None, 'label': None, 'quantity': None, 'opacity': None
        }
    if sld_type not in ['linear', 'ramp', 'gradient', 'intervals', 'values']:
        print(
            'Unable to create SldStyle. Type must be in "linear", "ramp", "gradient", "intervals", "values".'
            )
        return None
    if items:
        sld_str = (
            f'<RasterSymbolizer> <ColorMap type="{sld_type}" extended="{extended}"> '
            )
        for item in items:
            sld_str += f'<ColorMapEntry '
            for k in sld_attr.keys():
                if item.get(k, None):
                    sld_str += f'{k}="{item[k]}" '
            sld_str += '/> + '
    return sld_str + '</ColorMap> </RasterSymbolizer>'


def scramble_id(seq_id):
    """
    This is called a feistel chipher.
    It creates a pseudo random, but unique identifier from a number.
    It can be used instead of sequential primary keys in api functions
    to prevent exposing backend details.
    It is its own inverse, so converting back is done by calling it again.

    In case of an id other than an unsigned integer in the 32 bit range we
    assume its a uuid or similar and we return it as is.

    further reading: https://wiki.postgresql.org/wiki/Pseudo_encrypt
    """
    try:
        val = int(seq_id) & 4294967295
    except ValueError:
        return seq_id
    if val != int(seq_id):
        return seq_id
    l1 = val >> 16 & 65535
    r1 = val & 65535
    for _ in range(0, 3):
        l2 = r1
        r2 = l1 ^ int(round((1366 * r1 + 150889) % 714025 / 714025.0 * 32767)
            ) & 4294967295
        l1 = l2
        r1 = r2
    return ((r1 & 65535) << 16) + l1


def find_which(ol, which, test_func, *args):
    """
        from elist.elist import *
        def test_func(ele,x):
            cond = (ele > x)
            return(cond)

        ol = [1,2,3,4,5,6,7]
        last = find_which(ol,0,test_func,3)
        last
        last = find_which(ol,2,test_func,3)
        last
    """
    length = ol.__len__()
    seq = -1
    for i in range(0, length):
        cond = test_func(ol[i], *args)
        if cond:
            seq = seq + 1
            if seq == which:
                return {'index': i, 'value': ol[i]}
            else:
                pass
        else:
            pass
    return {'index': None, 'value': None}


def is_member_everyone(target_user, requesting_user):
    """
    Always return True. All users are part of 'Everyone'.
    """
    return True


def _lower(string: str) ->str:
    """Properly lowercase transforms Turkish string ("İ" -> "i", "I" -> "ı")."""
    return string.replace('İ', 'i').replace('I', 'ı').lower()


def AddSNConstantForDifferentSN(*args, **kwargs):
    """ Stub Anduin function."""
    print('AddSNConstantForDifferentSN', args, kwargs)


def S_IMODE(mode):
    """Return the portion of the file's mode that can be set by
    os.chmod().
    """
    return mode & 4095


def to_float(val):
    """Convert string to float, but also handles None and 'null'."""
    if val is None:
        return None
    if str(val) == 'null':
        return None
    return float(val)


def scan_setup_py():
    """Validate the contents of setup.py against Versioneer's expectations."""
    found = set()
    setters = False
    errors = 0
    with open('setup.py', 'r') as f:
        for line in f.readlines():
            if 'import versioneer' in line:
                found.add('import')
            if 'versioneer.get_cmdclass()' in line:
                found.add('cmdclass')
            if 'versioneer.get_version()' in line:
                found.add('get_version')
            if 'versioneer.VCS' in line:
                setters = True
            if 'versioneer.versionfile_source' in line:
                setters = True
    if len(found) != 3:
        print('')
        print('Your setup.py appears to be missing some important items')
        print('(but I might be wrong). Please make sure it has something')
        print('roughly like the following:')
        print('')
        print(' import versioneer')
        print(' setup( version=versioneer.get_version(),')
        print('        cmdclass=versioneer.get_cmdclass(),  ...)')
        print('')
        errors += 1
    if setters:
        print("You should remove lines like 'versioneer.VCS = ' and")
        print("'versioneer.versionfile_source = ' . This configuration")
        print('now lives in setup.cfg, and should be removed from setup.py')
        print('')
        errors += 1
    return errors


def zenodo_harvest_url(community_name, format='oai_datacite3'):
    """Build a URL for the Zenodo Community's metadata.

    Parameters
    ----------
    community_name : str
        Name of the community.
    format : str
        OAI-PMH metadata specification name. See https://zenodo.org/dev.

    Returns
    -------
    url : str
        OAI-PMH metadata URL.
    """
    template = (
        'http://zenodo.org/oai2d?verb=ListRecords&metadataPrefix={metadata_format}&set=user-{community}'
        )
    return template.format(metadata_format=format, community=community_name)


def select():
    """Select a sketch stroke

    """
    pass


def switch_get(fritz, args):
    """Command that get the device switch state."""
    print(fritz.get_switch_state(args.ain))


@classmethod
def paper_doc_add_comment_details(cls, val):
    """
        Create an instance of this class set to the
        ``paper_doc_add_comment_details`` tag with value ``val``.

        :param PaperDocAddCommentDetails val:
        :rtype: EventDetails
        """
    return cls('paper_doc_add_comment_details', val)


@classmethod
def list_supported_networks(cls):
    """Lists all networks supported by nodes returned by this driver

        :return: [String] list of network names
        """
    return cls.SUPPORTED_NETWORKS


def read_content(path):
    """
    Read the contents of a file, return as a string

    """
    with open(path, 'r') as f:
        return f.read()


def labels(indices, node_labels=None):
    """Get the labels for a tuple of mechanism indices."""
    if node_labels is None:
        return tuple(map(str, indices))
    return node_labels.indices2labels(indices)


def tracking_object_remove():
    """Remove object for tracking

    """
    pass


@staticmethod
def _get_parent_dn(dn):
    """
        Gets the dn of the parent object
        Meant to be overridden by inheriting classes.
        Raises exception if not overridden.

        :returns: string containing dn
        """
    return dn.split('/overlay')[0]


@staticmethod
def write_property_sheets(cmake_file, property_indent,
    config_condition_expr, property_value, width, **kwargs):
    """ Write property sheets functor (helper) """
    del kwargs
    config = '"${CMAKE_CONFIGURATION_TYPES}" '
    width_diff = 0
    if config_condition_expr is not None:
        config = config_condition_expr.replace('$<CONFIG:', '').replace('>', ''
            )
        config += ' '
        width_diff = len('$<CONFIG:>') - 1
    if property_value:
        for property_sheet_cmake in property_value:
            result_width = width - width_diff
            if result_width < 0:
                result_width = 0
            cmake_file.write('{}use_props(${{PROJECT_NAME}} {:<{width}}"{}")\n'
                .format(property_indent, config, property_sheet_cmake,
                width=result_width))


def psi_Mg_Na_CO3_HMW84(T, P):
    """c-c'-a: magnesium sodium carbonate [HMW84]."""
    psi = 0.0
    valid = T == 298.15
    return psi, valid


def datetime_to_unix_miliseconds_epoch(dt):
    """
    The number of milliseconds after Jan 1, 1970 00:00:00 UTC
    """
    import time
    return time.mktime(dt.timetuple()) * 1000.0 + dt.microsecond / 1000.0


def main(arg1=55, arg2='test', arg3=None):
    """
    This is a sample program to show how a learning agent can
    be logged using AIKIF.
    The idea is that this main function is your algorithm, which
    will run until it finds a successful result. The result is
    returned and the time taken is logged.

    There can optionally be have additional functions
    to call to allow for easy logging access
    """
    print('Starting dummy AI algorithm with :', arg1, arg2, arg3)
    if arg3 is None:
        arg3 = [5, 6, 7, 5, 4]
    result = arg1 + arg3[0] * 7566.545
    print('Done - returning ', result)
    return result


def render_pep440_pre(pieces):
    """TAG[.post.devDISTANCE] -- No -dirty.

    Exceptions:
    1: no tags. 0.post.devDISTANCE
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        if pieces['distance']:
            rendered += '.post.dev%d' % pieces['distance']
    else:
        rendered = '0.post.dev%d' % pieces['distance']
    return rendered


def contextfunction(f):
    """This decorator can be used to mark a function or method context callable.
    A context callable is passed the active :class:`Context` as first argument when
    called from the template.  This is useful if a function wants to get access
    to the context or functions provided on the context object.  For example
    a function that returns a sorted list of template variables the current
    template exports could look like this::

        @contextfunction
        def get_exported_names(context):
            return sorted(context.exported_vars)
    """
    f.contextfunction = True
    return f


def remove_is_a_reactions(model):
    """
    Removes 'isa' reactions from the model. 'isa' reactions can be found in yeast.net models and contain
    purely hierarchical information, e.g. 'lauroyl-CoA isa fatty-acyl-CoA'.
    :param model: libsbml.Model model of interest
    :return: void (input model is modified inplace)
    """
    to_remove = []
    for reaction in model.getListOfReactions():
        if 1 == reaction.getNumReactants() == reaction.getNumProducts(
            ) and reaction.getName().find('isa '
            ) != -1 and model.getCompartment(reaction.getListOfReactants().
            get(0).getSpecies()) == model.getCompartment(reaction.
            getListOfReactants().get(0).getSpecies()):
            to_remove.append(reaction.getId())
    for r_id in to_remove:
        model.removeReaction(r_id)


def list_adresposities_adapter(obj, request):
    """
    Adapter for rendering a list of
    :class:`crabpy.gateway.crab.Adrespositie` to json.
    """
    return {'id': obj.id, 'herkomst': {'id': obj.herkomst.id, 'naam': obj.
        herkomst.naam, 'definitie': obj.herkomst.definitie}}


@classmethod
def repo_issues(cls, rn, *options):
    """
        List the issues associated with a repo.
        """
    repomgr = cls._ocean.RepoManager(cls._ocean)
    return repomgr.list_opened_issues(None, rn)


@staticmethod
def flair_type(is_link):
    """Return LINK_FLAIR or USER_FLAIR depending on ``is_link`` value."""
    return 'LINK_FLAIR' if is_link else 'USER_FLAIR'


@classmethod
def get_default_policy(cls):
    """
        Returns the default overrun policy.
        """
    return cls('skip-until-unlock')


def insert(index, item):
    """Insert item before index"""


def get_attribute(element, attribute_name):
    """Low level method to extract an attribute from a node allowing for various
    cases.

    Expected cases: - No attributes for this node --> None - Attributes exist
    but requested one doesn't. --> None - Requested attribute does exist. -->
    Value (as string).

    Args:
        element: ElementTree Element
        attribute_name: name of attribute to extract from element.

    Returns:
        - Value of element if it exists.
        - None otherwise.
    """
    attributes = getattr(element, 'attrib', {})
    if attribute_name not in attributes:
        return None
    else:
        return attributes[attribute_name]


def default_userinfo(claims, user):
    """
    Default function for setting OIDC_USERINFO.
    `claims` is a dict that contains all the OIDC standard claims.
    """
    return claims


@classmethod
def get_storage_by_task_name(cls, task_name):
    """Get storage instance that was assigned to the given task.

        :param task_name: task's name for which storage should be get
        :rtype: DataStorage
        """
    storage_name = cls.get_storage_name_by_task_name(task_name, graceful=True)
    if storage_name:
        return cls.get_connected_storage(storage_name)
    return None


def p_opt_LIMIT(p):
    """opt_LIMIT : LIMIT NUMBER"""
    p[0] = p[2]


@classmethod
def __parse_registration_type(cls, row, field):
    """
        Indicate whether the family agrees to become a member of the APE.

        :param row: A list of values corresponding to a row of the sheet
            document containing information about the family that registers to
            the school bus transportation service.

        :param field: An item of the enumeration `RegistrationFields`
            corresponding to the positional fields in the row that refer to
            the fees that the family is going to pay to register to the the
            school bus transportation service.

            There are two different fees depending on whether a family accepts
            to become or not a member of the parents association.

        :return: `True` if the family agrees to become a member of the APE;
            `False` otherwise.
        """
    field_index = field.value - 1
    registration_type = row[field_index].strip()
    for keyword, agreed in cls.SUBSCRIPTION_AGREEMENTS.items():
        if keyword in registration_type:
            return agreed
    else:
        return False


def _normalize_list_argument(arg, name):
    """returns a list of strings from an argument that can be either
    list of strings, None (returns []), or a single string returns
    ([arg])"""
    if arg is None:
        return []
    elif isinstance(arg, str):
        return [arg]
    elif isinstance(arg, (list, tuple)):
        return arg
    raise TypeError(
        "Argument '%s' must be None, a string, or a sequence of strings, not %r"
         % (name, type(arg)))


def wrap_tuple(unwrapped):
    """ Wraps any non-tuple types in a tuple """
    return unwrapped if isinstance(unwrapped, tuple) else (unwrapped,)


def to_list(items):
    """
    Converts comma-delimited string into list of items
    """
    try:
        values = items.split(',')
        if isinstance(values, list):
            return values
    except Exception:
        pass
    return items


def isbuffer(obj) ->bool:
    """
    Test whether `obj` is an object that supports the buffer API, like a bytes
    or bytearray object.
    """
    try:
        with memoryview(obj):
            return True
    except TypeError:
        return False


def safe_communicate(subproc, stdin=''):
    """Executes a Popen.communicate and returns output in a way that is
    compatible with Python 2 & 3 keeping input and output as strings (since
    Python 3 requires bytes objects otherwise)"""
    if not subproc.universal_newlines:
        stdin = stdin.encode('utf-8') if hasattr(stdin, 'encode') else stdin
    stdout, stderr = map(lambda x: x.decode() if hasattr(x, 'decode') else
        x, subproc.communicate(stdin))
    return stdout, stderr


def namespaced(obj, tagname, namespace=None):
    """
    Utility to create a namespaced tag for an object
    """
    namespace = getattr(obj, 'namespace', namespace)
    if namespace is not None:
        tagname = '{%s}%s' % (namespace, tagname)
    return tagname


def extractDirInfo(dirname):
    """
    Extracts the metadata recursivly form all the subdirs/files

    :param dirname: the top directory
    :returns: the list of metadata tuples: name, size, link, st_mode, st_nlink
    """
    from os import walk, lstat
    from os.path import join, islink
    metadata = []
    for root, _dirs, files in walk(dirname):
        for f in files:
            n = join(root, f)
            sr = lstat(n)
            ret = (n.replace(dirname, ''), sr.st_size, islink(n), sr.
                st_mode, sr.st_nlink),
            metadata.append(ret)
    return sorted(metadata)


def rename_residues(fhandle, name_from, name_to):
    """Changes the residue name of residues matching a pattern to another.
    """
    records = 'ATOM', 'HETATM', 'TER', 'ANISOU'
    for line in fhandle:
        if line.startswith(records):
            line_resname = line[17:20].strip()
            if line_resname == name_from:
                yield line[:17] + name_to.rjust(3) + line[20:]
                continue
        yield line


def conditional_casting(str_value):
    """Tries to cast a string value to an integer or float.
    Falls back to the most general type if the casting fails.

    :param str_value: (string) value to be casted.
    :return: (int, float or string) the casted input value.

    >>> conditional_casting('1')
    1
    >>> conditional_casting('12a')
    '12a'
    >>> conditional_casting('12.0')
    12.0
    >>> conditional_casting('12a.0')
    '12a.0'
    """
    try:
        try:
            int_value = int(str_value)
            return int_value
        except ValueError:
            float_value = float(str_value)
            return float_value
    except ValueError:
        return str_value


def _fullname(obj):
    """
    Get the fullname from a Python object
    """
    return obj.__module__ + '.' + obj.__name__


@classmethod
def register_view(cls):
    """Attach view to app or blueprint.

    Called by the metaclass when the class is created.

    """
    if cls.rules is None:
        raise ValueError('No rules found for %r' % (cls,))
    view = cls.as_view(cls.endpoint)
    allowed_methods = set(cls.methods)
    for rule, methods in cls.rules.items():
        methods = set(methods) & allowed_methods
        if methods:
            cls.__app__.add_url_rule(rule=rule, view_func=view, methods=methods
                )


def preset_add(name: str='', remove_name: bool=False, remove_active: bool=
    False, use_focal_length: bool=False):
    """Add or remove a Camera Preset

    :param name: Name, Name of the preset, used to make the path name
    :type name: str
    :param remove_name: remove_name
    :type remove_name: bool
    :param remove_active: remove_active
    :type remove_active: bool
    :param use_focal_length: Include Focal Length, Include focal length into the preset
    :type use_focal_length: bool
    """
    pass


@classmethod
def _from_et(cls, root, parent):
    """
        Create a :class:`Circle` from a :code:`circle` element.

        :param root: The element tree tree to parse.
        :param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
        :rtype: :class:`Circle`
        """
    n = cls()
    n._init_from_et(root, parent)
    return n


def render_git_describe(pieces):
    """TAG[-DISTANCE-gHEX][-dirty].

    Like 'git describe --tags --dirty --always'.

    Exceptions:
    1: no tags. HEX[-dirty]  (note: no 'g' prefix)
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        if pieces['distance']:
            rendered += '-%d-g%s' % (pieces['distance'], pieces['short'])
    else:
        rendered = pieces['short']
    if pieces['dirty']:
        rendered += '-dirty'
    return rendered


def check_gindexer_compatibility(gindexer, resolution, store_whole_genome):
    """Sanity check for gindexer.

    This function tests if the gindexer is compatible with
    other properties of the dataset, including the resolution and
    the store_whole_genome argument

    A ValueError is thrown if the gindexer is not valid.
    """
    if resolution is not None and resolution > 1 and store_whole_genome:
        if gindexer is not None and gindexer.binsize % resolution > 0:
            raise ValueError(
                'binsize must be an integer-multipe of resolution. Got binsize={} and resolution={}'
                .format(gindexer.binsize, resolution))
        for iv_ in (gindexer or []):
            if iv_.start % resolution > 0:
                raise ValueError(
                    'Please ensure that all interval starts line up with the resolution-sized bins. This is necessary to prevent rounding issues. Interval ({}:{}-{}) not compatible with resolution {}. '
                    .format(iv_.chrom, iv_.start, iv_.end, resolution) +
                    'Consider using "janggu-trim <input_roi> <trun_output> -divisible_by {resolution}"'
                    .format(resolution=resolution))
    if not store_whole_genome and gindexer is None:
        raise ValueError('Either specify roi or store_whole_genome=True')


def print_state(childs, last_upd):
    """Prints current state for each child."""
    for child in childs:
        print(child, childs[child])
    print(str(last_upd))


def _construct(s):
    """ We override _construct here to finish the saved __call__
    connections right after constructing the model. The reason why we
    take this detour instead of connecting in __call__ directly, is that
    __call__ is done before setattr, and hence the child components don't
    know their name yet. _dsl.constructed is called in setattr after name
    tagging, so this is valid. (see NamedObject.py). """
    if not s._dsl.constructed:
        if s._dsl.param_tree is None:
            kwargs = s._dsl.kwargs
        elif s._dsl.param_tree.leaf is None:
            kwargs = s._dsl.kwargs
        else:
            kwargs = s._dsl.kwargs.copy()
            if 'construct' in s._dsl.param_tree.leaf:
                more_args = s._dsl.param_tree.leaf['construct']
                kwargs.update(more_args)
        s.construct(*s._dsl.args, **kwargs)
        if s._dsl.call_kwargs is not None:
            s._continue_call_connect()
        s._dsl.constructed = True


def is_imaginary_part_bounded(z, v):
    """
    Check that the imaginary part of z is in (-v, v).
    """
    imag = z.imag()
    return -v < imag and imag < v


def append_add(dct, key, val, unique=False):
    """Append new (unique) value to the list of 'key'.
    If 'key' does not exist, create new list.
    """
    if key in dct:
        if unique:
            if val in dct[key]:
                pass
            else:
                dct[key].append(val)
        else:
            dct[key].append(val)
    else:
        dct[key] = [val]


def assert_bytes(*args):
    """
    porting helper, assert args type
    """
    try:
        for x in args:
            assert isinstance(x, (bytes, bytearray))
    except:
        print('assert bytes failed', list(map(type, args)))
        raise


def get_doc():
    """Get documentation of this resource

    :return: rst string
    :rtype: str
    """
    return """
    The ``alignak_notifications`` model is a cache used internally by the backend to store the
    notifications that must be sent out to the Alignak arbiter.
    """


def Window(title='New Window', width='auto', height='auto', resizable=False):
    """
    Return a basic config for new windows

    :param title: The window title
    :type title: str
    :param width: Width of the window at startup
    :type width: int
    :param height: Height of the window at startup
    :type height: int
    :param resizable: Wether the user can resize the window
    :type resizable: bool
    :rtype: dict
    """
    return {'title': title, 'width': width, 'height': height, 'resizable':
        resizable}


def D_est(Ht_est, Hs_est, n):
    """Basic Equation: ((Ht-Hs)/(1.0-Hs))*(n/(n-1))"""
    n = float(n)
    if (1.0 - Hs_est) * (n / (n - 1)) == 0.0:
        return 0.0
    else:
        D_est = (Ht_est - Hs_est) / (1.0 - Hs_est) * (n / (n - 1))
        return D_est


def index(x, y):
    """Convert (x, y) coordinates to tiles index."""
    return int((x + 200) // 50 + (y + 200) // 50 * 8)


def generator(func):
    """Generator methods on a Blueprint don't get flagged as fields.

    Subsequently, they aren't subject to field treatment, and remain
    callable on a mastered Blueprint instance.
    """
    func.is_generator = True
    return func


def _iter_id(iterable):
    """Generator: ((id(o), o) for o in iterable)."""
    for item in iterable:
        yield id(item), item


def first(iface, row):
    """Return first result row model entry providing given interface

        Args:
            iface: zope.interface based specification
            row: sqlachemy query result row
        """


def get_remoteadb_url(environment: str, enterprise_id: str, device_id: str,
    remoteadb_id: str=None) ->str:
    """
    Build and return remoteadb url for scapi endpoint
    :param environment:
    :param enterprise_id:
    :param device_id:
    :param remoteadb_id:
    :return:
    """
    host = f'https://{environment}-api.shoonyacloud.com'
    url = (
        f'{host}/api/v0/enterprise/{enterprise_id}/device/{device_id}/remoteadb/'
        )
    if remoteadb_id:
        url = f'{url}{remoteadb_id}'
    return url


def consecutive_pairs(iterable, circular=False):
    """Returns consecutive pairs of items from the given iterable.

    When `circular` is ``True``, the pair consisting of the last
    and first elements is also returned.

    Example:

        >>> list(consecutive_pairs(range(5)))
        [(0, 1), (1, 2), (2, 3), (3, 4)]
        >>> list(consecutive_pairs(range(5), circular=True))
        [(0, 1), (1, 2), (2, 3), (3, 4), (4, 0)]
        >>> list(consecutive_pairs([]))
        []
        >>> list(consecutive_pairs([], circular=True))
        []
        >>> list(consecutive_pairs([0]))
        []
        >>> list(consecutive_pairs([0], circular=True))
        [(0, 0)]
    """
    it = iter(iterable)
    try:
        prev = it.next()
    except StopIteration:
        return
    first = prev
    for item in it:
        yield prev, item
        prev = item
    if circular:
        try:
            yield item, first
        except UnboundLocalError:
            yield first, first


def name_to_label_mapping(obonetwork):
    """
    builds name <=> label lookup dictionaries starting
    from an OBO file, including synonyms
    """
    id_to_name = {}
    name_to_id = {}
    for nodeid, data in obonetwork.nodes(data=True):
        try:
            id_to_name[nodeid] = data['name']
            name_to_id[data['name']] = nodeid
        except KeyError:
            pass
        if 'synonym' in data:
            for synonim in data['synonym']:
                name_to_id[synonim.split('"')[1]] = nodeid
    return id_to_name, name_to_id


def combine_expression_columns(df, columns_to_combine, remove_combined=True):
    """
    Combine expression columns, calculating the mean for 2 columns

    :param df: Pandas dataframe
    :param columns_to_combine: A list of tuples containing the column names to combine
    :return:
    """
    df = df.copy()
    for ca, cb in columns_to_combine:
        df['%s_(x+y)/2_%s' % (ca, cb)] = (df[ca] + df[cb]) / 2
    if remove_combined:
        for ca, cb in columns_to_combine:
            df.drop([ca, cb], inplace=True, axis=1)
    return df


@classmethod
def regist(clz, target):
    """注册module的装饰器,也可以当作方法注册多对多关系表,如
        NoteUserThrough = User.roles.get_through_model()
        AioOrm.regist(NoteUserThrough)
        """
    clz._regist_classes[target.__name__] = target
    return target


@staticmethod
def get_ntp_status(mibversion):
    """return the correct ntp status depending on the firmware"""
    if mibversion == 'NG':
        return {'0': 'notAvailable', '1': 'notSynchronized', '2':
            'synchronized'}
    return {'0': 'notSynchronized', '1': 'noGoodRefclock', '2':
        'syncToExtRefclock', '3': 'syncToSerialRefclock', '4':
        'normalOperationPPS', '5': 'normalOperationRefclock', '99': 'unknown'}


def scan_setup_py():
    """Validate the contents of setup.py against Versioneer's expectations."""
    found = set()
    setters = False
    errors = 0
    with open('setup.py', 'r') as f:
        for line in f.readlines():
            if 'import versioneer' in line:
                found.add('import')
            if 'versioneer.get_cmdclass()' in line:
                found.add('cmdclass')
            if 'versioneer.get_version()' in line:
                found.add('get_version')
            if 'versioneer.VCS' in line:
                setters = True
            if 'versioneer.versionfile_source' in line:
                setters = True
    if len(found) != 3:
        print('')
        print('Your setup.py appears to be missing some important items')
        print('(but I might be wrong). Please make sure it has something')
        print('roughly like the following:')
        print('')
        print(' import versioneer')
        print(' setup( version=versioneer.get_version(),')
        print('        cmdclass=versioneer.get_cmdclass(),  ...)')
        print('')
        errors += 1
    if setters:
        print("You should remove lines like 'versioneer.VCS = ' and")
        print("'versioneer.versionfile_source = ' . This configuration")
        print('now lives in setup.cfg, and should be removed from setup.py')
        print('')
        errors += 1
    return errors


def _set_play_to_work(params, name: str, index: int, value: float):
    """Adjust the Parameters.play_to_work parameter"""
    if index is not None:
        raise IndexError('You cannot index the play_to_work parameter')
    params.play_to_work = value


@staticmethod
def parse(v):
    """
        Parse a slice string, of the same form as used by __getitem__

        >>> Slice.parse("2:3,7,10:12")

        :param v: Input string
        :return: A list of tuples, one for each element of the slice string
        """
    parts = v.split(',')
    slices = []
    for part in parts:
        p = part.split(':')
        if len(p) == 1:
            slices.append(int(p[0]))
        elif len(p) == 2:
            slices.append(tuple(p))
        else:
            raise ValueError("Too many ':': {}".format(part))
    return slices


def get_telephone(trip):
    """
    Returns the telephone number
    :param trip: Object
    :return: string containing telephone number
    """
    tel = trip['tel']
    if isinstance(tel, list):
        tel = tel[0]
    return tel


def add_metadata(environ, identity):
    """
        Add metadata to the identity (which is a dictionary).  One
        value is always guaranteed to be in the dictionary when
        add_metadata is called: 'repoze.who.userid', representing the
        user id of the identity.  Availability and composition of
        other keys will depend on the identifier plugin which created
        the identity.
        """


def bech32_polymod(values):
    """Internal function that computes the Bech32 checksum."""
    generator = [996825010, 642813549, 513874426, 1027748829, 705979059]
    chk = 1
    for value in values:
        top = chk >> 25
        chk = (chk & 33554431) << 5 ^ value
        for i in range(5):
            chk ^= generator[i] if top >> i & 1 else 0
    return chk


def custom_dir(c, add: list):
    """Implement custom `__dir__`, adding `add` to `cls`"""
    return dir(type(c)) + list(c.__dict__.keys()) + add


def strOrInt(v):
    """
    Determines whether v is String or Integer and returns appropriate object.
    :param v:
    :return:
    """
    v = str(v)
    if str.isnumeric(v):
        return int(v)
    else:
        return v


def updateNEXTENDKw(fobj):
    """ Update NEXTEND keyword in PRIMARY header (if present) to accurately
        reflect the number of extensions in the MEF file.
    """
    if 'nextend' in fobj[0].header:
        fobj[0].header['nextend'] = len(fobj) - 1


def _build_bgzip_vcf_command_str(vcf_path):
    """Generate command string to bgzip vcf file."""
    command = ' '.join(['bgzip -c', vcf_path])
    return command


def poisearch():
    """
    @api {post} /map/search/poisearch poi搜索
    @apiVersion 1.0.0
    @apiGroup Search
    @apiDescription poi搜索

    @apiParam (Headers) {String} token 令牌
    @apiParam (Headers) {String} device_token 设备令牌
    @apiParam (Headers) {String} content_type 内容类型
    @apiParam (Headers) {String} timestamp 时间戳
    @apiParam (Headers) {String} location 经纬度

    @apiParam (Body) {String} keywords 关键字
    @apiParam (Body) {String} page 页数
    @apiParam (Body) {String} location 经纬度

    @apiSuccess (Success) {Int}  count 总条数
    @apiSuccess (Success) {Object[]} pois 搜索POI信息列表
    @apiSuccess (Success) {String} pois.distance 离中心点距离
    @apiSuccess (Success) {String} pois.pcode poi所在省份编码
    @apiSuccess (Success) {String[]} pois.biz_ext 深度信息
    @apiSuccess (Success) {String} pois.biz_ext.cost 人均消费
    @apiSuccess (Success) {String} pois.biz_ext.rating 评分
    @apiSuccess (Success) {String} pois.importance 重要性
    @apiSuccess (Success) {String} pois.recommend 推荐
    @apiSuccess (Success) {String} pois.type 兴趣点类型
    @apiSuccess (Success) {String[]} pois.photos 照片相关信息
    @apiSuccess (Success) {String} pois.photos.title 图片介绍
    @apiSuccess (Success) {String} pois.photos.url 具体链接
    @apiSuccess (Success) {String} pois.discount_num 优惠信息数目
    @apiSuccess (Success) {String} pois.gridcode 地理格ID
    @apiSuccess (Success) {String} pois.poiweight poi权重
    @apiSuccess (Success) {String} pois.shopinfo 商店信息
    @apiSuccess (Success) {String} pois.typecode 兴趣点类型编码
    @apiSuccess (Success) {String} pois.adname 区域名称
    @apiSuccess (Success) {String} pois.citycode 城市编码
    @apiSuccess (Success) {String} pois.children  	是否按照层级展示子POI数据
    @apiSuccess (Success) {String} pois.alias 别名
    @apiSuccess (Success) {String} pois.tel 该POI的电话
    @apiSuccess (Success) {String} pois.id 唯一ID
    @apiSuccess (Success) {String} pois.tag  该POI的特色内容
    @apiSuccess (Success) {String} pois.event
    @apiSuccess (Success) {String} pois.entr_location 入口经纬度
    @apiSuccess (Success) {String} pois.indoor_map 是否有室内地图标志
    @apiSuccess (Success) {String} pois.email 该POI的电子邮箱
    @apiSuccess (Success) {String} pois.timestamp 印时戳
    @apiSuccess (Success) {String} pois.website 该POI的网址
    @apiSuccess (Success) {String} pois.address 地址
    @apiSuccess (Success) {String} pois.adcode 区域编码
    @apiSuccess (Success) {String} pois.pname poi所在省份名称
    @apiSuccess (Success) {String} pois.biz_type 行业类型
    @apiSuccess (Success) {String} pois.cityname 城市名
    @apiSuccess (Success) {String} pois.match
    @apiSuccess (Success) {String} pois.postcode 邮编
    @apiSuccess (Success) {String} pois.business_area 所在商圈
    @apiSuccess (Success) {Object} pois.indoor_data 室内地图相关数据
    @apiSuccess (Success) {String} pois.indoor_data.cmsid
    @apiSuccess (Success) {String} pois.indoor_data.truefloor 所在楼层
    @apiSuccess (Success) {String} pois.indoor_data.cpid 当前POI的父级POI
    @apiSuccess (Success) {String} pois.indoor_data.floor 楼层索引
    @apiSuccess (Success) {String} pois.sqtype 类型(poi\\关键字)
    @apiSuccess (Success) {String} pois.exit_location 出口经纬度
    @apiSuccess (Success) {String} pois.name 名称
    @apiSuccess (Success) {String} pois.location 经纬度
    @apiSuccess (Success) {String} pois.shopid 商店id
    @apiSuccess (Success) {String} pois.navi_poiid 地图编号
    @apiSuccess (Success) {String} pois.groupbuy_num 团购数据

    @apiSuccessExample {json} Success-Response:
    {
        "data": {
            "count": 100,
            "pois": [{
                "distance": "2035",
                "pcode": "310000",
                "biz_ext": {
                    "cost": "7.00",
                    "rating": ""
                },
                "importance": "",
                "recommend": "0",
                "type": "汽车服务;加油站;中国石化",
                "photos": [{
                    "title": "",
                    "url": "http://store.is.autonavi.com/showpic/71666921fe9a22e260cc5aa1fd79bf11"
                }],
                "discount_num": "0",
                "gridcode": "4621713701",
                "poiweight": "",
                "shopinfo": "0",
                "typecode": "010101",
                "adname": "嘉定区",
                "citycode": "021",
                "children": "",
                "alias": "",
                "tel": "021-59596307;021-59596305",
                "id": "B00155HDQT",
                "tag": "",
                "event": "",
                "entr_location": "",
                "indoor_map": "0",
                "email": "",
                "timestamp": "",
                "website": "",
                "address": "曹安公路4680号,黄沈村委会附近",
                "adcode": "310114",
                "pname": "上海市",
                "biz_type": "",
                "cityname": "上海市",
                "match": "0",
                "postcode": "",
                "business_area": "黄渡",
                "indoor_data": {
                    "cmsid": "",
                    "truefloor": "",
                    "cpid": "",
                    "floor": ""
                },
                "sqtype": "POI",
                "exit_location": "",
                "name": "中国石化加油站",
                "location": "121.218745,31.277413",
                "shopid": "",
                "navi_poiid": "H51F009010_22224",
                "groupbuy_num": "0"
            }]
        },
        "req_id": "r_d43e8ce8102248a3a268a3b9cfa35481",
        "err_resp": {
            "code": "0",
            "msg": null
        }
     }

    @apiError (Error) 21003  No keyword in the request params
    @apiErrorExample {json} Error-Response:
    {
        "err_resp": {
            "code": "21003",
            "msg": "No keyword in the request params!"
            },
        "req_id": "r_e4a3fe57fa8045b1afb668254fd66601"
    }
    """


def p_enum_body(t):
    """enum_body : LBRACE enum_constant_list RBRACE"""
    t[0] = t[2]


def final(f):
    """This decorator can be used to indicate to type checkers that
    the decorated method cannot be overridden, and decorated class
    cannot be subclassed. For example:

        class Base:
            @final
            def done(self) -> None:
                ...
        class Sub(Base):
            def done(self) -> None:  # Error reported by type checker
                ...
        @final
        class Leaf:
            ...
        class Other(Leaf):  # Error reported by type checker
            ...

    There is no runtime checking of these properties.
    """
    return f


def palettecolor_reveal():
    """Unhide all hidden Grease Pencil palette colors

    """
    pass


@classmethod
def list_obj(cls, criteria, skip=None, first=None, configname='default'):
    """ find all object with the given search criteria.
            The return value is generator. Each next call will
            fetch a new instance and return it as object.
        """
    for uuid, in cls.list(criteria, ('_uuid',), skip, first, configname):
        yield cls(uuid=uuid)


def _str_or_none(string):
    """ Return a string of None if string is empty. """
    if string is None or string == '':
        return None
    return string


def __init__(cls, name, bases, attrs):
    """Store the command classes here for reference"""
    if 'command' in attrs:
        code = attrs['command']
        cls._messages[code] = cls


def get_directory_contents(directory):
    """
    return a sorted list of the contents of a directory
    """
    contents = []
    for child in directory.iterdir():
        contents.append(child)
    return sorted(contents)


def strftime(to_format):
    """strftime(to_format)(dt_obj) -> str

    Return datetime, time or date object dt_obj formatted with to_format.

    :: str -> (datetime.datetime|datetime.date|datetime.time) -> str

    >>> strftime('%Y-%m-%d')(datetime.date(2112, 12, 21))
    '2112-12-21'
    """
    return lambda dt_obj: dt_obj.strftime(to_format)


@classmethod
def sf_external_invite_warn(cls, val):
    """
        Create an instance of this class set to the ``sf_external_invite_warn``
        tag with value ``val``.

        :param SfExternalInviteWarnType val:
        :rtype: EventType
        """
    return cls('sf_external_invite_warn', val)


def _flatten_results(result, default_value=None):
    """ Formats results to map to a single value or default value if empty. """
    for k in list(result):
        v = result[k]
        if len(v) > 1:
            raise ValueError(
                'Expected one result, but more returned for "{}": {}'.
                format(k, v))
        if len(v) == 1:
            result[k] = v[0]
        elif default_value is not None:
            result[k] = default_value
        else:
            del result[k]
    return result


def printCommands(*several_commands):
    """
    Simply prints several commands given to it
    Args:
        *several_commands (list|tuple): Container of commands
    Returns: None
    """
    for commands in several_commands:
        print(' '.join(commands).strip())


def plot_histograms(ax, prng, nb_samples=10000):
    """Plot 4 histograms and a text annotation.
    """
    params = (10, 10), (4, 12), (50, 12), (6, 55)
    for a, b in params:
        values = prng.beta(a, b, size=nb_samples)
        ax.hist(values, histtype='stepfilled', bins=30, alpha=0.8, density=True
            )
    ax.annotate('Annotation', xy=(0.25, 4.25), xycoords='data', xytext=(0.9,
        0.9), textcoords='axes fraction', va='top', ha='right', bbox=dict(
        boxstyle='round', alpha=0.2), arrowprops=dict(arrowstyle='->',
        connectionstyle='angle,angleA=-95,angleB=35,rad=10'))
    return ax


def delete_ip_set(IPSetId=None, ChangeToken=None):
    """
    Permanently deletes an  IPSet . You can't delete an IPSet if it's still used in any Rules or if it still includes any IP addresses.
    If you just want to remove an IPSet from a Rule , use  UpdateRule .
    To permanently delete an IPSet from AWS WAF, perform the following steps:
    See also: AWS API Documentation

    Examples
    The following example deletes an IP match set  with the ID example1ds3t-46da-4fdb-b8d5-abc321j569j5.
    Expected Output:

    :example: response = client.delete_ip_set(
        IPSetId='string',
        ChangeToken='string'
    )

    :type IPSetId: string
    :param IPSetId: [REQUIRED]
            The IPSetId of the IPSet that you want to delete. IPSetId is returned by CreateIPSet and by ListIPSets .

    :type ChangeToken: string
    :param ChangeToken: [REQUIRED]
            The value returned by the most recent call to GetChangeToken .

    :rtype: dict
    :return: {
        'ChangeToken': 'string'
    }

    :returns:
    IPSetId (string) -- [REQUIRED]
    The IPSetId of the  IPSet that you want to delete. IPSetId is returned by  CreateIPSet and by  ListIPSets .

    ChangeToken (string) -- [REQUIRED]
    The value returned by the most recent call to  GetChangeToken .

    """
    pass


def check_dense_hemi(hemisphere):
    """
    Check hemisphere argument for compatibility.

    Parameters
    ----------
    hemisphere : 'left' or 'right' or None
        if bilateral, use None

    Returns
    -------
    'left' or 'right' or None

    Raises
    ------
    ValueError : invalid hemisphere argument

    """
    options = ['left', 'l', 'L', 'right', 'r', 'R', None, 'lr', 'LR']
    if hemisphere not in options:
        raise ValueError('{} is not a valid hemisphere'.format(hemisphere))
    if hemisphere in ['left', 'l', 'L']:
        return 'left'
    if hemisphere in ['right', 'r', 'R']:
        return 'right'
    if hemisphere in ['None', 'lr', 'LR']:
        return None


@staticmethod
def draw_mayavi_graph(G, **kwds):
    """
        Draws the provided network with mayavi. This requires the Mayavi python library
        (mayavi.mlab)

        **Optional Keywords**:
         - *node_size* = The size of the nodes. Default is 40.
         - *edge_thickness* = The thickness of the edges. Default is 4
         - *show* = If true, the model is displayed in the mayavi viewer after exporting. Default is True
         - *path* = A path to save the mayavi vtk file to after generating it.
        """
    import networkx as nx
    import numpy as np
    try:
        from mayavi import mlab
    except ImportError:
        print(
            "Error loading mayavi package: mayavi is not installed or is not on the python path. To install with pip, use 'pip install mayavi' (or 'conda install mayavi'"
            )
        return
    node_size = kwds.get('node_size', 250)
    edge_thickness = kwds.get('edge_thickness', 10)
    G2 = nx.convert_node_labels_to_integers(G)
    x = []
    y = []
    z = []
    nCols = []
    for n in G2.nodes():
        assert 'centroid' in G2.node[n
            ], 'Error: node centroids are not defined.'
        centroid = G2.node[n]['centroid']
        x.append(centroid[0])
        y.append(centroid[1])
        z.append(centroid[2])
        nCols.append(int(G2.node[n]['lithology']))
    edge_groups = {}
    from matplotlib.colors import ColorConverter
    cc = ColorConverter()
    for e in G2.edges(data=True):
        e_type = e[2]['edgeType']
        if e_type not in edge_groups:
            col = e[2].get('colour', (0.3, 0.3, 0.3))
            if not type(col) is tuple:
                col = cc.to_rgb(col)
            edge_groups[e_type] = ([], [], []), [], col, []
        id_start = len(edge_groups[e_type][0][0])
        edge_groups[e_type][0][0].append(x[e[0]])
        edge_groups[e_type][0][1].append(y[e[0]])
        edge_groups[e_type][0][2].append(z[e[0]])
        edge_groups[e_type][3].append(e[2].get('weight', 1.0) * edge_thickness)
        id_end = len(edge_groups[e_type][0][0])
        edge_groups[e_type][0][0].append(x[e[1]])
        edge_groups[e_type][0][1].append(y[e[1]])
        edge_groups[e_type][0][2].append(z[e[1]])
        edge_groups[e_type][3].append(e[2].get('weight', 1.0) * edge_thickness)
        edge_groups[e_type][1].append((id_start, id_end))
    mlab.figure(1, bgcolor=(1, 1, 1))
    mlab.clf()
    pts = mlab.points3d(x, y, z, nCols, scale_factor=node_size, scale_mode=
        'none', resolution=20)
    for k in list(edge_groups.keys()):
        e = edge_groups[k]
        pts2 = mlab.points3d(e[0][0], e[0][1], e[0][2], e[3], scale_factor=
            edge_thickness, scale_mode='none', resolution=5)
        pts2.mlab_source.dataset.lines = np.array(e[1])
        tube = mlab.pipeline.tube(pts2, tube_radius=edge_thickness)
        tube.filter.vary_radius = 'vary_radius_by_scalar'
        tube.filter.radius_factor = 5
        mlab.pipeline.surface(tube, color=e[2])
    if 'path' in kwds:
        try:
            from tvtk.api import write_data
        except:
            print('Warning: tvtk not installed - cannot write vtk file.')
        write_data(pts.mlab_source.dataset, kwds['path'])
    if kwds.get('show', True):
        mlab.show()


def str_repalce(x, old, new):
    """
    Replace old values with new in strin `x`.

    :param x: str;
    :param old: Union[str, Iterable[str]];
    :param new: Union[str, Iterable[str]];
    :return: str;
    """
    old = [old] if isinstance(old, str) else old
    new = [new] if isinstance(new, str) else new
    for _old, _new in zip(old, new):
        x = str(x).replace(_old, _new)
    return x


def hidedot():
    """Toggle hide hidden dot files

    """
    pass


def render_git_describe(pieces):
    """TAG[-DISTANCE-gHEX][-dirty].

    Like 'git describe --tags --dirty --always'.

    Exceptions:
    1: no tags. HEX[-dirty]  (note: no 'g' prefix)
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        if pieces['distance']:
            rendered += '-%d-g%s' % (pieces['distance'], pieces['short'])
    else:
        rendered = pieces['short']
    if pieces['dirty']:
        rendered += '-dirty'
    return rendered


@staticmethod
def write(writer, value):
    """
        Writes Zserio varuint64 type to the bit stream.

        :param writer: Bit stream where to write.
        :param value: Zserio varuint64 type to write.
        """
    writer.writeVarUInt64(value)


def testRoundTrip():
    """
    Function to run test suite for pySBOL
    """
    import sbol.unit_tests as unit_tests
    unit_tests.runRoundTripTests()


def _compute_size_by_dict(indices, idx_dict):
    """
    Computes the product of the elements in indices based on the dictionary
    idx_dict.

    Parameters
    ----------
    indices : iterable
        Indices to base the product on.
    idx_dict : dictionary
        Dictionary of index sizes

    Returns
    -------
    ret : int
        The resulting product.

    Examples
    --------
    >>> _compute_size_by_dict('abbc', {'a': 2, 'b':3, 'c':5})
    90

    """
    ret = 1
    for i in indices:
        ret *= idx_dict[i]
    return ret


@staticmethod
def p_expression_uminus(p):
    """expression : '-' expression %prec UMINUS"""
    p[0] = -p[2]


def get_slave_class(domain_class):
    """Fetch a slave class given a domain class.
        :param domain_class:
        :returns: the slave class or None
        """


def determine_loader(ext):
    """Returns a loader name for a given file extension

    Parameters
    ----------
    ext : str
        File ending excluding the ``.``. Same as what would be returned by
        :func:`os.path.splitext`

    Returns
    -------
    name : str
        Name of the meta loader (see
        :py:mod:`~edflow.data.believers.meta_loaders` .

    Raises
    ------
    ValueError
        If the file extension cannot be handled by the implemented loaders.
        Feel free to implement you own and publish them to ``edflow``.
    """
    if ext == 'png':
        return 'image'
    elif ext == 'npy':
        return 'np'
    else:
        raise ValueError('Cannot load file with extension `{}`'.format(ext))


def get_func_and_script_url_from_initiator(initiator):
    """Remove line number and column number from the initiator."""
    if initiator:
        return initiator.rsplit(':', 2)[0].split(' line')[0]
    else:
        return ''


def restart(time=0):
    """Restart the server.

        The `time` should be greater-equal 0.

        If the `time` is 0, then we do a hard shutdown, i.e. closing
        all sockets without waiting for tasks to complete.

        If the `time` is not 0, then we will give the tasks `time` seconds to
        finish before shutting down.
        """


def getCreationDate():
    """Returns the creation date.
        """


def __call__(context, macros, debug=0, wrap=60, metal=1, tal=1, showtal=-1,
    strictinsert=1, stackLimit=100, i18nInterpolate=1, sourceAnnotations=0):
    """
        Render template in the provided template *context*.

        Optional arguments:

        :keyword bool debug: enable debugging output to sys.stderr (off by default).
        :keyword int wrap: try to wrap attributes on opening tags to this number of
            column (default: 60).
        :keyword bool metal: enable METAL macro processing (on by default).
        :keyword bool tal: enable TAL processing (on by default).
        :keyword int showtal: do not strip away TAL directives.  A special value of
            -1 (which is the default setting) enables showtal when TAL
            processing is disabled, and disables showtal when TAL processing is
            enabled.  Note that you must use 0, 1, or -1; true boolean values
            are not supported (for historical reasons).
        :keyword bool strictinsert: enable TAL processing and stricter HTML/XML
            checking on text produced by structure inserts (on by default).
            Note that Zope turns this value off by default.
        :keyword int stackLimit: set macro nesting limit (default: 100).
        :keyword bool i18nInterpolate: enable i18n translations (default: on).
        :keyword bool sourceAnnotations: enable source annotations with HTML comments
            (default: off).
        """


def _join_translated(translated_parts, os_sep_class):
    """Join translated glob pattern parts.

    This is different from a simple join, as care need to be taken
    to allow ** to match ZERO or more directories.
    """
    res = ''
    for part in translated_parts[:-1]:
        if part == '.*':
            res += part
        else:
            res += part + os_sep_class
    if translated_parts[-1] == '.*':
        res += '.+'
        res += '({os_sep_class}?.*)?'.format(os_sep_class=os_sep_class)
    else:
        res += translated_parts[-1]
    return res


@classmethod
def update(cls, *packages):
    """
        invoca el comando de yum para actualizar paquetes

        Parameters
        ==========
        pkgs: tuple of strings
            lista de los paquetes que se quieren installar
        """
    result = cls('update', *packages)()
    return result


def lookup_ssh_host_config(hostname, config):
    """
    Provided only as a backward-compatible wrapper around `.SSHConfig`.
    """
    return config.lookup(hostname)


def is_run_step(step):
    """Return true iff the given step is the "run" step."""
    return step._funcname == 'start_runs'


def count_overall_frequency(tokenized_documents):
    """Count the overall occurence of all (tokenised) words through the
    whole corpus.

    """
    document_frequency = {}
    for document in tokenized_documents:
        for word in document:
            if word in document_frequency:
                document_frequency[word] += 1
            else:
                document_frequency[word] = 1
    return document_frequency


def main():
    """Function to be called when file executed via terminal."""
    print(__doc__)


def _read_data(cls, input_file):
    """Reads a BIO data."""
    with open(input_file) as f:
        lines = []
        words = []
        labels = []
        for line in f:
            contends = line.strip()
            word = line.strip().split(' ')[0]
            label = line.strip().split(' ')[-1]
            if contends.startswith('-DOCSTART-'):
                words.append('')
                continue
            if len(contends) == 0:
                l = ' '.join([label for label in labels if len(label) > 0])
                w = ' '.join([word for word in words if len(word) > 0])
                lines.append([l, w])
                words = []
                labels = []
                continue
            words.append(word)
            labels.append(label)
        return lines


def assign_attributes(model, **kwargs):
    """Assign all attributes from the supplied `kwargs` dictionary to the
    model. This does the same thing as the default declarative constructor,
    when provided a dictionary of attributes and values.

    """
    cls = type(model)
    for field, value in kwargs.items():
        if not hasattr(cls, field):
            msg = '{0} has no field named "{1!r}"'.format(cls.__name__, field)
            raise TypeError(msg)
        setattr(model, field, value)


@classmethod
def _from_dict(cls, _dict):
    """Initialize a CreateValue object from a json dictionary."""
    args = {}
    if 'value' in _dict:
        args['value'] = _dict.get('value')
    else:
        raise ValueError(
            "Required property 'value' not present in CreateValue JSON")
    if 'metadata' in _dict:
        args['metadata'] = _dict.get('metadata')
    if 'synonyms' in _dict:
        args['synonyms'] = _dict.get('synonyms')
    if 'patterns' in _dict:
        args['patterns'] = _dict.get('patterns')
    if 'type' in _dict or 'value_type' in _dict:
        args['value_type'] = _dict.get('type') or _dict.get('value_type')
    return cls(**args)


def stop_app(proc):
    """
    Stop application by sending a newline to stdin
    """
    if proc:
        proc.kill()


def parse_bdist_wininst(name):
    """Return (base,pyversion) or (None,None) for possible .exe name"""
    lower = name.lower()
    base, py_ver, plat = None, None, None
    if lower.endswith('.exe'):
        if lower.endswith('.win32.exe'):
            base = name[:-10]
            plat = 'win32'
        elif lower.startswith('.win32-py', -16):
            py_ver = name[-7:-4]
            base = name[:-16]
            plat = 'win32'
        elif lower.endswith('.win-amd64.exe'):
            base = name[:-14]
            plat = 'win-amd64'
        elif lower.startswith('.win-amd64-py', -20):
            py_ver = name[-7:-4]
            base = name[:-20]
            plat = 'win-amd64'
    return base, py_ver, plat


def getBotID(cursor):
    """
    Gets a suitable Bot User ID from a Humhub User Group called 'Bots'

    :return: Bots Humhub User ID
    :rtype: int
    """
    query = (
        "SELECT `user_id` FROM `group` JOIN `group_user` ON `group`.`id` = `group_user`.`group_id` WHERE `group`.`name` = 'Bots' ORDER BY user_id DESC LIMIT 1;"
        )
    cursor.execute(query)
    return cursor.fetchone()[0]


def format_number(number):
    """
    >>> format_number(1)
    1
    >>> format_number(22)
    22
    >>> format_number(333)
    333
    >>> format_number(4444)
    '4,444'
    >>> format_number(55555)
    '55,555'
    >>> format_number(666666)
    '666,666'
    >>> format_number(7777777)
    '7,777,777'
    """
    char_list = list(str(number))
    length = len(char_list)
    if length <= 3:
        return number
    result = ''
    if length % 3 != 0:
        while len(char_list) % 3 != 0:
            c = char_list[0]
            result += c
            char_list.remove(c)
        result += ','
    i = 0
    while len(char_list) > 0:
        c = char_list[0]
        result += c
        char_list.remove(c)
        i += 1
        if i % 3 == 0:
            result += ','
    return result[0:-1] if result[-1] == ',' else result


def func_trim(parser, text, char=None):
    """Trims all leading and trailing whitespaces from ``text``. The optional
       second parameter specifies the character to trim."""
    if char:
        return text.strip(char)
    else:
        return text.strip()


def duplicate(seq):
    """ Find first duplicate element.
    """
    seen = set()
    for n in seq:
        if n in seen:
            return n
        else:
            seen.add(n)
    raise ValueError('Not found')


def extract_7z_singlefile(archive, compression, cmd, verbosity, interactive,
    outdir):
    """Extract a singlefile archive (eg. gzip or bzip2) with '7z e'.
    This makes sure a single file and no subdirectories are created,
    which would cause errors with patool repack."""
    cmdlist = [cmd, 'e']
    if not interactive:
        cmdlist.append('-y')
    cmdlist.extend(['-o%s' % outdir, '--', archive])
    return cmdlist


@classmethod
def add(cls, title, creator, parent=None):
    """Creates a category.

        :param str title:
        :param User creator:
        :param Category|None parent:
        :return:
        """
    obj = cls(title=title, creator=creator, parent=parent)
    obj.save()
    return obj


def propagate_constraints(eq, wc):
    """
  Takes a basis of constraints and propagates them to produce all constraints.

  Takes dicts eq and wc where
    y in eq[x] means that x is equal y  and
    y in wc[x] means that y is complementary to x
  and produces eq_all and wc_all where
    eq_all[x] = {y | y == x} (set of *all* items equal to x)
    wc_all[x] = {y | y ~= x} (set of *all* items equal to x)

  NOTE: Assumes that if  y in eq[x]  =>  x in eq[y]  and likewise for wc.
  """
    keys = list(eq.keys())
    assert list(wc.keys()
        ) == keys, 'eq.keys() and wc.keys() must be equal to the set of items to constrain over'
    eq_all = {}
    wc_all = {}
    for x in keys:
        if x not in eq_all:
            eq_set = set(eq[x])
            eq_set.add(x)
            wc_set = set(wc[x])
            eq_done = set()
            wc_done = set()
            while eq_set - eq_done or wc_set - wc_done:
                for y in (eq_set - eq_done):
                    assert y in keys and y not in eq_all, (x, y)
                    eq_set.update(eq[y])
                    wc_set.update(wc[y])
                    eq_done.add(y)
                for y in (wc_set - wc_done):
                    assert y in keys and y not in eq_all, (x, y)
                    wc_set.update(eq[y])
                    eq_set.update(wc[y])
                    wc_done.add(y)
            for y in eq_set:
                eq_all[y] = eq_set
                wc_all[y] = wc_set
            for y in wc_set:
                eq_all[y] = wc_set
                wc_all[y] = eq_set
    return eq_all, wc_all


@classmethod
def initialize(cls, settings):
    """
        Called just before the `Server` class is instantiated, and passed the settings dict. Can be used to perform
        settings manipulation, server class patching (such as for performance tracing operations), and more. Use with
        great care and caution. Overriding methods must call `super` and return `cls` or a new/modified `cls`, which
        will be used to instantiate the server. See the documentation for `Server.main` for full details on the chain
        of `Server` method calls.

        :return: The server class or a new/modified server class
        """
    return cls


@staticmethod
def _editdistance(a, b):
    """ Simple unweighted Levenshtein distance """
    r0 = range(0, len(b) + 1)
    r1 = [0] * (len(b) + 1)
    for i in range(0, len(a)):
        r1[0] = i + 1
        for j in range(0, len(b)):
            c = 0 if a[i] is b[j] else 1
            r1[j + 1] = min(r1[j] + 1, r0[j + 1] + 1, r0[j] + c)
        r0 = r1[:]
    return r1[len(b)]


def replicate(item, match):
    """Create tuple of `item` copied `len(match)` times"""
    return (item,) * len(match)


@staticmethod
def prepare_filter(couples):
    """
        Prepares the filter in order to fill the count table

        :param couples: (tag, value) couples
        :return: Str query of the corresponding filter
        """
    query = ''
    and_to_write = False
    for couple in couples:
        tag = couple[0]
        value = couple[1]
        if and_to_write:
            query += ' AND '
        and_to_write = True
        query += '({' + tag + '} == "' + str(value) + '")'
    query = '(' + query + ')'
    return query


@staticmethod
def read_fasta(fasta, delim=None, as_id=0):
    """read from fasta fasta file 'fasta'
        and split sequence id at 'delim' (if set)

        example:

        >idpart1|idpart2

        ATGTGA

        and 'delim="|"' returns ("idpart1", "ATGTGA")
        """
    name = ''
    fasta = open(fasta, 'r')
    while True:
        line = name or fasta.readline()
        if not line:
            break
        seq = []
        while True:
            name = fasta.readline()
            name = name.rstrip()
            if not name or name.startswith('>'):
                break
            else:
                seq.append(name)
        joined_seq = ''.join(seq)
        line = line[1:]
        if delim:
            line = line.split(delim)[as_id]
        yield line.rstrip(), joined_seq.rstrip()
    fasta.close()


@classmethod
def from_api_data(cls, data):
    """Creates a new PurchaseResults object from API data from ticketswitch.

        Args:
            data (dict): the part of the response from a ticketswitch API call
                that concerns the results of a purchase attempt.

        Returns:
            :class:`PurchaseResult <pyticketswitch.purchase_result.PurchaseResult>`:
            a new
            :class:`PurchaseResult <pyticketswitch.purchase_result.PurchaseResult>`
            object populated with the data from the api.

        """
    kwargs = {'success': data.get('success'), 'failed_3d_secure': data.get(
        'failed_3d_secure'), 'failed_avs': data.get('failed_avs'),
        'failed_cv_two': data.get('failed_cv_two'), 'error': data.get(
        'purchase_error'), 'failure_reason': data.get('failure_reason'),
        'is_partial': data.get('is_partial'), 'is_semi_credit': data.get(
        'is_semi_credit')}
    return cls(**kwargs)


def getMemberareaCreationFlag():
    """ Return True if the membership tool will create a member area for
            a user at login.

        o Permission:  Manage portal
        """


def render_pep440_old(pieces):
    """TAG[.postDISTANCE[.dev0]] .

    The ".dev0" means dirty.

    Eexceptions:
    1: no tags. 0.postDISTANCE[.dev0]
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        if pieces['distance'] or pieces['dirty']:
            rendered += '.post%d' % pieces['distance']
            if pieces['dirty']:
                rendered += '.dev0'
    else:
        rendered = '0.post%d' % pieces['distance']
        if pieces['dirty']:
            rendered += '.dev0'
    return rendered


def evoke_version(app):
    """single version number combining the major and minor parts
    (for internal use only, allowing simple numerical comparison)
    """
    major, minor = app.Config.evoke_version.split('.')
    return int(major) * 1000000 + int(minor)


def get_elastic_ips(ec2) ->list:
    """
    List all Elastic IPs reserved in the account
    """
    boto_elastic_ips = ec2.describe_addresses()
    elastic_ips = []
    for elastic_ip in boto_elastic_ips['Addresses']:
        if 'PrivateIpAddress' in elastic_ip:
            elastic_ips.append(elastic_ip['PrivateIpAddress'] + '/32')
        elastic_ips.append(elastic_ip['PublicIp'] + '/32')
    return elastic_ips


def check_for_updates():
    """
        Checks for updates and returns a tuple:
            update_available, latest_version, current_version
    """
    from pyxrd.generic.outdated import check_outdated
    from pyxrd.__version import __version__
    is_outdated, latest_version = check_outdated('pyxrd', __version__)
    return is_outdated, latest_version, __version__


def now(ctx):
    """
    Returns the current date and time
    """
    return ctx.now.astimezone(ctx.timezone)


def train_2d(trainer, steps=20):
    """Optimize a 2-dim objective function with a customized trainer."""
    x1, x2, s1, s2 = -5, -2, 0, 0
    results = [(x1, x2)]
    for i in range(steps):
        x1, x2, s1, s2 = trainer(x1, x2, s1, s2)
        results.append((x1, x2))
    print('epoch %d, x1 %f, x2 %f' % (i + 1, x1, x2))
    return results


def _convert_softmax_nd(builder, node, graph, err):
    """
    convert to CoreML SoftMax ND Layer:
    https://github.com/apple/coremltools/blob/655b3be5cc0d42c3c4fa49f0f0e4a93a26b3e492/mlmodel/format/NeuralNetwork.proto#3547
    """
    axis = node.attrs.get('axis', 1)
    builder.add_softmax_nd(name=node.name, input_name=node.inputs[0],
        output_name=node.outputs[0] + ('_softmax' if node.op_type ==
        'LogSoftmax' else ''), axis=axis)
    if node.op_type == 'LogSoftmax':
        builder.add_unary(name=node.name + '_log', input_name=node.outputs[
            0] + '_softmax', output_name=node.outputs[0], mode='log')


def DBG(text):
    """DBG - temporary debugging function

    Args:
        text (str): text to print
    """
    print(f'LEP: {text}')


def megabytes(bits=None, bytes=None, kilobytes=None, gigabytes=None,
    terabytes=None, petabytes=None):
    """Usage: Convert to megabytes. Example: megabytes(bits=42561261)"""
    if bits is not None:
        return bits / 8000000.0
    elif bytes is not None:
        return bytes / 1000000.0
    elif kilobytes is not None:
        return kilobytes / 1000
    elif gigabytes is not None:
        return gigabytes * 1000
    elif terabytes is not None:
        return terabytes * 1000000.0
    elif petabytes is not None:
        return petabytes * 1000000000.0
    else:
        raise Exception(
            'You must specify one value. Example: bits, bytes, kilobytes, gigabytes, terabytes, petabytes'
            )


@classmethod
def sso_remove_cert_details(cls, val):
    """
        Create an instance of this class set to the ``sso_remove_cert_details``
        tag with value ``val``.

        :param SsoRemoveCertDetails val:
        :rtype: EventDetails
        """
    return cls('sso_remove_cert_details', val)


def step(a):
    """ Return logic step function
        ^   .........
        |   |
        |___|________
            a
    """
    return lambda x: 1.0 if x > a else 0.0


def create(hub, name, sls_sources, render, runtime, subs, cache_dir, test):
    """
    Create a new instance to execute against
    """
    hub.idem.RUNS[name] = {'sls_sources': sls_sources, 'render': render,
        'runtime': runtime, 'subs': subs, 'cache_dir': cache_dir, 'states':
        {}, 'test': test, 'resolved': set(), 'files': set(), 'high': {},
        'errors': [], 'iorder': 100000, 'sls_refs': {}, 'blocks': {},
        'running': {}, 'run_num': 1, 'add_low': []}


def targets(obj, reftype):
    """ Return a generator consisting of objects which have ``obj`` as a
        relationship target using ``reftype``. ``obj`` can be an object or an
        object id."""


def parse_name(endpoint):
    """Parse the last element of a given endpoint"""
    return endpoint.rstrip('/').split('/')[-1]


def entry_spread_yield(data, value, _idx):
    """
    Yield Percentage is (option entry price / stockprice).

    For example it would search options that have yldpct between
    and including .05 to .10 (5 and 10 percent).
    """
    pass


def test_rpm(archive, compression, cmd, verbosity, interactive):
    """Test a RPM archive."""
    cmdlist = [cmd, 'V']
    if verbosity > 1:
        cmdlist.append('-v')
    cmdlist.extend(['-p', '--', archive])
    return cmdlist


def output_file_add_socket(file_path: str='Image'):
    """Add a new input to a file output node

    :param file_path: File Path, Sub-path of the output file
    :type file_path: str
    """
    pass


def polyval(f, x, m=None):
    """
    Evalutates a polynomial at a particular point, optionally modulo something.
    Input:
        f -- List.  These are the polynomial's coefficients in order of
             increasing degree.
        x -- Integer.  Evaluate here.
        m -- Integer or None (default).  If not None, evaluate modulo m.
    Output: An integer.
    Examples:
    >>> polyval([1,2,3], 2)
    17
    >>> polyval([1,2,3], 2, 3)
    2
    """
    out = 0
    if m is None:
        for a in reversed(f):
            out = a + out * x
    else:
        for a in reversed(f):
            out = (a + out * x) % m
    return out


@staticmethod
def get_pyaudio():
    """
        Imports the pyaudio module and checks its version. Throws exceptions if pyaudio can't be found or a wrong version is installed
        """
    try:
        import pyaudio
    except ImportError:
        raise AttributeError('Could not find PyAudio; check installation')
    from distutils.version import LooseVersion
    if LooseVersion(pyaudio.__version__) < LooseVersion('0.2.9'):
        raise AttributeError(
            'PyAudio 0.2.9 or later is required (found version {})'.format(
            pyaudio.__version__))
    return pyaudio


def _split_tree(layout):
    """Return a tuple of two layouts, one containing the left
    subtree of the root vertex, and one containing the original tree
    with the left subtree removed."""
    one_found = False
    m = None
    for i in range(len(layout)):
        if layout[i] == 1:
            if one_found:
                m = i
                break
            else:
                one_found = True
    if m is None:
        m = len(layout)
    left = [(layout[i] - 1) for i in range(1, m)]
    rest = [0] + [layout[i] for i in range(m, len(layout))]
    return left, rest


@classmethod
def getActiveOrCreate(cls, checkpointPath, setupFunc):
    """
        Either return the active StreamingContext (i.e. currently started but not stopped),
        or recreate a StreamingContext from checkpoint data or create a new StreamingContext
        using the provided setupFunc function. If the checkpointPath is None or does not contain
        valid checkpoint data, then setupFunc will be called to create a new context and setup
        DStreams.

        @param checkpointPath: Checkpoint directory used in an earlier streaming program. Can be
                               None if the intention is to always create a new context when there
                               is no active context.
        @param setupFunc:      Function to create a new JavaStreamingContext and setup DStreams
        """
    if setupFunc is None:
        raise Exception('setupFunc cannot be None')
    activeContext = cls.getActive()
    if activeContext is not None:
        return activeContext
    elif checkpointPath is not None:
        return cls.getOrCreate(checkpointPath, setupFunc)
    else:
        return setupFunc()


def is_byte_range_valid(start, stop, length):
    """Checks if a given byte content range is valid for the given length.

    .. versionadded:: 0.7
    """
    if (start is None) != (stop is None):
        return False
    elif start is None:
        return length is None or length >= 0
    elif length is None:
        return 0 <= start < stop
    elif start >= stop:
        return False
    return 0 <= start < length


def validate_boolean(option, value):
    """Validates that 'value' is True or False."""
    if isinstance(value, bool):
        return value
    raise TypeError('%s must be True or False' % (option,))


def metadata_from_package(variant):
    """Return metadata relative `variant`

    Blocking call, during change of profile.

    IMPORTANT: this function must return at least the
        members part of the original function, else the program
        will not function. Very few safeguards are put in place
        in favour of performance.

    Arguments:
        variant (rez.packages_.Variant): Package from which to retrieve data

    Returns:
        dict: See function for values and types

    """
    data = getattr(variant, '_data', {})
    return dict(data, **{'label': data.get('label', variant.name),
        'background': data.get('background'), 'icon': data.get('icon', ''),
        'hidden': data.get('hidden', False)})


@staticmethod
def _split_line(line: str) ->list:
    """Every message in the file is timestamped in the following format:
          1585817817.5626152:{"type":"RECORD","value":{"col_1":"value_1"}}

        This method split the original message to timestamp and the real message
        componets and returns as list of two items.
        """
    return line.split(':', 1)


@classmethod
def set_max_size(cls, pid, size):
    """Set the maximum number of connections for the specified pool

        :param str pid: The pool to set the size for
        :param int size: The maximum number of connections

        """
    with cls._lock:
        cls._ensure_pool_exists(pid)
        cls._pools[pid].set_max_size(size)


def _read_hyperparameters(idx, hist):
    """Read hyperparameters as a dictionary from the specified history dataset."""
    return hist.iloc[(idx), 2:].to_dict()


def lsquare_of_sums(inlist):
    """
Adds the values in the passed list, squares the sum, and returns
the result.

Usage:   lsquare_of_sums(inlist)
Returns: sum(inlist[i])**2
"""
    s = sum(inlist)
    return float(s) * s


def activation_channels_apoz(activation):
    """Calculate the APoZ of each of an activation's channels.

    APoZ is the Average Percentage of Zeros (or simply: average sparsity) and is defined in:
    "Network Trimming: A Data-Driven Neuron Pruning Approach towards Efficient Deep Architectures".

    The activation usually has the shape: (batch_size, num_channels, h, w).

    "We first use global average pooling to convert the output of layer i, which is a
    c x h x w tensor, into a 1 x c vector."

    Returns - for each channel: the batch-mean of its sparsity.
    """
    if activation.dim() == 4:
        view_2d = activation.view(-1, activation.size(2) * activation.size(3))
        featuremap_apoz = view_2d.abs().gt(0).sum(dim=1).float() / (activation
            .size(2) * activation.size(3))
        featuremap_apoz_mat = featuremap_apoz.view(activation.size(0),
            activation.size(1))
    elif activation.dim() == 2:
        featuremap_apoz_mat = activation.abs().gt(0).sum(dim=1).float(
            ) / activation.size(1)
    else:
        raise ValueError('activation_channels_apoz: Unsupported shape: '.
            format(activation.shape))
    return 100 - featuremap_apoz_mat.mean(dim=0).mul(100).cpu()


def get_paginator(operation_name=None):
    """
    Create a paginator for an operation.

    :type operation_name: string
    :param operation_name: The operation name. This is the same name
            as the method name on the client. For example, if the
            method name is create_foo, and you'd normally invoke the
            operation as client.create_foo(**kwargs), if the
            create_foo operation can be paginated, you can use the
            call client.get_paginator('create_foo').

    :rtype: L{botocore.paginate.Paginator}
    """
    pass


def add_default_args(parser, version=None, include=None):
    """
    Add default arguments to a parser. These are:
        - config: argument for specifying a configuration file.
        - user: argument for specifying a user.
        - dry-run: option for running without side effects.
        - verbose: option for running verbosely.
        - quiet: option for running quietly.
        - version: option for spitting out version information.

    Args:
        version (str): version to return on <cli> --version
        include (Sequence): default arguments to add to cli. Default: (config, user, dry-run, verbose, quiet)
    """
    include = include or ('config', 'user', 'dry-run', 'verbose', 'quiet')
    if 'config' in include:
        parser.add_argument('-c', '--config', dest='config_file', metavar=
            'PATH', default=None, type=str, help=
            'bots config file (json or yaml)')
    if 'user' in include:
        parser.add_argument('-u', '--user', dest='screen_name', type=str,
            help='Twitter screen name')
    if 'dry-run' in include:
        parser.add_argument('-n', '--dry-run', action='store_true', help=
            "Don't actually do anything")
    if 'verbose' in include:
        parser.add_argument('-v', '--verbose', action='store_true', help=
            'Run talkatively')
    if 'quiet' in include:
        parser.add_argument('-q', '--quiet', action='store_true', help=
            'Run quietly')
    if version:
        parser.add_argument('-V', '--version', action='version', version=
            '%(prog)s ' + version)


def symbol(property):
    """ Return the part of a URI after the last **/** or *#*, `property` is a
    string denoting a URI

    .. code-block:: python

        >>> print ns.symbol('http://sometest.ns/ns#symbol')
        symbol

    """
    if '#' in property:
        return property.rsplit('#', 1)[-1]
    return property.rsplit('/', 1)[-1]