def fetch_method(name, modules):
    """ Get function from list of modules. """
    for module in modules:
        if hasattr(module, name):
            return getattr(module, name)
    raise ValueError('Cannot find method ' + name + ' in ' + ', '.join([
        module.__name__ for module in modules]))


def is_snippet(t, sch, ech):
    """
    Returns if ``t`` is a snippet. A snippet must start with sch and end
    with ech.
    """
    if t and t[0] == sch and t[-1] == ech:
        return True
    else:
        return False


def _l2s(lst, separator='+'):
    """Combine a list of objects into a string, with a separator"""
    s = ''
    for i in lst:
        if s != '':
            s += separator
        s += '"' + str(i) + '"'
    return s


def _checkimagearg(x, y, im):
    """x and y can be arrays or single-item dicts
    (each dict comprises an axis name (or tuple of axis name/position) and array (can be None))
    """
    if x is not None:
        if isinstance(x, dict):
            x = list(x.values())[0]
        if x is not None and x.shape[0] != im.shape[1]:
            raise AttributeError(
                'Width of image does not match the length of x')
    if y is not None:
        if isinstance(y, dict):
            y = list(y.values())[0]
        if y is not None and y.shape[0] != im.shape[0]:
            raise AttributeError(
                'Height of image does not match the length of y')


def districts_within_tolerance(partition, attribute_name='population',
    percentage=0.1):
    """Check if all districts are within a certain percentage of the "smallest"
    district, as defined by the given attribute.

    :param partition: partition class instance
    :param attrName: string that is the name of an updater in partition
    :param percentage: what percent difference is allowed
    :return: whether the districts are within specified tolerance
    :rtype: bool
    """
    if percentage >= 1:
        percentage *= 0.01
    values = partition[attribute_name].values()
    max_difference = max(values) - min(values)
    within_tolerance = max_difference <= percentage * min(values)
    return within_tolerance


def get_longest_increasing_subsequence(X):
    """Returns the Longest Increasing Subsequence in the Given List/Array"""
    N = len(X)
    P = [0] * N
    M = [0] * (N + 1)
    L = 0
    for i in range(N):
        lo = 1
        hi = L
        while lo <= hi:
            mid = (lo + hi) // 2
            if X[M[mid]] < X[i]:
                lo = mid + 1
            else:
                hi = mid - 1
        newL = lo
        P[i] = M[newL - 1]
        M[newL] = i
        if newL > L:
            L = newL
    S = []
    k = M[L]
    for i in range(L - 1, -1, -1):
        S.append(X[k])
        k = P[k]
    return S[::-1]


def bundle1allowed(repo, action):
    """Whether a bundle1 operation is allowed from the server.

    Priority is:

    1. server.bundle1gd.<action> (if generaldelta active)
    2. server.bundle1.<action>
    3. server.bundle1gd (if generaldelta active)
    4. server.bundle1
    """
    ui = repo.ui
    gd = b'generaldelta' in repo.requirements
    if gd:
        v = ui.configbool(b'server', b'bundle1gd.%s' % action)
        if v is not None:
            return v
    v = ui.configbool(b'server', b'bundle1.%s' % action)
    if v is not None:
        return v
    if gd:
        v = ui.configbool(b'server', b'bundle1gd')
        if v is not None:
            return v
    return ui.configbool(b'server', b'bundle1')


def CRF(val):
    """CorrectedRepublishedFrom"""
    return val


def is_empty(obj):
    """
    check for "", "   " and None
    :param obj:data to be tested
    :return: True if it is one of "" or "  " or None otherwise False
    """
    if not obj or not obj.strip():
        return True
    else:
        return False


def extract_data(condition, mnemonic):
    """Function extracts data from given mnemmonic at a given condition
    Parameters
    ----------
    condition : object
        conditon object that holds one or more subconditions
    mnemonic : AstropyTable
        holds single table with mnemonic data
    Return
    ------
    temp : list  or None
        holds data that applies to given condition
    """
    temp = []
    for element in mnemonic:
        if condition.state(float(element['time'])):
            temp.append(float(element['value']))
    if len(temp) > 0:
        return temp
    else:
        return None


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


def _im_func(f):
    """Wrapper to get at the underlying function belonging to a method.

    Python 2 is slightly different because classes have "unbound methods"
    which wrap the underlying function, whereas on Python 3 they're just
    functions. (Methods work the same way on both versions.)
    """
    if hasattr(f, '__func__'):
        return f.__func__
    else:
        return f


@staticmethod
def get_subtype(object_dictionary):
    """
        Given the hash representation of a subtype of this class,
        use the info in the hash to return the class of the subtype.
        """
    type = object_dictionary['destinationType']
    if type == 'objectStorageUri':
        return 'ExportImageViaObjectStorageUriDetails'
    if type == 'objectStorageTuple':
        return 'ExportImageViaObjectStorageTupleDetails'
    else:
        return 'ExportImageDetails'


@staticmethod
def get_addresses_model():
    """
        This is needed so the BaseConnection can validate the
        provided addresses and throw an error if any are missing.
        As well as automatically generate documentation.
        NOTE: types must always be "str"
        return = {
            'required_addresses': {
                'req_address_name_1': str,
                'req_address_name_2': str,
            },
            'optional_addresses': {
                'opt_address_name_1': str,
                'opt_address_name_2': str,
            },
        }
        """
    return {'required_addresses': {'publisher': str}, 'optional_addresses': {}}


@classmethod
def from_string(cls, raw_filter, rule_limit):
    """
        Creates a new Filter instance from the given string.

        *raw_filter* is the raw filter : a string that may contain several
        regular expressions (separated by a newline char) and tags.

        *rule_limit* is the Rule's limit above which the Action is executed.

        Raises :class:`exceptions.ValueError` if the given string could not be
        compiled in at least one suitable :class:`re.RegexObject`.

        Returns a new :class:`Filter` instance.
        """
    parsed_filter = cls.replace_tags(raw_filter)
    regexes = cls.build_regex_list(parsed_filter, rule_limit)
    return cls(regexes)


def ztp(dic, data):
    """
    3D Matrix Transpose
    """
    raise NotImplementedError


def getChangeSources():
    """Return a list of IChangeSource objects."""


def delete_auto_scaling_group(AutoScalingGroupName=None, ForceDelete=None):
    """
    Deletes the specified Auto Scaling group.
    If the group has instances or scaling activities in progress, you must specify the option to force the deletion in order for it to succeed.
    If the group has policies, deleting the group deletes the policies, the underlying alarm actions, and any alarm that no longer has an associated action.
    To remove instances from the Auto Scaling group before deleting it, call  DetachInstances with the list of instances and the option to decrement the desired capacity so that Auto Scaling does not launch replacement instances.
    To terminate all instances before deleting the Auto Scaling group, call  UpdateAutoScalingGroup and set the minimum size and desired capacity of the Auto Scaling group to zero.
    See also: AWS API Documentation

    Examples
    This example deletes the specified Auto Scaling group.
    Expected Output:
    This example deletes the specified Auto Scaling group and all its instances.
    Expected Output:

    :example: response = client.delete_auto_scaling_group(
        AutoScalingGroupName='string',
        ForceDelete=True|False
    )

    :type AutoScalingGroupName: string
    :param AutoScalingGroupName: [REQUIRED]
            The name of the group to delete.

    :type ForceDelete: boolean
    :param ForceDelete: Specifies that the group will be deleted along with all instances associated with the group, without waiting for all instances to be terminated. This parameter also deletes any lifecycle actions associated with the group.

    :return: response = client.delete_auto_scaling_group(
        AutoScalingGroupName='my-auto-scaling-group',
    )

    print(response)

    """
    pass


def pretty_name(name):
    """Converts 'first_name' to 'first name'"""
    if not name:
        return ''
    return name.replace('_', ' ')


@classmethod
def register_dict_to_class(cls, classname, converter):
    """
        Registers a custom converter function that creates objects from a dict with the given classname tag in it.
        The function is called with two parameters: the classname and the dictionary to convert to an instance of the class.

        This mechanism is not used for the pickle serializer.
        """
    cls.__custom_dict_to_class_registry[classname] = converter


def update_tab_actions(actions):
    """Allows to change the default actions for a tab. The ``actions``
        argument contains a list of actions (dicts) and should be returned by
        this method after modifying it.

        Example actions:
        [{'label': _(u'Reset table configuration'),
          'href': 'javascript:reset_grid_state()',
          'description': _(u'Resets the table configuration for this tab.'),
          'class': 'additional-css-class'}]
        """


def plus_or_dot(pieces):
    """Return a + if we don't already have one, else return a ."""
    if '+' in pieces.get('closest-tag', ''):
        return '.'
    return '+'


def __init__(field, context, request):
    """Adapts field, context and request.
        """


@staticmethod
def get(s, key, default=None):
    """
        Get a settings value from key. Try to get key as it is, transforming to lower case and to upper case. If not
        found, a default value will be returned.

        :param s: Settings module or object.
        :param key: Settings key.
        :param default: Default value.
        :return: Settings value. Default value if key is not found.
        """
    return getattr(s, key, getattr(s, key.lower(), getattr(s, key.upper(),
        default)))


def serialize_dtype(dt):
    """ Serialize dtype to bytes

    >>> serialize_dtype(np.dtype('i4'))
    b'<i4'
    >>> serialize_dtype(np.dtype('M8[us]'))
    b'<M8[us]'
    """
    return dt.str.encode()


def setDomainOnActivation(domain, event):
    """Set the permission id upon registration activation.

    Let's see how this notifier can be used. First we need to create an event
    using the permission instance and a registration stub:

    >>> class Registration:
    ...     def __init__(self, obj, name):
    ...         self.component = obj
    ...         self.name = name

    >>> domain1 = TranslationDomain()
    >>> domain1.domain
    '<domain not activated>'

    >>> import zope.interface.interfaces
    >>> event = zope.interface.interfaces.Registered(
    ...     Registration(domain1, 'domain1'))

    Now we pass the event into this function, and the id of the domain should
    be set to 'domain1'.

    >>> setDomainOnActivation(domain1, event)
    >>> domain1.domain
    'domain1'
    """
    domain.domain = event.object.name


def _finishdatamigration(ui, srcrepo, dstrepo, requirements):
    """Hook point for extensions to perform additional actions during upgrade.

    This function is called after revlogs and store files have been copied but
    before the new store is swapped into the original location.
    """


def Dt(f):
    """UFL operator: <Not implemented yet!> The partial derivative of *f* with respect to time."""
    raise NotImplementedError


def _join_path(path, name):
    """Join a prefix path and an entity name to form a new path."""
    return (path + '.' if path != '' else '') + name


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


