def allow_inherit_docstring(cls):
    """
    The base classes of a provided class will be used to copy and inherit the first
    docstring it finds.

    :param cls: class the decorator function will be used on to inherit the docstring
                from its base classes.
    :returns: class with the inherited docstring.
    """
    bases = cls.__bases__
    for attr, attribute in cls.__dict__.items():
        if hasattr(attribute, 'inherit_docstring'):
            if not attribute.__doc__:
                for mro_cls in (mro_cls for base in bases for mro_cls in
                    base.mro() if hasattr(mro_cls, attr)):
                    doc = getattr(getattr(mro_cls, attr), '__doc__')
                    if doc:
                        attribute.__doc__ = doc
                        break
    return cls


def create_recovered_ln_likelihood_ratio_table(connection, coinc_def_id):
    """
	Create a temporary table named "recovered_ln_likelihood_ratio"
	containing two columns:  "simulation_id", the simulation_id of an
	injection, and "ln_likelihood_ratio", the highest log likelihood
	ratio at which that injection was recovered by a coincidence of
	type coinc_def_id.
	"""
    cursor = connection.cursor()
    cursor.execute(
        """
CREATE TEMPORARY TABLE recovered_ln_likelihood_ratio (simulation_id TEXT PRIMARY KEY, ln_likelihood_ratio REAL)
	"""
        )
    cursor.execute(
        """
INSERT OR REPLACE INTO
	recovered_ln_likelihood_ratio
SELECT
	sim_burst.simulation_id AS simulation_id,
	MAX(coinc_event.likelihood) AS ln_likelihood_ratio
FROM
	sim_burst
	JOIN coinc_event_map AS a ON (
		a.table_name == "sim_burst"
		AND a.event_id == sim_burst.simulation_id
	)
	JOIN coinc_event_map AS b ON (
		b.coinc_event_id == a.coinc_event_id
	)
	JOIN coinc_event ON (
		b.table_name == "coinc_event"
		AND b.event_id == coinc_event.coinc_event_id
	)
WHERE
	coinc_event.coinc_def_id == ?
GROUP BY
	sim_burst.simulation_id
	"""
        , (coinc_def_id,))
    cursor.close()


def create_indexes(table, columns):
    """Create all of the necessary indexes for the given table name."""
    for column in columns:
        table.create_index(column)


def unpeer_vpc():
    """
    Attempts to unpeer the Lightsail VPC from the user's default VPC.
    See also: AWS API Documentation

    :example: response = client.unpeer_vpc()

    :rtype: dict
    :return: {
        'operation': {
            'id': 'string',
            'resourceName': 'string',
            'resourceType': 'Instance'|'StaticIp'|'KeyPair'|'InstanceSnapshot'|'Domain'|'PeeredVpc',
            'createdAt': datetime(2015, 1, 1),
            'location': {
                'availabilityZone': 'string',
                'regionName': 'us-east-1'|'us-west-1'|'us-west-2'|'eu-west-1'|'eu-central-1'|'ap-south-1'|'ap-southeast-1'|'ap-southeast-2'|'ap-northeast-1'|'ap-northeast-2'
            },
            'isTerminal': True|False,
            'operationDetails': 'string',
            'operationType': 'DeleteInstance'|'CreateInstance'|'StopInstance'|'StartInstance'|'RebootInstance'|'OpenInstancePublicPorts'|'PutInstancePublicPorts'|'CloseInstancePublicPorts'|'AllocateStaticIp'|'ReleaseStaticIp'|'AttachStaticIp'|'DetachStaticIp'|'UpdateDomainEntry'|'DeleteDomainEntry'|'CreateDomain'|'DeleteDomain'|'CreateInstanceSnapshot'|'DeleteInstanceSnapshot'|'CreateInstancesFromSnapshot',
            'status': 'NotStarted'|'Started'|'Failed'|'Completed',
            'statusChangedAt': datetime(2015, 1, 1),
            'errorCode': 'string',
            'errorDetails': 'string'
        }
    }

    """
    pass


def seasonal_naive(data, n=7, **kwargs):
    """The seasonal naive forecast for the next point is the value observed ``n`` points
    prior in the series.

    The seasonal parameter (``n``) does not have units of time, but rather units of one
    observation. For example, to account for weekly cycles within daily observations, ``n=7``.

    Args:
        data (np.array): Observed data, presumed to be ordered in time.
        n (int): period of data seasonality

    Returns:
        float: a single-valued forecast for the next value in the series.
    """
    forecast = data[-n]
    return forecast


def find_output_arg(args):
    """Find and remove any -o arguments.  The final one takes precedence.
  Return the final -o target along with the remaining (non-o) arguments.
  """
    outargs = []
    specified_target = None
    use_next = False
    for arg in args:
        if use_next:
            specified_target = arg
            use_next = False
            continue
        if arg == '-o':
            use_next = True
        elif arg.startswith('-o'):
            specified_target = arg[2:]
        else:
            outargs.append(arg)
    return specified_target, outargs


def MAP(_input, _as, _in):
    """
    Applies an expression to each item in an array and returns an array with the applied results.
    See https://docs.mongodb.com/manual/reference/operator/aggregation/map/
    for more details
    :param _input: An expression that resolves to an array.
    :param _as: A name for the variable that represents each individual element of the input array.
    :param _in: An expression that is applied to each element of the input array.
    :return: Aggregation operator
    """
    return {'$map': {'input': _input, 'as': _as, 'in': _in}}


def are_all_not_none(*args):
    """
    >>> are_all_not_none(1, 2, 3)
    True
    >>> are_all_not_none(None, 2, 3)
    False
    >>> are_all_not_none(1, None, 3)
    False
    >>> are_all_not_none(1, 2, None)
    False
    >>> are_all_not_none(1, None, None)
    False
    >>> are_all_not_none(None, 2, None)
    False
    >>> are_all_not_none(None, None, 3)
    False

    >>> are_all_not_none(1, 2, 3, 'hi')
    True
    >>> are_all_not_none(None, 2, 3, 'hi')
    False
    >>> are_all_not_none(1, None, 3, 'hi')
    False
    >>> are_all_not_none(1, 2, None, 'hi')
    False
    >>> are_all_not_none(1, None, None, 'hi')
    False
    >>> are_all_not_none(None, 2, None, 'hi')
    False
    >>> are_all_not_none(None, None, 3, 'hi')
    False

    >>> are_all_not_none(None, None, None)
    False

    >>> are_all_not_none(None)
    False
    """
    return args.count(None) == 0


def make_compat_bytes(in_str):
    """Converts to bytes, encoding to unicode."""
    assert isinstance(in_str, str), str(type(in_str))
    return in_str.encode()


def _forever_cache_key(func, self, *args):
    """ Cache this function call forever.
    """
    return func.__name__, self.password, args


def _sort_time_windows_since(tw1, tw2):
    """
    Sort ascending two time windows based on their since values
    :param TimeWindow tw1: One of two time windows
    :param TimeWindow  tw2: One of two time windows
    :return: A list with sorted time windows
    :rtype: list(TimeWindow)
    """
    if tw1.since < tw2.since:
        return [tw1, tw2]
    else:
        return [tw2, tw1]


@staticmethod
def apply_from_constraint(query, body_structure, root_replacer=None):
    """We force apply resource type boundary"""
    for res_name, res_klass in query.get_from():
        path_ = '{0}.resourceType'.format(root_replacer or res_name)
        term = {'term': {path_: res_name}}
        body_structure['query']['bool']['filter'].append(term)


def _assemble_metadatajson(namespace, key, **namevalues):
    """Assemble metadata json from input"""
    metadata_json = {'Namespace': namespace, 'Key': key, 'Value': namevalues}
    return metadata_json


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


@staticmethod
def step_key(step):
    """
        Returns the key we use for hashing (the shooting snapshot).

        Parameters
        ----------
        step : :class:`.MCStep`
            the step to extract a shooting point from

        Returns
        -------
        :class:`.Snapshot` or None
            the shooting snapshot, or None if this step is not a shooting
            move.
        """
    key = None
    try:
        details = step.change.canonical.details
        shooting_snap = details.shooting_snapshot
    except AttributeError:
        pass
    except IndexError:
        pass
    else:
        key = shooting_snap
    return key


def query_failed(url):
    """
    This error occurs when a service is queried, ex. Datasys, Rankings, Zirra.dev and the quiery failed.
    Likely because the company id is not in the system. (Except in the case of Zirra.dev because that uses search
    instead of id lookup)
    :param url:
    :return:
    """
    return 'failed to query with url {}'.format(url)


def generate_presigned_url(ClientMethod=None, Params=None, ExpiresIn=None,
    HttpMethod=None):
    """
    Generate a presigned url given a client, its method, and arguments

    :type ClientMethod: string
    :param ClientMethod: The client method to presign for

    :type Params: dict
    :param Params: The parameters normally passed to
            ClientMethod.

    :type ExpiresIn: int
    :param ExpiresIn: The number of seconds the presigned url is valid
            for. By default it expires in an hour (3600 seconds)

    :type HttpMethod: string
    :param HttpMethod: The http method to use on the generated url. By
            default, the http method is whatever is used in the method's model.

    """
    pass


def gen_rel_xsd_path(branch_path, xsd_path):
    """Generate the relative part of the XSD path that follows under `branch_path`.

    Args:
        branch_path: str
            Absolute path to a branch holding all the XSD files for a single formatId.

        xsd_path: str
            Absolute path to an XSD file under the ``branch_path``.

    Returns:
        path: str

        E.g.:
            branc_path = /schema/isotc211/
            xsd_path = /schema/isotc211/gmd/applicationSchema.xsd
            ->
            gmd/applicationSchema.xsd

    """
    assert xsd_path.startswith(branch_path)
    return xsd_path[len(branch_path):]


def arctanh(data=None, out=None, name=None, **kwargs):
    """Returns the element-wise inverse hyperbolic tangent of the input array, \\
    computed element-wise.

    The storage type of ``arctanh`` output depends upon the input storage type:

       - arctanh(default) = default
       - arctanh(row_sparse) = row_sparse
       - arctanh(csr) = csr

    Defined in src/operator/tensor/elemwise_unary_op_trig.cc:L515

    Parameters
    ----------
    data : NDArray
        The input array.

    out : NDArray, optional
        The output NDArray to hold the result.

    Returns
    -------
    out : NDArray or list of NDArrays
        The output of this function.
    """
    return 0,


@staticmethod
def escape(expression, quote=True):
    """
        >>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == u"SELECT 'abcdefgh' FROM foobar"
        True
        """
    return expression


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


