def _convert_mem_units(from_val, from_units: str=None, to_units: str=None,
    sig_digits=None):
    """
    Convert memory units.

    Arguments:
        from_val {[type]} -- [description]

    Keyword Arguments:
        from_units {str} -- [description] (default: {None})
        to_units {str} -- [description] (default: {None})
        sig_digits {[type]} -- [description] (default: {None})

    Returns:
        [type] -- [description]
    """
    from_units = from_units or 'B'
    _mem_units_map = {'B': 1, 'K': 1024 ** 1, 'MB': 1024 ** 2, 'GB': 1024 **
        3, 'TB': 1024 ** 4}
    num_bytes = from_val * _mem_units_map[from_units]
    return_tuple = not to_units
    if not to_units:
        cutover_factor = 800
        if to_units not in _mem_units_map:
            if num_bytes < 100:
                to_units = 'B'
            if num_bytes < cutover_factor * _mem_units_map['K']:
                to_units = 'K'
            elif num_bytes < cutover_factor * _mem_units_map['MB']:
                to_units = 'MB'
            elif num_bytes < cutover_factor * _mem_units_map['GB']:
                to_units = 'GB'
            else:
                to_units = 'TB'
    result = num_bytes * 1.0 / _mem_units_map[to_units]
    if not sig_digits:
        sig_digits = 1 if result >= 10 else 2
    if return_tuple:
        return round(result, sig_digits), to_units
    return round(result, sig_digits)


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


def currency_data_list():
    """Returns the most recent currency data as a list of dictionaries.
        ex)
        [
            {
            code: "EUR",
            rate: [156.05, 160.25, ...],
            name: u"Euro",
            unit: u"€"
            },
            {...},{...},...
        ]
        """


def is_transition_allowed(constraint_type: str, from_tag: str, from_entity:
    str, to_tag: str, to_entity: str):
    """
    Given a constraint type and strings ``from_tag`` and ``to_tag`` that
    represent the origin and destination of the transition, return whether
    the transition is allowed under the given constraint type.

    Parameters
    ----------
    constraint_type : ``str``, required
        Indicates which constraint to apply. Current choices are
        "BIO", "IOB1", "BIOUL", and "BMES".
    from_tag : ``str``, required
        The tag that the transition originates from. For example, if the
        label is ``I-PER``, the ``from_tag`` is ``I``.
    from_entity: ``str``, required
        The entity corresponding to the ``from_tag``. For example, if the
        label is ``I-PER``, the ``from_entity`` is ``PER``.
    to_tag : ``str``, required
        The tag that the transition leads to. For example, if the
        label is ``I-PER``, the ``to_tag`` is ``I``.
    to_entity: ``str``, required
        The entity corresponding to the ``to_tag``. For example, if the
        label is ``I-PER``, the ``to_entity`` is ``PER``.

    Returns
    -------
    ``bool``
        Whether the transition is allowed under the given ``constraint_type``.
    """
    if to_tag == 'START' or from_tag == 'END':
        return False
    if constraint_type == 'BIOUL':
        if from_tag == 'START':
            return to_tag in ('O', 'B', 'U')
        if to_tag == 'END':
            return from_tag in ('O', 'L', 'U')
        return any([from_tag in ('O', 'L', 'U') and to_tag in ('O', 'B',
            'U'), from_tag in ('B', 'I') and to_tag in ('I', 'L') and
            from_entity == to_entity])
    elif constraint_type == 'BIO':
        if from_tag == 'START':
            return to_tag in ('O', 'B')
        if to_tag == 'END':
            return from_tag in ('O', 'B', 'I')
        return any([to_tag in ('O', 'B'), to_tag == 'I' and from_tag in (
            'B', 'I') and from_entity == to_entity])
    elif constraint_type == 'IOB1':
        if from_tag == 'START':
            return to_tag in ('O', 'I')
        if to_tag == 'END':
            return from_tag in ('O', 'B', 'I')
        return any([to_tag in ('O', 'I'), to_tag == 'B' and from_tag in (
            'B', 'I') and from_entity == to_entity])
    elif constraint_type == 'BMES':
        if from_tag == 'START':
            return to_tag in ('B', 'S')
        if to_tag == 'END':
            return from_tag in ('E', 'S')
        return any([to_tag in ('B', 'S') and from_tag in ('E', 'S'), to_tag ==
            'M' and from_tag in ('B', 'M') and from_entity == to_entity,
            to_tag == 'E' and from_tag in ('B', 'M') and from_entity ==
            to_entity])
    else:
        raise f'Unknown constraint type: {constraint_type}'


def munii_NH3_NH4_SO4_CB89(T, P):
    """n-a-a': ammonia ammonium sulfate [CB89]."""
    munii = -0.00153
    valid = T == 298.15
    return munii, valid


def _find_reserved_periods(events, quantity, capacity):
    """Find the reserved periods."""
    reserved_periods = []
    used = 0
    reserved_start = None
    for event_date in sorted(events):
        used += events[event_date]['quantity']
        if not reserved_start and used + quantity > capacity:
            reserved_start = event_date
        elif reserved_start and used + quantity <= capacity:
            reserved_periods.append((reserved_start, event_date))
            reserved_start = None
    return reserved_periods


def _validate_ft_struct(ft_struct):
    """Run validation checks on the ft_structure."""
    if isinstance(ft_struct, list):
        raise RuntimeError('Loading of data in cell arrays is not supported')


def get_keywords():
    """Get the keywords needed to look up the version information."""
    git_refnames = '$Format:%d$'
    git_full = '$Format:%H$'
    git_date = '$Format:%ci$'
    keywords = {'refnames': git_refnames, 'full': git_full, 'date': git_date}
    return keywords


def any(iter):
    """ For < Python2.5 compatibility. """
    for elem in iter:
        if elem:
            return True
    return False


def smart_with_parent(smart_string):
    """Return lxml 'smart' string representation (UTF-8) with parent relation.

    lxml 'smart' string is a text node (atomic value) or an attribute node:
     * text node (tail, entity): contains text; never empty
     * attribute node: contains the value of the attribute
    """
    smart_repr = None
    parent_rel = None
    if smart_string.is_attribute:
        parent_rel = 'of'
        smart_repr = "@%s = '%s'" % (smart_string.attrname, smart_string)
    elif smart_string.is_text:
        parent_rel = 'in'
        if smart_string.isspace():
            smart_repr = 'whitespace'
        else:
            smart_repr = "'%s'" % smart_string
    elif smart_string.is_tail:
        parent_rel = 'after'
        if smart_string.isspace():
            smart_repr = 'tail whitespace'
        else:
            smart_repr = "tail '%s'" % smart_string
    return smart_repr, parent_rel


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


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

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

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


def format_success(event_dict=None):
    """
    Creates or updates an event dict to include the standard 'error' and 'has_error' fields with default values

    Args:
        event_dict (dict): Optional input to pass a dict of existing results to update. If none is provided, a dict
            containing only the new default fields will be returned.

    Returns:
        dict: New or updated dict containing default 'error' and 'has_error' keys
    """
    if not isinstance(event_dict, dict):
        event_dict = {'result': event_dict}
    event_dict.update({'error': None, 'has_error': False})
    return event_dict


def slot_paste():
    """Copy the texture settings and nodes

    """
    pass


def load_referenced_json_config(filepath):
    """
    Loads a json file that has "jsonref" style references and resolves the references
    :param string filepath: The path from which to reads the JSON
    :return: dict
    """
    import jsonref
    from copy import deepcopy
    with open(filepath, 'r') as f:
        config = jsonref.load(f)
    config = deepcopy(config)
    return config


def serializeSchema(schema, name=u''):
    """Return an XML string representing the given schema interface. This
        is a convenience method around the serializeModel() method, below.
        """


@staticmethod
def removeChildren(namespace, prefixes, extendedModule, referedModule):
    """
        This static method is used to remove children from the extended module.

        Parameters
        ----------
        namespace: string
            namespace of the referedModule.
        prefixes: list
            list of prefixes of objects to remove.
        extendedModule: ExtendedModule
            :class:`ExtendedModule` object to remove objects from.
        referedModule: module
            refered module object.
        """
    locals = extendedModule.locals
    to_remove = []
    for key in locals.keys():
        if not key.startswith('__'):
            for prefix in prefixes:
                if key.startswith(prefix):
                    to_remove.append(key)
    for key in to_remove:
        del locals[key]


@classmethod
def get_operations(cls, request, ppm_id):
    """
        Make a request to P2MD to get a full history of all data operations conducted
        for the participant.
        """
    return cls.get(request, f'/sources/api/ppm/{ppm_id}')


def _attachment_name_or_type(name_or_type):
    """
    Returns a query item matching messages that have attachments with a
    certain name or file type.

    Args:
        name_or_type (str): The specific name of file type to match.

    Returns:
        The query string.

    """
    return f'filename:{name_or_type}'


def p_relation(p):
    """relation : left_rel
                | right_rel"""
    p[0] = p[1]


def _get_comparable_seq(seq_i, seq_j, start_phase, end_phase):
    """
    Return the residues of the exon/subexon that can be shared.

    It takes into account that first/last residue could be different
    if the start/end phase is different from 0 or -1.

    >>> _get_comparable_seq("ASMGSLTSSPSSL", "TSMGSLTSSPSSC", 1, 2)
    ('SMGSLTSSPSS', 'SMGSLTSSPSS')
    """
    if start_phase in [1, 2]:
        seq_i = seq_i[1:]
        seq_j = seq_j[1:]
    if end_phase in [1, 2]:
        seq_i = seq_i[:-1]
        seq_j = seq_j[:-1]
    return seq_i, seq_j


@classmethod
def load(cls, encoded_data, strict=False):
    """
        Loads a BER/DER-encoded byte string using the current class as the spec

        :param encoded_data:
            A byte string of BER or DER encoded data

        :param strict:
            A boolean indicating if trailing data should be forbidden - if so, a
            ValueError will be raised when trailing data exists

        :return:
            A Concat object
        """
    return cls(contents=encoded_data, strict=strict)


@classmethod
def fromkeys(cls, iterable, value=None):
    """
        Create a new trie with keys from ``iterable`` and values set to
        ``value``.

        Parameters are the same with ``dict.fromkeys()``.
        """
    trie = cls()
    for key in iterable:
        trie[key] = value
    return trie


def get_client_ip(request):
    """Retrieve the real IP address of the client."""
    if 'HTTP_X_REAL_IP' in request.META:
        return request.META.get('HTTP_X_REAL_IP')
    elif 'REMOTE_ADDR' in request.META:
        return request.META.get('REMOTE_ADDR')
    else:
        return '0.0.0.0'


@classmethod
def from_unmatched(cls, unmatched):
    """Construct a `MatchResult` from just unmatched segments."""
    return cls(matched_segments=(), unmatched_segments=cls.seg_to_tuple(
        unmatched))


def target_end(info):
    """
        Process event of target's success or failure.

        Input:
        `info`  # An object with information about target's number and result.
        """


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

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


