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

        :param TeamMergeRequestAcceptedShownToPrimaryTeamDetails val:
        :rtype: EventDetails
        """
    return cls('team_merge_request_accepted_shown_to_primary_team_details', val
        )


def ReadInt1(s):
    """Convert first byte from a string to an unsigned 8-bit integer."""
    if type(s) == int:
        return s
    elif type(s) == bytes:
        return s[0]


def iterbytes(b):
    """Iterate over bytes, returning bytes instead of ints (python3)"""
    if isinstance(b, memoryview):
        b = b.tobytes()
    i = 0
    while True:
        a = b[i:i + 1]
        i += 1
        if a:
            yield a
        else:
            break


def populate_namespace_with_module_classes(mod, loc):
    """Export the classes that submodules list in __all_classes__."""
    names = mod.__all_classes__
    for name in names:
        loc[name] = getattr(mod, name)
    return names


def _round_to_n(sequence, n=100):
    """ Resolves issue when dividing by N results in a set of numbers that don't add up to N again

        E.g. 100 / 3 = 33
             33 * 3 = 99

        For the above example, this function returns [33, 33, 34]
     """
    if sum(sequence) != n:
        sequence[-1] = n - sum(sequence[:-1])
    return sequence


def translate(model, reaction_xref_file_name, metabolite_xref_file_name,
    from_namespace, to_namespace):
    """ Translate IDs in a model from one namespace to another namespace.

    Parameters
    ----------
    model : cobra.core.Model
        Model to translate
    reaction_xref_file_name : str
        Path to cross reference file with ID mapping for reactions
    metabolite_xref_file_name : str
        Path to cross reference file with ID mapping for metabolites
    from_namespace : str
        Namespace of IDs in input model
    to_namespace : str
        Namespace of IDs in output model

    Returns
    -------
    cobra.core.Model
        New model with translated IDs
    """
    return


def is_matched_to_b(jet):
    """returns true if jet.match is a b quark.
    matching must be done before.
    does not work because of low matching efficiency?
    """
    is_bjet = False
    if jet.match and abs(jet.match.pdgid()) == 5:
        is_bjet = True
    return is_bjet


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

        :param GroupChangeMemberRoleType val:
        :rtype: EventType
        """
    return cls('group_change_member_role', val)


def update_http_headers(resource_data, response_headers):
    """
    Updates resource data dict with AWS entities if matching header found.
    :param resource_data: event's resource data dict
    :param response_headers: response headers from HTTP request
    :return: update resource data dict
    """
    for header_key, header_value in response_headers.items():
        if header_key.lower() == 'x-amzn-requestid':
            if '.appsync-api.' not in resource_data['metadata']['url']:
                resource_data['type'] = 'api_gateway'
            resource_data['metadata']['request_trace_id'] = header_value
            break
    return resource_data


def underscored2camel_case(v):
    """converts ott_id to ottId."""
    vlist = v.split('_')
    c = []
    for n, el in enumerate(vlist):
        if el:
            if n == 0:
                c.append(el)
            else:
                c.extend([el[0].upper(), el[1:]])
    return ''.join(c)


def takewhile_peek(predicate, iterable):
    """
    Like takewhile, but takes a peekable iterable and doesn't
    consume the non-matching item.

    >>> items = Peekable(range(10))
    >>> is_small = lambda n: n < 4

    >>> small_items = takewhile_peek(is_small, items)

    >>> list(small_items)
    [0, 1, 2, 3]

    >>> list(items)
    [4, 5, 6, 7, 8, 9]

    >>> empty = takewhile_peek(is_small, Peekable([]))
    >>> list(empty)
    []

    >>> items = Peekable([3])
    >>> small_items = takewhile_peek(is_small, items)
    >>> list(small_items)
    [3]
    >>> list(items)
    []

    >>> items = Peekable([4])
    >>> small_items = takewhile_peek(is_small, items)
    >>> list(small_items)
    []
    >>> list(items)
    [4]
    """
    while True:
        try:
            if not predicate(iterable.peek()):
                break
            yield next(iterable)
        except StopIteration:
            break


def _np_repeat(a, repeats, axis=None):
    """
    Repeat elements of an array.

    Parameters
    ----------
    a : ndarray
        Input array.
    repeats : int
        The number of repetitions for each element.
    axis : int, optional
        The axis along which to repeat values.  By default, use the
        flattened input array, and return a flat output array.

    Returns
    -------
    repeated_array : ndarray
        Output array which has the same shape as `a`, except along
        the given axis.

    Notes
    -----
    Unlike the official NumPy ``repeat`` operator, this operator currently
    does not support array of ints for the parameter `repeats`.

    Examples
    --------
    >>> x = np.arange(4).reshape(2, 2)
    >>> x
    array([[0., 1.],
           [2., 3.]])
    >>> np.repeat(x, repeats=3)
    array([0., 0., 0., 1., 1., 1., 2., 2., 2., 3., 3., 3.])
    >>> np.repeat(x, repeats=3, axis=0)
    array([[0., 1.],
           [0., 1.],
           [0., 1.],
           [2., 3.],
           [2., 3.],
           [2., 3.]])
    >>> np.repeat(x, repeats=3, axis=1)
    array([[0., 0., 0., 1., 1., 1.],
           [2., 2., 2., 3., 3., 3.]])
    """
    pass


def _is_locally_created(tx):
    """
    Check if we can send back the transaction if it was locally created

    :param sakia.data.entities.Transaction tx: the transaction
    :return: True if the transaction was locally created
    """
    return tx.local


def should_build_with_cython(package, release=None):
    """Returns the previously used Cython version (or 'unknown' if not
    previously built) if Cython should be used to build extension modules from
    pyx files.  If the ``release`` parameter is not specified an attempt is
    made to determine the release flag from `astropy.version`.
    """
    try:
        version_module = __import__(package + '.cython_version', fromlist=[
            'release', 'cython_version'])
    except ImportError:
        version_module = None
    if release is None and version_module is not None:
        try:
            release = version_module.release
        except AttributeError:
            pass
    try:
        cython_version = version_module.cython_version
    except AttributeError:
        cython_version = 'unknown'
    have_cython = False
    try:
        import Cython
        have_cython = True
    except ImportError:
        pass
    if have_cython and (not release or cython_version == 'unknown'):
        return cython_version
    else:
        return False


def _rfc822_escape(header):
    """Return a version of the string escaped for inclusion in an
    RFC-822 header, by ensuring there are 8 spaces space after each newline.
    """
    lines = header.split('\n')
    header = ('\n' + 8 * ' ').join(lines)
    return header


def add_argument_yes(parser):
    """Add a ``--yes`` argument to the parser."""
    parser.add_argument('-y', '--yes', action='store_true', default=False,
        help="Don't ask for confirmation to {} the package(s).".format(
        parser.get_command_name()))


def update_compute_environment(computeEnvironment=None, state=None,
    computeResources=None, serviceRole=None):
    """
    Updates an AWS Batch compute environment.
    See also: AWS API Documentation

    Examples
    This example disables the P2OnDemand compute environment so it can be deleted.
    Expected Output:

    :example: response = client.update_compute_environment(
        computeEnvironment='string',
        state='ENABLED'|'DISABLED',
        computeResources={
            'minvCpus': 123,
            'maxvCpus': 123,
            'desiredvCpus': 123
        },
        serviceRole='string'
    )

    :type computeEnvironment: string
    :param computeEnvironment: [REQUIRED]
            The name or full Amazon Resource Name (ARN) of the compute environment to update.

    :type state: string
    :param state: The state of the compute environment. Compute environments in the ENABLED state can accept jobs from a queue and scale in or out automatically based on the workload demand of its associated queues.

    :type computeResources: dict
    :param computeResources: Details of the compute resources managed by the compute environment. Required for a managed compute environment.
            minvCpus (integer) --The minimum number of EC2 vCPUs that an environment should maintain.
            maxvCpus (integer) --The maximum number of EC2 vCPUs that an environment can reach.
            desiredvCpus (integer) --The desired number of EC2 vCPUS in the compute environment.

    :type serviceRole: string
    :param serviceRole: The name or full Amazon Resource Name (ARN) of the IAM role that allows AWS Batch to make calls to ECS, Auto Scaling, and EC2 on your behalf.

    :rtype: dict
    :return: {
        'computeEnvironmentName': 'string',
        'computeEnvironmentArn': 'string'
    }

    """
    pass