@classmethod
def build_request(cls, request_type, event):
    """
        Maps the input body to the appropriate request
        object based on the request type
        :param request_type: Indicates the event type
        :param event: the incoming event body
        :return: The constructed request object
        """
    body = event.get('body')
    headers = event.get('headers')
    claims = {}
    if 'requestContext' in event:
        authorizer = event.get('requestContext').get('authorizer')
        claims = authorizer.get('claims') if authorizer else {}
    request = request_type(body, headers, claims)
    return request


def gddeltaconfig(ui):
    """helper function to know if incoming delta should be optimised
    """
    return ui.configbool(b'format', b'generaldelta')


def format_date(date_time):
    """Format the date as YYYY-MM-DD"""
    return date_time.strftime('%Y-%m-%d')


def to_bool(value):
    """
    Converts a string representation of a number into boolean.

    :param str value: a string representation of a number to convert

    :returns: `False` if `value` is equal to `'0'`, `True` otherwise
    :rtype: :class:`bool`

    **Examples:**

    .. code-block:: python

       >>> to_bool('0')
       False
       >>> to_bool('1')
       True
       >>> to_bool('-1')
       True
    """
    return int(value) != 0


def contour_lines_from_endpoints(endpoints, crossing_points, connections,
    min_length=3, backtrack_from_end=False, extend_endpoints=True):
    """
    Follow contour lines and create contours

    - endpoints: an iterable of crossing point IDs (could be facet ids)
    - crossing_points: a mapping from crossing point ID to position coordinates
    - connections: a mapping from ID to IDs
    """
    contours = []
    endpoint_ids = list(endpoints)
    while endpoint_ids:
        end_id = endpoint_ids.pop()
        if not end_id in crossing_points:
            continue
        contour = [crossing_points.pop(end_id)]
        queue = list(connections[end_id])
        prev = end_id
        has_backtracked = False
        while queue:
            nb_id = queue.pop()
            if nb_id in crossing_points:
                cpoint = crossing_points.pop(nb_id)
                if cpoint != contour[-1]:
                    contour.append(cpoint)
                if extend_endpoints:
                    for candidate in queue:
                        if candidate in crossing_points:
                            endpoint_ids.append(candidate)
                queue = list(connections[nb_id])
                prev = nb_id
            if nb_id == end_id and prev in connections[end_id] and len(contour
                ) > min_length - 1 and not has_backtracked:
                contour.append(contour[0])
                break
            if backtrack_from_end and not queue and not has_backtracked:
                contour = contour[::-1]
                queue = list(connections[end_id])
                has_backtracked = True
        contours.append(contour)
    return contours


def get_value(kv, key, value=None):
    """get value from the keyvalues (options)"""
    res = []
    for k, v in kv:
        if k == key:
            value = v
        else:
            res.append([k, v])
    return value, res


@classmethod
def mains_status(cls):
    """Get wall power status"""
    return int(cls.get_store().get('mains-source').decode())


def speedx(clip, factor=None, final_duration=None):
    """
    Returns a clip playing the current clip but at a speed multiplied
    by ``factor``. Instead of factor one can indicate the desired
    ``final_duration`` of the clip, and the factor will be automatically
    computed.
    The same effect is applied to the clip's audio and mask if any.
    """
    if final_duration:
        factor = 1.0 * clip.duration / final_duration
    newclip = clip.fl_time(lambda t: factor * t, apply_to=['mask', 'audio'])
    if clip.duration is not None:
        newclip = newclip.set_duration(1.0 * clip.duration / factor)
    return newclip


def check_priors(options):
    """Checks whether priors provided by user, and default
    values assigned by extract_metrics function are valid
    assignments.

    Keyword arguments:
    options -- contains all options used to fit model (dictionary)
    """
    for keys in options['priors_definitions']:
        if options['priors_definitions'][keys] not in ('Unif', 'Norm',
            'Log-Norm', 'Beta', 'Gamma'):
            raise Exception(
                """One of the prior distributions defined is not
                            a valid argument from options available!"""
                )
    for values in options['priors_params']:
        for i in range(0, len(options['priors_params'][values])):
            if options['priors_params'][values][i] > 10000 or options[
                'priors_params'][values][i] < -10000:
                raise Exception(
                    """One of the parameters that define a prior
                    distribution is greater than 10000 or less than -10000!"""
                    )


def merge_pairs(list, should_merge, merge):
    """
    Merges adjacent elements of list using the function merge
    if they satisfy the predicate should_merge.

    >>> merge_pairs([], None, None)
    []

    >>> merge_pairs([1], None, None)
    [1]

    >>> merge_pairs([1, 2], lambda x, y: False, None)
    [1, 2]

    >>> merge_pairs([1, 2], lambda x, y: y == x + 1, lambda x, y: (x, y))
    [(1, 2)]

    >>> merge_pairs([1, 2, 3], lambda x, y: y == x + 1, lambda x, y: (x, y))
    [(1, 2), 3]

    >>> merge_pairs([1, 2, 3, 4], lambda x, y: y == x + 1, lambda x, y: (x, y))
    [(1, 2), (3, 4)]
    """
    ret = []
    i = 0
    while i < len(list) - 1:
        a = list[i]
        b = list[i + 1]
        if should_merge(a, b):
            ret.append(merge(a, b))
            i += 2
        else:
            ret.append(a)
            i += 1
    if i == len(list) - 1:
        ret.append(list[i])
    return ret


def _export_to_mirror(file, file_id, mirror):
    """Export a file-like object with file_id to mirror."""
    with mirror.new_file(_id=file_id) as dst:
        dst.write(file.read())


def vmax_dual(wavelength, prf1, prf2):
    """Doppler velocity [m/s] from dual PRF scheme radar (+ or -).

    From Jorgensen (1983), Eqn 2

    Parameters
    ----------
    wavelength : float
        Radar wavelength [m]
    prf1 : float
        First Pulse repetition frequency [Hz]
    prf2 : float
        Second Pulse repetition frequency [Hz]

    Notes
    -----
    In the case of a mobile platform (such as the NOAA P-3 aircraft, the
    Doppler velocity must be adjusted for movement of the scanning platform.

    The fore/aft angle is defined as the angle fore or aft from a plane
    normal to the direction of motion
    """
    return wavelength / (4 * (1.0 / prf1 - 1.0 / prf2))


@staticmethod
def _sortedSetAdd(list, element):
    """
        Insert element into the list, sorted using element.compare(). If it is a
        duplicate of an existing list element, don't add it.
        """
    i = 0
    while i < len(list):
        comparison = list[i].compare(element)
        if comparison == 0:
            return
        if not comparison < 0:
            break
        i += 1
    list.insert(i, element)


def jwt_get_username_from_payload_handler(payload):
    """
    Override this function if username is formatted differently in payload
    """
    return payload.get('username')


def reset():
    """Return brush to defaults based on current tool

    """
    pass


@classmethod
def build(cls, *, levels: list):
    """Build an Equalizer class with the provided levels.

        Parameters
        ------------
        levels: List[Tuple[int, float]]
            A list of tuple pairs containing a band int and gain float.
        """
    return cls(levels)


def unregisterSynch(synch):
    """Unregister an `ISynchronizer`.

        Synchronizers are notified about some major events in a transaction's
        life.  See `ISynchronizer` for details.
        """


def readable(fileobj):
    """Determines whether or not a file-like object is readable.

    :param fileobj: The file-like object to determine if readable

    :returns: True, if readable. False otherwise.
    """
    if hasattr(fileobj, 'readable'):
        return fileobj.readable()
    return hasattr(fileobj, 'read')


def first(iterable, default=None, key=None):
    """
    Return first element of `iterable` that evaluates true, else return None
    (or an optional default value).

    >>> first([0, False, None, [], (), 42])
    42

    >>> first([0, False, None, [], ()]) is None
    True

    >>> first([0, False, None, [], ()], default='ohai')
    'ohai'

    >>> import re
    >>> m = first(re.match(regex, 'abc') for regex in ['b.*', 'a(.*)'])
    >>> m.group(1)
    'bc'

    The optional `key` argument specifies a one-argument predicate function
    like that used for `filter()`.  The `key` argument, if supplied, must be
    in keyword form.  For example:

    >>> first([1, 1, 3, 4, 5], key=lambda x: x % 2 == 0)
    4

    """
    if key is None:
        for el in iterable:
            if el:
                return el
    else:
        for el in iterable:
            if key(el):
                return el
    return default


def sanitize(value, surround=True):
    """
    Sanitize a table or column name by replacing square and round brackets with
    curly ones and optionally surrounding the whole string in square brackets.

    Args:
        value (str): the value to sanitize
        surround (bool, optional): whether to surround the result in square
            brackets. Defaults to ``True``.
    """
    for o, n in zip('[()]', '{{}}'):
        value = value.replace(o, n)
    return '[{}]'.format(value) if surround else value


def folder():
    """The current canonical folder
        """


def psi_K_Cl_SO4_PK74(T, P):
    """c-a-a': potassium chloride sulfate [PK74]."""
    psi = 0.0
    valid = T == 298.15
    return psi, valid


def testArgs():
    """Arguments for SVM.test
    -  ``GPU=<gpus>``

       Sets the number of GPUs that are going to be used. Currently, there
       is no checking whether your system actually has many GPUs. In
       addition, the number of used threads is reduced to .

       Allowed values: : integer between 0 and ???

       Default values: = 0

       Unfortunately, this option is not activated for the binaries you are
       currently using. Install CUDA and recompile to activate this option.

    -  ``h=[<level>]``

       Displays all help messages.

       Meaning of specific values: = 0 => short help messages = 1 =>
       detailed help messages

       Allowed values: : 0 or 1

       Default values: = 0

    -  ``L=c(<loss>,[<neg_weight>,<pos_weight>])``

       Sets the loss that is used to compute empirical errors. The optional
       weights can only be set, if specifies a loss that has weights.

       Meaning of specific values: = 0 => binary classification loss = 1 =>
       multiclass class = 2 => least squares loss = 3 => weighted least
       squares loss = 5 => your own template loss

       Allowed values: : integer between 0 and 2 : float > 0.0 : float > 0.0

       Default values: = 0 = 1.0 = 1.0

    -  ``T=<threads>``

       Sets the number of threads that are going to be used. Each thread is
       assigned to a logical processor on the system, so that the number of
       allowed threads is bounded by the number of logical processors. On
       systems with activated hyperthreading each physical core runs one
       thread, if does not exceed the number of physical cores. Since hyper-
       threads on the same core share resources, using more threads than
       cores does usually not increase the performance significantly, and
       may even decrease it.

       Meaning of specific values: = 0 => 4 threads are used (all physical
       cores run one thread) = -1 => 3 threads are used (all but one of the
       physical cores run one thread)

       Allowed values: : integer between -1 and 4

       Default values: = 0

    -  ``v=c(<weighted>,<scenario>,[<npl_class>])``

       Sets the weighted vote method to combine decision functions from
       different folds. If = 1, then weights are computed with the help of
       the validation error, otherwise, equal weights are used. In the
       classification scenario, the decision function values are first
       transformed to -1 and +1, before a weighted vote is performed, in the
       regression scenario, the bare function values are used in the vote.
       In the weighted NPL scenario, the weights are computed according to
       the validation error on the samples with label , the rest is like in
       the classification scenario. can only be set for the NPL scenario.

       Meaning of specific values: = 0 => classification = 1 => regression =
       2 => NPL

       Allowed values: : 0 or 1 : integer between 0 and 2 : -1 or 1

       Default values: = 1 = 0 = 1

    -  ``o=<display_roc_style>``

       Sets a flag that decides, wheather classification errors are
       displayed by true positive and false positives.

       Allowed values: : 0 or 1

       Default values: : Depends on option -v

    """