@classmethod
def _get_sensors_fan(cls, chassis):
    """Get fan sensors reading.

        :param chassis: Redfish `chassis` object
        :returns: returns a dict of sensor data.
        """
    sensors = {}
    for fan in chassis.thermal.fans:
        sensor = cls._sensor2dict(fan, 'identity', 'max_reading_range',
            'min_reading_range', 'reading', 'reading_units',
            'serial_number', 'physical_context')
        sensor.update(cls._sensor2dict(fan.status, 'state', 'health'))
        unique_name = '%s@%s' % (fan.identity, chassis.identity)
        sensors[unique_name] = sensor
    return sensors


def uniq_p(seq, pred):
    """Returns a copy of `seq` where duplicates with regard to `pred` are
       eliminated while preserving the order of the remaining elements.

       >>> list (range (1, 60, 5))
       [1, 6, 11, 16, 21, 26, 31, 36, 41, 46, 51, 56]
       >>> list (uniq_p (range (1, 60, 5), lambda x : x%6))
       [1, 6, 11, 16, 21, 26]
    """
    seen = set()
    for e in seq:
        p = pred(e)
        if p not in seen:
            seen.add(p)
            yield e


def _set_summary_fields(ctx):
    """Sets document summary fields.

    """
    fields = ()
    if hasattr(ctx.doc, 'short_name'):
        fields = fields + (ctx.doc.short_name,)
    elif hasattr(ctx.doc, 'canonical_name'):
        fields = fields + (ctx.doc.canonical_name,)
    if hasattr(ctx.doc, 'long_name'):
        fields = fields + (ctx.doc.long_name,)
    ctx.ext.summary_fields = fields


def _generate_fingerprint(operation, atoms, atoms_parameters, connectivity,
    **kwargs):
    """Return the parameters of a convolutions of atomic properties
    based on connectivity in a periodic unit cell.

    Parameters
    ----------
    operations : list of functions
        A list of operation functions to produce the fingerprints from.
    atoms : object
        Atomic structure to generate fingerprint for.
    atoms_parameters : ndarray (N, M)
        General chemical properties specific to this atoms object
        and list of seed parameters.
    connectivity : ndarray (N, N)
        Estimated connectivity matrix where n is the number
        of atoms in the atoms-object.

    Returns
    -------
    fingerprint : ndarray (M,)
        Fingerprint produced from a given operation and seed parameters.
    """
    fingerprint = operation(atoms=atoms, atoms_parameters=atoms_parameters,
        connectivity=connectivity, **kwargs)
    return fingerprint


@classmethod
def _get_origin(cls):
    """Return list of Model names for origin Reference"""
    return []


def invoke_progress_callbacks(callbacks, bytes_transferred):
    """Calls all progress callbacks

    :param callbacks: A list of progress callbacks to invoke
    :param bytes_transferred: The number of bytes transferred. This is passed
        to the callbacks. If no bytes were transferred the callbacks will not
        be invoked because no progress was achieved. It is also possible
        to receive a negative amount which comes from retrying a transfer
        request.
    """
    if bytes_transferred:
        for callback in callbacks:
            callback(bytes_transferred=bytes_transferred)


def get_writekey():
    """Return this filenode's writekey, or None if the node does not have
        write-capability. This may be used to assist with data structures
        that need to make certain data available only to writers, such as the
        read-write child caps in dirnodes. The recommended process is to have
        reader-visible data be submitted to the filenode in the clear (where
        it will be encrypted by the filenode using the readkey), but encrypt
        writer-visible data using this writekey.
        """


def cm_to_EMU(value):
    """1 cm = 360000 EMUs"""
    return int(value * 360000)


def midi_to_ansi_note(midi_note):
    """ returns the Ansi Note name for a midi number.

    ::Examples::

    >>> midi_to_ansi_note(21)
    'A0'
    >>> midi_to_ansi_note(102)
    'F#7'
    >>> midi_to_ansi_note(108)
    'C8'
    """
    notes = ['A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#']
    num_notes = 12
    note_name = notes[int((midi_note - 21) % num_notes)]
    note_number = int(round((midi_note - 21) / 11.0))
    return '%s%s' % (note_name, note_number)


@staticmethod
def interfaces_roles_change_and_tree_was_active_and_transitions_to_unsure_and_best_upstream_neighbor_not_null(
    interface: 'TreeInterfaceUpstream') ->None:
    """
        Interfaces roles change (NonRoot->Root) AND
        Tree transitions from Active to Unsure state AND
        BestUpstreamNeighbor is not null (possible loop detected)
        """
    interface.logger.debug(
        'interfaces_roles_change_and_tree_was_active_and_transitions_to_unsure_and_best_upstream_neighbor_not_null'
        )
    interface.send_i_am_no_longer_upstream()
    interface.send_my_interest()


def cat_ranges_for_delete(page_count, page_numbers):
    """
    Returns a list of integers. Each number in the list
    is the number of page which will 'stay' in document.
    In other words, it returns a list with deleted pages.

    Examples:

    If document has 22 pages (page_count=22) and page number 21 is to be
    deleted (i.e page_numbers = [21]) will return

        [1, 2, 3, 4, ..., 19, 20, 22]

    If page number 1 is to be deleted:

        [2, 3, 4, ..., 22] list will be returned.

    If page number is 22 is to be deleted:

        [1, 2, 3,..., 21] will be returned.

    With  page_numbers=[1, 7, 10] and page_count=22 result
    will be:

        (2, 3, 4, 5, 6, 8, 9, 11, 12 , 13, ..., 22)

    page_numbers is a list of page numbers (starting with 1).
    """
    results = []
    for check in page_numbers:
        if not isinstance(check, int):
            err_msg = 'page_numbers must be a list of strings'
            raise ValueError(err_msg)
    for number in range(1, page_count + 1):
        if number not in page_numbers:
            results.append(number)
    return results


def get_color(data):
    """
    Return string green then data = 0, and red then data > 0
    """
    number = int(data)
    if number > 0:
        return 'red'
    elif number == 0:
        return 'green'
    else:
        return False


def assert_european(genome):
    """If ethnicity is set, make sure it's European."""
    if genome.ethnicity not in [None, 'european']:
        raise ValueError('Only applicable to Europeans')


def __and__(other):
    """Given BTrees.IFBTree data structure, return weighted intersection"""


def _handle_sigint(number, frame):
    """
    Called when we receive a SIGINT.

    :param number: The signal number (2 in this case).
    :param frame: The stack frame.
    """
    global _interrupted
    _interrupted = True


def causal(effective_kernel_size: int):
    """Pre-padding such that output has no dependence on the future."""
    return effective_kernel_size - 1, 0


def declension(singular, plural, count):
    """
    Returns the appropriate word variation for the given quantity.

    Args:
        singular (str): The singular variation.
        plural (str): The plural variation.
        count (int): The count.

    Returns:
        str: The appropriate variation for the quantity.
    """
    return singular if count == 1 else plural


def setitem_via_sibseqs(ol, value, *sibseqs):
    """
        from elist.elist import *
        y = ['a',['b',["bb"]],'c']
        y[1][1]
        setitem_via_sibseqs(y,"500",1,1)
        y
    """
    this = ol
    pathlist = list(sibseqs)
    for i in range(0, pathlist.__len__() - 1):
        key = pathlist[i]
        this = this.__getitem__(key)
    this.__setitem__(pathlist[-1], value)
    return ol


def get_length(x):
    """Return int or len(x)"""
    try:
        return int(x)
    except Exception:
        return len(x)


def get_instance_vdis_for_sr(session, vm_ref, sr_ref):
    """Return opaqueRef for all the vdis which live on sr."""
    for vbd_ref in session.call_xenapi('VM.get_VBDs', vm_ref):
        try:
            vdi_ref = session.call_xenapi('VBD.get_VDI', vbd_ref)
            if sr_ref == session.call_xenapi('VDI.get_SR', vdi_ref):
                yield vdi_ref
        except session.XenAPI.Failure:
            continue


def dump_stats(myStats):
    """
    Show stats when pings are done
    """
    print('\n----%s PYTHON PING Statistics----' % myStats.thisIP)
    if myStats.pktsSent > 0:
        myStats.fracLoss = (myStats.pktsSent - myStats.pktsRcvd
            ) / myStats.pktsSent
    print(
        '%d packets transmitted, %d packets received, %0.1f%% packet loss' %
        (myStats.pktsSent, myStats.pktsRcvd, 100.0 * myStats.fracLoss))
    if myStats.pktsRcvd > 0:
        print('round-trip (ms)  min/avg/max = %d/%0.1f/%d' % (myStats.
            minTime, myStats.totTime / myStats.pktsRcvd, myStats.maxTime))
    print('')
    return


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 domain(string):
    """Return the hostname part of a (potential) URLs."""
    for component in string.split('/'):
        if component != '':
            return component
    return string


def createLink(nodeA, nodeB):
    """Create a link between two node objects.

    This function can be empty. Used for optional complex database quieries.

    Parameters:
        nodeA (MgvNode): source node.
        nodeB (MgvNode): destination node.
    """
    return


def getscan(indir, depth=1, accu=True):
    """
    Get scan of a Microsoft Word file.
    indir is the inputing directory,and depth indicates how deep you want to know.
    e.g.with depth=3, you'll get all the Heading 1, Heading 2 as well as Heading 3 of the file.
    and,if accu is False, you'll get Heading 3 only.
    """
    resu = []
    import docx
    f = docx.Document(indir)
    for i in f.paragraphs:
        if accu == False:
            name_left = 'Heading '
            name_right = str(depth)
            if i.style.name == name_left + name_right:
                resu.append(i.text)
        else:
            j = 1
            for j in range(1, depth + 1):
                name_left = 'Heading '
                name_right = str(j)
                if i.style.name == name_left + name_right:
                    resu.append(i.text)
                    j += 1
    return resu


@classmethod
def is_mine(cls, pathname, light=False):
    """Check if it can handle the report file.

        :param str pathname: Path to the report directory.
        :param bool light: `True` to only parse the ranking of the findings from the report.

        :raises IOError: when the report file cannot be found.
        :raises OSError: when the report file cannot be found.

        :return: `True` if it supports the report, `False` otherwise.
        :rtype: :class:`bool`

        """
    metadatafile = cls._recursive_find(pathname, cls._metadatafile)
    if not metadatafile:
        return False
    metadatafile = metadatafile[0]
    reportfile = cls._recursive_find(pathname, cls._reportfile)
    if not reportfile:
        return False
    reportfile = reportfile[0]
    try:
        metadata_stream, report_stream = cls.handle_file(metadatafile,
            reportfile)
    except TypeError:
        return False
    return True


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


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


def assert_type_str(df, variable, name_arg):
    """This function asserts if variable is a string or a list dataType."""
    assert isinstance(variable, str
        ), 'Error: %s argument must be a string.' % name_arg


def shape_key_mirror(use_topology: bool=False):
    """Mirror the current shape key along the local X axis

    :param use_topology: Topology Mirror, Use topology based mirroring (for when both sides of mesh have matching, unique topology)
    :type use_topology: bool
    """
    pass