def setMessage(msgid, message, mod_time=None):
    """Set a message to the catalog. If `mod_time` is ``None`` use the
        current time instead as modification time."""


def _normaliseBounds(shape, bounds):
    """Adjust the given ``bounds`` so that it is compatible with the given
    ``shape``.

    Bounds must be specified for at least three dimensions - if the shape
    has more than three dimensions, additional bounds are added.

    A :exc:`ValueError` is raised if the provided bounds are invalid.

    :arg bounds: Sequence of ``(lo, hi)`` bounds - see :func:`roi`.
    :returns:    An adjusted sequence of bounds.
    """
    bounds = list(bounds)
    if len(bounds) < 3:
        raise ValueError('')
    if len(bounds) > len(shape):
        raise ValueError('')
    for b in bounds:
        if len(b) != 2 or b[0] >= b[1]:
            raise ValueError('')
    if len(bounds) < len(shape):
        for s in shape[len(bounds):]:
            bounds.append((0, s))
    return bounds


def setStrict(on=''):
    """ Turn on assertions (which may cause conflicts) """
    global STRICT
    STRICT = on


def lookupNameservers(name, timeout=None):
    """
        Perform an NS record lookup.

        @type name: L{bytes} or L{str}
        @param name: DNS name to resolve.

        @type timeout: Sequence of C{int}
        @param timeout: Number of seconds after which to reissue the query.
            When the last timeout expires, the query is considered failed.

        @rtype: L{Deferred}
        @return: A L{Deferred} which fires with a three-tuple of lists of
            L{twisted.names.dns.RRHeader} instances.  The first element of the
            tuple gives answers.  The second element of the tuple gives
            authorities.  The third element of the tuple gives additional
            information.  The L{Deferred} may instead fail with one of the
            exceptions defined in L{twisted.names.error} or with
            C{NotImplementedError}.
        """


def pair_uv_to_hf(network, volmesh):
    """Pairs the directed edges (u, v) of a network to the corresponding halffaces of the dual volmesh.

    Parameters
    ----------
    volmesh : VolMesh
        A volmesh object representing a polyhedral force diagram.
    network : Network
        A network object representing a polyhedral form diagram.

    Returns
    -------
    dictionary
        A dictionary of (u, v)-u_hfkey pairs.

    """
    uv_hf_dict = {}
    for u, v in network.edges():
        u_hfkey, v_hfkey = volmesh.cell_pair_halffaces(u, v)
        uv_hf_dict[u, v] = u_hfkey
    return uv_hf_dict


def version_param(params):
    """Return the value of the HTTP version parameter, or `None` if no
    version parameter is supplied.

    """
    for k, v in params.items():
        if k.lower() == 'version':
            return v


def bubbleFraction(ub, us, umf, emf):
    """
    Determine the fraction of the bed that is in the bubble phase using
    Equations 6.26 through 6.29 from Kunii and Levenspiel [1]_.

    Parameters
    ----------
    ub : float
        Bubble rise velocity [m/s, cm/s, etc.]
    us : float
        Superficial gas velocity [m/s, cm/s, etc.]
    umf : float
        Minimum fluidization velocity [m/s, cm/s, etc.]
    emf : float
        Minimum fluidization void fraction [-]

    Returns
    -------
    delta : float
        Fraction of the total bed volume that is in bubbles [-]

    Note
    ----
    Units are not important, provided they are consistent, as the calculation
    returns a dimensionless quantity.

    References
    ----------
    .. [1] Daizo Kunii and Octave Levenspiel. Fluidization Engineering.
           Butterworth-Heinemann, 2nd edition, 1991.
    """
    ue = umf / emf
    ub_ue_ratio = float(ub) / float(ue)
    if ub_ue_ratio < 1:
        delta = (us - umf) / (ub + 2 * umf)
    elif ub_ue_ratio > 10:
        delta = us / ub
    elif ub_ue_ratio > 5:
        delta = (us - umf) / (ub - umf)
    elif ub_ue_ratio < 3:
        delta = (us - umf) / (ub + umf)
    else:
        delta = (us - umf) / ub
    return delta


@classmethod
def from_values(cls, *args, **kwargs):
    """Create a new request object based on the values provided.  If
        environ is given missing values are filled from there.  This method is
        useful for small scripts when you need to simulate a request from an URL.
        Do not use this method for unittesting, there is a full featured client
        object (:class:`Client`) that allows to create multipart requests,
        support for cookies etc.

        This accepts the same options as the
        :class:`~werkzeug.test.EnvironBuilder`.

        .. versionchanged:: 0.5
           This method now accepts the same arguments as
           :class:`~werkzeug.test.EnvironBuilder`.  Because of this the
           `environ` parameter is now called `environ_overrides`.

        :return: request object
        """
    from werkzeug.test import EnvironBuilder
    charset = kwargs.pop('charset', cls.charset)
    kwargs['charset'] = charset
    builder = EnvironBuilder(*args, **kwargs)
    try:
        return builder.get_request(cls)
    finally:
        builder.close()


def lyap_dense_solver_options():
    """Return available dense Lyapunov solvers with default options for the SciPy backend.

    Returns
    -------
    A dict of available solvers with default solver options.
    """
    return {'scipy': {'type': 'scipy'}}


def join_sequence_of_dicts(seq):
    """
    Joins a sequence of dicts into a single dict

    Parameters
    ----------
    seq: sequence
        Sequence of dicts to join

    Returns
    -------
    dict

    Raises
    ------
    RuntimeError if a duplicate key is encountered.
    """
    r = {}
    for d in seq:
        for k, v in d.items():
            if k in r:
                raise RuntimeError(
                    'Duplicate key %r (new value: %r, was: %r)' % (k, v, r[k]))
            r[k] = v
    return r


def get_subscribe_broadcast_messages(received_message, subscription_id,
    connection_id):
    """
    Return a BroadcastMessage to be delivered to other connections,
    possibly connected through redis pub/sub

    This message is called whenever an user subscribes to a topic.
    """
    assert received_message is not None, 'get_subscribe_broadcast_message requires a received_message'
    assert subscription_id is not None, 'get_subscribe_broadcast_message requires a subscription_id'
    assert connection_id is not None, 'get_subscribe_broadcast_message requires a connection_id'
    return []


def scaleto255(value):
    """Scale the input value from 0-100 to 0-255."""
    if value > 98:
        value = 100
    return max(0, min(255, value * 255.0 / 100.0))


def make_public_key(prime, base, rnumber):
    """
        Returns (base^number) mod prime, the public key used for the key exchange.
    """
    pub_key = base ** rnumber % prime
    return pub_key


def default_tzinfo(dt, tzinfo):
    """
    Sets the the ``tzinfo`` parameter on naive datetimes only

    This is useful for example when you are provided a datetime that may have
    either an implicit or explicit time zone, such as when parsing a time zone
    string.

    .. doctest::

        >>> from dateutil.tz import tzoffset
        >>> from dateutil.parser import parse
        >>> from dateutil.utils import default_tzinfo
        >>> dflt_tz = tzoffset("EST", -18000)
        >>> print(default_tzinfo(parse('2014-01-01 12:30 UTC'), dflt_tz))
        2014-01-01 12:30:00+00:00
        >>> print(default_tzinfo(parse('2014-01-01 12:30'), dflt_tz))
        2014-01-01 12:30:00-05:00

    :param dt:
        The datetime on which to replace the time zone

    :param tzinfo:
        The :py:class:`datetime.tzinfo` subclass instance to assign to
        ``dt`` if (and only if) it is naive.

    :return:
        Returns an aware :py:class:`datetime.datetime`.
    """
    if dt.tzinfo is not None:
        return dt
    else:
        return dt.replace(tzinfo=tzinfo)


@classmethod
def get_sequences(cls, samples, registry):
    """
        Return list of sequences from a list of samples.

        :param samples: list of samples
        :param registry: connector registry
        :return:
        """
    dnas = []
    for sample in samples:
        if isinstance(sample, cls):
            dnas.append(sample)
        else:
            dnas.append(cls(sample, registry))
    sequences = []
    for dna in dnas:
        sequences.append(dna.sequence())
    return sequences


@classmethod
def set_verbose(cls, verbose):
    """ Toggle verbosity. """
    cls.get_instance().verbose = verbose


def display_assignation(positions):
    """Shows the assignation."""
    for r in positions:
        for s in range(positions[r]):
            if r != 'NA':
                print(r + 1)
            else:
                print('NA')


def read_homefile(filepath: str='', load_ui: bool=True, use_empty: bool=
    False, use_splash: bool=False, app_template='Template'):
    """Open the default file (doesn’t save the current file)

    :param filepath: File Path, Path to an alternative start-up file
    :type filepath: str
    :param load_ui: Load UI, Load user interface setup from the .blend file
    :type load_ui: bool
    :param use_empty: Empty
    :type use_empty: bool
    :param use_splash: Splash
    :type use_splash: bool
    """
    pass


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

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

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


def upload_documents(documents=None, contentType=None):
    """
    Posts a batch of documents to a search domain for indexing. A document batch is a collection of add and delete operations that represent the documents you want to add, update, or delete from your domain. Batches can be described in either JSON or XML. Each item that you want Amazon CloudSearch to return as a search result (such as a product) is represented as a document. Every document has a unique ID and one or more fields that contain the data that you want to search and return in results. Individual documents cannot contain more than 1 MB of data. The entire batch cannot exceed 5 MB. To get the best possible upload performance, group add and delete operations in batches that are close the 5 MB limit. Submitting a large volume of single-document batches can overload a domain's document service.
    The endpoint for submitting UploadDocuments requests is domain-specific. To get the document endpoint for your domain, use the Amazon CloudSearch configuration service DescribeDomains action. A domain's endpoints are also displayed on the domain dashboard in the Amazon CloudSearch console.
    For more information about formatting your data for Amazon CloudSearch, see Preparing Your Data in the Amazon CloudSearch Developer Guide . For more information about uploading data for indexing, see Uploading Data in the Amazon CloudSearch Developer Guide .
    See also: AWS API Documentation

    :example: response = client.upload_documents(
        documents=b'bytes'|file,
        contentType='application/json'|'application/xml'
    )

    :type documents: bytes or seekable file-like object
    :param documents: [REQUIRED]
            A batch of documents formatted in JSON or HTML.

    :type contentType: string
    :param contentType: [REQUIRED]
            The format of the batch you are uploading. Amazon CloudSearch supports two document batch formats:
            application/json
            application/xml

    :rtype: dict
    :return: {
        'status': 'string',
        'adds': 123,
        'deletes': 123,
        'warnings': [
            {
                'message': 'string'
            },
        ]
    }

    """
    pass


@classmethod
def teal(cls):
    """A factory method that returns a :class:`Colour` with a value of ``0x1abc9c``."""
    return cls(1752220)


@classmethod
def light_grey(cls):
    """A factory method that returns a :class:`Colour` with a value of ``0x979c9f``."""
    return cls(9936031)