@classmethod
def value_from_buffer(cls, bfr, encoding):
    """ Read a NUL terminated UTF-16 string from `bfr`, return field.
        The mandatory parameter `encoding` specifies the UTF16 encoding to use
        (`'utf_16_be'` or `'utf_16_le'`).
    """
    bs_length = 2
    while True:
        bfr.extend(bs_length)
        nul_pos = bs_length - 2
        if bfr[nul_pos] == 0 and bfr[nul_pos + 1] == 0:
            break
        bs_length += 2
    if nul_pos == 0:
        utf16 = ''
    else:
        utf16_bs = bfr.take(nul_pos)
        utf16 = utf16_bs.decode(encoding)
    bfr.take(2)
    return utf16


def graph_delta_values(y, edge_weights):
    """ Computes delta values from an arbitrary graph as in the objective
    function of GSFA. The feature vectors are not normalized to weighted
    unit variance or weighted zero mean.
    """
    R = 0
    deltas = 0
    for i, j in edge_weights.keys():
        w_ij = edge_weights[i, j]
        deltas += w_ij * (y[j] - y[i]) ** 2
        R += w_ij
    return deltas / R


def make_path_safe(path):
    """
    Make a path safe for use in Cypher

    Parameters
    ----------
    path : str
        Path to sanitize

    Returns
    -------
    str
        Cypher-safe path
    """
    return path.replace('\\', '/').replace(' ', '%20')


def get_detail_view_name(model):
    """
    Given a model class, return the view name to use for URL relationships
    that refer to instances of the model.
    """
    return '%(model_name)s-detail' % {'app_label': model._meta.app_label,
        'model_name': model._meta.object_name.lower()}


def check_args(args):
    """Checking user input
    """
    pass


def rel_to_abs_tuple(target: tuple, namespace: tuple):
    """Convert name relative to namespace to absolute"""
    ns = namespace
    nslen = len(ns)
    dots = 0
    while dots < len(target) and target[dots] == '.':
        dots += 1
    if target[0] == '.' * len(target[0]):
        dots = len(target[0])
    else:
        raise ValueError('invalid tuple')
    shared = nslen - dots + 1
    tg = target[1:]
    abs = ns[:shared] + tg
    return abs


@staticmethod
def no_color(text_to_color, **kwargs):
    """Returns the text undecorated"""
    return text_to_color


def django_url_preprocessor(url, root_url):
    """
    Convert url from the simplified string version for app developers to Django regular expression.

    e.g.:

        '/example/resource/{variable_name}/'
        r'^/example/resource/?P<variable_name>[1-9A-Za-z\\-]+/$'
    """
    DEFAULT_EXPRESSION = '[0-9A-Za-z-]+'
    url_parts = url.split('/')
    django_url_parts = []
    if root_url in url_parts:
        index = url_parts.index(root_url)
        url_parts.pop(index)
    for part in url_parts:
        if '{' in part or '}' in part:
            variable_name = part.replace('{', '').replace('}', '')
            part = '(?P<{0}>{1})'.format(variable_name, DEFAULT_EXPRESSION)
        django_url_parts.append(part)
    django_url_joined = '/'.join(django_url_parts)
    if django_url_joined != '':
        django_url = '^{0}/$'.format(django_url_joined)
    else:
        django_url = '^$'
    return django_url


def string_to_number(string):
    """
    Return either integer or float conversion of specified string.
    """
    if not string:
        return 0
    try:
        return int(string)
    except ValueError:
        return float(string)


def axis_name_generator(range_of_axis=1):
    """
    Axis name generator for n axis scan.
    @type range_of_axis: int
    """
    current = 1
    names = [u'Slow', u'Slower', u'Slowest', u'Fast', u'Faster', u'Fastest']
    mapping = [[3], [0, 3], [1, 0, 3], [1, 0, 3, 4], [2, 1, 0, 3, 4], [2, 1,
        0, 3, 4, 5]]
    col = range_of_axis - 1
    while current <= range_of_axis:
        if range_of_axis <= 6:
            yield u'{}'.format(names[mapping[col][current - 1]])
        elif current == range_of_axis:
            yield u'Fast {}'.format(current)
        elif current == 1:
            yield u'Slow {}'.format(current)
        else:
            yield u'{}'.format(current)
        current += 1


def classdot2func(path):
    """ Convert a path such as 'android.support.v4.app.ActivityCompat'
        into a method string 'CLASS_Landroid_support_v4_app_ActivityCompat'
        so we can call d.CLASS_Landroid_support_v4_app_ActivityCompat.get_source()
    """
    func = 'CLASS_L' + path.replace('.', '_').replace('$', '_')
    return func


def conv_output_size(image_length: int, kernel_length: int, stride: int) ->int:
    """
    Computes output dimension given input dimension, kernel size and stride,
    assumign no padding, *per* dimension given

    :param image_length: int image size on one dimension
    :param kernel_length: int kernel_length size on one dimension
    :param stride: int Stride size on one dimension
    :return: int -- convolved output image size on one dimension

    """
    try:
        assert image_length >= kernel_length
    except AssertionError:
        raise Exception('Image dimension {0} smaller than kernel dimension {1}'
            .format(image_length, kernel_length))
    return int((image_length - kernel_length) / stride + 1)


def interval_set_to_set(intervals):
    """ Convert interval set to python set

    >>> interval_set_to_set([])
    set()
    >>> interval_set_to_set([(1, 1), (3, 4)])
    {1, 3, 4}
    """
    s = set()
    for begin, end in intervals:
        for x in range(begin, end + 1):
            s.add(x)
    return s


def format_output(org_amt, conv_amt, org_ufrom, conv_uto):
    """Return a string containing the original amount, original unit,
    converted amount, and unit converted to in a nice easy to read format."""
    return '{0} {1} is {2} {3}'.format(org_amt, org_ufrom, conv_amt, conv_uto)


def default_context(engine, context=None) ->dict:
    """Return a dict with an engine, using the existing values if provided"""
    if context is None:
        context = {}
    context.setdefault('engine', engine)
    return context


def _label_bar(ax, bars, text_format, **kwargs):
    """
    Attach a text label to each bar displaying its y value
    """
    max_y_value = ax.get_ylim()[1]
    inside_distance = max_y_value * 0.05
    outside_distance = max_y_value * 0.01
    for bar in bars:
        text = text_format.format(bar.get_height())
        text_x = bar.get_x() + bar.get_width() / 2
        is_inside = bar.get_height() >= max_y_value * 0.15
        if is_inside:
            color = 'black'
            text_y = bar.get_height() - inside_distance
        else:
            color = 'white'
            text_y = bar.get_height() + outside_distance
        ax.text(text_x, text_y, text, ha='center', va='bottom', color=color,
            **kwargs)


def get_checkstring():
    """
        Get the checkstring that I think currently exists on the remote
        server.
        """


def build_file_share_error_response(asset_id: str, error_msg: str=''):
    """
    Builds a proper error response to the jquery-file-share browser client

    {"files": [
      {
        "asset_id": "5f66e619-ab8d-4491-8b49-740476e6b08c",
        "error": "Key server error"
      },
      {
        "asset_id": "22727033-67ee-4b5a-8095-4a565b3ebfd9",
        "error": "Bad Request"
      }
    ]}

    :param error_msg:
    :param asset_id: Asset uuid of the file to be shared
    :return: A properly formatted response
    """
    response = dict()
    response['files'] = list()
    file_dict = dict()
    file_dict['asset_id'] = asset_id
    file_dict['error'] = error_msg
    response['files'].append(file_dict)
    return response


def hr(width=70):
    """ Return simple ascii horizontal rule """
    if width < 2:
        return ''
    return '# ' + (width - 2) * '~'


def replace_content(element, wrapper):
    """Similar to above but keeps parent tag
    """
    del element[:]
    if wrapper is not None:
        element.text = wrapper.text
        element.extend(wrapper.getchildren())


@classmethod
def getSize(cls, policy, size, sizeList):
    """Get the correct size based on the given resize policy.

        * resizePolicy -- The resize policy
        * size -- The main single size (width or height) of the widget
        * sizeList -- The list of the single dimension size (widths or heights)
                      of widgets's children

        """
    policyMap = {cls.Fixed: cls.__getFixedSize, cls.Expanding: cls.
        __getExpandingSize}
    policyFn = policyMap.get(policy)
    if policyFn is not None:
        return policyFn(size, sizeList)
    else:
        raise Exception('Unknown Policy [%s]' % policy)


def rated_as_bool(text):
    """
    Returns true if param = "rated" and false otherwise
    (usually if param = "unrated"). Used inside different parsing context.
    :param text: "rated" or "unrated"
    """
    if text == 'rated':
        return True
    else:
        return False


def compare_serial_containment(siglist, downsample=False):
    """Compare all combinations of signatures and return a matrix
    of containments. Processes combinations serially on a single
    process. Best to use when there is few signatures.

    :param list siglist: list of signatures to compare
    :param boolean downsample by max_hash if True
    :return: np.array similarity matrix
    """
    import numpy as np
    n = len(siglist)
    containments = np.ones((n, n))
    for i in range(n):
        for j in range(n):
            containments[i][j] = siglist[j].contained_by(siglist[i],
                downsample=downsample)
    return containments


@classmethod
def get_route_prefix(cls):
    """
        Returns a prefix which (by default) applies to all routes provided by
        this view class.
        """
    prefix = getattr(cls, 'route_prefix', None)
    if prefix:
        return prefix
    model_name = cls.get_normalized_model_name()
    return '{}s'.format(model_name)


def canvas(name='canvas1', size=(800, 600)):
    """
    Helper method for creating canvas
    If canvas with this name already exists, it will be returned
    """
    import ROOT
    canvas = ROOT.gROOT.FindObject(name)
    if canvas:
        return canvas
    else:
        width, height = size
        return ROOT.TCanvas(name, name, width, height)