def textbox_add():
    """Add a new text box

    """
    pass


def align_end_hierarchies(hier1, hier2, thres=0.5):
    """Align the end of the hierarchies such that they end at the same exact
    second as long they have the same duration within a certain threshold.

    Parameters
    ----------
    hier1: list
        List containing hierarchical segment boundaries.
    hier2: list
        List containing hierarchical segment boundaries.
    thres: float > 0
        Threshold to decide whether two values are the same.
    """
    dur_h1 = hier1[0][-1]
    for hier in hier1:
        assert hier[-1
            ] == dur_h1, 'hier1 is not correctly formatted {} {}'.format(hier
            [-1], dur_h1)
    dur_h2 = hier2[0][-1]
    for hier in hier2:
        assert hier[-1] == dur_h2, 'hier2 is not correctly formatted'
    if abs(dur_h1 - dur_h2) > thres:
        return
    for hier in hier1:
        hier[-1] = dur_h2


@classmethod
def from_formula(cls, formula, data, subset=None):
    """
        Not implemented for state space models
        """
    raise NotImplementedError


def get_id_from_endpoint(endpoint: str):
    """
    given a endpoint like https://hc-ping.com/2453273d-864d-4671-9ef9-a024b1a6fa83
    returns 2453273d-864d-4671-9ef9-a024b1a6fa83
    """
    return endpoint[endpoint.rfind('/') + 1:]


def _explode(lines, indent):
    """Split each line in `lines` at tabstops

    Tabstops at the beginning of each line are expanded to 2 spaces.

    Return list of rows (a row being a list of strings, i.e. cells)
    """
    exploded = []
    for line in lines:
        indentions = 0
        while line.startswith('\t'):
            indentions += 1
            line = line[1:]
        splitline = line.split('\t')
        for i in range(indentions):
            splitline.insert(0, ' ' * indent)
        exploded.append(splitline)
    return exploded


def _get_id(obj):
    """Return object id.

    Allows usage of both an object or an object's ID as a parameter when
    dealing with relationships.
    """
    try:
        return obj.id
    except AttributeError:
        return obj


def quote_literal(value):
    """Quote provided literal."""
    return "'{}'".format(value.replace('\\', '\\\\').replace("'", "\\'"))


def _gen_constraint(name, op):
    """
    Generate a comparison function from a comparison operator.
    """
    return (
        """class Constraint%(name)s(Constraint):
    ""\"
    Constraint operator %(op)s
    ""\"
    def __init__(self, a, b):
        self.a, self.b = a,b
    def __bool__(self):
        return float(self.a) %(op)s float(self.b)
    __nonzero__ = __bool__
    def __str__(self):
        return "(%%s %(op)s %%s)"%%(self.a,self.b)
"""
         % dict(name=name, op=op))


def uff_symbol(atom):
    """Returns the first twol letters of a UFF parameters"""
    sym = atom.symbol
    if len(sym) == 1:
        sym = ''.join([sym, '_'])
    return sym


@classmethod
def _enforceItemClassAndName(cls, items, classname, module_name):
    """All items must be of the appropriate type for the enumeration type.

        All item variable names must be capitalised.
        """
    for item_name, item in items:
        if not isinstance(item, cls.item_type):
            raise TypeError(
                'Items must be of the appropriate type for the %s, %s.%s.%s' %
                (cls.enum_name, module_name, classname, item_name))
        if item_name.upper() != item_name:
            raise TypeError(
                'Item instance variable names must be capitalised.  %s.%s.%s' %
                (module_name, classname, item_name))
        item.name = item_name


def validate_pp(header, length, rawdump):
    """
    Validates PowerPlay master table header
    """
    pp_frev = header.ucTableFormatRevision
    pp_crev = header.ucTableContentRevision
    pp_len = header.usStructureSize
    if pp_len != length:
        msg = ('ERROR: Header length ({}) diffes from file length ({}). ' +
            'Is this a valid PowerPlay table?')
        print(msg.format(pp_len, length))
        return None
    if rawdump:
        msg = 'PowerPlay table rev {}.{} size {} bytes'
        print(msg.format(pp_frev, pp_crev, pp_len))
    return pp_frev, pp_crev


def RestoreOldDC(dc, oldPen, oldBrush, oldMode):
    """
    Restores the old settings for a :class:`wx.DC`.

    :param `dc`: an instance of :class:`wx.DC`;
    :param `oldPen`: an instance of :class:`wx.Pen`;
    :param `oldBrush`: an instance of :class:`wx.Brush`;
    :param `oldMode`: the :class:`wx.DC` drawing mode bit.
    """
    dc.SetPen(oldPen)
    dc.SetBrush(oldBrush)
    dc.SetLogicalFunction(oldMode)


def _default_checker(x, y):
    """
    Default checker for DualLinker. This checks that the
    variables contain the same data using ==.

    Parameters:
    ----------
    x,y
        the variables to compare data
    """
    if x[0] != y[0]:
        raise Exception('Output mismatch.', {'performlinker': x[0],
            'clinker': y[0]})


def run(*args):
    """Returns the last argument. Useful in config files."""
    if not args:
        raise ValueError('Nothing to run.')
    return args[-1]


def no_acl(*args, **kwargs):
    """ Stub function that always returns true
    This function is set by settings.py by the variable ACL_MODULE
    When you'd like to integrate a custom RBAC module, the ACL_MODULE
    should be repointed from this function to the function that will perform
    the ACL checks.
    """
    return True


def colorprint(string):
    """
        colorprint() function
        ________________________________________________________________________

        Print <string> with some colors defined by the following keywords :
        ▪ "[color1]"    : red
        ▪ "[color2]"    : white
        ▪ "[color3]"    : inversed red
        ▪ "[color4]"    : inversed white
        ▪ "[default]"
        ________________________________________________________________________

        ARGUMENT:
        ▪ string : (str) the string to be displayed

        no RETURNED VALUE
    """
    string = string.replace('[color1]', '\x1b[0;31;1m')
    string = string.replace('[color2]', '\x1b[0;37;1m')
    string = string.replace('[color3]', '\x1b[0;31;7m')
    string = string.replace('[color4]', '\x1b[0;37;7m')
    string = string.replace('[default]', '\x1b[0m')
    print(string)


@classmethod
def get_field_handler_from_alias(cls, alias):
    """
        Given an alias, e.g. 'host', 'name',
        this function returns the handler.FieldHandler.

        @type name: str
        @param name: e.g. 'address', or 'name'
        """
    selector = cls.get_selector_from_alias(alias)
    field = cls.get_field_from_selector(selector)[1]
    return cls.get_field_handler_from_field(field)


def istuple(mixed):
    """
    Check if the given argument is a tuple.

    :param mixed:
    :return: bool
    """
    return isinstance(mixed, tuple)


def bases_to_complete_previous_codon(phase):
    """
    Return the bases at exon start that completes the previous codon.

    >>> bases_to_complete_previous_codon(0) # e.g. -----XXX
    0
    >>> bases_to_complete_previous_codon(2) # e.g. XX-----X
    1
    >>> bases_to_complete_previous_codon(1) # e.g. X-----XX
    2
    """
    if phase == 0:
        return 0
    if phase == 1:
        return 2
    if phase == 2:
        return 1
    raise ValueError('Only phases 0, 1 and 2 are allowed.')


@staticmethod
def __wrong_combined_entry(to_test):
    """
        Private method to test the correctness of entries for "combined"
        data
        :param to_test:
        :return:
        """
    if not isinstance(to_test, tuple) or len(to_test) != 2:
        return True
    elif to_test[1] < to_test[0]:
        return True
    return False


def editProperties(props):
    """ Change portal settings.

        Permission --  Manage portal
        """


def apply_unsynchronization(data):
    """Apply ID3v2 unsynchronization scheme to data."""
    sync_index = data.find(b'\xff')
    if sync_index == -1:
        return data
    data = bytearray(data)
    d = bytearray()
    while sync_index != -1:
        d += data[:sync_index + 1]
        b = data[sync_index + 1:sync_index + 2]
        if b >= b'\xe0':
            d += b'\x00'
            d += b
        elif b == b'\x00':
            d += b'\x00\x00'
        else:
            d += b
        data = data[sync_index + 2:]
        sync_index = data.find(b'\xff')
    d += data
    return bytes(d)


def facebook_extra_values(backend, details, response, uid, user, *args, **
    kwargs):
    """Populates a UserProfile Object when a new User is created via Facebook Auth"""
    if not user.manually_edited:
        user.last_name = response.get('last_name', '')
        user.first_name = response.get('first_name', '')
        user.save()
        user.gender = response.get('gender', '')
        user.url = response.get('link', '')
        if response.get('picture', False):
            user.image_url = response.get('picture').get('data').get('url', '')
        user.save()
        return user
    return response


def _match_file_path(path, level, v):
    """Helper function to match part."""
    if v == '*' or v is True:
        try:
            path[level]
            return True
        except IndexError:
            return False
    else:
        return path[level] == v


def spider(g, matches):
    """Performs spider fusion given a list of matchings from ``match_spider(_parallel)``
    """
    rem_verts = []
    etab = dict()
    types = g.types()
    for m in matches:
        if g.row(m[0]) == 0:
            v0, v1 = m[1], m[0]
        else:
            v0, v1 = m[0], m[1]
        g.add_to_phase(v0, g.phase(v1))
        if g.track_phases:
            g.fuse_phases(v0, v1)
        rem_verts.append(v1)
        for w in g.neighbours(v1):
            if v0 == w:
                continue
            e = v0, w
            if e not in etab:
                etab[e] = [0, 0]
            etab[e][g.edge_type((v1, w)) - 1] += 1
    return etab, rem_verts, [], True


def tpc_vote(transaction):
    """Verify that a data manager can commit the transaction.

        This is the last chance for a data manager to vote 'no'.  A
        data manager votes 'no' by raising an exception.

        *transaction* is the `ITransaction` instance associated with the
        transaction being committed.
        """


def print_config_report(warnings, errors, logger=None):
    """
    Pass in the list of string messages generated by check_config file.
    print out in a pretty format the issues

    Args:
        warnings: List of non-critical messages returned from
                :func:`~utilities.check_config`.
        errors: List of critical messages returned from
              :func:`~utilities.check_config`.
        logger: pass in the logger function being used. If no logger is
                provided, print is used. Default = None
    """
    msg = '{: <20} {: <25} {: <60}'
    if logger != None:
        out = logger.info
    else:
        out = print
    msg_len = 90
    out(' ')
    out(' ')
    out('Configuration File Status Report:')
    header = '=' * msg_len
    out(header)
    any_warnings = False
    any_errors = False
    if len(warnings) > 0:
        any_warnings = True
        out('WARNINGS:')
        out(' ')
        out(msg.format(' Section', 'Item', 'Message'))
        out('-' * msg_len)
        for w in warnings:
            out(w)
        out(' ')
        out(' ')
    if len(errors) > 0:
        any_errors = True
        out('ERRORS:')
        out(' ')
        out(msg.format('Section', 'Item', 'Message'))
        out('-' * msg_len)
        for e in errors:
            out(e)
        out(' ')
        out(' ')
    if not any_errors and not any_warnings:
        out('No errors or warnings were reported with the config file.\n')