def connack_string(connack_code):
    """Return the string associated with a CONNACK result."""
    if connack_code == 0:
        return 'Connection Accepted.'
    elif connack_code == 1:
        return 'Connection Refused: unacceptable protocol version.'
    elif connack_code == 2:
        return 'Connection Refused: identifier rejected.'
    elif connack_code == 3:
        return 'Connection Refused: broker unavailable.'
    elif connack_code == 4:
        return 'Connection Refused: bad user name or password.'
    elif connack_code == 5:
        return 'Connection Refused: not authorised.'
    else:
        return 'Connection Refused: unknown reason.'


def qualifyKind(kind):
    """
    Qualifies the breathe ``kind`` and returns an qualifier string describing this
    to be used for the text output (e.g. in generated file headings and link names).

    The output for a given kind is as follows:

    +-------------+------------------+
    | Input Kind  | Output Qualifier |
    +=============+==================+
    | "class"     | "Class"          |
    +-------------+------------------+
    | "define"    | "Define"         |
    +-------------+------------------+
    | "enum"      | "Enum"           |
    +-------------+------------------+
    | "enumvalue" | "Enumvalue"      |
    +-------------+------------------+
    | "file"      | "File"           |
    +-------------+------------------+
    | "function"  | "Function"       |
    +-------------+------------------+
    | "group"     | "Group"          |
    +-------------+------------------+
    | "namespace" | "Namespace"      |
    +-------------+------------------+
    | "struct"    | "Struct"         |
    +-------------+------------------+
    | "typedef"   | "Typedef"        |
    +-------------+------------------+
    | "union"     | "Union"          |
    +-------------+------------------+
    | "variable"  | "Variable"       |
    +-------------+------------------+

    The following breathe kinds are ignored:

    - "autodoxygenfile"
    - "doxygenindex"
    - "autodoxygenindex"

    Note also that although a return value is generated, neither "enumvalue" nor
    "group" are actually used.

    :Parameters:
        ``kind`` (str)
            The return value of a Breathe ``compound`` object's ``get_kind()`` method.

    :Return (str):
        The qualifying string that will be used to build the reStructuredText titles and
        other qualifying names.  If the empty string is returned then it was not
        recognized.
    """
    if kind == 'dir':
        return 'Directory'
    else:
        return kind.capitalize()


@staticmethod
def strip(elem):
    """
        Removes extra whitespace between xml elements and within the text.

        :param elem: the root element to remove the whitespace between and its children.
        :type elem: Element
        """
    for elem in elem.iter():
        if elem.text:
            elem.text = elem.text.strip()
        if elem.tail:
            elem.tail = elem.tail.strip()


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 flipcheck(content):
    """Checks a string for anger and soothes said anger

    Args:
        content (str): The message to be flipchecked

    Returns:
        putitback (str): The righted table or text
    """
    punct = '!"#$%&\'*+,-./:;<=>?@[\\]^_`{|}~ ━─'
    tamperdict = str.maketrans('', '', punct)
    tamperproof = content.translate(tamperdict)
    if '(╯°□°）╯︵' in tamperproof:
        if '┻┻' in tamperproof:
            length = 0
            for letter in content:
                if letter == '━':
                    length += 1.36
                elif letter == '─':
                    length += 1
                elif letter == '-':
                    length += 0.5
            putitback = '┬'
            for i in range(int(length)):
                putitback += '─'
            putitback += '┬\ufeff ノ( ゜-゜ノ)'
            return putitback
        else:
            flipdict = str.maketrans(
                'abcdefghijklmnopqrstuvwxyzɐqɔpǝɟbɥıظʞןɯuodbɹsʇnʌʍxʎz😅🙃😞😟😠😡☹🙁😱😨😰😦😧😢😓😥😭'
                ,
                'ɐqɔpǝɟbɥıظʞןɯuodbɹsʇnʌʍxʎzabcdefghijklmnopqrstuvwxyz😄🙂🙂🙂🙂🙂🙂😀😀🙂😄🙂🙂😄😄😄😁'
                )
            flipstart = content.index('︵')
            flipped = content[flipstart + 1:]
            flipped = str.lower(flipped).translate(flipdict)
            putitback = ''.join(list(reversed(list(flipped))))
            putitback += 'ノ( ゜-゜ノ)'
            return putitback
    else:
        return False


def _procesar_simul(símismo):
    """
        Esta función procesa las predicciones del modelo después de una simulación, si necesario.
        """
    raise NotImplementedError


def __setitem__(key, value):
    """
        Set db or resource value
        """


def is_int(string):
    """Check whether string is integer."""
    try:
        int(string)
        return True
    except ValueError:
        return False


def mandelbrot_calc_row(y, w, h, image_rows, max_iteration=1000):
    """ Calculate one row of the mandelbrot set with size wxh """
    y0 = y * (2 / float(h)) - 1
    for x in range(w):
        x0 = x * (3.5 / float(w)) - 2.5
        i, z = 0, 0 + 0.0j
        c = complex(x0, y0)
        while abs(z) < 2 and i < max_iteration:
            z = z ** 2 + c
            i += 1
        color = i % 8 * 32, i % 16 * 16, i % 32 * 8
        image_rows[y * w + x] = color


def encode_datetime(value):
    """Encode a DATETIME into standard ISO 8601 Internet Format"""
    return value.isoformat().split('.')[0] + 'Z'


@staticmethod
def can_convert(unit1, unit2):
    """
        Returns true if the given units differ only by a multiplication. For
        example, ``[m/s]`` can be converted to ``[miles/hour]`` but not to
        ``[kg]``.
        """
    return unit1._x == unit2._x


def view_zoom_ratio(ratio: float=1.0):
    """Change zoom ratio of sequencer preview

    :param ratio: Ratio, Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out
    :type ratio: float
    """
    pass


def render():
    """Plain render method without keyword arguments."""


def null_removal_drop(dataframe, colname):
    """Drops rows with nulls on dataframe[colname]"""
    dataframe = dataframe.dropna(subset=[colname])
    return dataframe


def psi_Ca_Na_Cl_HMW84(T, P):
    """c-c'-a: calcium sodium chloride [HMW84]."""
    psi = -0.007
    valid = T == 298.15
    return psi, valid


@staticmethod
def user_parse(data):
    """Parse information from provider."""
    resp = data.get('response', [{}])[0]
    yield 'id', resp.get('uid')
    yield 'first_name', resp.get('first_name')
    yield 'last_name', resp.get('last_name')
    location = resp.get('location', {})
    yield 'city', location.get('city')
    yield 'country', location.get('country')
    yield 'picture', resp.get('pic128max')


def ci_index(_list, _value):
    """Case-insensitively finds an item in a list"""
    if _value is not None:
        for index in range(len(_list)):
            if _list[index].lower() == _value.lower():
                return index
    return -1


def getid(obj):
    """Wrapper to get  object's ID.

    Abstracts the common pattern of allowing both an object or an
    object's ID (UUID) as a parameter when dealing with relationships.
    """
    try:
        return obj.id
    except AttributeError:
        return obj


def disp_found(num):
    """ Display 'N locations discovered' in yellow/white. """
    from x84.bbs import getterminal, echo
    term = getterminal()
    disp_n = term.bold_white(u'{}'.format(num))
    locations = term.yellow(u'Location{s} discovered'.format(s=u's' if num >
        1 else u''))
    dotdot = term.bold_black(u'...')
    echo(u'\r{disp_n} {locations} {dotdot}'.format(disp_n=disp_n, locations
        =locations, dotdot=dotdot))


def get_delta(vmag_matrix, deriv_step):
    """ Convert voltage mag. data into the change in voltage mag. wrt time.

    This function finds the change in voltage magntiude between
    time-points. The spacing between time-points is a variable that can be
    changed. The change in voltage magnitude is calculated as Delta_Vmag =
    Vmag(node x, time t) - Vmag(node x, time t-deriv_step).

    Args
    -------
    vmag_matrix: 2D ndarray, shape (# of data-points, # of nodes)
        This is the voltage magnitude data at different nodes. We want to
        transform this data so we end up with the change
        in voltage magnitude from one time-point to the next for each node.

    deriv_step: int
        This parameter decides how many time-points for which
        to compute the voltage magntiude difference at a node. Ex. if
        deriv_step = 5, then the change in voltage magnitude will be
        Delta_Vmag = Vmag(node x, time t) - Vmag(node x, time t-5).

    Returns
    -------
    vmag_matrix: 2D ndarray, shape (# of data-points, # of nodes)
        This matrix now represents the change in voltage
        magnitude at a node from one time-point to the next. Each column
        corresponds to a different node and each row to a time-point.
    """
    end = len(vmag_matrix[:, (1)]) - 1
    vmag_matrix = vmag_matrix[deriv_step + 1:-1, :] - vmag_matrix[1:end -
        deriv_step, :]
    return vmag_matrix


def resource_available():
    """No-op placeholder for easy hookage"""
    pass


def __setitem__(index, item):
    """`x.__setitem__(index, item)` <==> `x[index] = item`

        Declaring this interface does not specify whether `__setitem__`
        supports slice objects.
        """


def handle_commands(irc, source, command, args):
    """Handle commands sent to the PyLink service bots (PRIVMSG)."""
    target = args['target']
    text = args['text']
    sbot = irc.get_service_bot(target)
    if sbot:
        sbot.call_cmd(irc, source, text)


def on_master_process():
    """
    Check whether the current code is executing on the master process (rank 0)
    if MPI is used.

    Returns
    -------
    True if rank is 0, if mpi4py is not present or if MPI is not used,
    otherwise False.
    """
    try:
        from mpi4py import MPI
        comm = MPI.COMM_WORLD
        rank = comm.Get_rank()
        if rank == 0:
            return True
        else:
            return False
    except ImportError:
        return True


def close():
    """Disconnect the tunnel.

        Note that this will terminate the remote process and any state will
        be lost. This does not destroy the Tunnel object, which can be
        reconnected with :meth:`.connect()`.

        """
    raise NotImplementedError()


def quantity_to_tuple(quantity, unit_str):
    """Splits a quantity into a tuple of (value,unit) where unit is FITS compliant.

    Useful to write FITS header keywords with units in a comment.

    Parameters
    ----------
    quantity : astropy quantity
        The Astropy quantity to split.
    unit_str: str
        Unit string representation readable by astropy.units (e.g. 'm', 'TeV', ...)

    Returns
    -------
    tuple
        A tuple containing the value and the quantity.
    """
    return quantity.to(unit_str).value, quantity.to(unit_str).unit.to_string(
        format='FITS')


def __contains__(obj):
    """Returns True if the object has a score"""


def getmean(data):
    """Determine the mean image across all frames.

    Parameters
    ----------
    data : array_like
        Data array as made by image2array. Should be shaped `(frames, y, x)`.

    Returns
    -------
    numpy.ndarray
        y by x array for the mean values

    """
    return data.mean(axis=0)


def lambd_NH3_ClO3_CB89(T, P):
    """n-a: ammonia chlorate [CB89]."""
    lambd = -0.004
    valid = T == 298.15
    return lambd, valid