def select_constraint_target():
    """Select bones used as targets for the currently selected bones

    """
    pass


def delta(v, d):
    """
    Limits of v +/- d for array v and d.
    """
    return zip(v - d, v + d)


def register_language(template_class, extension, sample_extension=None):
    """Register a template language with the system.

        template_class - a class which implements ITemplate
        extension - the filename extension to register this
                    language. (example: .jsont)
        sample_extension - the filename extension of sample data files
                           for an extension. (example: .json)
        """


def psi_Mg_HSO4_SO4_RC99(T, P):
    """c-a-a': magnesium bisulfate sulfate [RC99]."""
    psi = -0.078418
    valid = T == 298.15
    return psi, valid


def split_pem(pem_bytes: bytes):
    """
    Split a give PEM file with multiple certificates.

    :param pem_bytes: The pem data in bytes with multiple certs
    :return: yields a list of certificates contained in the pem file
    """
    started, pem_data = False, b''
    for line in pem_bytes.splitlines(False):
        if line == b'' and not started:
            continue
        if line[0:5] in (b'-----', b'---- '):
            if not started:
                started = True
            else:
                pem_data = pem_data + line + b'\r\n'
                yield pem_data
                started = False
                pem_data = b''
        if started:
            pem_data = pem_data + line + b'\r\n'


def is_int(string):
    """ 检查字符串是不是合法的 int. validate if string is a valid int.

    Examples::

        if is_int('wrong string'): ...

    :rtype: bool
    """
    try:
        int(string)
        return True
    except ValueError:
        return False


@staticmethod
def _prepare_for_group_by(record_store_with_group_by_rdd):
    """Creates a new rdd where:

        The first element of each row contains array of grouping
        key and event timestamp fields.

        Grouping key and event timestamp fields are used by
        partitioning and sorting function to partition the data
        by grouping key and then sort the elements in a group by the
        timestamp
        """
    record_store_data = record_store_with_group_by_rdd.record_store_data
    group_by_columns_list = (record_store_with_group_by_rdd.
        group_by_columns_list)
    group_by_key_value = ''
    for gcol in group_by_columns_list:
        group_by_key_value = '^'.join((group_by_key_value, '='.join((gcol,
            eval('.'.join(('record_store_data', gcol)))))))
    return [[group_by_key_value, record_store_data.event_timestamp_string],
        record_store_data]


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 get_inclusive_urls(urls, start, stop):
    """Yield URLs which are of the range [start, stop]"""
    in_range = False
    out_range = False
    for url in urls:
        if url in start or start in url:
            in_range = True
        if url in stop or stop in url:
            out_range = True
        if in_range:
            yield url
        if out_range:
            break


def p_trackitem(t):
    """trackitem : index
                 | isrc
                 | pregap
                 | postgap
                 | flags
                 | title
                 | performer
                 | songwriter"""
    t[0] = t[1]


@staticmethod
def _get_defaults_dict(key: str, value) ->dict:
    """
        Since we're allowing nested config stuff now, not storing the
        _defaults as a flat dict sounds like a good idea. May turn out
        to be an awful one but we'll see.
        """
    ret = {}
    partial = ret
    splitted = key.split('__')
    for i, k in enumerate(splitted, start=1):
        if not k.isidentifier():
            raise RuntimeError("'{}' is an invalid config key.".format(k))
        if i == len(splitted):
            partial[k] = value
        else:
            partial[k] = {}
            partial = partial[k]
    return ret


@staticmethod
def identity(thing):
    """
        a single-input-single-output identity function
        """
    return thing


def get_one_veri_set_para_dims(one_veri_set_dict):
    """
    获取一种veri_set的等级的name  和shape
    :param one_veri_set_dict:   一个veri_set 的字典比如   {
            "name": "ts_bias",
            "method": ["ts", "bias"],
            "para1": [0.1, 5, 10, 20],
            "para1Name": ["小雨", ">=5毫米", ">=10毫米", ">=20毫米"],
            "plot_type": "bar"
        }
    :return:
    """
    shape = []
    coords = {}
    para1 = None
    if 'para1' in one_veri_set_dict.keys():
        para1 = one_veri_set_dict['para1']
        if para1 is not None:
            shape.append(len(para1))
            coords['para1'] = para1
    if 'para2' in one_veri_set_dict.keys():
        para2 = one_veri_set_dict['para2']
        if para1 is not None:
            shape.append(len(para2))
            coords['para2'] = para2
    return coords, shape


def top(root_ideal, start_index):
    """ Given a column index ``start_index``, look at it's :meth:`up_path` and return the final index.

        EXAMPLES:

        The picture below represents the root ideal ``ri``:

        .. image:: _static/root-ideal.JPG
            :width: 180px
            :align: center
            :alt: The root ideal [(0,2), (0,3), (0,4), (1,3), (1,4), (2,4)]

        ::

            sage: ri = RootIdeals().init_from_partition([3, 2, 1], 5)
            sage: ri.top(0)
            0
            sage: ri.top(1)
            1
            sage: ri.top(2)
            0
            sage: ri.top(3)
            1
            sage: ri.top(4)
            0

        ..  SEEALSO::

            :meth:`down`, :meth:`up`, :meth:`down_path`, :meth:`up_path`, :meth:`bottom`
        """
    return root_ideal.up_path(start_index)[-1]


def difference_pyramid(pyr, inplace=False):
    """Difference between levels of a derivative of gaussian pyramid

    :param d: gaussian pyramid
    :param inplace: bool, do the work in place or make a copy, default False
    :return: list of differences

    The output has length one less than the input
    diff_pyr = [pyr[0] - pyr[1], pyr[1] - pyr[2], ..., pyr[N-2] - pyr[N-1]]
    """
    N = len(pyr)
    if type(pyr[0]) == list:
        M = len(pyr[0])
    else:
        M = 1
    if inplace:
        output = pyr
    elif M > 1:
        output = [[None] * M] * N
    else:
        output = [None] * N
    for n in range(N - 1):
        if M > 1:
            for m in range(M):
                output[n][m] = pyr[n][m] - pyr[n + 1][m]
        else:
            output[n] = pyr[n] - pyr[n + 1]
    output = output[:-1]
    return output


@staticmethod
def _repr_iterable_item(obj_type: str, prefix: str, indent: int,
    no_indent_start: bool, result: str, suffix: str) ->str:
    """Repr iterable item.

        :param obj_type: Object type
        :type obj_type: str
        :param prefix: prefix
        :type prefix: str
        :param indent: start indentation
        :type indent: int
        :param no_indent_start: do not indent open bracket and simple parameters
        :type no_indent_start: bool
        :param result: result of pre-formatting
        :type result: str
        :param suffix: suffix
        :type suffix: str
        :return: formatted repr of "result" with prefix and suffix to explain type.
        :rtype: str
        """
    return f"""{'':<{indent if not no_indent_start else 0}}{obj_type}({prefix}{result}
{'':<{indent}}{suffix})"""


def exact_filter(query, model, filters):
    """Applies exact match filtering to a query.

    Returns the updated query.  Modifies filters argument to remove
    filters consumed.

    :param query: query to apply filters to
    :param model: model object the query applies to, for IN-style
                  filtering
    :param filters: dictionary of filters; values that are lists,
                    tuples, sets, or frozensets cause an 'IN' test to
                    be performed, while exact matching ('==' operator)
                    is used for other values
    """
    filter_dict = {}
    if filters is None:
        filters = {}
    for key, value in filters.items():
        if isinstance(value, (list, tuple, set, frozenset)):
            column_attr = getattr(model, key)
            query = query.filter(column_attr.in_(value))
        else:
            filter_dict[key] = value
    if filter_dict:
        query = query.filter_by(**filter_dict)
    return query


def filter_dict(lam, bigZ, bigZlag):
    """
    Dictionary of spatially filtered variables for use in SUR

    Parameters
    ----------
    lam        : array
                 n_eq x 1 array of spatial autoregressive parameters
    bigZ       : dictionary
                 of vector or matrix of variables, one for
                 each equation
    bigZlag    : dictionary
                 of vector or matrix of spatially lagged
                 variables, one for each equation

    Returns
    -------
    Zfilt      : dictionary
                 with spatially filtered variables
                 Z - lam*WZ, one for each equation

    """
    n_eq = lam.shape[0]
    if not (len(bigZ.keys()) == n_eq and len(bigZlag.keys()) == n_eq):
        raise Exception('Error: incompatible dimensions')
    Zfilt = {}
    for r in range(n_eq):
        lami = lam[r][0]
        Zfilt[r] = bigZ[r] - lami * bigZlag[r]
    return Zfilt