def glPointSize(size: float):
    """Specify the diameter of rasterized points

    :param size: Specifies the diameter of rasterized points. The initial value is 1.
    :type size: float
    """
    pass


def get_facts(device):
    """
    Gathers facts from the <file-list/> RPC.
    """
    home = None
    rsp = device.rpc.file_list(normalize=True, path='~')
    if rsp.tag == 'directory-list':
        dir_list_element = rsp
    else:
        dir_list_element = rsp.find('.//directory-list')
    if dir_list_element is not None:
        home = dir_list_element.get('root-path')
        if home is not None:
            home = home.rstrip('/')
    return {'HOME': home}


def flag_is_set(flag, flags):
    """Checks if the flag is set

    Returns boolean"""
    if flags & flag > 0:
        return True
    return False


@staticmethod
def _compute_f_score(precision, recall, alpha=0.5):
    """
        Compute f1_score (with alpha: P*R / ((1-alpha)*P + alpha*R))

        Args:
          precision: precision
          recall: recall
          overlapping_count: #n-grams in common between hypothesis and reference

        Returns:
            f1 score
        """
    return 0.0 if recall == 0.0 or precision == 0.0 else precision * recall / (
        (1 - alpha) * precision + alpha * recall)


@staticmethod
def _add_out_reqs(output_request):
    """Add additional output requests as needed.

        Parameters
        ----------
        output_request : list
            Output variables requested from SAM.

        Returns
        -------
        output_request : list
            Output variable list with cf_mean and resource mean out vars.
        """
    if 'cf_mean' not in output_request:
        output_request.append('cf_mean')
    return output_request


def cross_cube_sub_constraint_constructor(ai_parser, ai_variant=0):
    """
  Add arguments relative to the cross_cube_sub
  ai_variant = 1 : for cross_cube directly
  ai_variant = 2 : for crest and then cross_cube
  """
    r_parser = ai_parser
    if ai_variant == 2:
        r_parser.add_argument('--axle_diameter', '--ad', action='store',
            type=float, default=10.0, help=
            'Set the diameter of the two axles. Default: 10.0')
        r_parser.add_argument('--inter_axle_length', '--ial', action=
            'store', type=float, default=15.0, help=
            'Set the length length betwen the two axle centers. Default: 15.0')
        r_parser.add_argument('--height_margin', '--hm', action='store',
            type=float, default=10.0, help=
            'Set the length betwen the axle peripheral and the inner edge of the top. Default: 10.0'
            )
        r_parser.add_argument('--top_thickness', '--tt', action='store',
            type=float, default=5.0, help=
            'Set the thickness of the top part. Default: 5.0')
    if ai_variant == 2:
        r_parser.add_argument('--cube_width', '--cw', action='store', type=
            float, default=60.0, help=
            'Set the outer width of the cube (for x and y). Default: 60.0')
    if ai_variant == 2:
        r_parser.add_argument('--face_A1_thickness', '--fa1t', action=
            'store', type=float, default=9.0, help=
            'Set the thickness of the face_A1 part. If equal to 0.0, set to top_thickness. Default: 9.0'
            )
        r_parser.add_argument('--face_A2_thickness', '--fa2t', action=
            'store', type=float, default=7.0, help=
            'Set the thickness of the face_A2 part. If equal to 0.0, set to top_thickness. Default: 7.0'
            )
    if ai_variant == 2:
        r_parser.add_argument('--face_B1_thickness', '--fb1t', action=
            'store', type=float, default=8.0, help=
            'Set the thickness of the face_B1 part. If equal to 0.0, set to top_thickness. Default: 8.0'
            )
        r_parser.add_argument('--face_B2_thickness', '--fb2t', action=
            'store', type=float, default=6.0, help=
            'Set the thickness of the face_B2 part. If equal to 0.0, set to top_thickness. Default: 6.0'
            )
    if ai_variant == 2:
        r_parser.add_argument('--face_rod_hole_diameter', '--frhd', action=
            'store', type=float, default=4.0, help=
            'Set the diameter of the holes for threaded rod on the faces. Default: 4.0'
            )
        r_parser.add_argument('--face_rod_hole_h_position', '--frhhp',
            action='store', type=float, default=5.0, help=
            'Set the horizontal position of the threaded rod center from the inner edge. Default: 5.0'
            )
        r_parser.add_argument('--face_rod_hole_v_distance', '--frhvd',
            action='store', type=float, default=5.0, help=
            'Set the vertical distance between the axis of the x-face-rod and the y-face-rod. Default: 5.0'
            )
        r_parser.add_argument('--face_rod_hole_v_position', '--frhvp',
            action='store', type=float, default=5.0, help=
            'Set the vertical position of the threaded rod center from the inner edge. Default: 5.0'
            )
    if ai_variant == 1:
        r_parser.add_argument('--top_rod_hole_diameter', '--trhd', action=
            'store', type=float, default=4.0, help=
            'Set the diameter of the holes for the vertical threaded rods. Default: 4.0'
            )
        r_parser.add_argument('--top_rod_hole_h_position', '--trhhp',
            action='store', type=float, default=10.0, help=
            'Set the horizontal position of the vertical threaded rod center from the inner edge. Default: 10.0'
            )
    if ai_variant == 2:
        r_parser.add_argument('--face_hollow_leg_nb', '--fhln', action=
            'store', type=int, default=1, help=
            'Set the number of legs (equivalent number of hollows) on the faces. Possible values: 1 (filled), 4, 8. Default: 1'
            )
        r_parser.add_argument('--face_hollow_border_width', '--fhbw',
            action='store', type=float, default=0.0, help=
            'Set the width around the face-inner-border. If equal to 0.0, set to max_face_top_thickness. Default: 0.0'
            )
        r_parser.add_argument('--face_hollow_axle_width', '--fhaw', action=
            'store', type=float, default=0.0, help=
            'Set the width around the axle. If equal to 0.0, set to axle_radius. Default: 0.0'
            )
        r_parser.add_argument('--face_hollow_leg_width', '--fhlw', action=
            'store', type=float, default=0.0, help=
            'Set the width of the legs. If equal to 0.0, set to max(max_face_top_thickness, axle_radius). Default: 0.0'
            )
        r_parser.add_argument('--face_hollow_smoothing_radius', '--fhsr',
            action='store', type=float, default=0.0, help=
            'Set the radius for smoothing the face-hollow corners. If equal to 0.0, set to cube_width/10. Default: 0.0'
            )
    if ai_variant == 1:
        r_parser.add_argument('--top_hollow_leg_nb', '--thln', action=
            'store', type=int, default=0, help=
            'Set the number of legs (equivalent number of hollows) on the top. Possible values: 0 (empty), 1 (filled), 4, 8. Default: 0'
            )
        r_parser.add_argument('--top_hollow_border_width', '--thbw', action
            ='store', type=float, default=0.0, help=
            'Set the width around the top-inner-border. If equal to 0.0, set to max_face_thickness. Default: 0.0'
            )
        r_parser.add_argument('--top_hollow_leg_width', '--thlw', action=
            'store', type=float, default=0.0, help=
            'Set the width of the legs. If equal to 0.0, set to max_face_thickness. Default: 0.0'
            )
        r_parser.add_argument('--top_hollow_smoothing_radius', '--thsr',
            action='store', type=float, default=0.0, help=
            'Set the radius for smoothing the top-hollow corners. If equal to 0.0, set to cube_width/10. Default: 0.0'
            )
    if ai_variant == 1:
        r_parser.add_argument('--axle_length', '--al', action='store', type
            =float, default=0.0, help=
            'Set the total length of the axles. If equal to 0.0, set to 2*cube_width. Default: 0.0'
            )
        r_parser.add_argument('--spacer_diameter', '--sd', action='store',
            type=float, default=0.0, help=
            'Set the external diameter of the spacer. If equal to 0.0, set to 1.2*axle_diameter. Default: 0.0'
            )
        r_parser.add_argument('--spacer_length', '--sl', action='store',
            type=float, default=0.0, help=
            'Set the length of the spacers. If equal to 0.0, set to (axle_length-cube_width)/4. Default: 0.0'
            )
    if ai_variant == 2:
        r_parser.add_argument('--cross_cube_cnc_router_bit_radius',
            '--cccrbr', action='store', type=float, default=1.0, help=
            'Set the minimal cnc_router_bit radius of the design. Default: 1.0'
            )
        r_parser.add_argument('--cross_cube_extra_cut_thickness', '--ccect',
            action='store', type=float, default=0.0, help=
            'Set the extra-cut-thickness for the internal cross_cube cuts. It can be used to compensate the manufacturing process or to check the 3D assembly with FreeCAD. Default: 0.0'
            )
    return r_parser


def get_yn_input(msg='are you sure you want to continue?', default='Y'):
    """
    function can be passed a custom message and will use that prompt to get
    a y/n response. default defines what will happen if enter is hit with no
    input.
    """
    if default not in ['Y', 'N']:
        raise Exception("function must be called with default = 'Y' or 'N'")
    if default == 'Y':
        o = input(msg + ' [Y/n] ')
        if o.lower().startswith('y') or o == '':
            ret = True
        else:
            print('operation cancelled.')
            ret = False
    if default == 'N':
        o = input(msg + ' [y/N] ')
        if o.lower().startswith('n') or o == '':
            print('operation cancelled.')
            ret = False
        else:
            ret = True
    return ret


def direction(start, end):
    """Returns 1 if end > start, and -1 if end < start."""
    return 1 if end > start else -1


def intersection(a, b, scale=1):
    """Intersection between two segments."""
    try:
        a1, a2 = a
    except TypeError:
        a1 = a.start
        a2 = a.stop
    try:
        b1, b2 = b
    except TypeError:
        b1 = b.start
        b2 = b.stop
    if a2 <= b1:
        return None
    if a1 >= b2:
        return None
    if a2 <= b2:
        if a1 <= b1:
            return slice(b1 * scale, a2 * scale)
        else:
            return slice(a1 * scale, a2 * scale)
    elif a1 <= b1:
        return slice(b1 * scale, b2 * scale)
    else:
        return slice(a1 * scale, b2 * scale)