def hook_add_selob(use_bone: bool=False):
    """Hook selected vertices to the first selected object

    :param use_bone: Active Bone, Assign the hook to the hook objects active bone
    :type use_bone: bool
    """
    pass


def mk_divisable(img, div):
    """
    Reshapes image so as to be divisible by div.
    """
    y_clip = img.shape[0] % div
    x_clip = img.shape[1] % div
    return img[y_clip:, x_clip:]


def filter_unwanted(filename):
    """ Returns true for hidden or unwanted files """
    return filename.startswith('.')


def joinLinks(links, sep=', ', last=None, sort=False):
    """Returns a string joining *links* as reStructuredText."""
    links = list(links)
    if sort:
        links.sort()
    if last is None:
        last = ''
    else:
        last = last + '`' + links.pop() + '`_'
    return '`' + ('`_' + sep + '`').join(links) + '`_' + last


@staticmethod
def devices():
    """List all the available devices."""
    return []


def as_is(x):
    """ Return the value as it is. """
    return x


def buildIssueSearchQuery(criteria, **kwargs):
    """Build canonical query for issue search.
        """


def fst(pair, strict=True):
    """Return the first element of `pair`.

    If `strict` is True, `pair` needs to unpack to exactly two values.  If
    `strict` is False this is the same as ``pair[0]``.

    .. note:: This is an idiomatic function intended for using in compositions
       or as the argument or high-level functions.  Don't use it in your code
       as a replacement of ``x[0]``.

    .. versionadded:: 1.8.5

    """
    if strict:
        res, _ = pair
        return res
    else:
        return pair[0]


def unauthenticated_userid(request):
    """ Return the *unauthenticated* userid.  This method
        performs the same duty as ``authenticated_userid`` but is
        permitted to return the userid based only on data present
        in the request; it needn't (and shouldn't) check any
        persistent store to ensure that the user record related to
        the request userid exists.

        This method is intended primarily a helper to assist the
        ``authenticated_userid`` method in pulling credentials out
        of the request data, abstracting away the specific headers,
        query strings, etc that are used to authenticate the request.

        """


def format_length(length):
    """Return length in the format MM:SS or HH:MM:SS."""
    length = int(length)
    if length < 3600:
        minutes = length // 60
        seconds = length % 60
        return '{}:{}'.format(format(minutes, '02'), format(seconds, '02'))
    else:
        hours = length // 3600
        minutes = length % 3600 // 60
        seconds = length % 3600 % 60
        return '{}:{}:{}'.format(hours, format(minutes, '02'), format(
            seconds, '02'))


def read_file_text(full_file_name):
    """
    Reads the text from the file and returns it as a string.
    """
    with open(full_file_name, 'r') as the_file:
        return the_file.read()


def optimize():
    """Recalculate the sculpt BVH to improve performance

    """
    pass


def _test_obsdup(t):
    """Check if there are duplicate observations"""
    return t.shape[0] != len(set(t.ids(axis='observation')))


@classmethod
def new(cls, **kwds):
    """
        convenience alias for creating new TOTP key, same as ``TOTP(new=True)``
        """
    return cls(new=True, **kwds)


def checksum_calc(nmea_str):
    """ Loop through all of the given characters and xor the current to the
        previous (cumulatively).
    """
    chksum_val = 0
    nmea_str = nmea_str.replace('$', '')
    nmea_str = nmea_str.split('*')[0]
    for next_char in nmea_str:
        chksum_val ^= ord(next_char)
    return '%02X' % chksum_val


@classmethod
def create_entry(cls, db, dow, time, zone, temp):
    """ Create a schedule entry in the database.

        dow is the day of week, counting from 0 being Monday. """
    cursor = db.cursor()
    cursor.execute(
        'insert into schedule (day, starttime, zone, temp) values (%s, %s, %s, %s)'
        , (dow, time, zone, temp))


def atom_extract(Mask_3D, atom):
    """
    Given (a list of) 3D Mask, extract the coord's of needed atom.
    """
    xyz_list = []
    if type(Mask_3D) is list:
        for i in Mask_3D:
            for x, y in enumerate(i.des):
                if y == atom:
                    if i.values.size == 3:
                        i.values = i.values.reshape(1, 3)
                    xyz_list.append(i.values[x])
    else:
        for x, y in enumerate(Mask_3D.des):
            if y == atom:
                if Mask_3D.values.size == 3:
                    Mask_3D.values = Mask_3D.values.reshape(1, 3)
                xyz_list.append(Mask_3D.values[x])
    return xyz_list


def _revert_alt(keys):
    """TWC automatically changes a-key to a sequence of esc + key, because
    that's how shells work. We have to revert this, because it's internal
    implementation detail."""
    if len(keys) > 1 and keys[0] == 'escape':
        return 'a-{}'.format(''.join(keys[1:]))
    return keys


def setKeyFn(fn):
    """
    set the prefix dictionary key function

    Note: This is not multithread/multiprocess safe. It should only be set before anything starts setting the keys.
    """
    global __name_key_fn
    __name_key_fn = fn


@classmethod
def load(cls, experiment_name, sagemaker_boto_client=None):
    """
        Load an existing experiment and return an ``Experiment`` object representing it.

        Args:
            experiment_name: (str): Name of the experiment
            sagemaker_boto_client (SageMaker.Client, optional): Boto3 client for SageMaker.
                If not supplied, a default boto3 client will be created and used.

        Returns:
            sagemaker.experiments.experiment.Experiment: A SageMaker ``Experiment`` object
        """
    return cls._construct(cls._boto_load_method, experiment_name=
        experiment_name, sagemaker_boto_client=sagemaker_boto_client)


def three_bytes(address):
    """Convert a 24 bit address to a string with 3 bytes"""
    return '%c%c%c' % (address & 255, address >> 8 & 255, address >> 16 & 255)


def get_roster(game_json):
    """
    Parse the roster info in the game json

    :param game_json: Json of all the info for a game

    :return: Dict: Key = Player id, Value = Name
    """
    players = {}
    for player in game_json['roster_player']:
        players[player['id']] = ' '.join([player['first_name'].strip(),
            player['last_name'].strip()])
    return players


@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['type']
    if type == 'INTERNAL_COMPUTE':
        return 'InternalAuthorizationDetails'
    if type == 'OCIC':
        return 'OcicAuthorizationDetails'
    else:
        return 'AuthorizationDetails'


@classmethod
def run(cls, power_rose_h5_fpath, excl_fpath, agg_dset='powerrose_100m',
    tm_dset='techmap_wtk', resolution=128, excl_area=0.0081, max_workers=
    None, chunk_point_len=1000, out_fpath=None):
    """
        Aggregate powerrose to supply curve points, find neighboring supply
        curve point gids and rank them based on prominent powerrose direction

        Parameters
        ----------
        power_rose_h5_fpath : str
            Filepath to .h5 file containing power rose data, of same format as
            WTK data with directions on axis 0 (rows) and sites on axis 1
            (columns)
        excl_fpath : str
            Filepath to exclusions h5 with techmap dataset.
        agg_dset : str, optional
            Powerrose dataset to aggreate, by default 'powerrose_100m'
        tm_dset : str, optional
            Dataset name in the techmap file containing the
            exclusions-to-resource mapping data,
            by default 'techmap_wtk'
        resolution : int, optional
            SC resolution, must be input in combination with gid. Prefered
            option is to use the row/col slices to define the SC point instead,
            by default 64
        excl_area : float, optional
            Area of an exclusion cell (square km), by default 0.0081
        max_workers : int | None, optional
            Number of cores to run summary on. None is all
            available cpus, by default None
        chunk_point_len : int, optional
            Number of SC points to process on a single parallel worker,
            by default 100
        out_fpath : str
            Path to .csv file to save output table to

        Returns
        -------
        sc_pr : pandas.DataFrame
            Update meta data table with neighboring supply curve point gids
            and power-rose value at each cardinal direction
        """
    pr = cls(power_rose_h5_fpath, excl_fpath, agg_dset=agg_dset, tm_dset=
        tm_dset, resolution=resolution)
    sc_pr = pr.prominent_directions(excl_area=excl_area, max_workers=
        max_workers, chunk_point_len=chunk_point_len)
    if out_fpath:
        sc_pr.to_csv(out_fpath, index=False)
    return sc_pr


def plot_geo_time_value(x, y, year, value, proj='plate', titre='Annee', **
    kwargs):
    """
    Returns  many maps done with cartopy
    :param          x               vecteur de longitudes
    :param          y               vecteur de latitudes
    :param          value           vecteur des valeurs representees
    :param          year            vecteur des annees sur lesquelles les cartes sont faites
    :param          proj            le type de projection utilisee
    :param          titre           le titre voulu pour le graphique
    :kwargs                         parametres additionnels
    """
    import cartopy.crs as ccrs
    import cartopy.feature as cfeature
    from matplotlib import pyplot as plt
    from cartopy.feature import NaturalEarthFeature, COLORS
    import numpy as np
    import math
    import pandas as pd
    resolution = '50m'
    BORDERS = NaturalEarthFeature('cultural', 'admin_0_boundary_lines_land',
        resolution, edgecolor='black', facecolor='none')
    STATES = NaturalEarthFeature('cultural',
        'admin_1_states_provinces_lakes', resolution, edgecolor='black',
        facecolor='none')
    COASTLINE = NaturalEarthFeature('physical', 'coastline', resolution,
        edgecolor='black', facecolor='none')
    LAKES = NaturalEarthFeature('physical', 'lakes', resolution, edgecolor=
        'face', facecolor=COLORS['water'])
    LAND = NaturalEarthFeature('physical', 'land', resolution, edgecolor=
        'face', facecolor=COLORS['land'], zorder=-1)
    OCEAN = NaturalEarthFeature('physical', 'ocean', resolution, edgecolor=
        'face', facecolor=COLORS['water'], zorder=-1)
    RIVERS = NaturalEarthFeature('physical', 'rivers_lake_centerlines',
        resolution, edgecolor=COLORS['water'], facecolor='none')
    assert isinstance(x, np.ndarray
        ), 'Erreur, x n est pas de type np.ndarray(vecteur)'
    assert isinstance(y, np.ndarray
        ), 'Erreur, y n est pas de type np.ndarray(vecteur)'
    assert isinstance(year, np.ndarray
        ), 'Erreur, year n est pas de type np.ndarray(vecteur)'
    assert isinstance(value, pd.DataFrame
        ), 'Erreur, values n est pas de type pd.DataFrame'
    assert len(x) == len(y), 'Erreur, x et y doit etre de meme taille'
    assert type(year[0]
        ) == np.int32, 'Erreur, les annees ne sont pas des entiers'
    assert type(proj
        ) == str, 'Erreur: vous devez choisir une variable de projection de type string (pensez a changer)'
    assert proj in ['mercator', 'plate'
        ], 'Erreur: la projection doit etre "mercato" ou "plate"'
    assert type(titre) == str, 'Erreur, titre est un string'
    RADIUS = 6378137.0
    if len(year) % 2 == 1:
        a = len(year) // 2 + 1
    else:
        a = len(year) / 2
    fig = plt.figure(figsize=(10, 7))
    c = [0] * len(x)
    b = [0] * len(y)
    if proj == 'mercator':
        for j in range(len(c)):
            c[j] = math.radians(x[j]) * RADIUS
            b[j] = math.log(math.tan(math.pi / 4 + math.radians(y[j]) / 2)
                ) * RADIUS
    else:
        c = x
        b = y
    for i in range(len(year)):
        if proj == 'plate':
            ax = fig.add_subplot(a, 2, i + 1, projection=ccrs.PlateCarree())
        else:
            ax = fig.add_subplot(a, 2, i + 1, projection=ccrs.Mercator())
        ax.set_extent([-5, 10, 41, 52])
        ax.add_feature(BORDERS)
        ax.add_feature(LAKES)
        ax.add_feature(LAND)
        ax.add_feature(OCEAN)
        ax.add_feature(RIVERS)
        ax.add_feature(COASTLINE)
        if max(value.iloc[:, (i)]) <= 1:
            plt.scatter(c, b, s=value.iloc[:, (i)] * 100, c=value.iloc[:, (
                i)], alpha=0.5)
        elif max(value.iloc[:, (i)]) <= 10:
            plt.scatter(c, b, s=value.iloc[:, (i)] * 10, c=value.iloc[:, (i
                )], alpha=0.5)
        else:
            plt.scatter(c, b, s=value.iloc[:, (i)], c=value.iloc[:, (i)],
                alpha=0.5)
        plt.colorbar()
        ax.set_title(str(titre) + ':' + str(year[i]))