def ensure_ext(filepath, ext: str, case_sensitive: bool=False):
    """Return the path with the extension added if it is not already set.

    :param ext: The extension to check for, can be a compound extension. Should start with a dot, such as ‘.blend’ or ‘.tar.gz’.
    :type ext: str
    :param case_sensitive: Check for matching case when comparing extensions.
    :type case_sensitive: bool
    """
    pass


@staticmethod
def _handle_twofactor(message=''):
    """ Called when SteamGuard requires two-factor authentication..
        Asks the user to enter the code.

        Args:
            message: Optional. A message from Steam service.

        Returns:
            A string containing the code.
        """
    print('SteamGuard requires mobile authentication...')
    twofactorcode = input('Please enter the code sent to your phone: ')
    twofactorcode.upper()
    return twofactorcode


@staticmethod
def is_channel(obj):
    """
        Returns whether the item given is a valid channel (for a mapping key).

        For IRC, this checks if the item's name starts with a "#".

        Other platforms SHOULD redefine this if they track channels by some other format (e.g. numerical IDs).
        """
    return str(obj).startswith('#')


def getRolesForPrincipal(principal_id):
    """Get the roles granted to a principal.

        Return the list of (role id, setting) assigned or removed from
        this principal.

        If no roles have been assigned to
        this principal, then the empty list is returned.
        """


def _GetBounds(bbox, delta, M, N):
    """
    Returns bounds of object in global label image.

    Parameters
    ----------
    bbox : tuple
        Bounding box (min_row, min_col, max_row, max_col).
    delta : int
        Used to dilate nuclei and define cytoplasm region.
        Default value = 8.
    M : int
        X size of label image.
    N : int
        Y size of label image.

    Returns
    -------
    min_row : int
        Minum row of the region bounds.
    max_row : int
        Maximum row of the region bounds.
    min_col : int
        Minum column of the region bounds.
    max_col : int
        Maximum column of the region bounds.

    """
    min_row, min_col, max_row, max_col = bbox
    min_row_out = max(0, min_row - delta)
    max_row_out = min(M - 1, max_row + delta)
    min_col_out = max(0, min_col - delta)
    max_col_out = min(N - 1, max_col + delta)
    return min_row_out, max_row_out, min_col_out, max_col_out


def getDayNames():
    """Return a list of weekday names."""


def removeReader(reader):
    """
        Removes an object previously added with L{addReader}.

        @return: C{None}.
        """


def pushkey(namespace, key, old, new):
    """Set a value using the ``pushkey`` protocol.

        Arguments correspond to the pushkey namespace and key to operate on and
        the old and new values for that key.

        Returns a string with the peer result. The value inside varies by the
        namespace.
        """


def text_count(widget, index1, index2, *options):
    """Hack Text count command. Return integer, or tuple if len(options) > 1.

    Tkinter does not provide a wrapper for the Tk Text widget count command
    at Python 2.7.1

    widget is a Tkinter Text widget.
    index1 and index2 are Indicies as specified in TkCmd documentation.
    options must be a tuple of zero or more of option values.  If no options
    are given the Tk default option is used.  If less than two options are
    given an integer is returned.  Otherwise a tuple of integers is returned
    (in the order specified in TkCmd documentation).

    See text manual page in TkCmd documentation for valid option values and
    index specification.

    Example:
    chars, lines = text_count(widget, start, end, '-chars', '-lines')

    """
    return widget.tk.call((widget._w, 'count') + options + (index1, index2))


def validate_custom_page_path(path):
    """
    Check if a custom page path is valid or not,
    to prevent malicious requests.

    :param path: custom page path (url path)
    :return: valid or not
    """
    sp = path.split('/')
    if '.' in sp or '..' in sp:
        return False
    return True


def get_repo_slug(repo_owner=None, repo_name=None):
    """
    Return repo slug.

    This function concatenates repo_owner and repo_name,
    fe. buildtimetrend/service

    Parameters :
    - repo_owner : name of the Github repo owner, fe. `buildtimetrend`
    - repo_name : name of the Github repo, fe. `service`
    """
    if repo_owner is not None and repo_name is not None:
        return '%s/%s' % (str(repo_owner), str(repo_name))
    else:
        return None


def replace_file_content(filepath, old, new, max=1):
    """ Modify the content of `filepath`, replacing `old` for `new`.

    Parameters
    ----------
    filepath: str
        Path to the file to be modified. It will be overwritten.

    old: str
        This is old substring to be replaced.

    new: str
        This is new substring, which would replace old substring.

    max: int
        If larger than 0, Only the first `max` occurrences are replaced.
    """
    with open(filepath, 'r') as f:
        content = f.read()
    content = content.replace(old, new, max)
    with open(filepath, 'w') as f:
        f.write(content)


def pressure_fpa(force, area):
    """Usage: pressure_fpa(force of object, areaof object)"""
    return force / area


def create_user_crumbs(request, crumbs):
    """Creates the base-list of breadcrumbs, depending on the current
    users authorisation level.
    """
    if request.current_user.has_permission('admin.users.view'):
        crumbs.insert(0, {'title': 'Users', 'url': request.route_url('users')})
    if request.current_user.has_permission('admin'):
        try:
            crumbs.insert(0, {'title': 'Administration', 'url': request.
                route_url('admin')})
        except:
            pass
    crumbs[-1]['current'] = True
    return crumbs


def remove_cookie_by_name(cookiejar, name, domain=None, path=None):
    """Unsets a cookie by name, by default over all domains and paths.

    Wraps CookieJar.clear(), is O(n).
    """
    clearables = []
    for cookie in cookiejar:
        if cookie.name != name:
            continue
        if domain is not None and domain != cookie.domain:
            continue
        if path is not None and path != cookie.path:
            continue
        clearables.append((cookie.domain, cookie.path, cookie.name))
    for domain, path, name in clearables:
        cookiejar.clear(domain, path, name)


def merge_dicts(*dicts):
    """return dict created by updating each dict in sequence, last key wins"""
    result = {}
    for d in dicts:
        result.update(d)
    return result


def setup_subsubparser_installsdk(parser):
    """ Parser for pybombs prefix install-sdk """
    parser.add_argument('sdkname', help='SDK Package Name', nargs=1)


def _el_orb_tuple(string):
    """Parse the element and orbital argument strings.

    The presence of an element without any orbitals means that we want to plot
    all of its orbitals.

    Args:
        string (`str`): The selected elements and orbitals in in the form:
            `"Sn.s.p,O"`.

    Returns:
        A list of tuples specifying which elements/orbitals to plot. The output
        for the above example would be:

            `[('Sn', ('s', 'p')), 'O']`
    """
    el_orbs = []
    for split in string.split(','):
        splits = split.split('.')
        el = splits[0]
        if len(splits) == 1:
            el_orbs.append(el)
        else:
            el_orbs.append((el, tuple(splits[1:])))
    return el_orbs


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 build_multiply_suppressed_warning_header(oWarning, iIndent=0):
    """
    Creates a header for a warning that has been suppressed by more than one suppression rule.

    Parameters :

      oWarning : (warning object)

    Returns (list of strings)
    """
    sIndent = ' ' * iIndent
    lReturn = []
    lReturn.append(sIndent + '~' * (80 - iIndent))
    lReturn.append(sIndent + 'Warning ID  : ' + oWarning.get_id())
    lReturn.append(sIndent + 'Line Number : ' + str(oWarning.get_linenumber()))
    lReturn.append(sIndent + 'Message     : ' + oWarning.get_message())
    lReturn.append('')
    return lReturn


def get_polynomial_points(coefficients, num_points, prime):
    """ Calculates the first n polynomial points.
        [ (1, f(1)), (2, f(2)), ... (n, f(n)) ]
    """
    points = []
    for x in range(1, num_points + 1):
        y = coefficients[0]
        for i in range(1, len(coefficients)):
            exponentiation = x ** i % prime
            term = coefficients[i] * exponentiation % prime
            y = (y + term) % prime
        points.append((x, y))
    return points


def clear():
    """Remove all entries from the index."""