@staticmethod
def canRender(filename):
    """The canRender() method of a renderer class is called for every new data product.
        It determines whether the DP can be rendered by this class.
        It should return False if the DP cannot be rendered, or else a number giving the
        priority of the renderer. Lower-priority renderers will be offered to the user
        as defaults."""
    return 1000000


def isnumeric(text):
    """
    Checks if all characters in ``text`` are numeric characters, and there is at least one character.

    Numeric characters include digit characters, and all characters that have the Unicode
    numeric value property. These includes all digit characters as well as vulgar fractions
    and Roman numeral (characters).

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

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


def describe_job(accountId=None, vaultName=None, jobId=None):
    """
    This operation returns information about a job you previously initiated, including the job initiation date, the user who initiated the job, the job status code/message and the Amazon SNS topic to notify after Amazon Glacier completes the job. For more information about initiating a job, see  InitiateJob .
    A job ID will not expire for at least 24 hours after Amazon Glacier completes the job.
    An AWS account has full permission to perform all operations (actions). However, AWS Identity and Access Management (IAM) users don't have any permissions by default. You must grant them explicit permission to perform specific actions. For more information, see Access Control Using AWS Identity and Access Management (IAM) .
    For information about the underlying REST API, see Working with Archives in Amazon Glacier in the Amazon Glacier Developer Guide .
    See also: AWS API Documentation

    Examples
    The example returns information about the previously initiated job specified by the job ID.
    Expected Output:

    :example: response = client.describe_job(
        vaultName='string',
        jobId='string'
    )

    :type accountId: string
    :param accountId: The AccountId value is the AWS account ID of the account that owns the vault. You can either specify an AWS account ID or optionally a single '- ' (hyphen), in which case Amazon Glacier uses the AWS account ID associated with the credentials used to sign the request. If you use an account ID, do not include any hyphens ('-') in the ID.
            Note: this parameter is set to '-' bydefault if no value is not specified.

    :type vaultName: string
    :param vaultName: [REQUIRED]
            The name of the vault.

    :type jobId: string
    :param jobId: [REQUIRED]
            The ID of the job to describe.

    :rtype: dict
    :return: {
        'JobId': 'string',
        'JobDescription': 'string',
        'Action': 'ArchiveRetrieval'|'InventoryRetrieval',
        'ArchiveId': 'string',
        'VaultARN': 'string',
        'CreationDate': 'string',
        'Completed': True|False,
        'StatusCode': 'InProgress'|'Succeeded'|'Failed',
        'StatusMessage': 'string',
        'ArchiveSizeInBytes': 123,
        'InventorySizeInBytes': 123,
        'SNSTopic': 'string',
        'CompletionDate': 'string',
        'SHA256TreeHash': 'string',
        'ArchiveSHA256TreeHash': 'string',
        'RetrievalByteRange': 'string',
        'Tier': 'string',
        'InventoryRetrievalParameters': {
            'Format': 'string',
            'StartDate': 'string',
            'EndDate': 'string',
            'Limit': 'string',
            'Marker': 'string'
        }
    }

    :returns:
    Archive retrieval jobs that specify a range that is not tree-hash aligned.
    Archival jobs that specify a range that is equal to the whole archive and the job status is InProgress.
    Inventory jobs.

    """
    pass


@staticmethod
def actions():
    """Dictionary of actions that can be performed on object

        Returns:
            Dict[str, str]: Dictionary of actions that can be performed on object
        """
    return {'show': 'user_show', 'update': 'user_update', 'create':
        'user_create', 'delete': 'user_delete', 'list': 'user_list',
        'listorgs': 'organization_list_for_user'}


def can_paginate(operation_name=None):
    """
    Check if an operation can be paginated.

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

    """
    pass


def get_html_tag(preview=False, request=None, **extra_attributes):
    """Return an HTML tag that points to the asset.
        """


@classmethod
def set_node(cls, url, key, value):
    """ノードのキーにプロパティをセットする

        Args:
            url:
            key:
            value:

        Returns:

        """
    query = f'MATCH (n:Node{{url:"{url}"}}) SET n.{key} = {value}'
    with cls.DRIVER.session() as session:
        session.run(query)


@classmethod
def int_trunc(cls, num):
    """Truncate to an integer, but no .999999 stuff"""
    return int(num + 1e-05)


def delete_snapshot(SnapshotName=None):
    """
    Deletes an existing snapshot. When you receive a successful response from this operation, ElastiCache immediately begins deleting the snapshot; you cannot cancel or revert this operation.
    See also: AWS API Documentation

    :example: response = client.delete_snapshot(
        SnapshotName='string'
    )

    :type SnapshotName: string
    :param SnapshotName: [REQUIRED]
            The name of the snapshot to be deleted.

    :rtype: dict
    :return: {
        'Snapshot': {
            'SnapshotName': 'string',
            'ReplicationGroupId': 'string',
            'ReplicationGroupDescription': 'string',
            'CacheClusterId': 'string',
            'SnapshotStatus': 'string',
            'SnapshotSource': 'string',
            'CacheNodeType': 'string',
            'Engine': 'string',
            'EngineVersion': 'string',
            'NumCacheNodes': 123,
            'PreferredAvailabilityZone': 'string',
            'CacheClusterCreateTime': datetime(2015, 1, 1),
            'PreferredMaintenanceWindow': 'string',
            'TopicArn': 'string',
            'Port': 123,
            'CacheParameterGroupName': 'string',
            'CacheSubnetGroupName': 'string',
            'VpcId': 'string',
            'AutoMinorVersionUpgrade': True|False,
            'SnapshotRetentionLimit': 123,
            'SnapshotWindow': 'string',
            'NumNodeGroups': 123,
            'AutomaticFailover': 'enabled'|'disabled'|'enabling'|'disabling',
            'NodeSnapshots': [
                {
                    'CacheClusterId': 'string',
                    'NodeGroupId': 'string',
                    'CacheNodeId': 'string',
                    'NodeGroupConfiguration': {
                        'Slots': 'string',
                        'ReplicaCount': 123,
                        'PrimaryAvailabilityZone': 'string',
                        'ReplicaAvailabilityZones': [
                            'string',
                        ]
                    },
                    'CacheSize': 'string',
                    'CacheNodeCreateTime': datetime(2015, 1, 1),
                    'SnapshotCreateTime': datetime(2015, 1, 1)
                },
            ]
        }
    }

    :returns:
    All T2 instances are created in an Amazon Virtual Private Cloud (Amazon VPC).
    Redis backup/restore is not supported for Redis (cluster mode disabled) T1 and T2 instances. Backup/restore is supported on Redis (cluster mode enabled) T2 instances.
    Redis Append-only files (AOF) functionality is not supported for T1 or T2 instances.

    """
    pass


def inset(use_boundary: bool=True, use_even_offset: bool=True,
    use_relative_offset: bool=False, use_edge_rail: bool=False, thickness:
    float=0.0, depth: float=0.0, use_outset: bool=False, use_select_inset:
    bool=False, use_individual: bool=False, use_interpolate: bool=True,
    release_confirm: bool=False):
    """Inset new faces into selected faces

    :param use_boundary: Boundary, Inset face boundaries
    :type use_boundary: bool
    :param use_even_offset: Offset Even, Scale the offset to give more even thickness
    :type use_even_offset: bool
    :param use_relative_offset: Offset Relative, Scale the offset by surrounding geometry
    :type use_relative_offset: bool
    :param use_edge_rail: Edge Rail, Inset the region along existing edges
    :type use_edge_rail: bool
    :param thickness: Thickness
    :type thickness: float
    :param depth: Depth
    :type depth: float
    :param use_outset: Outset, Outset rather than inset
    :type use_outset: bool
    :param use_select_inset: Select Outer, Select the new inset faces
    :type use_select_inset: bool
    :param use_individual: Individual, Individual Face Inset
    :type use_individual: bool
    :param use_interpolate: Interpolate, Blend face data across the inset
    :type use_interpolate: bool
    :param release_confirm: Confirm on Release
    :type release_confirm: bool
    """
    pass


@staticmethod
def list(filters=None, limit=None, offset=None, order_by=None):
    """
        List experiment parameter records in parameter set.
        """


def eps_water(f_Hz, T_K):
    """ Calculate the dielectric permitiviy of water

    Formulas taken from dielectric permittivity of liquid water
    without salt according to
    Liebe et al. 1991 Int. J. IR+mm Waves 12(12), 659-675

    Based on MATLAB code by Christian Mätzler, June 2002
    Cosmetic changes by Christian Chwala, August 2012

    Parameters
    ----------
    f_Hz : array-like
        Frequency in Hz
    T_K : float
        Temperature in Kelvin

    Returns
    -------

    eps : np.complex

    """
    f_GHz = f_Hz * 1e-09
    teta = 1 - 300.0 / T_K
    e0 = 77.66 - 103.3 * teta
    e1 = 0.0671 * e0
    f1 = 20.2 + 146.4 * teta + 316 * teta * teta
    e2 = 3.52 + 7.52 * teta
    f2 = 39.8 * f1
    eps = e2 + (e1 - e2) / (1 - 1.0j * f_GHz / f2) + (e0 - e1) / (1 - 1.0j *
        f_GHz / f1)
    return eps


def get(name, default=None):
    """ Gets the cache value for the given name returns default
            if no value was previously set
        """


def bool_to_word(bool_value):
    """
    Converts a boolean to a "Yes" or "No"
    :param bool_value: a boolean
    :return: a string of the word representing the boolean
    """
    if bool_value is True:
        return 'Yes'
    else:
        return 'No'


def process(proc_data):
    """
    Final processing to conform to the schema.

    Parameters:

        proc_data:   (dictionary) raw structured data to process

    Returns:

        List of dictionaries. Structured data with the following schema:

        [
          {
            "job":      integer,
            "unit":     string,
            "type":     string,
            "state":    string
          }
        ]
    """
    for entry in proc_data:
        int_list = ['job']
        for key in int_list:
            if key in entry:
                try:
                    key_int = int(entry[key])
                    entry[key] = key_int
                except ValueError:
                    entry[key] = None
    return proc_data


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

        :param ShowcaseTrashedDeprecatedDetails val:
        :rtype: EventDetails
        """
    return cls('showcase_trashed_deprecated_details', val)


def getGTI(ifd):
    """Find the most up-to-date GTI table in the input file.

    Parameters
    ----------
    ifd: pyfits HDUList object
        The pyfits file handle for the input file

    Returns
    -------
    pyfits BinTableHDU object, or None
        The GTI extension from the input file, or None if there isn't one
    """
    last_extver = 0
    hdunum = 0
    for i in range(1, len(ifd)):
        hdu = ifd[i]
        extname = hdu.header.get('extname', 'MISSING')
        if extname.upper() == 'GTI':
            extver = hdu.header.get('extver', 1)
            if extver > last_extver:
                last_extver = extver
                hdunum = i
    if hdunum < 1:
        gti_hdu = None
    else:
        gti_hdu = ifd[hdunum]
    return gti_hdu