def path_info_split(path_info):
    """
    Splits off the first segment of the path.  Returns (first_part,
    rest_of_path).  first_part can be None (if PATH_INFO is empty), ''
    (if PATH_INFO is '/'), or a name without any /'s.  rest_of_path
    can be '' or a string starting with /.

    """
    if not path_info:
        return None, ''
    assert path_info.startswith('/'
        ), 'PATH_INFO should start with /: %r' % path_info
    path_info = path_info.lstrip('/')
    if '/' in path_info:
        first, rest = path_info.split('/', 1)
        return first, '/' + rest
    else:
        return path_info, ''


def key_freq(key_number: int, a4: float=440.0) ->float:
    """
    Return the note frequency for the given piano key number.
    C4 is key 40 and A4 is key 49 (=440 hz).
    https://en.wikipedia.org/wiki/Piano_key_frequencies
    """
    return 2 ** ((key_number - 49) / 12) * a4


@classmethod
def add_line_info(cls, t, matches):
    """
        Save line/column information from OSB `[` or OCB `{` tokens.
        """
    t._line = matches[0].line
    t._column = matches[0].column
    t._end_column = matches[-1].end_column


def ordinal(n):
    """Print a number followed by "st" or "nd" or "rd", as appropriate."""
    return '{}{}'.format(n, 'tsnrhtdd'[(n / 10 % 10 != 1) * (n % 10 < 4) *
        n % 10::4])


@classmethod
def register_notification(cls, notification_cls):
    """Register a class as concrete notification.

        This is used only to register concrete notification or payload
        classes. Do NOT register base classes intended for inheritance only.
        """
    cls.register_if(False)(notification_cls)
    cls.notification_classes.append(notification_cls)
    return notification_cls