def get_repository_policy(registryId=None, repositoryName=None):
    """
    Retrieves the repository policy for a specified repository.
    See also: AWS API Documentation

    Examples
    This example obtains the repository policy for the repository named ubuntu.
    Expected Output:

    :example: response = client.get_repository_policy(
        registryId='string',
        repositoryName='string'
    )

    :type registryId: string
    :param registryId: The AWS account ID associated with the registry that contains the repository. If you do not specify a registry, the default registry is assumed.

    :type repositoryName: string
    :param repositoryName: [REQUIRED]
            The name of the repository whose policy you want to retrieve.

    :rtype: dict
    :return: {
        'registryId': 'string',
        'repositoryName': 'string',
        'policyText': 'string'
    }

    """
    pass


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

        :param SsoAddCertDetails val:
        :rtype: EventDetails
        """
    return cls('sso_add_cert_details', val)


def split_lines(fragments):
    """
    Take a single list of (style_str, text) tuples and yield one such list for each
    line. Just like str.split, this will yield at least one item.

    :param fragments: List of (style_str, text) or (style_str, text, mouse_handler)
                      tuples.
    """
    line = []
    for item in fragments:
        if len(item) == 2:
            style, string = item
            parts = string.split('\n')
            for part in parts[:-1]:
                if part:
                    line.append((style, part))
                yield line
                line = []
            line.append((style, parts[-1]))
        else:
            style, string, mouse_handler = item
            parts = string.split('\n')
            for part in parts[:-1]:
                if part:
                    line.append((style, part, mouse_handler))
                yield line
                line = []
            line.append((style, parts[-1], mouse_handler))
    yield line


@classmethod
def instance(cls):
    """Return a reference to the singleton instance, or ``None`` if one
        does not exist.
        """
    return getattr(cls, '_{}_singleton'.format(cls.__name__), None)


@classmethod
def list_by_node_id(cls, context, node_id, limit=None, marker=None,
    sort_key=None, sort_dir=None):
    """Return a list of VolumeTarget objects related to a given node ID.

        :param context: security context
        :param node_id: the integer ID of the node
        :param limit: maximum number of resources to return in a single result
        :param marker: pagination marker for large data sets
        :param sort_key: column to sort results by
        :param sort_dir: direction to sort. "asc" or "desc".
        :returns: a list of :class:`VolumeTarget` objects
        :raises: InvalidParameterValue if sort_key does not exist
        """
    db_targets = cls.dbapi.get_volume_targets_by_node_id(node_id, limit=
        limit, marker=marker, sort_key=sort_key, sort_dir=sort_dir)
    return cls._from_db_object_list(context, db_targets)


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 ranaxis(dmin, dmax):
    """needs a doc string"""
    import random as rand
    return rand.random() * (dmax - dmin) + dmin


@staticmethod
def getMagnitude(data):
    """Return the magnitude of the given complex data. """
    return (data.real ** 2 + data.imag ** 2) ** 0.5


def median_from_dict(total, count):
    """
    total is the number of requests made
    count is a dict {response_time: count}
    """
    pos = (total - 1) / 2
    for k in sorted(count.keys()):
        if pos < count[k]:
            return k
        pos -= count[k]


def extract_alternative_constitutive(psi):
    """Separate psi matrix to events that are alternative vs constitutive

    Parameters
    ----------
    psi : pandas.DataFrame
        This is a (samples, features) shaped dataframe of the percent
        spliced-in values

    Returns
    -------
    alternative, constitutively0, constitutively1 : pandas.DataFrame
        Slices of the input dataframe that are alternative or constitutive
    """
    notnull = psi.notnull()
    constitutively0 = (psi == 0)[notnull].all()
    constitutively1 = (psi == 1)[notnull].all()
    alternative = psi.columns[~constitutively0 & ~constitutively1]
    constitutively0 = constitutively0[constitutively0].index
    constitutively1 = constitutively1[constitutively1].index
    return psi[alternative], psi[constitutively0], psi[constitutively1]


def in_query_params(haystack, needles, on_true=True, on_false=False,
    on_empty=False):
    """
    Utility method for checking that any needle from given list of needles is
    present in given haystack.
    """
    if not haystack:
        return on_empty
    for needle in needles:
        if needle in haystack:
            return on_true
    return on_false


@classmethod
def parse(cls, name, data_size, reader, parsers):
    """given a 4 byte name, data_size int, BitstreamReader
        and dict of {"atom":handler} sub-parsers,
        returns an atom of this class"""
    version, flags, byte_size = reader.parse('8u 24u 32u')
    return cls(version=version, flags=flags, byte_size=byte_size,
        block_sizes=[reader.read(32) for i in range(reader.read(32))])


def get_op_precedence(obj, precedence_data=precedence_data, type=type):
    """Given an AST node object, returns the precedence.
    """
    return precedence_data[type(obj)]


@classmethod
def set_connection(cls, connection):
    """Set a connection for the RGWAdmin session to use."""
    cls.connection = connection


@staticmethod
def decompress(tensor, ctx):
    """Returns the tensor unmodified."""
    return tensor


def unflatten(dictionary):
    """Turn all keys with format {key}.{subkey} into nested dictionaries"""
    unflattened_dictionary = dict()
    for key, value in dictionary.items():
        parts = key.split('.')
        sub_dictionary = unflattened_dictionary
        for part in parts[:-1]:
            if part not in sub_dictionary:
                sub_dictionary[part] = dict()
            sub_dictionary = sub_dictionary[part]
        sub_dictionary[parts[-1]] = value
    return unflattened_dictionary


def is_reduced(obj):
    """A simple predicate to test whether an object has a reduced structure.

     If `obj` does not have a `reducing_end` attribute, this will return :const:`False`

    Parameters
    ----------
    obj : object
        The object to check

    Returns
    -------
    bool
    """
    try:
        return obj.reducing_end is not None
    except AttributeError:
        return False


def single_plural(n, single, plural):
    """Return a single or plural form of a noun based on number."""
    if n == 1:
        return single
    else:
        return plural


@staticmethod
def construct_import_name(name, import_path):
    """Construct import name that will be used in generated config.

        :param name: name of the function that will be imported
        :param import_path: import that should be used to import function
        :return: string representation of function that will be used in generated config
        """
    return '_{import_path}_{name}'.format(import_path=import_path.replace(
        '.', '_'), name=name)


def get_directory(path: str) ->str:
    """Extract directory path."""
    return path.rsplit(sep='/', maxsplit=1)[0] + '/'


@staticmethod
def listify(x):
    """If x is a list then just return it.  If x is a dict then
        return a list with x as the sole item.

        Parameters
        ----------
        x : list, dict
            The list or dict to be listified.

        Returns
        -------
        list: x if x is a list.  If x is a dict then returns a list
        with x as the sole item.
        """
    retVal = x
    if isinstance(x, dict):
        retVal = [x]
    return retVal


def setGapExtPenalty(gap_ext_penalty):
    """Set gap extension penalty used for pairwise alignment."""
    if isinstance(gap_ext_penalty, (float, int)) and gap_ext_penalty <= 0:
        global GAP_EXT_PENALTY
        GAP_EXT_PENALTY = gap_ext_penalty
    else:
        raise TypeError('gap_ext_penalty must be a negative number or zero')


def register(identifier, icon):
    """Register the given icon sub-url to the identifier
        (meta_type, or mime type).
        """


@staticmethod
def check_morpheme_for_conformity(morpheme_root):
    """
        Checks if a morpheme-element is conformant to the Typecraft XML-model.

        It must have the following attributes:
            None

        It must have the following elements:
            None

        :param morpheme_root:
        :return:
        """
    return True


def get_registration_recipient_from_outputs(outputs):
    """
    There are three or four outputs:  the OP_RETURN, the registration
    address, the change address (i.e. from the name preorderer), and
    (for renwals) the burn address for the renewal fee.

    Given the outputs from a name register operation,
    find the registration address's script hex.

    By construction, it will be the first non-OP_RETURN
    output (i.e. the second output).
    """
    ret = None
    for output in outputs:
        output_script = output['scriptPubKey']
        output_asm = output_script.get('asm')
        output_hex = output_script.get('hex')
        output_addresses = output_script.get('addresses')
        if output_asm[0:9] != 'OP_RETURN' and output_hex is not None:
            ret = output_hex
            break
    if ret is None:
        raise Exception('No registration address found')
    return ret


def __register_func_sig(f, d):
    """
    registers all function names in global:functions.
    Only useful for print_funcs and get_function_signature right now, but later could be useful for online help
    #todo parse for signature and callback
    """
    bits = f.split(maxsplit=1)
    first_bracket = bits[1].find('(')
    f = bits[1][:first_bracket]
    rest = bits[1][first_bracket:]
    d[f] = rest


@classmethod
def get_stack(cls, name):
    """Get a stack and initialize it to empty."""
    return cls.__stacks.__dict__.setdefault(name, [])


def fH_PTBO87(TempK, Sal):
    """fH following PTBO87."""
    return 1.29 - 0.00204 * TempK + (0.00046 - 1.48e-06 * TempK) * Sal ** 2


def is_dict(coll):
    """
    Returns true if the collection passed is a dictionary.
    @sig is_dict :: [a] -> bool
    """
    return isinstance(coll, dict)


def delete_identity_provider(UserPoolId=None, ProviderName=None):
    """
    Deletes an identity provider for a user pool.
    See also: AWS API Documentation

    :example: response = client.delete_identity_provider(
        UserPoolId='string',
        ProviderName='string'
    )

    :type UserPoolId: string
    :param UserPoolId: [REQUIRED]
            The user pool ID.

    :type ProviderName: string
    :param ProviderName: [REQUIRED]
            The identity provider name.

    """
    pass


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

        :param PaperPublishedLinkChangePermissionDetails val:
        :rtype: EventDetails
        """
    return cls('paper_published_link_change_permission_details', val)


def _add_str_to_comment(ds, var, s):
    """Add a string to the `comment` attribute of an array in a Dataset"""
    c_ = ds[var].attrs.get('comment')
    c_ = '' if c_ is None else str(c_)
    if c_.endswith('.'):
        c_ += '  '
    ds[var].attrs['comment'] = c_ + s
    return ds


def announce(zelf, *args, **kwargs):
    """ announce to all the running oors. """
    from oor import fleet, kernel
    for bot in fleet:
        bot.announce(args[0])


def scope_matches(required_scope: str, scope: str):
    """
    Checks if two scopes match. They match if and only if the following is true:

        - All parts of required_scope are contained in scope, in the same order as supplied in required_scope.
        - If the scope starts with =, it must match the required scope exactly.

    Examples:
        required    = users:1:edit
        scope       = users:1
        OK
        required    = users:1:edit
        scope       = users:1:create
        NOT OK
        required    = users:1
        scope       = users:1:create
        NOT OK
        required    = company:1:timesheets:create
        scope       = company:1
        OK

    :param required_scope:
    :param scope:
    :return:
    """
    if scope[0] == '=':
        return required_scope == scope[1:]
    return scope in required_scope


def skip_header(filename):
    """Return the number of lines starting with `#`."""
    n = 0
    with open(filename) as f:
        while f.readline()[0] == '#':
            n += 1
    return n


def pad_rem(pv, size=None):
    """ Removes linear padding from array

    This is a convenience function that does the opposite
    of `pad_add`.

    Parameters
    ----------
    pv : 1D or 2D ndarray
        The array from which the padding will be removed.
    size : tuple of length 1 (1D) or 2 (2D), optional
        The final size of the un-padded array. Defaults to half the size
        of the input array.

    Returns
    -------
    pv : 1D or 2D ndarray
        Padded array `av` with pads appended to right and bottom.
    """
    if size is None:
        size = list()
        for s in pv.shape:
            assert s % 2 == 0, 'Uneven size; specify correct size of output!'
            size.append(int(s / 2))
    elif not hasattr(size, '__len__'):
        size = [size]
    assert len(pv.shape) in [1, 2], 'Only 1D and 2D arrays!'
    assert len(pv.shape) == len(size
        ), '`size` must have same length as `av.shape`!'
    if len(pv.shape) == 2:
        return pv[:size[0], :size[1]]
    else:
        return pv[:size[0]]


def sizeof_fmt(num, suffix='B'):
    """ By Fred Cirera, after https://stackoverflow.com/a/1094933/1870254"""
    for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']:
        if abs(num) < 1024.0:
            return '%3.1f%s%s' % (num, unit, suffix)
        num /= 1024.0
    return '%.1f%s%s' % (num, 'Yi', suffix)


def import_name_or_class(name):
    """ Import an object as either a fully qualified, dotted name, """
    if isinstance(name, str):
        module_name, object_name = name.rsplit('.', 1)
        mod = __import__(module_name)
        components = name.split('.')
        for comp in components[1:]:
            mod = getattr(mod, comp)
        return mod
    else:
        return name


def crop_2d(array, array_e, x_start=0, x_end=-1, y_start=0, y_end=-1):
    """
    Crop the data (:py:attr:`array`) with some given start and stop point.

    Args:
        array (:py:attr:`array_like`): The intensity map collected by the 2 dimensional detector.
        array_e (:py:attr:`array_like`): Uncertainty map collected by the 2-D detector.
        x_start (:py:attr:`int`): Start point in x-axis.
        x_end (:py:attr:`int`): End point in x-axis.
        y_start (:py:attr:`int`): Start point in y-axis.
        y_end (:py:attr:`int`): End point in y-axis.

    Returns:
        :py:attr:`array_like`: A cropped intensity map.
    """
    cropped_array = array[y_start:y_end, x_start:x_end]
    if array_e is not None:
        cropped_error = array_e[y_start:y_end, x_start:x_end]
        return cropped_array, cropped_error
    return cropped_array