@classmethod
def clear_cache(cls):
    """
        Clear all of the existing cache entries.
        """
    monitor_running = False
    if cls._monitor_thread:
        monitor_running = cls._monitor_thread.is_alive()
        cls.stop_cache_monitor()
    with cls._monitor_lock, cls._lock:
        while cls._cache:
            cls._cache.pop().delete()
    if monitor_running:
        cls.start_cache_monitor()


@classmethod
def open(cls, filename, line_parser=None):
    """Open this file and parse it."""
    f = open(filename, 'r')
    parsed = cls(f, line_parser)
    f.close()
    return parsed


def strip_url(url):
    """Ensure that the API endpoint URL does not end with a slash"""
    return url.rstrip('/')


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 strip_links(book, soup):
    """Replaces `a` elements with `span.link`"""
    for a in soup.find_all('a'):
        a.name = 'span'
        a['class'] = 'link'


def histogram_lengths(length, name_prefix):
    """Create a histogram of read counts per length."""
    counts = length.value_counts().to_frame(name='readCount')
    counts.index.rename('readLen', inplace=True)
    counts.sort_index(inplace=True)
    counts.to_csv('{}.hist.csv'.format(name_prefix), index=True)


def parse_single_layout(layout_str, num_bots=4, allow_enemy_chars=False):
    """Parse a single layout from a string

    See parse_layout for details about valid layout strings.
    """
    width = None
    rows = []
    start = False
    for i, line in enumerate(layout_str.splitlines()):
        row = line.strip()
        if not row:
            continue
        if not start:
            if row.count('#') != len(row):
                raise ValueError(
                    f'Layout must be enclosed by walls (line: {i})!')
            else:
                start = True
                width = len(row)
                if width % 2:
                    raise ValueError(
                        f'Layout width must be even (found {width})!')
                rows.append(row)
                continue
        if len(row) != width:
            raise ValueError(f'Layout rows have differing widths (line: {i})!')
        if row[0] != '#' or row[-1] != '#':
            raise ValueError(f'Layout must be enclosed by walls (line:{i})!')
        rows.append(row)
        if row.count('#') == len(row):
            start = False
            break
    if start:
        raise ValueError(f'Layout must be enclosed by walls (line:{i})!')
    height = len(rows)
    walls = []
    food = []
    bots = [None] * num_bots
    enemy = []
    noisy_enemy = []
    for y, row in enumerate(rows):
        for x, char in enumerate(row):
            coord = x, y
            if char == '#':
                walls.append(coord)
            elif char == '.':
                food.append(coord)
            elif char == ' ':
                continue
            elif char == 'E':
                if allow_enemy_chars:
                    enemy.append(coord)
                else:
                    raise ValueError(f'Enemy character not allowed.')
            elif char == '?':
                if allow_enemy_chars:
                    noisy_enemy.append(coord)
                else:
                    raise ValueError(f'Enemy character not allowed.')
            else:
                try:
                    bot_idx = int(char)
                    if bot_idx >= len(bots):
                        raise ValueError
                except ValueError:
                    raise ValueError(f'Unknown character {char} in maze!')
                if bots[bot_idx]:
                    raise ValueError(
                        f'Cannot set bot {bot_idx} to position {coord} (already at {bots[bot_idx]}).'
                        )
                bots[bot_idx] = coord
    walls.sort()
    food.sort()
    out = {'walls': walls, 'food': food, 'bots': bots}
    if allow_enemy_chars:
        out['enemy'] = sorted(enemy)
        out['noisy_enemy'] = sorted(noisy_enemy)
    return out


@staticmethod
def write_partition(df, path, fs, filename, partition_on, return_metadata,
    **kwargs):
    """
        Output a partition of a dask.DataFrame. This will correspond to
        one output file, unless partition_on is set, in which case, it will
        correspond to up to one file in each sub-directory.

        Parameters
        ----------
        df: dask.dataframe.DataFrame
        path: str
            Destination directory for data.  Prepend with protocol like ``s3://``
            or ``hdfs://`` for remote data.
        fs: FileSystem
        filename: str
        partition_on: List(str)
            Column(s) to use for dataset partitioning in parquet.
        return_metadata : bool
            Whether to return list of instances from this write, one for each
            output file. These will be passed to write_metadata if an output
            metadata file is requested.
        **kwargs: dict
            Other keyword arguments (including `fmd` and `index_cols`)

        Returns
        -------
        List of metadata-containing instances (if `return_metadata` is `True`)
        or empty list
        """
    raise NotImplementedError


def _default_conflict_solver(match, conflicting_match):
    """
    Default conflict solver for matches, shorter matches if they conflicts with longer ones

    :param conflicting_match:
    :type conflicting_match:
    :param match:
    :type match:
    :return:
    :rtype:
    """
    if len(conflicting_match.initiator) < len(match.initiator):
        return conflicting_match
    if len(match.initiator) < len(conflicting_match.initiator):
        return match
    return None


def fromSuccessResponse(cls, success_response, signed_only=True):
    """Create a C{L{TeamsResponse}} object from a successful OpenID
        library response
        (C{L{openid.consumer.consumer.SuccessResponse}}) response
        message

        @param success_response: A SuccessResponse from consumer.complete()
        @type success_response: C{L{openid.consumer.consumer.SuccessResponse}}

        @param signed_only: Whether to process only data that was
            signed in the id_res message from the server.
        @type signed_only: bool

        @rtype: TeamsResponse
        @returns: A Launchpad teams response containing the data
            that was supplied with the C{id_res} response.
        """
    self = cls()
    self.ns_uri = self._getTeamsNS(success_response.message)
    if signed_only:
        args = success_response.getSignedNS(self.ns_uri)
    else:
        args = success_response.message.getArgs(self.ns_uri)
    if 'is_member' in args:
        is_member_str = args['is_member']
        self.is_member = is_member_str.split(',')
    return self


@staticmethod
def _nack(message_id, subscription_id, **kwargs):
    """Reject receipt of a message. This only makes sense when the
        'acknowledgement' flag was set for the relevant subscription.
        :param message_id: ID of the message to be rejected.
        :param subscription_id: ID of the associated subscription.
        :param **kwargs: Further parameters for the transport layer. For example
               transaction: Transaction ID if rejection should be part of a
                            transaction
        """
    raise NotImplementedError('Transport interface not implemented')


def receive(input):
    """
        Accept an input, transition to the next state, and return the generated
        output.

        @raise UnhandledInput: If the received input is not acceptable in the
            current state.

        @raise IllegalInput: If the received input is not acceptable in any
            state by this state machine.
        """