def size_splitter(size, part_size):
    """Receive file size and return a list of size ranges"""
    result = []
    if size == 0:
        result.append('0-0')
        return result
    span = part_size if part_size <= size else size
    parts = max(size // span, 1)
    x = 0
    size = size - 1
    for i in range(parts):
        y = x + span - 1
        if size - y < span:
            y = size
        result.append(f'{x}-{y}')
        x = y + 1
    return result


def bytes_(s, encoding='utf-8', errors='strict'):
    """
    If ``s`` is an instance of ``text_type``, return
    ``s.encode(encoding, errors)``, otherwise return ``s``
    """
    if not isinstance(s, bytes) and s is not None:
        s = s.encode(encoding, errors)
    return s


def setQualifiedCoverages(qualified_coverages):
    """Set the qualified Coverages elements.

        The argument must be a sequence of Coverage `IDublinCoreElementItem`.
        """


@classmethod
def get_hint(cls, item):
    """Returns a hint for a variant instance or it's value.

        :param item:
        :rtype: str
        """
    if isinstance(item, cls):
        return item.hint
    return cls.hints[item]


def get_attributes(aspect, id):
    """Return the attributes pointing to a given ID in a given aspect."""
    attributes = {}
    for entry in aspect:
        if entry['po'] == id:
            attributes[entry['n']] = entry['v']
    return attributes


def parse_index(index_str):
    """ index or start:stop:step (all ints) """
    if ':' in index_str:
        s = index_str.split(':')
        s = list(map(lambda i: int(i) if len(i) > 0 else None, s))
        return slice(*s)
    return int(index_str)


@classmethod
def SerialMatcher(cls, serial):
    """Returns a device matcher for the given serial."""
    return lambda device: device.serial_number == serial


def convert_path(path):
    """Convert to the path the server will accept.

    Args:
        path (str): Local file path.
            e.g.:
                "D:/work/render/19183793/max/d/Work/c05/112132P-embery.jpg"

    Returns:
        str: Path to the server.
            e.g.:
                "/D/work/render/19183793/max/d/Work/c05/112132P-embery.jpg"

    """
    lower_path = path.replace('\\', '/')
    if lower_path[1] == ':':
        path_lower = lower_path.replace(':', '')
        path_server = '/' + path_lower
    else:
        path_server = lower_path[1:]
    return path_server


def set_image_data_format(data_format):
    """Sets the value of the data format convention.

    # Arguments
        data_format: string. `'channels_first'` or `'channels_last'`.

    # Example
    ```python
        >>> from keras import backend as K
        >>> K.image_data_format()
        'channels_first'
        >>> K.set_image_data_format('channels_last')
        >>> K.image_data_format()
        'channels_last'
    ```
    """
    global _IMAGE_DATA_FORMAT
    if data_format not in {'channels_last', 'channels_first'}:
        raise ValueError('Unknown data_format:', data_format)
    _IMAGE_DATA_FORMAT = str(data_format)


def isspace(text):
    """
    Checks if there are only whitespace characters in ``text`` and there is at least one character.

    Whitespace characters are those characters defined in the Unicode character database
    as "Other" or "Separator".

    :param text: The string to check
    :type text:  ``str``

    :return: True if there are only whitespace characters in ``text`` and there is at least one character, False otherwise.
    :rtype:  ``bool``
    """
    assert isinstance(text, str), '%s is not a string' % text
    return text.isspace()


def _next_pair_or_none(iterator):
    """
    Returns the next pair in an iterator of pairs, or a pair of None.
    """
    try:
        return next(iterator)
    except StopIteration:
        return None, None


def p_pddoc(p):
    """pddoc : pddoc eol
             | COMMENT_START pdbody COMMENT_END"""
    if len(p) == 3:
        if p[1]:
            p[0] = p[1]
        else:
            p[0] = p[2]
    else:
        p[0] = p[2]


def link(address):
    """Link this user to the given IAddress.

        Raises AddressAlreadyLinkedError if this IAddress is already linked to
        another user.
        """


def path_escape(str):
    """Escape any path separators in a string so it can be used as the name of a single folder."""
    return str


def github_self_anchor(doc):
    """Discard self anchors in <h3>.

    We stripped referents, and weasyprint warns it.
    """
    for el in doc.xpath('(//h1|//h2|//h3|//h4)/a'):
        if 'anchor' in el.classes:
            el.set('href', '')


def skip_prologue(text, cursor):
    """skip any prologue found after cursor, return index of rest of text"""
    prologue_elements = '!DOCTYPE', '?xml', '!--'
    done = None
    while done is None:
        openbracket = text.find('<', cursor)
        if openbracket < 0:
            break
        past = openbracket + 1
        found = None
        for e in prologue_elements:
            le = len(e)
            if text[past:past + le] == e:
                found = 1
                cursor = text.find('>', past)
                if cursor < 0:
                    raise ValueError("can't close prologue %r" % e)
                cursor = cursor + 1
        if found is None:
            done = 1
    return cursor


@staticmethod
def interleaveblastresults(query, subject):
    """
        Creates an interleaved string that resembles BLAST sequence comparisons
        :param query: Query sequence
        :param subject: Subject sequence
        :return: Properly formatted BLAST-like sequence comparison
        """
    matchstring = ''
    blaststring = ''
    for i, bp in enumerate(query):
        if bp == subject[i]:
            matchstring += '|'
        else:
            matchstring += ' '
    prev = 0
    for j in range(0, len(query), 60):
        """
            0000 OLC ATGAAGAAGATATTTGTAGCGGCTTTATTTGCTTTTGTTTCTGTTAATGCAATGGCAGCT
                     ||||||||||| ||| | |||| ||||||||| || ||||||||||||||||||||||||
                 ref ATGAAGAAGATGTTTATGGCGGTTTTATTTGCATTAGTTTCTGTTAATGCAATGGCAGCT
            0060 OLC GATTGTGCAAAAGGTAAAATTGAGTTCTCTAAGTATAATGAGAATGATACATTCACAGTA
                     ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
                 ref GATTGTGCAAAAGGTAAAATTGAGTTCTCTAAGTATAATGAGAATGATACATTCACAGTA
            """
        blaststring += '{} OLC {}\n         {}\n     ref {}\n'.format('{:04d}'
            .format(j), query[prev:j + 60], matchstring[prev:j + 60],
            subject[prev:j + 60])
        prev = j + 60
    return blaststring


def nice_pair(pair):
    """Make a nice string representation of a pair of numbers.

    If the numbers are equal, just return the number, otherwise return the pair
    with a dash between them, indicating the range.

    """
    start, end = pair
    if start == end:
        return '%d' % start
    else:
        return '%d-%d' % (start, end)


def get_campaign_versions(ApplicationId=None, CampaignId=None, PageSize=
    None, Token=None):
    """
    Returns information about your campaign versions.

    :example: response = client.get_campaign_versions(
        ApplicationId='string',
        CampaignId='string',
        PageSize='string',
        Token='string'
    )

    :type ApplicationId: string
    :param ApplicationId: [REQUIRED]

    :type CampaignId: string
    :param CampaignId: [REQUIRED]

    :type PageSize: string
    :param PageSize:

    :type Token: string
    :param Token:

    :rtype: dict
    :return: {
        'CampaignsResponse': {
            'Item': [
                {
                    'AdditionalTreatments': [
                        {
                            'Id': 'string',
                            'MessageConfiguration': {
                                'APNSMessage': {
                                    'Action': 'OPEN_APP'|'DEEP_LINK'|'URL',
                                    'Body': 'string',
                                    'ImageIconUrl': 'string',
                                    'ImageUrl': 'string',
                                    'JsonBody': 'string',
                                    'MediaUrl': 'string',
                                    'SilentPush': True|False,
                                    'Title': 'string',
                                    'Url': 'string'
                                },
                                'DefaultMessage': {
                                    'Action': 'OPEN_APP'|'DEEP_LINK'|'URL',
                                    'Body': 'string',
                                    'ImageIconUrl': 'string',
                                    'ImageUrl': 'string',
                                    'JsonBody': 'string',
                                    'MediaUrl': 'string',
                                    'SilentPush': True|False,
                                    'Title': 'string',
                                    'Url': 'string'
                                },
                                'GCMMessage': {
                                    'Action': 'OPEN_APP'|'DEEP_LINK'|'URL',
                                    'Body': 'string',
                                    'ImageIconUrl': 'string',
                                    'ImageUrl': 'string',
                                    'JsonBody': 'string',
                                    'MediaUrl': 'string',
                                    'SilentPush': True|False,
                                    'Title': 'string',
                                    'Url': 'string'
                                }
                            },
                            'Schedule': {
                                'EndTime': 'string',
                                'Frequency': 'ONCE'|'HOURLY'|'DAILY'|'WEEKLY'|'MONTHLY',
                                'IsLocalTime': True|False,
                                'QuietTime': {
                                    'End': 'string',
                                    'Start': 'string'
                                },
                                'StartTime': 'string',
                                'Timezone': 'string'
                            },
                            'SizePercent': 123,
                            'State': {
                                'CampaignStatus': 'SCHEDULED'|'EXECUTING'|'PENDING_NEXT_RUN'|'COMPLETED'|'PAUSED'
                            },
                            'TreatmentDescription': 'string',
                            'TreatmentName': 'string'
                        },
                    ],
                    'ApplicationId': 'string',
                    'CreationDate': 'string',
                    'DefaultState': {
                        'CampaignStatus': 'SCHEDULED'|'EXECUTING'|'PENDING_NEXT_RUN'|'COMPLETED'|'PAUSED'
                    },
                    'Description': 'string',
                    'HoldoutPercent': 123,
                    'Id': 'string',
                    'IsPaused': True|False,
                    'LastModifiedDate': 'string',
                    'Limits': {
                        'Daily': 123,
                        'Total': 123
                    },
                    'MessageConfiguration': {
                        'APNSMessage': {
                            'Action': 'OPEN_APP'|'DEEP_LINK'|'URL',
                            'Body': 'string',
                            'ImageIconUrl': 'string',
                            'ImageUrl': 'string',
                            'JsonBody': 'string',
                            'MediaUrl': 'string',
                            'SilentPush': True|False,
                            'Title': 'string',
                            'Url': 'string'
                        },
                        'DefaultMessage': {
                            'Action': 'OPEN_APP'|'DEEP_LINK'|'URL',
                            'Body': 'string',
                            'ImageIconUrl': 'string',
                            'ImageUrl': 'string',
                            'JsonBody': 'string',
                            'MediaUrl': 'string',
                            'SilentPush': True|False,
                            'Title': 'string',
                            'Url': 'string'
                        },
                        'GCMMessage': {
                            'Action': 'OPEN_APP'|'DEEP_LINK'|'URL',
                            'Body': 'string',
                            'ImageIconUrl': 'string',
                            'ImageUrl': 'string',
                            'JsonBody': 'string',
                            'MediaUrl': 'string',
                            'SilentPush': True|False,
                            'Title': 'string',
                            'Url': 'string'
                        }
                    },
                    'Name': 'string',
                    'Schedule': {
                        'EndTime': 'string',
                        'Frequency': 'ONCE'|'HOURLY'|'DAILY'|'WEEKLY'|'MONTHLY',
                        'IsLocalTime': True|False,
                        'QuietTime': {
                            'End': 'string',
                            'Start': 'string'
                        },
                        'StartTime': 'string',
                        'Timezone': 'string'
                    },
                    'SegmentId': 'string',
                    'SegmentVersion': 123,
                    'State': {
                        'CampaignStatus': 'SCHEDULED'|'EXECUTING'|'PENDING_NEXT_RUN'|'COMPLETED'|'PAUSED'
                    },
                    'TreatmentDescription': 'string',
                    'TreatmentName': 'string',
                    'Version': 123
                },
            ],
            'NextToken': 'string'
        }
    }

    :returns:
    (dict) -- 200 response
    CampaignsResponse (dict) -- List of available campaigns.
    Item (list) -- A list of campaigns.
    (dict) -- Campaign definition
    AdditionalTreatments (list) -- Treatments that are defined in addition to the default treatment.
    (dict) -- Treatment resource
    Id (string) -- The unique treatment ID.
    MessageConfiguration (dict) -- The message configuration settings.
    APNSMessage (dict) -- The message that the campaign delivers to APNS channels. Overrides the default message.
    Action (string) -- The action that occurs if the user taps a push notification delivered by the campaign: OPEN_APP  Your app launches, or it becomes the foreground app if it has been sent to the background. This is the default action. DEEP_LINK  Uses deep linking features in iOS and Android to open your app and display a designated user interface within the app. URL  The default mobile browser on the user's device launches and opens a web page at the URL you specify.
    Body (string) -- The message body. Can include up to 140 characters.
    ImageIconUrl (string) -- The URL that points to the icon image for the push notification icon, for example, the app icon.
    ImageUrl (string) -- The URL that points to an image used in the push notification.
    JsonBody (string) -- The JSON payload used for a silent push.
    MediaUrl (string) -- The URL that points to the media resource, for example a .mp4 or .gif file.
    SilentPush (boolean) -- Indicates if the message should display on the users device. Silent pushes can be used for Remote Configuration and Phone Home use cases.
    Title (string) -- The message title that displays above the message on the user's device.
    Url (string) -- The URL to open in the user's mobile browser. Used if the value for Action is URL.

    DefaultMessage (dict) -- The default message for all channels.
    Action (string) -- The action that occurs if the user taps a push notification delivered by the campaign: OPEN_APP  Your app launches, or it becomes the foreground app if it has been sent to the background. This is the default action. DEEP_LINK  Uses deep linking features in iOS and Android to open your app and display a designated user interface within the app. URL  The default mobile browser on the user's device launches and opens a web page at the URL you specify.
    Body (string) -- The message body. Can include up to 140 characters.
    ImageIconUrl (string) -- The URL that points to the icon image for the push notification icon, for example, the app icon.
    ImageUrl (string) -- The URL that points to an image used in the push notification.
    JsonBody (string) -- The JSON payload used for a silent push.
    MediaUrl (string) -- The URL that points to the media resource, for example a .mp4 or .gif file.
    SilentPush (boolean) -- Indicates if the message should display on the users device. Silent pushes can be used for Remote Configuration and Phone Home use cases.
    Title (string) -- The message title that displays above the message on the user's device.
    Url (string) -- The URL to open in the user's mobile browser. Used if the value for Action is URL.

    GCMMessage (dict) -- The message that the campaign delivers to GCM channels. Overrides the default message.
    Action (string) -- The action that occurs if the user taps a push notification delivered by the campaign: OPEN_APP  Your app launches, or it becomes the foreground app if it has been sent to the background. This is the default action. DEEP_LINK  Uses deep linking features in iOS and Android to open your app and display a designated user interface within the app. URL  The default mobile browser on the user's device launches and opens a web page at the URL you specify.
    Body (string) -- The message body. Can include up to 140 characters.
    ImageIconUrl (string) -- The URL that points to the icon image for the push notification icon, for example, the app icon.
    ImageUrl (string) -- The URL that points to an image used in the push notification.
    JsonBody (string) -- The JSON payload used for a silent push.
    MediaUrl (string) -- The URL that points to the media resource, for example a .mp4 or .gif file.
    SilentPush (boolean) -- Indicates if the message should display on the users device. Silent pushes can be used for Remote Configuration and Phone Home use cases.
    Title (string) -- The message title that displays above the message on the user's device.
    Url (string) -- The URL to open in the user's mobile browser. Used if the value for Action is URL.

    Schedule (dict) -- The campaign schedule.
    EndTime (string) -- The scheduled time that the campaign ends in ISO 8601 format.
    Frequency (string) -- How often the campaign delivers messages. Valid values: ONCE, HOURLY, DAILY, WEEKLY, MONTHLY
    IsLocalTime (boolean) -- Indicates whether the campaign schedule takes effect according to each user's local time.
    QuietTime (dict) -- The time during which the campaign sends no messages.
    End (string) -- The default end time for quiet time in ISO 8601 format.
    Start (string) -- The default start time for quiet time in ISO 8601 format.

    StartTime (string) -- The scheduled time that the campaign begins in ISO 8601 format.
    Timezone (string) -- The starting UTC offset for the schedule if the value for isLocalTime is true Valid values: UTC UTC+01 UTC+02 UTC+03 UTC+03:30 UTC+04 UTC+04:30 UTC+05 UTC+05:30 UTC+05:45 UTC+06 UTC+06:30 UTC+07 UTC+08 UTC+09 UTC+09:30 UTC+10 UTC+10:30 UTC+11 UTC+12 UTC+13 UTC-02 UTC-03 UTC-04 UTC-05 UTC-06 UTC-07 UTC-08 UTC-09 UTC-10 UTC-11

    SizePercent (integer) -- The allocated percentage of users for this treatment.
    State (dict) -- The treatment status.
    CampaignStatus (string) -- The status of the campaign, or the status of a treatment that belongs to an A/B test campaign. Valid values: SCHEDULED, EXECUTING, PENDING_NEXT_RUN, COMPLETED, PAUSED

    TreatmentDescription (string) -- A custom description for the treatment.
    TreatmentName (string) -- The custom name of a variation of the campaign used for A/B testing.

    ApplicationId (string) -- The ID of the application to which the campaign applies.
    CreationDate (string) -- The date the campaign was created in ISO 8601 format.
    DefaultState (dict) -- The status of the campaign's default treatment. Only present for A/B test campaigns.
    CampaignStatus (string) -- The status of the campaign, or the status of a treatment that belongs to an A/B test campaign. Valid values: SCHEDULED, EXECUTING, PENDING_NEXT_RUN, COMPLETED, PAUSED

    Description (string) -- A description of the campaign.
    HoldoutPercent (integer) -- The allocated percentage of end users who will not receive messages from this campaign.
    Id (string) -- The unique campaign ID.
    IsPaused (boolean) -- Indicates whether the campaign is paused. A paused campaign does not send messages unless you resume it by setting IsPaused to false.
    LastModifiedDate (string) -- The date the campaign was last updated in ISO 8601 format.
    Limits (dict) -- The campaign limits settings.
    Daily (integer) -- The maximum number of messages that the campaign can send daily.
    Total (integer) -- The maximum total number of messages that the campaign can send.

    MessageConfiguration (dict) -- The message configuration settings.
    APNSMessage (dict) -- The message that the campaign delivers to APNS channels. Overrides the default message.
    Action (string) -- The action that occurs if the user taps a push notification delivered by the campaign: OPEN_APP  Your app launches, or it becomes the foreground app if it has been sent to the background. This is the default action. DEEP_LINK  Uses deep linking features in iOS and Android to open your app and display a designated user interface within the app. URL  The default mobile browser on the user's device launches and opens a web page at the URL you specify.
    Body (string) -- The message body. Can include up to 140 characters.
    ImageIconUrl (string) -- The URL that points to the icon image for the push notification icon, for example, the app icon.
    ImageUrl (string) -- The URL that points to an image used in the push notification.
    JsonBody (string) -- The JSON payload used for a silent push.
    MediaUrl (string) -- The URL that points to the media resource, for example a .mp4 or .gif file.
    SilentPush (boolean) -- Indicates if the message should display on the users device. Silent pushes can be used for Remote Configuration and Phone Home use cases.
    Title (string) -- The message title that displays above the message on the user's device.
    Url (string) -- The URL to open in the user's mobile browser. Used if the value for Action is URL.

    DefaultMessage (dict) -- The default message for all channels.
    Action (string) -- The action that occurs if the user taps a push notification delivered by the campaign: OPEN_APP  Your app launches, or it becomes the foreground app if it has been sent to the background. This is the default action. DEEP_LINK  Uses deep linking features in iOS and Android to open your app and display a designated user interface within the app. URL  The default mobile browser on the user's device launches and opens a web page at the URL you specify.
    Body (string) -- The message body. Can include up to 140 characters.
    ImageIconUrl (string) -- The URL that points to the icon image for the push notification icon, for example, the app icon.
    ImageUrl (string) -- The URL that points to an image used in the push notification.
    JsonBody (string) -- The JSON payload used for a silent push.
    MediaUrl (string) -- The URL that points to the media resource, for example a .mp4 or .gif file.
    SilentPush (boolean) -- Indicates if the message should display on the users device. Silent pushes can be used for Remote Configuration and Phone Home use cases.
    Title (string) -- The message title that displays above the message on the user's device.
    Url (string) -- The URL to open in the user's mobile browser. Used if the value for Action is URL.

    GCMMessage (dict) -- The message that the campaign delivers to GCM channels. Overrides the default message.
    Action (string) -- The action that occurs if the user taps a push notification delivered by the campaign: OPEN_APP  Your app launches, or it becomes the foreground app if it has been sent to the background. This is the default action. DEEP_LINK  Uses deep linking features in iOS and Android to open your app and display a designated user interface within the app. URL  The default mobile browser on the user's device launches and opens a web page at the URL you specify.
    Body (string) -- The message body. Can include up to 140 characters.
    ImageIconUrl (string) -- The URL that points to the icon image for the push notification icon, for example, the app icon.
    ImageUrl (string) -- The URL that points to an image used in the push notification.
    JsonBody (string) -- The JSON payload used for a silent push.
    MediaUrl (string) -- The URL that points to the media resource, for example a .mp4 or .gif file.
    SilentPush (boolean) -- Indicates if the message should display on the users device. Silent pushes can be used for Remote Configuration and Phone Home use cases.
    Title (string) -- The message title that displays above the message on the user's device.
    Url (string) -- The URL to open in the user's mobile browser. Used if the value for Action is URL.

    Name (string) -- The custom name of the campaign.
    Schedule (dict) -- The campaign schedule.
    EndTime (string) -- The scheduled time that the campaign ends in ISO 8601 format.
    Frequency (string) -- How often the campaign delivers messages. Valid values: ONCE, HOURLY, DAILY, WEEKLY, MONTHLY
    IsLocalTime (boolean) -- Indicates whether the campaign schedule takes effect according to each user's local time.
    QuietTime (dict) -- The time during which the campaign sends no messages.
    End (string) -- The default end time for quiet time in ISO 8601 format.
    Start (string) -- The default start time for quiet time in ISO 8601 format.

    StartTime (string) -- The scheduled time that the campaign begins in ISO 8601 format.
    Timezone (string) -- The starting UTC offset for the schedule if the value for isLocalTime is true Valid values: UTC UTC+01 UTC+02 UTC+03 UTC+03:30 UTC+04 UTC+04:30 UTC+05 UTC+05:30 UTC+05:45 UTC+06 UTC+06:30 UTC+07 UTC+08 UTC+09 UTC+09:30 UTC+10 UTC+10:30 UTC+11 UTC+12 UTC+13 UTC-02 UTC-03 UTC-04 UTC-05 UTC-06 UTC-07 UTC-08 UTC-09 UTC-10 UTC-11

    SegmentId (string) -- The ID of the segment to which the campaign sends messages.
    SegmentVersion (integer) -- The version of the segment to which the campaign sends messages.
    State (dict) -- The campaign status. An A/B test campaign will have a status of COMPLETED only when all treatments have a status of COMPLETED.
    CampaignStatus (string) -- The status of the campaign, or the status of a treatment that belongs to an A/B test campaign. Valid values: SCHEDULED, EXECUTING, PENDING_NEXT_RUN, COMPLETED, PAUSED

    TreatmentDescription (string) -- A custom description for the treatment.
    TreatmentName (string) -- The custom name of a variation of the campaign used for A/B testing.
    Version (integer) -- The campaign version number.

    NextToken (string) -- The string that you use in a subsequent request to get the next page of results in a paginated response.

    """
    pass


def sd_similarity(s1, s2):
    """
    Calculates the Brey-Curtis similarity for two samples.

    .. note:

        s1 and s2 should be the same length, and
        the sum of each sample should equal 1.

    Args:

        s1: list of frequencies for sample 1
        s2: list of frequencies for sample 2

    Results:

        float: Brey-Curtis similarity (between 0 and 1)
    """
    num = 0
    denom = 0
    for x, y in zip(s1, s2):
        num += min(x, y) > 0
        denom += min(x) > 0
        denom += min(y) > 0
    return 1.0 * num / denom


def truncate_seq_pair(tokens_a, tokens_b, max_num_tokens, rng):
    """Truncates a pair of sequences to a maximum sequence length."""
    while True:
        total_length = len(tokens_a) + len(tokens_b)
        if total_length <= max_num_tokens:
            break
        trunc_tokens = tokens_a if len(tokens_a) > len(tokens_b) else tokens_b
        assert len(trunc_tokens) >= 1
        if rng.random() < 0.5:
            del trunc_tokens[0]
        else:
            trunc_tokens.pop()


def permute(x):
    """
    permute returns a number in the range 0 to 9999
    that is unique for each x
    """
    prime = 9887
    offset = 453
    maximum = 9999
    x = (x + offset) % maximum
    if x >= prime:
        return x
    else:
        residue = x * x % prime
        if x <= prime / 2:
            return residue
        else:
            return prime - residue


def ImportStoryIDs(path_to_file):
    """
    .. versionadded:: 0.1.0

    Reads FanFiction.Net story-ids from a file, where each story-id is on
    a separate line. Returns a list of strings representing story-ids.

    :param path_to_file: path to a file containing story-ids from
                         FanFiction.Net, where each story-id is
                         contained on a newline.
    :type path_to_file: str.
    :returns: A list of strings representing the story-ids.
    :rtype: list of strings.

    Example:

    >>> from ffscraper.Utils import ImportStoryIDs
    >>> sids = ffs.Utils.ImportStoryIDs('data/Coraline/sids.txt')
    >>> print(sids)
    ['123', '344']

    .. warning::
       This function was designed and tested with Unix-style paths and
       end-of-line characters in mind, these have not been tested thoroughly
       on Windows.
    """
    with open(path_to_file) as f:
        sids = f.read().splitlines()
    return sids


@staticmethod
def p_comma_separated_char_string_list(p):
    """comma_separated_char_string_list : STRING
                                            | STRING COMMA comma_separated_char_string_list"""
    try:
        p[0] = [p[1]] + p[3]
    except IndexError:
        p[0] = [p[1]]


@staticmethod
def include_stream_from_metadata(metadata):
    """
        Should this stream be sync'd - as described in the meta data

        There are two different formats
        1. As found in the documentation
        https://github.com/singer-io/getting-started/blob/master/docs/SYNC_MODE.md#streamfield-selection
        "metadata": [
        {
          "breadcrumb": [],
          "metadata": {
            "selected": "false"
          }
        }]

        2. As found in the catalog.json file created during --discovery
            "metadata": {
                "selected": true,
                "is_view": false,
                "schema-name": "orders"
            },

        Both formats are handled here
        """
    if isinstance(metadata, dict):
        return metadata.get('selected')
    for item in metadata:
        if item.get('breadcrumb') == []:
            if item.get('metadata') and item['metadata'].get('selected'
                ) == 'false':
                return False
    return True


def composite_get_choices_dict(field_list):
    """
    Converts a list of dictionaries containing the keys
    "field_name" and "choices" into a single dictionary
    with "field_name" value as key and "choices" as value.
    If choices is not defined, then an empty list is assigned.
    """
    choices_dict = {}
    for field in field_list:
        name = field.get('field_name', '')
        choices_dict[name] = field.get('choices', [])
    return choices_dict


@classmethod
def get_by_name(cls, context, name):
    """Return a ResourceClass object with the given string name.

        :param name: String name of the resource class to find

        :raises: ResourceClassNotFound if no such resource class was found
        """
    rc = context.rc_cache.all_from_string(name)
    obj = cls(context, id=rc['id'], name=rc['name'], updated_at=rc[
        'updated_at'], created_at=rc['created_at'])
    return obj


def cdata(data):
    """Wraps items in CDATA tag"""
    if not data:
        return ''
    return f'<![CDATA[\n{data}\n]]>'


def update(entry1, entry2):
    """Create a merged BibTeX entry with the data from entry2 taking precedence.
    """
    out = entry1
    if entry2 is not None:
        if entry2.type:
            out.type = entry2.type
        if entry2.persons:
            for key, value in entry2.persons.items():
                if value:
                    out.persons[key] = value
        for key, value in entry2.fields.items():
            if value:
                out.fields[key] = value
    return out


@classmethod
def _GetResolverHelper(cls, type_indicator):
    """Retrieves the path specification resolver helper for the specified type.

    Args:
      type_indicator (str): type indicator.

    Returns:
      ResolverHelper: a resolver helper.
    """
    if not cls._resolver_helpers_manager:
        from dfvfs.resolver_helpers import manager
        cls._resolver_helpers_manager = manager.ResolverHelperManager
    return cls._resolver_helpers_manager.GetHelper(type_indicator)


def num_if_possible(s):
    """Convert string to number if possible, otherwise return string."""
    try:
        return int(s)
    except ValueError:
        try:
            return float(s)
        except ValueError:
            return s


def m3s2cfm(m3s):
    """convert flow meter^3/second to cfm"""
    return m3s * 1.0 * 2118.880003


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

        :param FileDeleteDetails val:
        :rtype: EventDetails
        """
    return cls('file_delete_details', val)


def read_hook_hash(path):
    """Verify that the file at path is the therapist hook and return the hash"""
    with open(path, 'r') as f:
        f.readline()
        version_line = f.readline()
        if version_line.startswith('# THERAPIST'):
            return version_line.split()[2]


def compute_badge_message_and_color(badge):
    """Computes message and color from badge information"""
    structure = badge['structure']
    body = badge.get('body')
    if structure == 'KO':
        return 'structure invalide', 'red'
    if body == 'OK':
        return ('structure invalide', 'orange') if structure == 'WARN' else (
            'valide', 'green')
    p = (1 - badge['error-ratio']) * 100.0
    msg = 'cellules valides : {:.1f}%'.format(p)
    return (msg, 'red') if body == 'KO' else (msg, 'orange')


def to_css_length(l):
    """
    Return the standard length string of css.
    It's compatible with number values in old versions.
    :param l: source css length.
    :return: A string.
    """
    if isinstance(l, (int, float)):
        return '{}px'.format(l)
    else:
        return l


def tokenize_light(string, language):
    """Same behavior as :func:`tokenize` but returns tokenized strings instead
        of :class:`Token` objects"""
    from snips_nlu_utils import tokenize_light as _tokenize_light
    tokenized_string = _tokenize_light(string, language)
    return tokenized_string


def sunsky_preset_add(name: str='', remove_active: bool=False):
    """Add or remove a Sky & Atmosphere Preset

    :param name: Name, Name of the preset, used to make the path name
    :type name: str
    :param remove_active: remove_active
    :type remove_active: bool
    """
    pass


def common_segment_count(path, value):
    """Return the number of path segments common to both"""
    i = 0
    if len(path) <= len(value):
        for x1, x2 in zip(path, value):
            if x1 == x2:
                i += 1
            else:
                return 0
    return i


def human_time(seconds):
    """
    Returns a human-friendly time string that is always exactly 6
    characters long.

    Depending on the number of seconds given, can be one of::

        1w 3d
        2d 4h
        1h 5m
        1m 4s
          15s

    Will be in color if console coloring is turned on.

    Parameters
    ----------
    seconds : int
        The number of seconds to represent

    Returns
    -------
    time : str
        A human-friendly representation of the given number of seconds
        that is always exactly 6 characters.
    """
    units = [('y', 60 * 60 * 24 * 7 * 52), ('w', 60 * 60 * 24 * 7), ('d',
        60 * 60 * 24), ('h', 60 * 60), ('m', 60), ('s', 1)]
    seconds = int(seconds)
    if seconds < 60:
        return '   {0:2d}s'.format(seconds)
    for i in range(len(units) - 1):
        unit1, limit1 = units[i]
        unit2, limit2 = units[i + 1]
        if seconds >= limit1:
            return '{0:2d}{1}{2:2d}{3}'.format(seconds // limit1, unit1,
                seconds % limit1 // limit2, unit2)
    return '  ~inf'


def end_case(typ):
    """测完一个测试点后，该测试点状态为 [typ]"""
    print()


def size_formatted(bytes_size, suffix='B'):
    """
    Get a human readable representation of storage size

    Note: Taken from
        https://stackoverflow.com/questions/1094841/reusable-library-to-get-human-readable-version-of-file-size
    :param int bytes_size: The size of object in bytes
    :rtype: str
    """
    if bytes_size < 1024:
        return '%3dB' % bytes_size
    for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']:
        if abs(bytes_size) < 1024.0:
            return '%3.1f%s%s' % (bytes_size, unit, suffix)
        bytes_size /= 1024.0
    return '%.1f%s%s' % (bytes_size, 'Yi', suffix)


@classmethod
def graph_laplacian(cls, epsilon=1.0, n_eigenpairs=10, **kwargs
    ) ->'DiffusionMaps':
    """Instantiate new model to approximate graph Laplacian.

        Returns
        -------
        DiffusionMaps
            new instance
        """
    return cls(epsilon=epsilon, n_eigenpairs=n_eigenpairs, is_stochastic=
        True, alpha=0.0, **kwargs)


@staticmethod
def green(text):
    """ turns text green """
    return f'\x1b[92m{text}\x1b[0m'


@staticmethod
def approve_request():
    """
        Get a transaction approve :class:`paynlsdk.api.transaction.approve.Request` instance

        :return: Transaction approve request instance
        :rtype: paynlsdk.api.transaction.approve.Request
        """
    from paynlsdk.api.transaction.approve import Request
    return Request()


def _l2t_subterp(label):
    """Helper function converting subterp labels to text. Assumes label has
    more then one segment"""
    if label[1:] == ['Subpart', 'Interp']:
        return 'Interpretations for Regulation Text of Part ' + label[0]
    elif label[1:] == ['Appendices', 'Interp']:
        return 'Interpretations for Appendices of Part ' + label[0]
    elif len(label) == 4 and label[1] == 'Subpart' and label[3] == 'Interp':
        interpretations_for = 'Interpretations for Subpart '
        return interpretations_for + label[2] + ' of Part ' + label[0]


def get_component_by_id(models, id, identifier='id'):
    """ Retrieve a model instance by its identifier

    Args:
        model (:obj:list of `Model`): an iterable of `Model` objects
        id (:obj:`str`): the identifier being sought
        identifier (:obj:`str`, optional): the name of the identifier attribute

    Returns:
        :obj:`Model`: the retrieved Model instance if found, or None

    Raises:
        :obj:`AttributeError`: if `model` does not have the attribute specified by `identifier`
    """
    for model in models:
        try:
            if getattr(model, identifier) == id:
                return model
        except AttributeError:
            raise AttributeError("{} does not have the attribute '{}'".
                format(model.__class__.__name__, identifier))
    return None


@classmethod
def get(cls, project_id, model_id):
    """ Retrieve model parameters.

        Parameters
        ----------
        project_id : str
            The project's id.
        model_id : str
            Id of model parameters we requested.

        Returns
        -------
        ModelParameters
            The queried model parameters.
        """
    url = 'projects/{}/models/{}/parameters/'.format(project_id, model_id)
    return cls.from_location(url)


@classmethod
def clip(cls, n, minValue, maxValue):
    """ Clips a number to the specified minimum and maximum values. """
    return min(max(n, minValue), maxValue)


def get_sol(n, name, attr=''):
    """
    Retrieves solution for a given variable. Note that a lookup of all stored
    solutions is given in n.solutions.

    Parameters
    ----------
    n : pypsa.Network
    c : str
        general variable name (or component name if variable is attached to a
        component)
    attr: str
        attribute name of the variable

    Example
    -------
    get_dual(n, 'Generator', 'mu_upper')
    """
    pnl = n.solutions.at[(name, attr), 'pnl']
    if n.solutions.at[(name, attr), 'in_comp']:
        return n.pnl(name)[attr] if pnl else n.df(name)[attr + '_opt']
    else:
        return n.sols[name].pnl[attr] if pnl else n.sols[name].df[attr]


def frame_comps_from_set(frame_set):
    """
    A `set` of all component names every defined within any frame class in
    this `TransformGraph`.

    Broken out of the class so this can be called on a temporary frame set to
    validate new additions to the transform graph before actually adding them.
    """
    result = set()
    for frame_cls in frame_set:
        rep_info = frame_cls._frame_specific_representation_info
        for mappings in rep_info.values():
            for rep_map in mappings:
                result.update([rep_map.framename])
    return result


def readtime(wordcount: int, words_per_minute=300):
    """Given a number of words, estimate the time it would take to read
    them.

    :return: The time in minutes if it's more than 1, otherwise 1."""
    return max(1, round(wordcount / 300))


def ncoef_fmap(order):
    """Expected number of coefficients in a 2D transformation of a given order.

    Parameters
    ----------
    order : int
        Order of the 2D polynomial transformation.

    Returns
    -------
    ncoef : int
        Expected number of coefficients.

    """
    ncoef = 0
    for i in range(order + 1):
        for j in range(i + 1):
            ncoef += 1
    return ncoef


def allcap_differential(words):
    """
    Check whether just some words in the input are ALL CAPS
    :param list words: The words to inspect
    :returns: `True` if some but not all items in `words` are ALL CAPS
    """
    is_different = False
    allcap_words = 0
    for word in words:
        if word.isupper():
            allcap_words += 1
    cap_differential = len(words) - allcap_words
    if 0 < cap_differential < len(words):
        is_different = True
    return is_different


def image_from_view(filepath: str=''):
    """Make an image from the current 3D view for re-projection

    :param filepath: File Path, Name of the file
    :type filepath: str
    """
    pass


@classmethod
def existing(cls, connection=None, **kwargs):
    """Create an instance of an existing remote resource.

        When creating the instance set the ``_synchronized`` parameter
        of :class:`Resource` to ``True`` to indicate that it represents the
        state of an existing server-side resource. As such, all attributes
        passed in ``**kwargs`` are considered "clean", such that an immediate
        :meth:`update` call would not generate a body of attributes to be
        modified on the server.

        :param dict kwargs: Each of the named arguments will be set as
                            attributes on the resulting Resource object.
        """
    if cls.resource_key in kwargs:
        args = kwargs.pop(cls.resource_key)
        kwargs.update(**args)
    return cls(_synchronized=True, connection=connection, **kwargs)


@classmethod
def get_base(cls, name):
    """ Checks a string for a possible base name of an object (no prefix, no suffix).
            We need to do a full parse to make sure we've ruled out all the possible other parse queries

        :param name: str, string that represents a possible name of an object
        :return: str, the detected basename
        """
    return cls.parse_name(name).get('basename', None)


def composite_index(data):
    """
    Create a composite index based on the sentiment analysis based on Loughran and McDonald's
    dictionary and script.

    :param data: String to analyse.
    :return: List of values. See unused variable OUTPUT_FIELDS in the source, there is a lot.
    """
    OUTPUT_FIELDS = ['file type', 'file size', 'number of words',
        '% positive', '% negative', '% uncertainty', '% litigious',
        '% modal-weak', '% modal moderate', '% modal strong',
        '% constraining', '# of alphabetic', '# of digits', '# of numbers',
        'avg # of syllables per word', 'average word length', 'vocabulary']
    if data[2] + data[3] + data[4]:
        result = (data[3] - data[4]) / data[2]
    else:
        result = 0
    return result


def constant_time_compare(str_a, str_b):
    """
    Compare two strings, taking constant time
    """
    are_equal = len(str_a) == len(str_b)
    for a, b in zip(str_a, str_b):
        are_equal &= a == b
    return are_equal


def interpolate_bezier(knot1, handle1, handle2, knot2, resolution):
    """Interpolate a bezier spline segment.

	Parameters:
	knot1 (mathutils.Vector) – First bezier spline point.
	handle1 (mathutils.Vector) – First bezier spline handle.
	handle2 (mathutils.Vector) – Second bezier spline handle.
	knot2 (mathutils.Vector) – Second bezier spline point.
	resolution (int) – Number of points to return.

	Returns: The interpolated points

	Return type: list of mathutils.Vector’s"""
    from . import Vector
    return [Vector, Vector, Vector, Vector]


def upgrade():
    """A no-op migration for marking the Kilo release."""
    pass