def key2elements(key):
    """split key to elements"""
    words = key.split('.')
    first2words = words[:2]
    lastword = words[-1]
    namewords = words[2:-1]
    namephrase = '.'.join(namewords)
    if namephrase.startswith("'") and namephrase.endswith("'"):
        namephrase = namephrase[1:-1]
    return first2words + [namephrase] + [lastword]


@staticmethod
def get_for_t_or_latest(w, t):
    """
        Extract values from dict for given time point.
        """
    if t not in w:
        t = max(w)
    return w[t]


def json_is_podman_or_docker_format(json_rep):
    """Check if the inspected file is in a format from docker or podman.

    We know this because the type in the inspect command will be a list
    """
    return isinstance(json_rep, list)


@classmethod
def get(cls, session, parent=None):
    """Gets all of the fantrays from the APIC.  If parent
        is specified, it will only get fantrays that are
        children of the the parent.  The fantrays will
        also be added as children to the parent Node.

        The fantray object is derived mostly from the APIC 'eqptFt' class.

        :param session: APIC session
        :param parent: optional parent switch of class Node

        :returns: list of fantrays
        """
    fans = cls.get_obj(session, cls._get_apic_classes(), parent)
    return fans


def is_rate_limit_error_message(message):
    """Check if the supplied error message belongs to a rate limit error."""
    return isinstance(message, list) and len(message
        ) > 0 and 'code' in message[0] and message[0]['code'] == 88


def _KeyValueToDict(pair):
    """Converts an iterable object of key=value pairs to dictionary."""
    d = dict()
    for kv in pair:
        k, v = kv.split('=', 1)
        d[k] = v
    return d


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 invert_dict(d):
    """Returns a dictionary that maps from values to lists of keys.

    d: dict

    returns: dict
    """
    inv = dict()
    for key in d:
        val = d[key]
        if val not in inv:
            inv[val] = [key]
        else:
            inv[val].append(key)
    return inv


def weight_generator():
    """ Used for weight generation by calculate_731_checksum
    """
    while True:
        yield 7
        yield 3
        yield 1


def canonicalize_temperatures(parsed, current):
    """
	Canonicalizes the temperatures provided in parsed.

	Will make sure that returned result only contains extruder keys
	like Tn, so always qualified with a tool number.

	The algorithm for cleaning up the parsed keys is the following:

	  * If ``T`` is not included with the reported extruders, return
	  * If more than just ``T`` is reported:
	    * If both ``T`` and ``T0`` are reported, remove ``T`` from
	      the result.
	    * Else set ``T0`` to ``T`` and delete ``T`` (Smoothie extra).
	  * If only ``T`` is reported, set ``Tc`` to ``T`` and delete ``T``
	  * return

	Arguments:
	    parsed (dict): the parsed temperatures (mapping tool => (actual, target))
	      to canonicalize
	    current (int): the current active extruder
	Returns:
	    dict: the canonicalized version of ``parsed``
	"""
    reported_extruders = list(filter(lambda x: x.startswith('T'), parsed.
        keys()))
    if not 'T' in reported_extruders:
        return parsed
    current_tool_key = 'T%d' % current
    result = dict(parsed)
    if len(reported_extruders) > 1:
        if 'T0' in reported_extruders:
            if current_tool_key not in reported_extruders:
                result[current_tool_key] = result['T']
            del result['T']
        else:
            result['T0'] = result['T']
            del result['T']
    else:
        result[current_tool_key] = result['T']
        del result['T']
    return result


def should_scrolling_continue(rule_conf):
    """
    Tells about a rule config if it can scroll still or should stop the scrolling.

    :param: rule_conf as dict
    :rtype: bool
    """
    max_scrolling = rule_conf.get('max_scrolling_count')
    stop_the_scroll = 0 < max_scrolling <= rule_conf.get('scrolling_cycle')
    return not stop_the_scroll


@classmethod
def get_name(cls):
    """returns the name of the class (can be overridden)"""
    return cls.__name__


def create_compute_environment(computeEnvironmentName=None, type=None,
    state=None, computeResources=None, serviceRole=None):
    """
    Creates an AWS Batch compute environment. You can create MANAGED or UNMANAGED compute environments.
    In a managed compute environment, AWS Batch manages the compute resources within the environment, based on the compute resources that you specify. Instances launched into a managed compute environment use the latest Amazon ECS-optimized AMI. You can choose to use Amazon EC2 On-Demand instances in your managed compute environment, or you can use Amazon EC2 Spot instances that only launch when the Spot bid price is below a specified percentage of the On-Demand price.
    In an unmanaged compute environment, you can manage your own compute resources. This provides more compute resource configuration options, such as using a custom AMI, but you must ensure that your AMI meets the Amazon ECS container instance AMI specification. For more information, see Container Instance AMIs in the Amazon EC2 Container Service Developer Guide . After you have created your unmanaged compute environment, you can use the  DescribeComputeEnvironments operation to find the Amazon ECS cluster that is associated with it and then manually launch your container instances into that Amazon ECS cluster. For more information, see Launching an Amazon ECS Container Instance in the Amazon EC2 Container Service Developer Guide .
    See also: AWS API Documentation

    Examples
    This example creates a managed compute environment with specific C4 instance types that are launched on demand. The compute environment is called C4OnDemand.
    Expected Output:
    This example creates a managed compute environment with the M4 instance type that is launched when the Spot bid price is at or below 20% of the On-Demand price for the instance type. The compute environment is called M4Spot.
    Expected Output:

    :example: response = client.create_compute_environment(
        computeEnvironmentName='string',
        type='MANAGED'|'UNMANAGED',
        state='ENABLED'|'DISABLED',
        computeResources={
            'type': 'EC2'|'SPOT',
            'minvCpus': 123,
            'maxvCpus': 123,
            'desiredvCpus': 123,
            'instanceTypes': [
                'string',
            ],
            'imageId': 'string',
            'subnets': [
                'string',
            ],
            'securityGroupIds': [
                'string',
            ],
            'ec2KeyPair': 'string',
            'instanceRole': 'string',
            'tags': {
                'string': 'string'
            },
            'bidPercentage': 123,
            'spotIamFleetRole': 'string'
        },
        serviceRole='string'
    )

    :type computeEnvironmentName: string
    :param computeEnvironmentName: [REQUIRED]
            The name for your compute environment. Up to 128 letters (uppercase and lowercase), numbers, and underscores are allowed.

    :type type: string
    :param type: [REQUIRED]
            The type of the compute environment.

    :type state: string
    :param state: The state of the compute environment. If the state is ENABLED , then the compute environment accepts jobs from a queue and can scale out automatically based on queues.

    :type computeResources: dict
    :param computeResources: Details of the compute resources managed by the compute environment. This parameter is required for managed compute environments.
            type (string) -- [REQUIRED]The type of compute environment.
            minvCpus (integer) -- [REQUIRED]The minimum number of EC2 vCPUs that an environment should maintain.
            maxvCpus (integer) -- [REQUIRED]The maximum number of EC2 vCPUs that an environment can reach.
            desiredvCpus (integer) --The desired number of EC2 vCPUS in the compute environment.
            instanceTypes (list) -- [REQUIRED]The instances types that may launched.
            (string) --
            imageId (string) --The Amazon Machine Image (AMI) ID used for instances launched in the compute environment.
            subnets (list) -- [REQUIRED]The VPC subnets into which the compute resources are launched.
            (string) --
            securityGroupIds (list) -- [REQUIRED]The EC2 security group that is associated with instances launched in the compute environment.
            (string) --
            ec2KeyPair (string) --The EC2 key pair that is used for instances launched in the compute environment.
            instanceRole (string) -- [REQUIRED]The Amazon ECS instance role applied to Amazon EC2 instances in a compute environment.
            tags (dict) --Key-value pair tags to be applied to resources that are launched in the compute environment.
            (string) --
            (string) --

            bidPercentage (integer) --The minimum percentage that a Spot Instance price must be when compared with the On-Demand price for that instance type before instances are launched. For example, if your bid percentage is 20%, then the Spot price must be below 20% of the current On-Demand price for that EC2 instance.
            spotIamFleetRole (string) --The Amazon Resource Name (ARN) of the Amazon EC2 Spot Fleet IAM role applied to a SPOT compute environment.

    :type serviceRole: string
    :param serviceRole: [REQUIRED]
            The full Amazon Resource Name (ARN) of the IAM role that allows AWS Batch to make calls to other AWS services on your behalf.

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

    """
    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


def dist2_test(v1, v2, idx1, idx2, len2):
    """Square of distance equal"""
    return (v1 - v2).mag2() == len2


def __ne__(A, other):
    """Returns true if both objects are not equal"""
    return not A == other


def older_message(m, lastm):
    """return true if m is older than lastm by timestamp"""
    atts = {'time_boot_ms': 0.001, 'time_unix_usec': 1e-06, 'time_usec': 1e-06}
    for a in list(atts.keys()):
        if hasattr(m, a):
            mul = atts[a]
            t1 = m.getattr(a) * mul
            t2 = lastm.getattr(a) * mul
            if t2 >= t1 and t2 - t1 < 60:
                return True
    return False


def final_cleanup(engine):
    """Perform final cleanup operations after all scripts have run."""
    pass


def dw_resume(client, database_name, server_name, resource_group_name):
    """
    Resumes a datawarehouse.
    """
    client.resume(server_name=server_name, resource_group_name=
        resource_group_name, database_name=database_name).wait()


def MixedModeConverterVoltage():
    """MixedModeConverterVoltage
    Voltage mixed-mode converter
    @return the s-paramater matrix of a voltage mixed-mode converter.
    Ports 1 2 3 4 are + - D C

    this one has the right definition for differential
    and common mode voltage the way we usually understand it meaning
    that the differential voltage is the difference and the common-mode
    voltage is the average of the plus and minus inputs.
    """
    DF = 1.0
    CF = 2.0
    return [[0.0, 0.0, DF / 2.0, CF / 2.0], [0.0, 0.0, -DF / 2.0, CF / 2.0],
        [1.0 / DF, -1.0 / DF, 0.0, 0.0], [1.0 / CF, 1.0 / CF, 0.0, 0.0]]


def _checkPdfdoc(utext):
    """return true if no Pdfdoc encoding errors"""
    try:
        utext.encode('pdfdoc')
        return 1
    except UnicodeEncodeError as e:
        return 0


@classmethod
def get_contact_type(cls, contact_id):
    """
        Get the type ID for the contactID
        :return: contactType
        """
    return cls.contactTypes[0]