def median(iterable, sort=True):
    """Returns the value that separates the lower half from the higher half of
    values in the list."""
    s = sorted(iterable) if sort is True else list(iterable)
    n = len(s)
    if n == 0:
        raise ValueError('median() arg is an empty sequence')
    if n % 2 == 0:
        return float(s[n // 2 - 1] + s[n // 2]) / 2
    return s[n // 2]


@classmethod
def sensor_map(cls):
    """
        Return sensor map
        """
    raise NotImplementedError()


def f_name(**var):
    """ #### Return the name of a keyword variable as a string.
        An alternative to using a list comprehension with function <v_name>
        that manipulates f-strings directly.

        Example:
        ```
            the_value = 'some_value'
            print(f_name(the_value=the_value))
        ```

        This method is 2x slower than v_name (n = 10000)
        - 'profile_v_name'  4.98 ms
        - 'profile_f_name'  10.97 ms
        """
    return f'var={var!r}'


@classmethod
def register_notification(cls, notification_cls):
    """Register a class as notification.
        Use 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 format_speed(speed):
    """Return a bytes/s measurement as a human readable string."""
    kb_spd = float(speed) / 1024
    return round(kb_spd, 2 if kb_spd < 0.1 else 1)


def p_dictorsetmaker_9(p):
    """dictorsetmaker : test dictorsetmaker_star2"""
    keys, values = p[2]
    p[0] = keys, [p[1]] + values


def remove_interface_suffix(interface):
    """Remove a possible "<if>@<endpoint>" suffix from an interface' name.

    This suffix can appear in some kernel versions, and intends on specifying,
    for example, a veth's pair. However, this interface name is useless to us
    as further 'ip' commands require that the suffix be removed.
    """
    return interface.partition('@')[0]


def prettyBytes(b):
    """
    Pretty-print bytes
    """
    prefixes = ['B', 'KiB', 'MiB', 'GiB', 'TiB']
    while b >= 1024 and len(prefixes) > 1:
        b /= 1024
        prefixes.pop(0)
    return f'{b:.1f} {prefixes[0]}'


def format_f(num, decimals=2):
    """
    Formats float with comma decimal separator

    :param num:
    :param decimals:
    :return:
    """
    if isinstance(num, float):
        fstring = '%%.%df' % decimals
        return (fstring % num).replace('.', ',')
    return num


def get_build_metric_name(model_id):
    """
    Get build # name on stats server

    :param model_id: model ID
    :type model_id: str
    :return: str -- build # name on stats server
    """
    return '{}.metrics.build'.format(model_id)


def unnorm(x, m, s):
    """
    function to un-normalise the data - used in download_tpf_mast
    """
    y = x * s
    a = y + m
    return a


def _findRow(subNo, model):
    """Finds a row in a given model which has a column with a given
    number."""
    items = model.findItems(str(subNo))
    if len(items) == 0:
        return None
    if len(items) > 1:
        raise IndexError('Too many items with sub number %s' % subNo)
    return items[0].row()


def compare_para_dict(para_dict_old, para_dict_new):
    """Compare two parameter dictionaries.

    Parameters
    ----------
    para_dict_old : dictionary
        old parameter dictionary
    para_dict_new : dictionary
        new parameter dictionary

    Returns
    -------
    status : bool
        True if same, False if different
    """
    shared_item = set(para_dict_old.items()) & set(para_dict_new.items())
    if len(shared_item) == len(para_dict_old):
        return True
    else:
        return False


def get_zcs_settings(session, return_type=None, **kwargs):
    """
    Retrieves details for Zadara Container Services, such as the configured
    network, ports, etc.

    :type session: zadarapy.session.Session
    :param session: A valid zadarapy.session.Session object.  Required.

    :type return_type: str
    :param return_type: If this is set to the string 'json', this function
        will return a JSON string.  Otherwise, it will return a Python
        dictionary.  Optional (will return a Python dictionary by default).

    :rtype: dict, str
    :returns: A dictionary or JSON data set as a string depending on
        return_type parameter.
    """
    path = '/api/settings/container_service.json'
    return session.get_api(path=path, return_type=return_type, **kwargs)


def generate_plan(routine_environment, exercise_data, **kwargs):
    """ dumps output helpful for debugging and returns all routines
    """
    output = print if 'output' not in kwargs else kwargs['output'].write
    output(routine_environment)
    for exercise_name, exercise in exercise_data.items():
        output('{0}:\n   {1}'.format(exercise_name, exercise))
    return [[]]


def plot_bands(ax=None, kpath=None, bands=None, showlegend=False, E_Fermi=
    None, color1=(0, 0, 0.8), style1='solid', lw1=0.7, color2=(0.8, 0, 0),
    style2='dashed', lw2=0.7):
    """
    - Returns axes object and plot on which all matplotlib allowed actions could be performed.
    - **Parameters**
        - ax         : Matplotlib axes object, if not given, one is created.
        - kpath      : 1D array from `get_kpts().kpath` or `export_vasprun().kpath`.
        - bands      : Dictionary Object from `get_evals()` or `export_vasprun().bands`.
        - showlegend : Boolean, default is False, if true, gives legend for spin-polarized calculations.
        - E_Fermi    : If not given, automatically picked from bands object.
        - **kwargs   : lines color,width and style to distinguish spin Up and Down.
    - **Returns**
        - ax : matplotlib axes object with plotted bands.
    """
    if ax == None:
        import matplotlib.pyplot as plt
        fig, ax = plt.subplots(1, 1, figsize=(3.4, 2.6))
    else:
        ax == ax
    if kpath == None:
        raise ValueError(
            'kpath is not provided. Use get_kpath() or export_vasprun().kpath to generate it.'
            )
    if bands == None:
        raise ValueError(
            'bands object is not provided. Use get_evals() or export_vasprun().bands to generate it.'
            )
    if E_Fermi == None:
        E_Fermi = bands.E_Fermi
    if bands.ISPIN == 1:
        en = bands.evals - E_Fermi
        ax.plot(kpath, en, color=color1, lw=lw1, ls=style1)
    if bands.ISPIN == 2:
        enUp = bands.evals.SpinUp - E_Fermi
        enDown = bands.evals.SpinDown - E_Fermi
        ax.plot(kpath, enUp, color=color1, lw=lw1, ls=style1)
        ax.plot(kpath, enDown, color=color2, lw=lw2, ls=style2)
        if showlegend == True:
            ax.plot([], [], color=color1, lw=lw1, ls=style1, label='Spin Up')
            ax.plot([], [], color=color2, lw=lw2, ls=style2, label='Spin Down')
            ax.legend(fontsize='small', frameon=False, ncol=2,
                bbox_to_anchor=(0, 1), loc='lower left')
    return ax


def pointMutant(seq, mut):
    """
	Takes as input a sequence `seq` to mutate
	and a tuple `mut` in the form (index, 'mutated nt') ex. `(3, 'A')`.
	Returns a nucleotide sequence with a point mutation.
	"""
    return seq[:mut[0]] + mut[1] + seq[mut[0] + 1:]


def export_matrices(hdf5_file, op2_model):
    """exports the matrices to HDF5"""
    if len(op2_model.matrices):
        matrix_group = hdf5_file.create_group('matrices')
        for key, matrix in sorted(op2_model.matrices.items()):
            matrixi_group = matrix_group.create_group(key.encode('latin-1'))
            if hasattr(matrix, 'export_to_hdf5'):
                matrix.export_to_hdf5(matrixi_group, op2_model.log)
            else:
                msg = 'HDF5: key=%r type=%s cannot be exported' % (key, str
                    (type(matrix)))
                op2_model.log.warning(msg)
                raise NotImplementedError(msg)


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

        :param TeamMergeRequestSentShownToSecondaryTeamType val:
        :rtype: EventType
        """
    return cls('team_merge_request_sent_shown_to_secondary_team', val)


@classmethod
def _config_options_map(cls):
    """
        Map config option name to StoragePolicy parameter name.
        """
    return {'name': 'name', 'aliases': 'aliases', 'policy_type':
        'policy_type', 'default': 'is_default', 'deprecated':
        'is_deprecated', 'diskfile_module': 'diskfile_module'}


def handle_message(sender, message):
    """
    Handles message events from the AlarmDecoder.
    """
    print(sender, message.raw)


@classmethod
def test_compute_output_shape(cls, input_shape=(None, 16)):
    """若推断失败，需重写`compute_output_shape`"""
    layer = cls()
    layer.build(input_shape)
    _ = layer.compute_output_shape(input_shape)
    print(_)


def hex_to_dec(x):
    """
    Convert hex to decimal
    """
    try:
        return int(x, 16)
    except:
        return None


def _chain_from_iterable_of_lists(iterable):
    """
    Specialized implementation of itertools.chain.from_iterable.
    Each item in *iterable* should be a list.  This function is
    careful not to keep references to yielded objects.
    """
    for element in iterable:
        element.reverse()
        while element:
            yield element.pop()


@staticmethod
def _convert(hypothesis):
    """Convert hypothesis to a 'frozenset' in order to make it hashable."""
    if isinstance(hypothesis, frozenset):
        return hypothesis
    else:
        return frozenset(hypothesis)


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 _attr_ladd(attr, value):
    """Create a 'list add' dictionary for update_workspace_attributes()"""
    return {'op': 'AddListMember', 'attributeName': attr,
        'addUpdateAttribute': value}


def allowed_ext(filename, fileExts):
    """
    the file extension is allowed to upload to server
    """
    return '.' in filename and filename.rsplit('.', 1)[1] in fileExts


def add_feather_vertex(location: float=(0.0, 0.0)):
    """Add vertex to feather

    :param location: Location, Location of vertex in normalized space
    :type location: float
    """
    pass


def get_replication_jobs(replicationJobId=None, nextToken=None, maxResults=None
    ):
    """
    The GetReplicationJobs API will return all of your ReplicationJobs and their details. This API returns a paginated list, that may be consecutively called with nextToken to retrieve all ReplicationJobs.
    See also: AWS API Documentation

    :example: response = client.get_replication_jobs(
        replicationJobId='string',
        nextToken='string',
        maxResults=123
    )

    :type replicationJobId: string
    :param replicationJobId: The unique identifier for a Replication Job.

    :type nextToken: string
    :param nextToken: Pagination token to pass as input to API call

    :type maxResults: integer
    :param maxResults: The maximum number of results to return in one API call. If left empty, this will default to 50.

    :rtype: dict
    :return: {
        'replicationJobList': [
            {
                'replicationJobId': 'string',
                'serverId': 'string',
                'serverType': 'VIRTUAL_MACHINE',
                'vmServer': {
                    'vmServerAddress': {
                        'vmManagerId': 'string',
                        'vmId': 'string'
                    },
                    'vmName': 'string',
                    'vmManagerName': 'string',
                    'vmManagerType': 'VSPHERE',
                    'vmPath': 'string'
                },
                'seedReplicationTime': datetime(2015, 1, 1),
                'frequency': 123,
                'nextReplicationRunStartTime': datetime(2015, 1, 1),
                'licenseType': 'AWS'|'BYOL',
                'roleName': 'string',
                'latestAmiId': 'string',
                'state': 'PENDING'|'ACTIVE'|'FAILED'|'DELETING'|'DELETED',
                'statusMessage': 'string',
                'description': 'string',
                'replicationRunList': [
                    {
                        'replicationRunId': 'string',
                        'state': 'PENDING'|'MISSED'|'ACTIVE'|'FAILED'|'COMPLETED'|'DELETING'|'DELETED',
                        'type': 'ON_DEMAND'|'AUTOMATIC',
                        'statusMessage': 'string',
                        'amiId': 'string',
                        'scheduledStartTime': datetime(2015, 1, 1),
                        'completedTime': datetime(2015, 1, 1),
                        'description': 'string'
                    },
                ]
            },
        ],
        'nextToken': 'string'
    }

    :returns:
    (dict) --
    replicationJobList (list) -- List of Replication Jobs
    (dict) -- Object representing a Replication Job
    replicationJobId (string) -- The unique identifier for a Replication Job.
    serverId (string) -- Unique Identifier for a server
    serverType (string) -- Type of server.
    vmServer (dict) -- Object representing a VM server
    vmServerAddress (dict) -- Object representing a server's location
    vmManagerId (string) -- Unique Identifier for VM Manager
    vmId (string) -- Unique Identifier for a VM

    vmName (string) -- Name of Virtual Machine
    vmManagerName (string) -- VM Manager Name
    vmManagerType (string) -- VM Management Product
    vmPath (string) -- Path to VM

    seedReplicationTime (datetime) -- Timestamp of an operation
    frequency (integer) -- Interval between Replication Runs. This value is specified in hours, and represents the time between consecutive Replication Runs.
    nextReplicationRunStartTime (datetime) -- Timestamp of an operation
    licenseType (string) -- The license type to be used for the Amazon Machine Image (AMI) created after a successful ReplicationRun.
    roleName (string) -- Name of service role in customer's account to be used by SMS service.
    latestAmiId (string) -- The AMI id for the image resulting from a Replication Run.
    state (string) -- Current state of Replication Job
    statusMessage (string) -- String describing current status of Replication Job
    description (string) -- The description for a Replication Job/Run.
    replicationRunList (list) -- List of Replication Runs
    (dict) -- Object representing a Replication Run
    replicationRunId (string) -- The unique identifier for a Replication Run.
    state (string) -- Current state of Replication Run
    type (string) -- Type of Replication Run
    statusMessage (string) -- String describing current status of Replication Run
    amiId (string) -- The AMI id for the image resulting from a Replication Run.
    scheduledStartTime (datetime) -- Timestamp of an operation
    completedTime (datetime) -- Timestamp of an operation
    description (string) -- The description for a Replication Job/Run.

    nextToken (string) -- Pagination token to pass as input to API call

    """
    pass


def expand_float(data):
    """helper method for ``expand_thru_case_control``"""
    out = []
    for datai in data:
        out.append(float(datai))
    out.sort()
    return out


def do_string(data):
    """Emulate gmx_fio_do_string

    gmx_fio_do_string reads a string from a XDR file. On the contraty to the
    python unpack_string, gmx_fio_do_string reads the size as an unsigned
    interger before reading the actual string.

    See <gromacs-2016-src>/src/gromacs/fileio/gmx_system_xdr.c:454
    """
    data.unpack_int()
    return data.unpack_string()


def unassignHomeFolder(principalId, delete=False):
    """Remove a home folder assignment.

        If `delete` is `True`, then delete the home folder including all of
        its content.
        """


@staticmethod
def _send(destination, message, **kwargs):
    """Send a message to a queue.
        :param destination: Queue name to send to
        :param message: A string to be sent
        :param **kwargs: Further parameters for the transport layer. For example
               headers: Optional dictionary of header entries
               expiration: Optional expiration time, relative to sending time
               transaction: Transaction ID if message should be part of a
                            transaction
        """
    raise NotImplementedError('Transport interface not implemented')


@classmethod
def _get_attributes(cls):
    """
    Returns a map of property names to attr instances (or None for default
    attribute behavior) describing the properties of the object.

    By default, this method will return the class's _ATTRIBUTES field.
    Classes can override this method to do custom initialization of the
    attributes when needed.
    """
    return cls._ATTRIBUTES


def hide_history_entry(date):
    """ Marks a specific history entry as hidden
        """


def weighted_jaccard_similarity(A, B):
    """
    Function computing the weighted Jaccard similarity.

    Runs in O(n), n being the sum of A & B's sizes.

    Args:
        A (Counter): First weighted set.
        B (Counter): Second weighted set.

    Returns:
        float: Weighted Jaccard similarity between A & B.

    """
    if A is B:
        return 1.0
    if len(A) == 0 or len(B) == 0:
        return 0.0
    I = 0.0
    U = 0.0
    done = set()
    if len(A) > len(B):
        A, B = B, A
    for k, weight_A in A.items():
        weight_B = B.get(k, 0.0)
        if weight_B != 0.0:
            done.add(k)
        if weight_A < weight_B:
            I += weight_A
            U += weight_B
        else:
            I += weight_B
            U += weight_A
    for k, v in B.items():
        if k in done:
            continue
        U += v
    return I / U


def datetime_passed_now(source):
    """
    Compares provided datetime with current time on the basis of Django
    settings. Checks source is in future or in past. False if it's in future.
    Parameters
    ----------
    source: datetime object than may or may not be naive

    Returns
    -------
    bool

    Author: Himanshu Shankar (https://himanshus.com)
    """
    import datetime
    import pytz
    if source.tzinfo is not None and source.tzinfo.utcoffset(source
        ) is not None:
        return source <= datetime.datetime.utcnow().replace(tzinfo=pytz.utc)
    else:
        return source <= datetime.datetime.now()


def validation_error(err, status_code=403):
    """
    Return a JSON message describing a validation error.
    """
    errors = err.messages
    msg = {'status_code': status_code, 'error': True}
    if len(errors) == 1:
        msg['message'] = errors[0]
    else:
        msg['messages'] = errors
    return msg


@staticmethod
def p_memory_layout_optional_list_optional(p):
    """memory_layout_optional_list_optional : empty
                                                | memory_layout_optional_list"""
    p[0] = tuple() if p[1] is None else p[0]


def trm_indices(a, b):
    """
    Generate (i,j) indeces of a triangular matrix, between elements a and b.
    The matrix size is automatically determined from the number of elements.
    For instance: trm_indices((0,0),(2,1)) yields (0,0) (1,0) (1,1) (2,0)
    (2,1).

    Parameters
    ----------

    a : (int i, int j) tuple
        starting matrix element.

    b : (int i, int j) tuple
        final matrix element.
    """
    i, j = a
    while i < b[0]:
        if i == j:
            yield i, j
            j = 0
            i += 1
        else:
            yield i, j
            j += 1
    while j <= b[1]:
        yield i, j
        j += 1


def ssh_auth(username, address):
    """Render username and address part."""
    if username:
        return '{}@{}'.format(username, address)
    return '{}'.format(address)


def glCopyPixels(x, y, width: int, height: int, type):
    """Copy pixels into a 2D texture image

    :param target: Specifies the target texture.
    :type target: typing.Union[str, int]
    :param level: Specifies the level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap reduction image.
    :type level: int
    :param internalformat: Specifies the number of color components in the texture.
    :type internalformat: int
    :param y: Specify the window coordinates of the first pixel that is copied from the frame buffer. This location is the lower left corner of a rectangular block of pixels.
    :param width: Specifies the width of the texture image. Must be 2n+2(border) for some integer n. All implementations support texture images that are at least 64 texels wide.
    :type width: int
    :param height: Specifies the height of the texture image. Must be 2m+2(border) for some integer m. All implementations support texture images that are at least 64 texels high.
    :type height: int
    :param border: Specifies the width of the border. Must be either 0 or 1.
    :type border: int
    """
    pass


def test_arj(archive, compression, cmd, verbosity, interactive):
    """Test an ARJ archive."""
    cmdlist = [cmd, 't', '-r']
    if not interactive:
        cmdlist.append('-y')
    cmdlist.append(archive)
    return cmdlist


def safe_file_id(unicode_or_utf8_string):
    """File ids should now be utf8, but at one point they were unicode.

    This is the same as safe_utf8, except it uses the cached encode functions
    to save a little bit of performance.

    :param unicode_or_utf8_string: A possibly Unicode file_id. (can also be
        utf8 or None).
    :return: None or a utf8 file id.
    """
    if (unicode_or_utf8_string is None or unicode_or_utf8_string.__class__ ==
        bytes):
        return unicode_or_utf8_string
    raise TypeError(
        'Unicode file ids are no longer supported. File id generators should be creating utf8 file ids.'
        )


def hide(unselected: bool=False):
    """Hide selected particles

    :param unselected: Unselected, Hide unselected rather than selected
    :type unselected: bool
    """
    pass


def glob(obj, *args, **kwargs):
    """
    Creates a path in which all special glob characters in all the
    parent directories in the given setting are properly escaped.

    :param obj: The ``Setting`` object from which the key is obtained.
    :return:    Returns a path in which special glob characters are escaped.
    """
    return obj.__glob__(*args, **kwargs)


def bind_url(url):
    """binds an HTTP GET query string endpiont"""
    if url.find('?') == -1:
        binder = '?'
    if url.find('=') != -1:
        if url.find('&', -1) != -1:
            binder = ''
        else:
            binder = '&'
    if url.find('?') != -1:
        if url.find('?', -1) != -1:
            binder = ''
        elif url.find('&', -1) == -1:
            binder = '&'
    return '%s%s' % (url, binder)


def clear_solution():
    """Clear all calculated data

    """
    pass


@classmethod
def register_class(manager, *args):
    """ register_class(class1, class2, class3, ...)

        Register one or more classes. Registered classes can be saved and
        restored from ssdf.

        A class needs to implement two methods to qualify for registration:
        * A method __to_ssdf__() that returns an ssdf.Struct
        * A classmethod __from_ssdf__(s) that accepts an ssdf.Struct and
          creates an instance of that class.

        """
    for cls in args:
        incomp = manager.is_incompatible_class(cls)
        if incomp:
            raise ValueError('Cannot register class %s: %s.' % (cls.
                __name__, incomp))
        else:
            manager._registered_classes[cls.__name__] = cls


@staticmethod
def addDicts(dictList):
    """Add dictionaries"""
    i = 0
    dict = {}
    while i != len(dictList):
        dictTemp = dictList[i]
        listTemp = dictTemp.keys()
        j = 0
        while j != len(listTemp):
            key = listTemp[j]
            value = dictTemp[key]
            dict[key] = value
            j = j + 1
        i = i + 1
    return dict


def perform_replacement(entity, mapping_list):
    """Perform a replacement on the value of an entity using a replacement mapping, if applicable."""
    if not entity.value:
        return
    entity_value = entity.value
    for mapping_dict in mapping_list:
        if 'search_string' in mapping_dict.keys():
            search_string = mapping_dict['search_string']
            replacement = mapping_dict['replacement']
            if search_string in entity_value:
                entity.value = entity_value.replace(search_string, replacement)
        if 'regex' in mapping_dict.keys():
            compiled_regex = mapping_dict['regex']
            replacement = mapping_dict['replacement']
            if compiled_regex.search(entity_value):
                entity.value = compiled_regex.sub(replacement, entity_value)


def fix_numbering(code, start):
    """Start is the lowest number from which we should remove 2"""
    for i, l in enumerate(code):
        if abs(l[0]) >= start:
            l[0] = l[0] / abs(l[0]) * (abs(l[0]) - 2)
        if abs(l[1]) >= start:
            l[1] = l[1] / abs(l[1]) * (abs(l[1]) - 2)
        code[i] = l
    return code


def assert_called(_mock_self):
    """assert that the mock was called at least once
        """
    self = _mock_self
    if self.call_count == 0:
        msg = "Expected '%s' to have been called." % (self._mock_name or 'mock'
            )
        raise AssertionError(msg)


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


def in_library_len(ind, dist, lib_len):
    """Returns the filtered indices and distances that are in that specific
    library length. This allows the distances to only be calculated once.

    This was created in an attempt to speed up the algorithm. It turns out the
    naive implementation was faster.

    Parameters
    ----------
    ind : 2d array
        Indices to be filtered.
    dist : 2d array
        Distances to be filtered.
    lib_len : int
        What indices to keep.

    Returns
    -------
    filt_ind : 2d array
        Filtered indices.
    filt_dist : 2d array
        Filtered distances.

    """
    mask = ind < lib_len
    filt_ind = ind[mask].reshape(-1, lib_len)
    filt_dist = dist[mask].reshape(-1, lib_len)
    return filt_ind, filt_dist


def is_fp_closed(obj):
    """
    Checks whether a given file-like object is closed.

    :param obj:
        The file-like object to check.
    """
    try:
        return obj.isclosed()
    except AttributeError:
        pass
    try:
        return obj.closed
    except AttributeError:
        pass
    try:
        return obj.fp is None
    except AttributeError:
        pass
    raise ValueError('Unable to determine whether fp is closed.')


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 write_pls_playlist(filename, files):
    """
    Write a PLS playlist named filename containing files.
    """
    out = open(filename, 'w', encoding='utf-8')
    out.write('[playlist]\n')
    count = 0
    for f in files:
        count = count + 1
        out.write('File{0}={1}\n'.format(count, f))
    out.write('NumberOfEntries={0}\n'.format(count))
    out.write('Version=2\n')
    out.close()


def PmfProbEqual(pmf1, pmf2):
    """Probability that a value from pmf1 equals a value from pmf2.

    Args:
        pmf1: Pmf object
        pmf2: Pmf object

    Returns:
        float probability
    """
    total = 0
    for v1, p1 in pmf1.Items():
        for v2, p2 in pmf2.Items():
            if v1 == v2:
                total += p1 * p2
    return total


def parabolic_turning_point(y):
    """
    Find the location of the turning point for a parabola
    ``y(x) = ax^2 + bx + c``, given input values ``y(-1), y(0), y(1)``.
    The maximum is located at ``x0 = -b / 2a``. Assumes
    that the input array represents an equally spaced sampling at the
    locations ``y(-1), y(0) and y(1)``.

    Parameters
    ----------
    y : `numpy.ndarray`
        A one dimensional numpy array of shape "3" with entries that sample the
        parabola at "-1", "0", and "1".

    Returns
    -------
    `float`
        A float, the location of the parabola maximum.
    """
    numerator = -0.5 * y.dot([-1, 0, 1])
    denominator = y.dot([1, -2, 1])
    return numerator / denominator