def create_route_table(DryRun=None, VpcId=None):
    """
    Creates a route table for the specified VPC. After you create a route table, you can add routes and associate the table with a subnet.
    For more information about route tables, see Route Tables in the Amazon Virtual Private Cloud User Guide .
    See also: AWS API Documentation

    Examples
    This example creates a route table for the specified VPC.
    Expected Output:

    :example: response = client.create_route_table(
        DryRun=True|False,
        VpcId='string'
    )

    :type DryRun: boolean
    :param DryRun: Checks whether you have the required permissions for the action, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation . Otherwise, it is UnauthorizedOperation .

    :type VpcId: string
    :param VpcId: [REQUIRED]
            The ID of the VPC.

    :rtype: dict
    :return: {
        'RouteTable': {
            'RouteTableId': 'string',
            'VpcId': 'string',
            'Routes': [
                {
                    'DestinationCidrBlock': 'string',
                    'DestinationPrefixListId': 'string',
                    'GatewayId': 'string',
                    'InstanceId': 'string',
                    'InstanceOwnerId': 'string',
                    'NetworkInterfaceId': 'string',
                    'VpcPeeringConnectionId': 'string',
                    'NatGatewayId': 'string',
                    'State': 'active'|'blackhole',
                    'Origin': 'CreateRouteTable'|'CreateRoute'|'EnableVgwRoutePropagation',
                    'DestinationIpv6CidrBlock': 'string',
                    'EgressOnlyInternetGatewayId': 'string'
                },
            ],
            'Associations': [
                {
                    'RouteTableAssociationId': 'string',
                    'RouteTableId': 'string',
                    'SubnetId': 'string',
                    'Main': True|False
                },
            ],
            'Tags': [
                {
                    'Key': 'string',
                    'Value': 'string'
                },
            ],
            'PropagatingVgws': [
                {
                    'GatewayId': 'string'
                },
            ]
        }
    }

    :returns:
    CreateRouteTable - The route was automatically created when the route table was created.
    CreateRoute - The route was manually added to the route table.
    EnableVgwRoutePropagation - The route was propagated by route propagation.

    """
    pass


def flatten_list(node):
    """
    List of expressions may be nested in groups of 32 and 1024
    items. flatten that out and return the list
    """
    flat_elems = []
    for elem in node:
        if elem == 'expr1024':
            for subelem in elem:
                assert subelem == 'expr32'
                for subsubelem in subelem:
                    flat_elems.append(subsubelem)
        elif elem == 'expr32':
            for subelem in elem:
                assert subelem == 'expr'
                flat_elems.append(subelem)
        else:
            flat_elems.append(elem)
            pass
        pass
    return flat_elems


def is_iterable(obj):
    """
    Checks whether the given object is an iterable by calling iter.
    :param obj: the object to check
    :return: true if the object is iterable
    """
    try:
        _ = iter(obj)
    except TypeError:
        return False
    else:
        return True


@staticmethod
def enable_undo():
    """
        Enables undo functionality
        """
    return False


@staticmethod
def metadata_id(item):
    """Extracts the identifier from a Git item."""
    return item['commit']


def removeServer(host, port, protocol):
    """ Remove a server definition

        Please note: I you remove the server definition of a server that
        is currently being used, that connection will continue to be
        used until it fails or until the Python process is restarted.
        """


def multi_send(ports, msg):
    """Send message on all ports."""
    for port in ports:
        port.send(msg)