@classmethod
def create_list(cls, accesse, options_list):
    """Create accesse and options menus."""
    for name in ('mechanic', 'master', 'boss', 'info'):
        options_list[name].update(options_list['basic'])
    options_list['admin'].update(options_list['boss'])
    return options_list[accesse]


def substrings(iterable):
    """Yield all of the substrings of *iterable*.

        >>> [''.join(s) for s in substrings('more')]
        ['m', 'o', 'r', 'e', 'mo', 'or', 're', 'mor', 'ore', 'more']

    Note that non-string iterables can also be subdivided.

        >>> list(substrings([0, 1, 2]))
        [(0,), (1,), (2,), (0, 1), (1, 2), (0, 1, 2)]

    """
    seq = []
    for item in iter(iterable):
        seq.append(item)
        yield item,
    seq = tuple(seq)
    item_count = len(seq)
    for n in range(2, item_count + 1):
        for i in range(item_count - n + 1):
            yield seq[i:i + n]


def split(p):
    """Same as posixpath.split, but faster

    >>> import posixpath
    >>> for f in [b'/absolute/path/to/file',
    ...           b'relative/path/to/file',
    ...           b'file_alone',
    ...           b'path/to/directory/',
    ...           b'/multiple/path//separators',
    ...           b'/file_at_root',
    ...           b'///multiple_leading_separators_at_root',
    ...           b'']:
    ...     assert split(f) == posixpath.split(f), f
    """
    ht = p.rsplit(b'/', 1)
    if len(ht) == 1:
        return b'', p
    nh = ht[0].rstrip(b'/')
    if nh:
        return nh, ht[1]
    return ht[0] + b'/', ht[1]


def startListening():
    """
        Start listening on this port.

        @raise CannotListenError: If it cannot listen on this port (e.g., it is
                                  a TCP port and it cannot bind to the required
                                  port number).
        """


def bed_variant_position(interval):
    """Get variant position from BedTool interval"""
    return interval.fields[0] + ':' + interval.fields[1]


@classmethod
def get_name(cls):
    """ Returns the name of the optimizer.

			# Return value

			A lower-case string unique to this optimizer.
		"""
    return cls.__name__.lower()


def tobool(value):
    """
    Tries to convert a wide variety of values to a boolean
    Raises an exception for unrecognised values
    """
    if str(value).lower() in ('yes', 'y', 'true', 't', '1', 'on'):
        return True
    if str(value).lower() in ('no', 'n', 'false', 'f', '0', 'off'):
        return False
    raise ValueError("Don't know how to convert " + str(value) + ' to boolean.'
        )


def stack(seq, dim):
    """Stack the sequence of tensors along the given dimension.

    Parameters
    ----------
    seq : list of Tensor
        The tensor sequence.
    dim : int
        The concat dim.

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


def comprise(list1, list2, **kwargs):
    """
        from elist.elist import *
        comprise([1,2,3,4,5],[2,3,4],mode="loose")
        comprise([1,2,3,4,5],[2,3,4])
        comprise([1,2,3,4,5],[2,3,4],mode="strict")
        comprise([1,2,3,4,5],[1,2,3,4],mode="strict")
        #not recursive ,only one level
        #please refer to ListTree.search for recursive support
    """
    if 'mode' in kwargs:
        mode = kwargs['mode']
    else:
        mode = 'loose'
    len_1 = list1.__len__()
    len_2 = list2.__len__()
    if len_2 > len_1:
        return False
    elif mode == 'strict':
        if list2 == list1[:len_2]:
            return True
        else:
            return False
    else:
        end = len_1 - len_2
        for i in range(0, end + 1):
            if list2 == list1[i:i + len_2]:
                return True
            else:
                pass
    return False


def __eq__():
    """ method to compare resources to keep them unique
        """


def normalize_language_code(code):
    """
    Undo the differences between language code notations
    """
    if code is None:
        return None
    else:
        return code.lower().replace('_', '-')


def normalizeCountry(country_str, target='iso3c'):
    """Return a normalized name/code for country in `country_str`.
    The input can be a code or name, the `target` determines output value.
    3 character ISO code is the default (iso3c), or 'iso2c'; otherwise then formal name is returned.

    Raises ``ValueError`` if the country is unrecognized.
    """
    from iso3166 import countries
    iso2 = 'iso2c'
    iso3 = 'iso3c'
    if country_str is None:
        return ''
    elif country_str.lower() == 'united states':
        country_str += ' of america'
    try:
        cc = countries.get(country_str)
    except KeyError:
        raise ValueError(f'Country not found: {country_str}')
    else:
        if target == iso3:
            return cc.alpha3
        elif target == iso2:
            return cc.alpha2
        else:
            return cc.name


def __key_expansion(key):
    """
        Input: key - String

        Output: extendedkey - String

        This method extends the key to the desired length using hash methods.
    """
    import hashlib
    extendedkey = ''
    keyhash = key
    for _ in range(32):
        keyhash = hashlib.sha224(keyhash.encode('utf-8')).hexdigest()
        extendedkey += keyhash
    extendedkey = extendedkey[:256]
    return extendedkey


def c_set(actor, parameters):
    """Set a facet of an element."""
    if not parameters:
        message = 'You must specify an element, a facet and a value.'
    else:
        arguments = parameters.split(' ', 2)
        if len(arguments) == 1:
            message = 'What facet of element "' + arguments[0
                ] + '" would you like to set?'
        elif len(arguments) == 2:
            message = 'What value would you like to set for the "' + arguments[
                1] + '" facet of the "' + arguments[0] + '" element?'
        else:
            element, facet, value = arguments
            if element not in actor.universe.contents:
                message = 'The "' + element + '" element does not exist.'
            else:
                try:
                    actor.universe.contents[element].set(facet, value)
                except PermissionError:
                    message = (
                        'The "%s" element is kept in read-only file "%s" and cannot be altered.'
                         % (element, actor.universe.contents[element].
                        origin.source))
                except ValueError:
                    message = (
                        'Value "%s" of type "%s" cannot be coerced to the correct datatype for facet "%s".'
                         % (value, type(value), facet))
                else:
                    message = ('You have successfully (re)set the "' +
                        facet + '" facet of element "' + element +
                        '". Try "show element ' + element +
                        '" for verification.')
    actor.send(message)
    return True


def add_comma_rs(_index, _value, _row_separator):
    """Adds a comma and row separator if index > 0, used in loops when making lists of references."""
    if _index > 0:
        return ',' + _row_separator + _value
    else:
        return _value


def rm(path, **kwargs):
    """Remove the file *path*"""
    import os
    return os.unlink(path, **kwargs)


@staticmethod
def cwuri_url(entity):
    """Return an absolute URL for entity's cwuri, necessary for one head ahead application
        handling relative path in cwuri.
        """
    return entity.cwuri


def get_sentence_tokenizer():
    """
    Loads the nltk sentence tokenizer
    """
    try:
        import nltk
    except ImportError:
        raise ImportError('Please install nltk (e.g. pip install nltk).')
    st_path = 'tokenizers/punkt/{0}.pickle'.format('english')
    try:
        sent_tok = nltk.data.load(st_path)
    except LookupError:
        nltk.download('punkt')
        sent_tok = nltk.data.load(st_path)
    return sent_tok


@staticmethod
def lovasz_grad(gt_sorted):
    """
        Computes gradient of the Lovasz extension w.r.t sorted errors
        See Alg. 1 in paper
        """
    p = len(gt_sorted)
    gts = gt_sorted.sum()
    intersection = gts - gt_sorted.float().cumsum(0)
    union = gts + (1 - gt_sorted).float().cumsum(0)
    jaccard = 1.0 - intersection / union
    if p > 1:
        jaccard[1:p] = jaccard[1:p] - jaccard[0:-1]
    return jaccard


def cat_ranges_for_reorder(page_count, new_order):
    """
    Returns a list of integers. Each number in the list
    is correctly positioned (newly ordered) page.

    Examples:

    If in document with 4 pages first and second pages were
    swapped, then returned list will be:

        [2, 1, 3, 4]

    If first page was swapped with last one (also 4 paegs document)
    result list will look like:

        [4, 2, 3, 1]
    """
    results = []
    page_map = {}
    for item in new_order:
        k = int(item['page_order'])
        v = int(item['page_num'])
        page_map[k] = v
    for number in range(1, page_count + 1):
        results.append(page_map[number])
    return results


def psi_Ca_Mg_Cl_PK74(T, P):
    """c-c'-a: calcium magnesium chloride [PK74]."""
    psi = 0.0
    valid = T == 298.15
    return psi, valid


def decode_response(client_message, to_object=None):
    """ Decode response from client message"""
    parameters = dict(response=None)
    if not client_message.read_bool():
        parameters['response'] = to_object(client_message.read_data())
    return parameters


def check_neurontree(neurontree=None):
    """
    This function checks a neurontree
    :param filename: path to swc file as string
    :return: NeuronTree object
    """
    if not neurontree.has_root():
        raise ValueError('Graph has no root defined!')
    if not neurontree.is_connected():
        raise ValueError('Graph has disconnected nodes!')


@classmethod
def _find_configuration_references(cls, code):
    """
        Find all configuration references within block configurations
        """
    references = []
    for match in cls._configuration_reference_re.finditer(code):
        references.append(cls('configuration', match.group('lib'), match.
            group('cfg')))
    return references


@classmethod
def last_operation(cls):
    """Last operation performed."""
    return cls._operations[-1]


def multi_params(schema):
    """Macro function for use in JSONSchema to support query parameters that
    may have multiple values.
    """
    return {'type': 'array', 'items': schema}


def activity_region(activity_arn):
    """
    Return the region for an AWS activity_arn.

    'arn:aws:states:us-east-2:123456789012:stateMachine:hello_world' => 'us-east-2'
    """
    if activity_arn:
        parts = activity_arn.split(':')
        return parts[3] if len(parts) >= 4 else None
    else:
        return None


@classmethod
def field_origin(cls, x, y):
    """Sets the origin coordinates of a field."""
    return cls(cls.FIELD_ORIGIN, x, y)


@staticmethod
def _path_esc(path: str) ->str:
    """Escape space character in the path.

        :param path: path to be escaped
        :type path: str
        :return: path with escaped spaces
        :rtype: str
        """
    return path.replace(' ', '\\ ')


@classmethod
def replace_non_letters_non_numbers_with_whitespace(cls, a_string):
    """
        This function replaces any sequence of non letters and non
        numbers with a single white space.
        """
    return cls.regex.sub(' ', a_string)


def raw_to_b64image(raw: str, alt: str='', title: str='', format: str='png'
    ) ->str:
    """Return given raw data (understood as base64-encoded png) as an HTML-ready png image"""
    data = f'data:image/{format};base64,{raw.strip()}'
    alt = f' alt="{alt}"' if alt else ''
    title = f' title="{title}"' if title else ''
    return f'<img src="{data}"{alt}{title} />'


@staticmethod
def _get_headers(response):
    """Access the headers from an HTTP response.

        Args:
            response (object): The HTTP response object.

        Raises:
            NotImplementedError: Always, since virtual.
        """
    raise NotImplementedError(u'This implementation is virtual.')


def sitemap_urls_from_robots(robots_text):
    """Return an iterator over all sitemap urls contained in the given
    robots.txt file
    """
    for line in robots_text.splitlines():
        if line.lstrip().lower().startswith('sitemap:'):
            yield line.split(':', 1)[1].strip()


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

        :param DesktopDeviceSessionLogInfo val:
        :rtype: LinkedDeviceLogInfo
        """
    return cls('desktop_device_session', val)


def bake():
    """Bake selected F-Curves to a set of sampled points defining a similar curve

    """
    pass


def cast_default(*, value: str, params: str, shared: dict) ->str:
    """Default caster, performing basic transformations.

    :param value: Current value.
    :param params: Additional value-related parameters.
    :param shared: Global shared parameters.

    """
    return value.replace('\\,', ',')


def median(values=None):
    """Return the median of 'values'

    Keyword arguments:
    values -- the list of numbers
    """
    sorts = sorted(values)
    length = len(sorts)
    result = None
    if not values:
        result = 0
    elif not length % 2:
        result = (sorts[length // 2] + sorts[length // 2 - 1]) / 2.0
    else:
        result = sorts[length // 2]
    return result


def format(o, keys=None, full=False):
    """ format an object into a displayable string. """
    if keys is None:
        keys = vars(o).keys()
    res = []
    txt = ''
    for k in keys:
        v = getattr(o, k, None)
        if not v:
            continue
        v = str(v)
        if full:
            res.append('%s=%s ' % (k, v))
        else:
            res.append(v)
    for v in res:
        txt += '%s ' % v.strip()
    return txt.strip()


def forcefield_toggle():
    """Toggle object’s force field

    """
    pass


def __new__(cls, *args, **kwds):
    """
        Dictionary with immutable keys: the values associated to each key can
        be changed, but new keys cannot be added or deleted.

        Example
        -------

        >>> D = frozenkeydict({'foo': 'bar', 'ham': 'spam'})
        >>> D['foo'] = 'foobar'
        >>> D['bacon'] = 'eggs'
        Traceback (most recent call last):
        ...
        KeyError: 'cannot add new keys to frozenkeydict.'

        """
    return dict.__new__(cls, *args, **kwds)


@classmethod
def get_by_user_or_404(cls, item_id, user):
    """
        return the object with the given id that is owned by the given user

        :param item_id: object id
        :param user: the user to use as a filter, assumes relationship name is user
        :return: the object
        :throws: 404 exception if not found
        """
    return cls.query.filter_by(id=item_id, user=user).first_or_404()


def xidz(numerator, denominator, value_if_denom_is_zero):
    """
    Implements Vensim's XIDZ function.
    This function executes a division, robust to denominator being zero.
    In the case of zero denominator, the final argument is returned.

    Parameters
    ----------
    numerator: float
    denominator: float
        Components of the division operation
    value_if_denom_is_zero: float
        The value to return if the denominator is zero

    Returns
    -------
    numerator / denominator if denominator > 1e-6
    otherwise, returns value_if_denom_is_zero
    """
    small = 1e-06
    if abs(denominator) < small:
        return value_if_denom_is_zero
    else:
        return numerator * 1.0 / denominator


def set_lock(lock) ->None:
    """
    Set lock object, used to have the same lock object
    in all processes even if using spawn process start method.
    """
    global sqlite_lock
    sqlite_lock = lock


def getPrincipal(id):
    """Get principal meta-data.

        Returns an object of type :class:`~.IPrincipal` for the given principal
        id. A :class:`PrincipalLookupError` is raised if the principal cannot be
        found.

        Note that the authentication utility nearest to the requested
        resource is called. It is up to authentication utility
        implementations to collaborate with utilities higher in the
        object hierarchy.
        """


@staticmethod
def metadata_id(item):
    """Extracts the identifier from a Puppet forge item."""
    item_id = item['owner']['username'] + '-' + item['name']
    return item_id


def prepare_definitions(defs, prefix=None):
    """
    prepares definitions from a dictionary

    With a provided dictionary of definitions in key-value pairs and builds them
    into an definition list. For example, if a dictionary contains a key ``foo``
    with a value ``bar``, the returns definitions will be a list with the values
    ``['foo=bar']``. If a key contains a value of ``None``, the key will be
    ignored and will not be part of the final definition list. If a ``prefix``
    value is provided, each definition entry will be prefixed with the provided
    value.

    Args:
        defs: the arguments to process
        prefix (optional): prefix value to prefix each definition

    Returns:
        list of arguments
    """
    final = []
    if defs:
        for key, val in defs.items():
            if val is None:
                continue
            if prefix:
                key = prefix + key
            else:
                key = key
            if val:
                final.append('{}={}'.format(key, val))
            else:
                final.append(key)
    return final


def bond_is_in_ring(bond):
    """Get whether the bond is in a ring of any size.
    Parameters
    ----------
    bond : rdkit.Chem.rdchem.Bond
        RDKit bond instance.
    Returns
    -------
    list
        List containing one bool only.
    """
    return [bond.IsInRing()]


def __ne__(A, other):
    """Returns true if both objects are not equal"""
    return not A == other


@classmethod
def get_policy(cls):
    """Return the ARN for the polciy that must be included."""
    return cls.policy_name_to_arn('CloudWatchAgentServerPolicy')


def unauthenticated(func):
    """Adds 'unauthenticated' attribute to decorated function.

    Usage:

    >>> @unauthenticated
    ... def mymethod(f):
    ...     pass
    """
    func.unauthenticated = True
    return func


def split(Instances):
    """'' Split the 4 attibutes, collect the data of the ith attributs, i=0,1,2,3
        Return a list like [['0.2', 'Iris-setosa'], ['0.2', 'Iris-setosa'],...]"""
    log = []
    for i in range(len(Instances)):
        log.append([Instances.iloc[i][0], Instances.iloc[i][1]])
    return log


def int_parse(s):
    """
    Parse an integer string in a log file.

    This is a simple variant on int() that returns None in the case of a single
    dash being passed to s.

    :param str s: The string containing the integer number to parse
    :returns: An int value
    """
    return int(s) if s != '-' else None


def add_source_identifier_to_subscription(SubscriptionName=None,
    SourceIdentifier=None):
    """
    Adds a source identifier to an existing RDS event notification subscription.
    See also: AWS API Documentation

    Examples
    This example add a source identifier to an event notification subscription.
    Expected Output:

    :example: response = client.add_source_identifier_to_subscription(
        SubscriptionName='string',
        SourceIdentifier='string'
    )

    :type SubscriptionName: string
    :param SubscriptionName: [REQUIRED]
            The name of the RDS event notification subscription you want to add a source identifier to.

    :type SourceIdentifier: string
    :param SourceIdentifier: [REQUIRED]
            The identifier of the event source to be added. An identifier must begin with a letter and must contain only ASCII letters, digits, and hyphens; it cannot end with a hyphen or contain two consecutive hyphens.
            Constraints:
            If the source type is a DB instance, then a DBInstanceIdentifier must be supplied.
            If the source type is a DB security group, a DBSecurityGroupName must be supplied.
            If the source type is a DB parameter group, a DBParameterGroupName must be supplied.
            If the source type is a DB snapshot, a DBSnapshotIdentifier must be supplied.

    :rtype: dict
    :return: {
        'EventSubscription': {
            'CustomerAwsId': 'string',
            'CustSubscriptionId': 'string',
            'SnsTopicArn': 'string',
            'Status': 'string',
            'SubscriptionCreationTime': 'string',
            'SourceType': 'string',
            'SourceIdsList': [
                'string',
            ],
            'EventCategoriesList': [
                'string',
            ],
            'Enabled': True|False,
            'EventSubscriptionArn': 'string'
        }
    }

    :returns:
    (string) --

    """
    pass


def parse_helm_list_output(helm_list_output):
    """
    Function will perform a manipulation on a string output from the 'helm list' command

    Returns an array of dicts with installed chart names and namespaces as strings
    as [{'chart_name': 'some_chart_name', 'name_space': 'some_name_space'}]

    by validating the first line, splitting by the tab delimiter,
    and checking that the first (0) value is 'NAME' and seventh (6) value is 'NAMESPACE'
    an exception will be raised if the structure was change by HELM developers

    :param helm_list_output: 'helm list' output as String
    :return: list of dicts
    """
    installed_charts = []
    installed_helm_stdout = helm_list_output.split('\n')
    first_line_stdout = installed_helm_stdout[0].split('\t')
    if first_line_stdout[0].strip() != 'NAME' or first_line_stdout[6].strip(
        ) != 'NAMESPACE':
        raise Exception(
            "'helm list' command output changed, probably due to helm version update, code change is needed to resolve this issue, contact the developer."
            )
    for line in installed_helm_stdout[1:]:
        chart_details = line.split('\t')
        temp_dictionary = {}
        if chart_details[0] != '':
            temp_dictionary.update({'chart_name': chart_details[0].strip()})
            temp_dictionary.update({'name_space': chart_details[6].strip()})
            installed_charts.append(temp_dictionary)
    return installed_charts


def bold(s):
    """
    Return the given string (``s``) surrounded by the ANSI escape codes to
    print it in bold.
    :param s: string to console format as bold
    :type s: str
    :returns: s surrounded by ANSI color escapes for green text
    :rtype: str
    """
    return '\x1b[1m' + s + '\x1b[0m'


@classmethod
def create(Class, **newdata):
    """create new asset on server and return created asset proxy instance"""
    return Class._v1_v1meta.create_asset(Class._v1_asset_type_name, newdata)


def plural(s, number, suffix='s'):
    """
    Insert the number into the string, and make plural where marked, if needed.

    The string should use `{number}` to mark the place(s) where the number is
    inserted and `{s}` where an "s" needs to be added if the number is not 1.

    For instance, a string could be "I saw {number} dog{s} in the forest".

    Argument `suffix` can be used for some forms or irregular plural, like:

        plural("I saw {number} fox{s} in the forest", x, "es")
        plural("I say {number} child{s} in the forest", x, "ren")

    :param s: string
    :type s: str
    :param number: number
    :type number: int
    :param suffix: the suffix to use; default is "s"
    :type suffix: str
    :rtype: str
    """
    return s.format(number=number, s=suffix if number % 100 != 1 else '')