def complex_to_fastpm(fn, ds, complex, BoxSize):
    """
        >>> c = numpy.fft.rfftn(numpy.random.normal(size=(128, 128, 128)))

        >>> complex_to_fastpm("IC", "Copy", c, 128.)

        >>> a = bigfile.BigFile("IC")['Copy'][:]
        >>> print(a[1], c.ravel()[1])
        >>> print(a[300], c.ravel()[300])
    """
    import bigfile
    import numpy
    bf = bigfile.BigFile(fn, create=True)
    bb = bf.create(ds, complex.dtype, complex.size, Nfile=1)
    Nmesh = complex.shape[0]
    bb.attrs['Nmesh'] = Nmesh
    bb.attrs['BoxSize'] = BoxSize
    bb.write(0, complex)
    bb.attrs['ndarray.ndim'] = 3
    bb.attrs['ndarray.shape'] = Nmesh, Nmesh, Nmesh // 2 + 1
    bb.attrs['ndarray.strides'] = Nmesh * (Nmesh // 2 + 1), Nmesh // 2 + 1, 1


def stub_string():
    """Returns an empty string.

    Returns:
        str: Empty string

    Example:

        >>> stub_string()
        ''

    .. versionadded:: 4.0.0
    """
    return ''


def fint(str_val):
    """ try to convert to int, then float if fails, then return None. """
    for f in [int, float]:
        try:
            return f(str_val)
        except (ValueError, TypeError):
            pass


def assign(username):
    """Add/assign a user (login) name to group"""


def clean_whitespace(string, compact=False):
    """Return string with compressed whitespace."""
    for a, b in (('\r\n', '\n'), ('\r', '\n'), ('\n\n', '\n'), ('\t', ' '),
        ('  ', ' ')):
        string = string.replace(a, b)
    if compact:
        for a, b in (('\n', ' '), ('[ ', '['), ('  ', ' '), ('  ', ' '), (
            '  ', ' ')):
            string = string.replace(a, b)
    return string.strip()


def calculate_expected_value(DataFrame, predicted_variable,
    probability_variable, ev_variable='EV'):
    """
    ev = predicted_value * probability

    Parameters
    ----------
    DataFrame:
    predicted_variable:
    probability_variable:

    Returns
    -------
    DataFrame

    """
    DataFrame[ev_variable] = DataFrame[predicted_variable] * DataFrame[
        probability_variable]
    return DataFrame


def _check_cpd_inputs(X, rank):
    """Checks that inputs to optimization function are appropriate.

    Parameters
    ----------
    X : ndarray
        Tensor used for fitting CP decomposition.
    rank : int
        Rank of low rank decomposition.

    Raises
    ------
    ValueError: If inputs are not suited for CP decomposition.
    """
    if X.ndim < 3:
        raise ValueError('Array with X.ndim > 2 expected.')
    if rank <= 0 or not isinstance(rank, int):
        raise ValueError('Rank is invalid.')


def add_attr2attributes(element, attributes, prefix=None):
    """
    Add attributes of elements to 'attributes' dictionary.
    :param element:
    :param attributes:
    :param prefix:
    :return:
    """
    attr = element.get('attr')
    if attr is not None:
        for key, value in attr.items():
            if prefix is None:
                dict_key = key
            else:
                dict_key = prefix + key[0].upper() + key[1:]
            if value.isdigit():
                attributes[dict_key] = int(value)
            else:
                attributes[dict_key] = value


def truncate_string_from_end(string: str, max_len: int) ->str:
    """If the string len is below the max_len, the function returns the same string.
	If the string is above the max len, the function returns only the last max_len characters plus '...' at the beginning."""
    if len(string) <= max_len:
        return string
    return f'Last {max_len} chars: "...{string[-max_len:]}"'


def blank(path):
    """ Return an empty request object (see
        :meth:`pyramid.request.Request.blank`)"""


def leap_year(gyear):
    """Determine if this is a Gregorian leap year.

    Parameters
    ----------
    gyear : int
        Gregorian year.

    Returns
    -------
    leap_year : bool
        True if a Gregorian leap year, else False.
    """
    mod1 = gyear % 4 == 0
    mod2 = True
    if gyear % 100 == 0:
        mod2 = gyear % 400 == 0
    leap_year = False
    if mod1 and mod2:
        leap_year = True
    return leap_year


@staticmethod
def _update_headers(headers, token):
    """Updates the Authorization header with the bearer token.

        :param dict headers: The HTTP Request headers
        :param str token: The OAuth token.
        """
    headers['Authorization'] = 'Bearer {}'.format(token)


def getFields():
    """Return list of language independent fields"""


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 fmtfloat(n, decimals=3, total=None):
    """Work around borken python float formatting"""
    s = '%0.*f' % (decimals, n)
    if total:
        s = (' ' * total + s)[-total:]
    return s


@staticmethod
def _check_quantile_range(quantile_range):
    """
        Checks for the validity of quantile_range.
        """
    if not isinstance(quantile_range, tuple) and not isinstance(quantile_range,
        list):
        raise TypeError('quantile_range must be a tuple or a list')
    if len(quantile_range) != 2:
        raise ValueError(
            'quantile_range must contain 2 elements: min_quantile and max_quantile'
            )
    min_quantile, max_quantile = quantile_range
    for quantile in (min_quantile, max_quantile):
        if not isinstance(quantile, float) and not isinstance(quantile, int):
            raise TypeError('min_quantile and max_quantile must be numbers')
        if quantile < 0 or 100 < quantile:
            raise ValueError(
                'min_quantile and max_quantile must be in [0; 100]')
    if min_quantile > max_quantile:
        raise ValueError(
            'min_quantile must be less than or equal to max_quantile')


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

    Like 'git describe --tags --dirty --always -long'.
    The distance/hash is unconditional.

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


def convert_title_to_id(title, doc_type, options):
    """
    Converts the human-readable title to an ID string.
    """
    if options['id_case'] in ['lowercase', 'lower-case', 'lower case']:
        converted_id = title.lower()
    elif options['id_case'] in ['capitalize', 'capitalise']:
        converted_id = title.capitalize()
    elif options['id_case'] in ['preserve', 'original']:
        converted_id = title
    else:
        print("Error: ID capitalization option not recognized: '{}'".format
            (options['id_case']))
        exit(1)
    subst_map = {' ': options['word_separator'], '(': '', ')': '', '?': '',
        '!': '', "'": '', '"': '', '#': '', '%': '', '&': '', '*': '', ',':
        '', '.': '-', '/': '-', ':': '-', ';': '', '@': '-at-', '\\': '',
        '`': '', '$': '', '^': '', '|': '', '[package]': '', '[option]': '',
        '[parameter]': '', '[variable]': '', '[command]': '',
        '[replaceable]': '', '[filename]': '', '[literal]': '',
        '[systemitem]': '', '[application]': '', '[function]': '', '[gui]':
        '', '[': '', ']': '', '{': '', '}': ''}
    for k in subst_map.keys():
        v = subst_map[k]
        converted_id = converted_id.replace(k, v)
    while '--' in converted_id:
        converted_id = converted_id.replace('--', '-')
    return converted_id


def statistic_by_interval(values, interval, statistic='mean'):
    """
    Calculates statistics from values across an interval.

    For example, to sum monthly data up to annual data: statistic_by_interval(monthy_values, 12, 'sum') => one entry per year

    :param values: values (must have 3 dimensions)
    :param interval: interval over which to sum  (e.g., 12 for summing months to year)
    :param statistic: one of 'mean', 'sum'
    :return: a numpy array with shape (values.shape[0] / interval, values.shape[1], values.shape[2])
    """
    if not statistic in ('mean', 'sum'):
        raise ValueError('Unsupported statistic {0}'.format(statistic))
    assert len(values.shape) == 3
    assert values.shape[0] % interval == 0
    num_intervals = int(values.shape[0] / interval)
    temp = values.reshape(num_intervals, interval, values.shape[1], values.
        shape[2])
    if statistic == 'mean':
        return temp[:, :interval, :, :].mean(axis=1)
    elif statistic == 'sum':
        return temp[:, :interval, :, :].sum(axis=1)


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 _powerString(s, npow, powchar='**', trailchar=''):
    """Raise string s to power npow with additional formatting."""
    if npow == 0:
        return ''
    elif npow == 1:
        return s + trailchar
    else:
        return s + powchar + str(npow) + trailchar


def auto_log(vmin, vmax):
    """
  Deduce whether the log scale should be used or not, judging from given range.

  >>> auto_log(0, 10)  # has zero, don't.
  False
  >>> auto_log(0.0, 1.0)  # has zero, don't.
  False
  >>> auto_log(-1.0, 1.0)  # has negative, don't.
  False
  >>> auto_log(1E-4, 1E1)  # positive & wide, do it.
  True
  >>> auto_log(10, 50)  # arbitary, don't
  False

  >>> ## If both are not initialize (e.g., null-stats), return None
  >>> ## in order to have same default as QHist.xlog
  >>> auto_log( 10, None ) is None
  True
  >>> auto_log( None, 100 ) is None
  True
  >>> auto_log( None, None ) is None
  True

  """
    if vmin is None or vmax is None:
        return None
    if vmin == 0.0 and vmax == 1.0:
        return False
    if vmin <= 0:
        return False
    if vmax / vmin >= 100.0:
        return True
    return False


def getTranslationMutator(instance):
    """Return a mutator for translatable values"""


def zip_has_files(files, zip_file):
    """
    Return True if zip has the files inside.

    Parameters
    ----------
    files : list of str
        files inside zip file
    zip_file : :py:class:`zipfile.ZipFile`

    Returns
    -------
    bool :
        True if files inside of `:py:meth:`zipfile.ZipFile.namelist()`
    """
    if set(files).issubset(set(zip_file.namelist())):
        return True
    else:
        return False


@classmethod
def adapt_emulated_to_native(cls, impl, **kw):
    """Given an impl, adapt this type's class to the impl assuming "native".

        The impl will be an :class:`.Emulated` class but not a
        :class:`.NativeForEmulated`.

        e.g.: postgresql.ENUM produces a type given an Enum instance.

        """
    return cls(**kw)


def contains_any(big, little):
    """Return True if big contains any element from little,
       False otherwise.
    """
    for x in little:
        if x in big:
            return True
    return False


def pyx_is_cplus(path):
    """
    Inspect a Cython source file (.pyx) and look for comment line like:

    # distutils: language = c++

    Returns True if such a file is present in the file, else False.
    """
    for line in open(path, 'rt'):
        if line.startswith('#') and '=' in line:
            splitted = line.split('=')
            if len(splitted) != 2:
                continue
            lhs, rhs = splitted
            if lhs.strip().split()[-1].lower() == 'language' and rhs.strip(
                ).split()[0].lower() == 'c++':
                return True
    return False


@classmethod
def action(cls, walkers, decisions):
    """Perform the instructions for a set of resampling records on
        walkers."""
    raise NotImplementedError


def format_timestamp(dt):
    """
    Format the given timestamp.

    :param datetime.datetime dt: A datetime.datetime object to be formatted.
    """
    return dt.strftime('%Y-%m-%dT%H:%M:%S.999-05:00')


def get_wikidata_csl_item(identifier):
    """
    Get a CSL JSON item with the citation metadata for a Wikidata item.
    identifier should be a Wikidata item ID corresponding to a citeable
    work, such as Q50051684.
    """
    url = f'https://www.wikidata.org/wiki/{identifier}'
    from manubot.cite.url import get_url_csl_item_zotero
    csl_item = get_url_csl_item_zotero(url)
    if 'DOI' in csl_item:
        csl_item['DOI'] = csl_item['DOI'].lower()
    if 'URL' not in csl_item:
        csl_item['URL'] = url
    return csl_item


def escape_spaces(text):
    """
    Escape spaces in the specified text

    .. note:: :func:`pipes.quote` should be favored where possible.
    """
    return text.replace(' ', '\\ ')


def normalise_kmer_frequency(observed, reference):
    """Normalize kmer counts - divide observed with reference counts."""
    normalised = {}
    for kmer, count in observed.items():
        try:
            normalised[kmer] = count / reference[kmer] * 10 ** 6
        except ZeroDivisionError:
            normalised[kmer] = count * 10 ** 6
    return normalised


def get_skip(x, y, di):
    """calculates a new (x, y) pair for after an arrow head"""
    return x + di[0] * 3, y + di[1] * 3


def get_initial_path_helper(node):
    """Compute the initial path label of a node recursively."""
    if node.parent == None:
        return ''
    else:
        return node.parent.get_path() + node.edge_label[0]


def paste_tracks():
    """Paste tracks from clipboard

    """
    pass


def get_step_g(step_f, norm_L2, N=1, M=1):
    """Get step_g compatible with step_f (and L) for ADMM, SDMM, GLMM.
    """
    return step_f * norm_L2 * N * M


@staticmethod
def comment_measure_numbers(score):
    """
        Comments measure numbers in ``score``.
        """
    import abjad
    offset_to_measure_number = {}
    for context in abjad.iterate(score).components(abjad.Context):
        if not context.simultaneous:
            break
    site = 'abjad.SegmentMaker.comment_measure_numbers()'
    measures = abjad.select(context).leaves().group_by_measure()
    for i, measure in enumerate(measures):
        measure_number = i + 1
        first_leaf = abjad.select(measure).leaf(0)
        start_offset = abjad.inspect(first_leaf).timespan().start_offset
        offset_to_measure_number[start_offset] = measure_number
    for leaf in abjad.iterate(score).leaves():
        offset = abjad.inspect(leaf).timespan().start_offset
        measure_number = offset_to_measure_number.get(offset, None)
        if measure_number is None:
            continue
        context = abjad.inspect(leaf).parentage().get(abjad.Context)
        if context.name is None:
            string = f'% [{context.lilypond_type} measure {measure_number}]'
        else:
            string = f'% [{context.name} measure {measure_number}]'
        literal = abjad.LilyPondLiteral(string, 'absolute_before')
        tag = abjad.Tag('COMMENT_MEASURE_NUMBERS').append(site)
        abjad.attach(literal, leaf, tag=tag)


def redirect_form(end_point, token):
    """Generate a redirect form for POSTing"""
    return (
        """
<html>
<head>
  <title>OpenID transaction in progress</title>
</head>
<body onload="document.forms[0].submit();">
<form action="%s" method="post" accept-charset="UTF-8"
 enctype="application/x-www-form-urlencoded">
<input type="hidden" name="token" value="%s" />
<input type="submit" value="Continue"/></form>
<script>
var elements = document.forms[0].elements;
for (var i = 0; i < elements.length; i++) {
  elements[i].style.display = "none";
}
</script>
</body>
</html>
"""
         % (end_point, token))


def load_op(onnx_node, desc=None, options=None, variables=None, dtype=None):
    """
    Sets up a class for a specific ONNX operator.

    @param      onnx_node       :epkg:`onnx` node
    @param      desc            internal representation
    @param      options         runtime options
    @param      variables       registered variables created by previous operators
    @param      dtype           float computational type
    @return                     runtime class
    """
    if desc is None:
        raise ValueError('desc should not be None.')
    if options is None:
        provider = 'python'
    else:
        provider = options.get('provider', 'python')
        if 'provider' in options:
            options = options.copy()
            del options['provider']
    if provider == 'python':
        from .ops_cpu import load_op as lo
        return lo(onnx_node, desc=desc, options=options)
    elif provider == 'onnxruntime2':
        from .ops_onnxruntime import load_op as lo
        return lo(onnx_node, desc=desc, options=options, variables=
            variables, dtype=dtype)
    else:
        raise ValueError("Unable to handle provider '{}'.".format(provider))


def get_port():
    """Returns a port number."""
    return 0


def formula_2002(foyer_fiscal, period, parameters):
    """
        Crédit d’impôt représentatif de la taxe additionnelle au droit de bail (case 4TQ)
        2002-
        """
    f4tq = foyer_fiscal('f4tq', period)
    P = parameters(period).impot_revenu.credits_impot.drbail
    return P.taux * f4tq


def sort_mixed_list(iterable):
    """
    Sort a list of strings and other objects:
    put the strings first and the others last

    Parameters
    ----------
    iterable : list

    Returns
    -------
    list
    """
    strings = []
    others = []
    for elem in iterable:
        if isinstance(elem, str):
            strings.append(elem)
        else:
            others.append(elem)
    res = strings + others
    return res


def _clitable_to_dict(cli_table):
    """Convert TextFSM cli_table object to list of dictionaries."""
    objs = []
    for row in cli_table:
        temp_dict = {}
        for index, element in enumerate(row):
            temp_dict[cli_table.header[index].lower()] = element
        objs.append(temp_dict)
    return objs


@staticmethod
def parse(sentence, scope, tnorm=None, snorm=None, cnorm=None):
    """
        Parse a str-rule with given scope and norms
        """
    from rules.parser import parse_rule
    return parse_rule(sentence, scope, tnorm, snorm, cnorm)


@staticmethod
def build_header_table(frequent):
    """
        Build the header table.
        """
    headers = {}
    for key in frequent.keys():
        headers[key] = None
    return headers


@staticmethod
def _transaction_abort(transaction_id, **kwargs):
    """Abort a transaction and roll back all operations.
        :param transaction_id: ID of transaction to be aborted.
        :param **kwargs: Further parameters for the transport layer.
        """
    raise NotImplementedError('Transport interface not implemented')


def on_key_event(text):
    """ Print the current text. """
    print('Current text:', text)


def str_val(arg: str) ->dict:
    """Creates the dictionary describing given string value.

    :param arg: String value
    :return: {Str: str}
    """
    return {'Str': arg}


def get_laplacian(qns):
    """Return the matrix representation of the laplacian for the
        specified quantum numbers.

        This should be a 2-dimensional array (matrix) whose indices can
        be reshaped if needed.
        """


def build_instance(Model, data, db):
    """
    Build a model instance.

    If the model instance doesn't have a primary key and the model supports
    natural keys, try to retrieve it from the database.
    """
    obj = Model(**data)
    if obj.pk is None and hasattr(Model, 'natural_key') and hasattr(Model.
        _default_manager, 'get_by_natural_key'):
        natural_key = obj.natural_key()
        try:
            obj.pk = Model._default_manager.db_manager(db).get_by_natural_key(*
                natural_key).pk
        except Model.DoesNotExist:
            pass
    return obj


def add_group_bonds(data_setters, bond_indices, bond_orders):
    """Add the bonds for this group.
    :param data_setters the class to push the data to
    :param bond_indices the indices of the atoms in the group that
    are bonded (in pairs)
    :param bond_orders the orders of the bonds"""
    for bond_index in range(len(bond_orders)):
        data_setters.set_group_bond(bond_indices[bond_index * 2],
            bond_indices[bond_index * 2 + 1], bond_orders[bond_index])


def selected(zelf, *args, **kwargs):
    """ list of desired objects. """
    if args:
        parsed = args[0]
    else:
        parsed = zelf.parsed
    if not parsed.args:
        return []
    if 'exclude' in kwargs:
        exclude = kwargs['exclude']
    else:
        exclude = None
    if 'exclude' in parsed.args:
        parsed.args.remove(exclude)
    if 'time' in parsed.wanted:
        kwargs['time'] = parsed.wanted.time
    objs = []
    result = []
    nr = -1
    for obj in zelf.objects(**kwargs):
        nr += 1
        if not obj.check_wanted(parsed.wanted):
            continue
        if not obj.selector(parsed.args):
            continue
        if obj.check_notwanted(parsed.not_wanted):
            continue
        if 'uniq' in parsed.switch:
            if obj[parsed.switch['uniq']] in result:
                continue
            else:
                result.append(obj[parsed.switch['uniq']])
        if 'index' in parsed and nr == parsed.index:
            return [obj]
        objs.append(obj)
    return objs


def cdriver2commtype(driver):
    """Convert a connection driver to a file type.

    Args:
        driver (str): The name of the connection driver.

    Returns:
        str: The corresponding file type for the driver.

    """
    _legacy = {'InputDriver': 'default', 'OutputDriver': 'default',
        'ZMQInputDriver': 'zmq', 'ZMQOutputDriver': 'zmq', 'IPCInputDriver':
        'ipc', 'IPCOutputDriver': 'ipc', 'RMQInputDriver': 'rmq',
        'RMQOutputDriver': 'rmq', 'RMQAsyncInputDriver': 'rmq_async',
        'RMQAsyncOutputDriver': 'rmq_async'}
    if driver in _legacy:
        return _legacy[driver]
    raise ValueError("Unknown driver: '%s'" % driver)


def importer(name):
    """Handles strange import cases, like pxssh which might show
    up in eithr the package pexpect or pxssh.
    """
    if name == 'pxssh':
        try:
            import pxssh
        except ImportError:
            try:
                from pexpect import pxssh
            except ImportError:
                raise ImportError('pxssh not found!')
        return pxssh
    elif name == 'NeighborList':
        try:
            from ase.neighborlist import NeighborList
        except ImportError:
            from ase.calculators.neighborlist import NeighborList
        return NeighborList


def p_asg_rule(p):
    """asg_item : RULE '(' INTEGER ',' STRING trap ')' rule_body
    """
    p[0] = 'RULE', p[3], p[5], p[6], p[8]


def reassign_inputs():
    """Reassign the inputs for the effect strip

    """
    pass


def _check_keys(data, keys):
    """Verify that the given data dict contains the specified keys."""
    for key in keys:
        if not key in data:
            msg = 'missing %s in data - %s' % (key, str(data.keys()))
            raise ValueError(msg)


def get_dry_info(dry_distro, name):
    """
    Get information about dry stacks
    """
    dry_stacks = dry_distro.get_stacks(True)
    if name in dry_stacks:
        stack = dry_stacks[name]
        if stack.vcs_config.type == 'svn':
            return (name, stack.vcs_config.release_tag, stack.vcs_config.
                type, None)
        else:
            return (name, stack.vcs_config.anon_repo_uri, stack.vcs_config.
                type, stack.vcs_config.release_tag)
    return None


def fetchiter(cursor, size=1000, batch=False, server_cursor=None):
    """
    Use a generator as an iterator for fetching large db record sets.

    Example:
      for row in fetchiter(cursor):
        ...

    Only for PostgreSQL
    -------------------
    You can use a previous server cursor declared as:
    `DECLARE {C} CURSOR FOR SELECT * FROM ...` where {C} is a string with the
    server cursor name.

    Then use the parameter server_cursor={C} where {C} is the cursor name,
    this will make each iteration runs `FETCH {size} FROM {C}` instead of the
    whole query.
    """
    while True:
        if server_cursor is None:
            results = cursor.fetchmany(size)
        else:
            cursor.execute('FETCH %s FROM {}'.format(server_cursor), (size,))
            results = cursor.fetchall()
        if not results:
            break
        if batch:
            yield results
        else:
            for result in results:
                yield result


def sub(w=3.5, h=2, s=0.3):
    """ Create flowchart subprocess (block with extra vertical lines)

        Parameters
        ----------
        w: float
            Width of box
        h: float
            Height of box
        s: float
            Spacing of side lines

        Anchors: N, S, E, W
    """
    elem = {'name': 'FLOWSUB', 'extend': False, 'lblloc': 'center',
        'lblofst': 0, 'theta': -90}
    elem['paths'] = [[[0, 0], [0, w / 2], [h, w / 2], [h, -w / 2], [0, -w /
        2], [0, 0]], [[0, w / 2 - s], [h, w / 2 - s]], [[0, -w / 2 + s], [h,
        -w / 2 + s]]]
    elem['anchors'] = {'W': [h / 2, -w / 2], 'E': [h / 2, w / 2], 'S': [h,
        0], 'N': [0, 0]}
    elem['drop'] = [h, 0]
    return elem


def gsreshaped(data):
    """
    gridsearch reshape values according to GridSearchCV.fit

    see https://stackoverflow.com/a/49241326
    """
    import pandas as pd
    import numpy as np
    if isinstance(data, (pd.Series, pd.DataFrame)):
        if len(data.shape) == 2 and data.shape[1] == 1:
            data = data.values.reshape(-1)
    elif isinstance(data, np.ndarray):
        if len(data.shape) == 2 and data.shape[1] == 1:
            data = data.reshape(-1)
    return data


def getWidgetById(form, id):
    """Get a widget by it's rendered DOM element id."""
    name = id.replace('-', '.')
    prefix = form.prefix + form.widgets.prefix
    if not name.startswith(prefix):
        raise ValueError('Name %r must start with prefix %r' % (name, prefix))
    shortName = name[len(prefix):]
    return form.widgets.get(shortName, None)


def get_original_route(urlpattern):
    """
    Get the original route/regex that was typed in by the user into the path(), re_path() or url() directive. This
    is in contrast with get_regex_pattern below, which for RoutePattern returns the raw regex generated from the path().
    """
    if hasattr(urlpattern, 'pattern'):
        return str(urlpattern.pattern)
    else:
        return urlpattern.regex.pattern


def monitorDocFromRequestSchema(schema):
    """
    prun and convert
    """
    doc = {}
    doc['_id'] = schema['RequestName']
    doc['workflow'] = schema['RequestName']
    doc['requestor'] = schema['Requestor']
    doc['campaign'] = schema['Campaign']
    doc['request_type'] = schema['RequestType']
    doc['priority'] = schema['RequestPriority']
    doc['group'] = schema['Group']
    doc['request_date'] = schema['RequestDate']
    doc['type'] = 'reqmgr_request'
    doc['inputdataset'] = schema.get('InputDataset', '')
    doc['vo_group'] = schema.get('VoGroup', '')
    doc['vo_role'] = schema.get('VoRole', '')
    doc['user_dn'] = schema.get('RequestorDN', '')
    doc['async_dest'] = schema.get('asyncDest', '')
    doc['dbs_url'] = schema.get('DbsUrl', '')
    doc['publish_dbs_url'] = schema.get('PublishDbsUrl', '')
    doc['outputdatasets'] = schema.get('OutputDatasets', [])
    doc['cmssw'] = schema.get('CMSSWVersion', [])
    doc['prep_id'] = schema.get('PrepID', None)
    return doc


def measure_type(x):
    """Takes Numeric Code and returns String API code

    Input Values: 1:"Base", 2:"Advanced", 3:"Misc", 4:"Four Factors", 5:"Scoring", 6:"Opponent", 7:"Usage"

    Used in:

    """
    measure = {(1): 'Base', (2): 'Advanced', (3): 'Misc', (4):
        'Four Factors', (5): 'Scoring', (6): 'Opponent', (7): 'Usage'}
    try:
        return measure[x]
    except:
        raise ValueError('Please enter a number between 1 and ' + str(len(
            measure)))


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 message_delete(transport, request, queue_name, message_id, claim_id=
    None, callback=None):
    """Deletes messages from `queue_name`

    :param transport: Transport instance to use
    :type transport: `transport.base.Transport`
    :param request: Request instance ready to be sent.
    :type request: `transport.request.Request`
    :param queue_name: Queue reference name.
    :type queue_name: `six.text_type`
    :param message_id: Message reference.
    :param message_id: `six.text_type`
    :param callback: Optional callable to use as callback.
        If specified, this request will be sent asynchronously.
        (IGNORED UNTIL ASYNC SUPPORT IS COMPLETE)
    :type callback: Callable object.
    """
    request.operation = 'message_delete'
    request.params['queue_name'] = queue_name
    request.params['message_id'] = message_id
    if claim_id:
        request.params['claim_id'] = claim_id
    transport.send(request)


@classmethod
def setdefault(cls, key, value):
    """ Allows to define default values
        """
    cls.defaults[key] = value


def update_server_engine_attributes(ServerName=None, AttributeName=None,
    AttributeValue=None):
    """
    Updates engine-specific attributes on a specified server. The server enters the MODIFYING state when this operation is in progress. Only one update can occur at a time. You can use this command to reset the Chef server's private key (CHEF_PIVOTAL_KEY ).
    This operation is asynchronous.
    This operation can only be called for servers in HEALTHY or UNHEALTHY states. Otherwise, an InvalidStateException is raised. A ResourceNotFoundException is thrown when the server does not exist. A ValidationException is raised when parameters of the request are not valid.
    See also: AWS API Documentation

    :example: response = client.update_server_engine_attributes(
        ServerName='string',
        AttributeName='string',
        AttributeValue='string'
    )

    :type ServerName: string
    :param ServerName: [REQUIRED]
            The name of the server to update.

    :type AttributeName: string
    :param AttributeName: [REQUIRED]
            The name of the engine attribute to update.

    :type AttributeValue: string
    :param AttributeValue: The value to set for the attribute.

    :rtype: dict
    :return: {
        'Server': {
            'AssociatePublicIpAddress': True|False,
            'BackupRetentionCount': 123,
            'ServerName': 'string',
            'CreatedAt': datetime(2015, 1, 1),
            'CloudFormationStackArn': 'string',
            'DisableAutomatedBackup': True|False,
            'Endpoint': 'string',
            'Engine': 'string',
            'EngineModel': 'string',
            'EngineAttributes': [
                {
                    'Name': 'string',
                    'Value': 'string'
                },
            ],
            'EngineVersion': 'string',
            'InstanceProfileArn': 'string',
            'InstanceType': 'string',
            'KeyPair': 'string',
            'MaintenanceStatus': 'SUCCESS'|'FAILED',
            'PreferredMaintenanceWindow': 'string',
            'PreferredBackupWindow': 'string',
            'SecurityGroupIds': [
                'string',
            ],
            'ServiceRoleArn': 'string',
            'Status': 'BACKING_UP'|'CONNECTION_LOST'|'CREATING'|'DELETING'|'MODIFYING'|'FAILED'|'HEALTHY'|'RUNNING'|'RESTORING'|'SETUP'|'UNDER_MAINTENANCE'|'UNHEALTHY'|'TERMINATED',
            'StatusReason': 'string',
            'SubnetIds': [
                'string',
            ],
            'ServerArn': 'string'
        }
    }

    :returns:
    CHEF_PIVOTAL_KEY : A base64-encoded RSA private key that is generated by AWS OpsWorks for Chef Automate. This private key is required to access the Chef API.
    CHEF_STARTER_KIT : A base64-encoded ZIP file. The ZIP file contains a Chef starter kit, which includes a README, a configuration file, and the required RSA private key. Save this file, unzip it, and then change to the directory where you've unzipped the file contents. From this directory, you can run Knife commands.

    """
    pass


def handle(*objects):
    """Call all of the handlers for the given objects

        Handlers are subscription adapter factories that don't produce
        anything.  They do all of their work when called.  Handlers
        are typically used to handle events.

        """


def get_latex_for_string(txt):
    """Convert to LaTeX form for the dummy back end.

    Parameters
    ----------
    txt : str
        The text component in LaTeX form (e.g. r'lpha^2'). It
        should not contain any non-LaTeX content.

    Returns
    -------
    latex : str
        The input text (i.e. no change).

    """
    return txt


def properties():
    """Toggle the properties region visibility

    """
    pass


@staticmethod
def getJavaPackage():
    """ Returns package name String. """
    return 'com.microsoft.ml.spark.cognitive.NER'


def files_handler(ctx, param, value):
    """Process and validate input file names"""
    return value


def FITSFile(ID, season, cadence='lc'):
    """
  Returns the name of the FITS file for a given target.

  :param ID: The target ID
  :param int season: The target season number
  :param str cadence: The cadence type. Default `lc`

  """
    raise NotImplementedError('This mission is not yet supported.')


@classmethod
def JungePowerLawDistribution(cls, rmin, rmax):
    """Set 6S to use a Junge Power Law distribution.

        Arguments:

        * ``rmin`` -- The minimum aerosol radius
        * ``rmax`` -- The maximum aerosol radius

        This returns an :class:`.AerosolDistribution` object. Components can then be added to this distribution using the :meth:`.add_component`
        method of the returned class.

        Example usage::

          s.aeroprofile = AeroProfile.JungePowerLawDistribution(0.1, 0.3)
          s.aeroprofile.add_component(...)

        """
    return cls.AerosolDistribution(rmin, rmax, 10)


def getFormatter(category, length=None, name=u''):
    """Get the NumberFormat based on the category, length and name of the
        format.

        The 'category' specifies the type of number format you would like to
        have. The available options are: 'decimal', 'percent', 'scientific',
        'currency'.

        The 'length' specifies the output length of the number. The allowed
        values are: 'short', 'medium', 'long' and 'full'. If no length was
        specified, the default length is chosen.

        Every length can have actually several formats. In this case these
        formats are named and you can specify the name here. If no name was
        specified, the first unnamed format is chosen.
        """


@staticmethod
def p_project_no(p):
    """project_no : PROJECT_NO IDENT"""
    p[0] = p[2]


def tilt_correct(number):
    """Changes an angle (in degrees) so that it is between 0º and 90º"""
    if number < 90.0:
        return number
    else:
        return 180.0 - number


def get_attr_order(model):
    """ Get the names of attributes in the order they should appear in ER diagrams

    Args:
        model (:obj:`type`): model

    Returns:
        :obj:`list` of :obj:`str`: names of attributes in the order they should appear in ER diagrams
    """
    attrs = list(model.Meta.attribute_order)
    attrs += sorted(set(model.Meta.attributes.keys()) - set(attrs))
    return attrs


@classmethod
def clean_pair(cls, attribute, value):
    """
    This will call `clean_attribute` on the attribute and also allows for the
    creation of boolean attributes.

    Ex. input(selected=True) is equivalent to input(selected="selected")
    """
    attribute = cls.clean_attribute(attribute)
    if value is True:
        value = attribute
    return attribute, value


@classmethod
def parse_buffer(cls, bfr, **kw):
    """ Function to parse repeated instances of `cls` from the buffer `bfr`
        until end of input.
    """
    while not bfr.at_eof():
        yield cls.from_buffer(bfr, **kw)


def locatie_element_adapter(obj, request=None):
    """
    Adapter for rendering
    :class:`oe_geoutils.data.models.LocatieElement` to json.

    Add the adapter to `jsonpublish`
    from jsonpublish import register_adapter
    register_adapter(LocatieElement, locatie_element_adapter)

    Add the adapter to your :class:`pyramid.renderers.JSON` json_renderer
    from pyramid.renderers import JSON
    json_renderer = JSON()
    json_renderer.add_adapter(LocatieElement, locatie_element_adapter)
    """
    locatie_element = {'id': obj.id, 'type': obj.type, 'provincie': {
        'niscode': obj.provincie_niscode, 'naam': obj.provincie_naam},
        'gemeente': {'niscode': obj.gemeente_niscode, 'naam': obj.
        gemeente_naam, 'id': obj.gemeente_crab_id}, 'deelgemeente': {
        'niscode': obj.deelgemeente_niscode, 'naam': obj.deelgemeente_naam}}
    return locatie_element


def _format_status_field(status_information):
    """Format the *status* field.

    :param status_information: The various fields information
    :type status_information: :class:`collections.defaultdict`
    :returns: The updated status informations
    :rtype: :class:`collections.defaultdict`
    """
    status_information['status'] = ' '.join(status_information['status']
        ).capitalize()
    return status_information


@staticmethod
def check_backend() ->bool:
    """Check if the backend is available."""
    try:
        import pygatt
        return True
    except ImportError:
        return False


def wave_frequency_t(time_period):
    """Usage: Finding the wave frequency using time period.
    f=1/T"""
    return 1 / time_period


def as_array():
    """
        This function must return a 2D numpy.ndarray, containing the data.
        """
    return None


def lang_exists(cursor, lang):
    """Checks if language exists for db"""
    query = 'SELECT lanname FROM pg_language WHERE lanname = %(lang)s'
    cursor.execute(query, {'lang': lang})
    return cursor.rowcount > 0


def find_in_line(string, lines, start=0):
    """Find the next line index containing a given string"""
    for n, line in enumerate(lines[start:], start):
        if string in line:
            return n
    raise RuntimeError("Could not find line '{}' in lines".format(string))


@staticmethod
def calculate_new_length(gene_split, gene_results, hit):
    """
            Function for calcualting new length if the gene is split on
            several contigs
        """
    first = 1
    for split in gene_split[hit['sbjct_header']]:
        new_start = int(gene_results[split]['sbjct_start'])
        new_end = int(gene_results[split]['sbjct_end'])
        if first == 1:
            new_length = int(gene_results[split]['HSP_length'])
            old_start = new_start
            old_end = new_end
            first = 0
            continue
        if new_start < old_start:
            new_length = new_length + (old_start - new_start)
            old_start = new_start
        if new_end > old_end:
            new_length = new_length + (new_end - old_end)
            old_end = new_end
    return new_length


def describe_adjustment_types():
    """
    Describes the policy adjustment types for use with  PutScalingPolicy .
    See also: AWS API Documentation

    Examples
    This example describes the available adjustment types.
    Expected Output:

    :example: response = client.describe_adjustment_types()

    :rtype: dict
    :return: {
        'AdjustmentTypes': [
            {
                'AdjustmentType': 'string'
            },
        ]
    }

    """
    pass


@staticmethod
def wholelist(name, value, seq):
    """
        Accepts a field name, value, and a field list.  This function
        implements acceptance of all fields by never requesting a field be
        skipped, thus returns False for all input.

        :param name:
            The field name to inspect.
        :param value:
            The field's value.
        :param seq:
            The list of fields associated with the ``Role``.
        """
    return False


def data_by_class(data):
    """
    Organize `data` by class.

    Parameters
    ----------
    data : list of dicts
        Each dict contains the key `symbol_id` which is the class label.

    Returns
    -------
    dbc : dict
        mapping class labels to lists of dicts
    """
    dbc = {}
    for item in data:
        if item['symbol_id'] in dbc:
            dbc[item['symbol_id']].append(item)
        else:
            dbc[item['symbol_id']] = [item]
    return dbc


def __combine_windows(w1, w2):
    """
    Joins two windows (defined by tuple of slices) such that their maximum
    combined extend is covered by the new returned window.
    """
    res = []
    for s1, s2 in zip(w1, w2):
        res.append(slice(min(s1.start, s2.start), max(s1.stop, s2.stop)))
    return tuple(res)


def _draw_diamond(cr):
    """
    Helper function to draw diamond shape for shared and composite
    aggregations.
    """
    cr.move_to(20, 0)
    cr.line_to(10, -6)
    cr.line_to(0, 0)
    cr.line_to(10, 6)
    cr.close_path()


def load_mtx(mtx_file, cell_axis='row', gene_names=None, cell_names=None,
    sparse=None):
    """magic.io is deprecated. Please use scprep.io instead.
       Read more at http://scprep.readthedocs.io/
    """
    raise RuntimeError(
        'magic.io is deprecated. Please use scprep.io instead. Read more at http://scprep.readthedocs.io'
        , FutureWarning)


def iteritems(obj, **kwargs):
    """Use this only if compatibility with Python versions before 2.7 is
    required. Otherwise, prefer viewitems().
    """
    func = getattr(obj, 'iteritems', None)
    if not func:
        func = obj.items
    return func(**kwargs)


def get_wsgi_header(header):
    """Returns a WSGI compliant HTTP header.
    See https://www.python.org/dev/peps/pep-3333/#environ-variables for
    information from the spec.
    """
    return 'HTTP_{}'.format(header.upper().replace('-', '_'))


def run_script(input_file, script_name, interpreter='python'):
    """Run a script in the context of the input_file's directory,
    return the text output formatted to be included as an rst
    literal text block.
    """
    from paver.easy import sh
    from paver.path import path
    rundir = path(input_file).dirname()
    output_text = sh(
        'cd %(rundir)s && %(interpreter)s %(script_name)s 2>&1' % vars(),
        capture=True)
    response = '\n::\n\n\t$ %(interpreter)s %(script_name)s\n\t' % vars()
    response += '\n\t'.join(output_text.splitlines())
    while not response.endswith('\n\n'):
        response += '\n'
    return response


def _is_match_as_iterable(var, targ):
    """
    list, tuple とマッチ. dict, generatorは無視
    """
    if not (isinstance(var, (tuple, list)) or isinstance(targ, (tuple, list))):
        return False
    return tuple(var) == tuple(targ)


def map_decision(max_digitsum, num_decisions, digitsum):
    """Maps the domain to a number of decisions."""
    return num_decisions / (float(max_digitsum) + 1) * (float(digitsum) + 1)


def zerocopy_from_numpy(np_array):
    """Create a tensor that shares the numpy array.

    Parameters
    ----------
    np_array : numpy.ndarray
        The numpy ndarray.

    Returns
    -------
    Tensor
        A framework-specific tensor.
    """
    pass


def image_meta(system_metadata):
    """Format image metadata for use in notifications from the instance
    system metadata.
    """
    image_meta = {}
    for md_key, md_value in system_metadata.items():
        if md_key.startswith('image_'):
            image_meta[md_key[6:]] = md_value
    return image_meta


def validar_casas_decimais(valor, minimo=1, maximo=2):
    """Valida o número de casas decimais. Se o número de casas decimais não
    estiver dentro do mínimo e máximo, será lançada uma exceção do tipo
    :py:exc:`ValueError`.

    :param valor: Um objeto :py:class:`~decimal.Decimal`.

    :param minimo: Valor inteiro maior ou igual a zero indicando o número
        mínimo de casas decimais. Se não informado, ``1`` é o mínimo.

    :param maximo: Valor inteiro maior ou igual a zero indicando o número
        máximo de casas decimais. Se não informado, ``2`` é o máximo.

    :raises ValueError: Se o valor possuir um número de casas decimais fora dos
        limites mínimo e máximo informados.

    """
    atributos = valor.as_tuple()
    if not minimo <= abs(atributos.exponent) <= maximo:
        raise ValueError(
            'Numero de casas decimais fora dos limites esperados (valor={!r}, minimo={!r}, maximo={!r}): {!r}'
            .format(valor, minimo, maximo, atributos))


def get_fields(fields, label):
    """ 搜索DICT中的label 获取值"""
    for res_dict in fields:
        if res_dict['label'] == label:
            return res_dict['value']
    return ''


def validate_settings(settings):
    """
    Raise an error in prod if we see any insecure settings.

    This used to warn during development but that was changed in
    71718bec324c2561da6cc3990c927ee87362f0f7
    """
    from django.core.exceptions import ImproperlyConfigured
    if settings.SECRET_KEY == '':
        msg = 'settings.SECRET_KEY cannot be blank! Check your local settings'
        if not settings.DEBUG:
            raise ImproperlyConfigured(msg)
    if getattr(settings, 'SESSION_COOKIE_SECURE', None) is None:
        msg = (
            'settings.SESSION_COOKIE_SECURE should be set to True; otherwise, your session ids can be intercepted over HTTP!'
            )
        if not settings.DEBUG:
            raise ImproperlyConfigured(msg)
    hmac = getattr(settings, 'HMAC_KEYS', {})
    if not len(hmac.keys()):
        msg = 'settings.HMAC_KEYS cannot be empty! Check your local settings'
        if not settings.DEBUG:
            raise ImproperlyConfigured(msg)


def freestyle_add_edge_marks_to_keying_set():
    """Add the data paths to the Freestyle Edge Mark property of selected edges to the active keying set

    """
    pass


def _np_dtype(attribute_type):
    """
    Return a relevant numpy dtype entry.
    """
    if attribute_type in ('double', 'float', 'real'):
        return float
    elif attribute_type in ('int', 'integer'):
        return int
    else:
        return object


def has_attachment(msg):
    """
    check whether has attachments
    :param msg:
    :return:
    """
    attachment_num = msg.get('X-ATTACHMENT-NUM')
    if attachment_num < 2:
        return False
    else:
        return True


@staticmethod
def find_neighbors_delaunay(pindex, triang):
    """
        Returns the indexes of points connected to ``pindex`` on the Gabriel
        chain subgraph of the Delaunay triangulation.
        """
    return triang.vertex_neighbor_vertices[1][triang.
        vertex_neighbor_vertices[0][pindex]:triang.vertex_neighbor_vertices
        [0][pindex + 1]]


@staticmethod
def _strip_elements(xml_str, element_names):
    """ Remove specified XML element nodes from the XML content.

        :param str xml_str:
        :param list element_names:
        :return: the list of lines
        :rtype: str
        """
    lines = []
    for line in xml_str.split('\n'):
        if len(line.strip()):
            found_it = False
            for key in element_names:
                if key in line:
                    found_it = True
                    break
            if not found_it:
                lines.append(line)
    return lines


def end(compatible_output=True):
    """Do any necessary cleaning up before exiting."""
    raise NotImplementedError


def find_max(node):
    """Find max value node"""
    while node and node.right:
        node = node.right
    return node


def count_query(tablename, condition):
    """
    Function to process query for count process
    """
    if isinstance(tablename, str):
        pass
    else:
        raise ValueError('Tablename should be a String')
    if condition == None or isinstance(condition, str):
        pass
    else:
        raise ValueError('Condition can only be either None or String')
    if condition == None:
        query = 'select count(*) from ' + tablename
    else:
        query = 'select count(*) from ' + tablename + ' where ' + condition
    return query


def is_exploits_commit(summary: str) ->bool:
    """Return True if this is a forces commit."""
    return '(exp)' in summary