def flowTo(drain):
    """
        Add a drain to this fount to consume its output.

        This will I{synchronously} call L{flowingFrom(fount)
        <IDrain.flowingFrom>} on C{drain} to indicate to C{drain} which
        L{IFount} its future input will come from - I{unless} this L{IFount} is
        exhausted and will never produce more output.  In this case, C{flowTo}
        must I{not} call C{flowingFrom}, and must return L{None}.

        Typically, this will return the result of L{drain.flowingFrom(fount)
        <IDrain.flowingFrom>} to allow construction of pipelines with the
        C{x.flowTo(...).flowTo(...).flowTo(...)} idiom; however,
        implementations of L{IFount} are at liberty to return L{None} or any
        valid L{IFount}.

        @raise AlreadyDraining: if there is already a drain (i.e.  C{flowTo}
            has already been called on this L{IFount}.)

        @return: another L{IFount} provider, or C{None}.  By convention, this
            will return the value of C{flowingFrom} and allow the drain to
            transform the C{outputType} (however, other transformations are
            allowed).
        """


@classmethod
def by_sha256(cls, session, sha256sum):
    """ Retrieve the files having the specified sha256sum. """
    query = session.query(cls).filter(cls.sha256sum == sha256sum)
    return query.all()


def put_bucket_analytics_configuration(Bucket=None, Id=None,
    AnalyticsConfiguration=None):
    """
    Sets an analytics configuration for the bucket (specified by the analytics configuration ID).
    See also: AWS API Documentation

    :example: response = client.put_bucket_analytics_configuration(
        Bucket='string',
        Id='string',
        AnalyticsConfiguration={
            'Id': 'string',
            'Filter': {
                'Prefix': 'string',
                'Tag': {
                    'Key': 'string',
                    'Value': 'string'
                },
                'And': {
                    'Prefix': 'string',
                    'Tags': [
                        {
                            'Key': 'string',
                            'Value': 'string'
                        },
                    ]
                }
            },
            'StorageClassAnalysis': {
                'DataExport': {
                    'OutputSchemaVersion': 'V_1',
                    'Destination': {
                        'S3BucketDestination': {
                            'Format': 'CSV',
                            'BucketAccountId': 'string',
                            'Bucket': 'string',
                            'Prefix': 'string'
                        }
                    }
                }
            }
        }
    )

    :type Bucket: string
    :param Bucket: [REQUIRED] The name of the bucket to which an analytics configuration is stored.

    :type Id: string
    :param Id: [REQUIRED] The identifier used to represent an analytics configuration.

    :type AnalyticsConfiguration: dict
    :param AnalyticsConfiguration: [REQUIRED] The configuration and any analyses for the analytics filter.
            Id (string) -- [REQUIRED] The identifier used to represent an analytics configuration.
            Filter (dict) -- The filter used to describe a set of objects for analyses. A filter must have exactly one prefix, one tag, or one conjunction (AnalyticsAndOperator). If no filter is provided, all objects will be considered in any analysis.
            Prefix (string) -- The prefix to use when evaluating an analytics filter.
            Tag (dict) -- The tag to use when evaluating an analytics filter.
            Key (string) -- [REQUIRED] Name of the tag.
            Value (string) -- [REQUIRED] Value of the tag.
            And (dict) -- A conjunction (logical AND) of predicates, which is used in evaluating an analytics filter. The operator must have at least two predicates.
            Prefix (string) -- The prefix to use when evaluating an AND predicate.
            Tags (list) -- The list of tags to use when evaluating an AND predicate.
            (dict) --
            Key (string) -- [REQUIRED] Name of the tag.
            Value (string) -- [REQUIRED] Value of the tag.

            StorageClassAnalysis (dict) -- [REQUIRED] If present, it indicates that data related to access patterns will be collected and made available to analyze the tradeoffs between different storage classes.
            DataExport (dict) -- A container used to describe how data related to the storage class analysis should be exported.
            OutputSchemaVersion (string) -- [REQUIRED] The version of the output schema to use when exporting data. Must be V_1.
            Destination (dict) -- [REQUIRED] The place to store the data for an analysis.
            S3BucketDestination (dict) -- [REQUIRED] A destination signifying output to an S3 bucket.
            Format (string) -- [REQUIRED] The file format used when exporting data to Amazon S3.
            BucketAccountId (string) -- The account ID that owns the destination bucket. If no account ID is provided, the owner will not be validated prior to exporting data.
            Bucket (string) -- [REQUIRED] The Amazon resource name (ARN) of the bucket to which data is exported.
            Prefix (string) -- The prefix to use when exporting data. The exported data begins with this prefix.

    """
    pass


def startcut(s, pre):
    """ If string `s` starts with `pre` cut it off and return the remaining string. """
    if s.startswith(pre):
        return s[len(pre):]
    else:
        return s


def gif(years, giffile='animation.gif', **kwargs):
    """
    Nous donne un graphique animee des cartes : le GIF

    :param years : le vecteur des annees sur lesquels la representation est faite
    :param giffile : nom de notre gif
    :param kwargs : arguments supplementaires
    """
    assert type(years
        ) == list, 'Erreur : vous devez entrer une liste, pensez a utiliser list()'
    assert type(giffile
        ) == str, 'Erreur : vous devez entrer une chaine de caracteres, pensez a utiliser str()'
    import imageio
    images_data = []
    for i in range(len(years)):
        data = imageio.imread('carte' + str(years[i]) + '.png')
        images_data.append(data)
    imageio.mimwrite(giffile, images_data, format='.gif', fps=1)


def createConn(MDB, PWD=''):
    """creates connection to database
    returns con(connection) and cur(cursor)
    example:
    con,cur=createConn("my.mdb")
    #now i'm connected
    cur.close()
    con.commit()#save
    con.close()
    """
    import pyodbc
    DRV = ['{Microsoft Access Driver (*.mdb)}',
        '{Microsoft Access Driver (*.mdb, *.accdb)}']
    try:
        con = pyodbc.connect('DRIVER={};DBQ={};PWD={}'.format(DRV[1], MDB, PWD)
            )
    except:
        con = pyodbc.connect('DRIVER={};DBQ={};PWD={}'.format(DRV[0], MDB, PWD)
            )
    cur = con.cursor()
    return con, cur


def _table_columns(first_table_row):
    """Find column ranges in output line.

    Return list of tuples (start,end) for each column
    detected by plus (+) characters in delimiter line.
    """
    positions = []
    start = 1
    while start < len(first_table_row):
        end = first_table_row.find('+', start)
        if end == -1:
            break
        positions.append((start, end))
        start = end + 1
    return positions


def publish_data(data):
    """publish a data_message on the IOPub channel

    Parameters
    ----------

    data : dict
        The data to be published. Think of it as a namespace.
    """
    from ipykernel.zmqshell import ZMQInteractiveShell
    ZMQInteractiveShell.instance().data_pub.publish_data(data)


def _process_cmap(cmap):
    """
    Returns a kwarg dict suitable for a ColorScale
    """
    option = {}
    if isinstance(cmap, str):
        option['scheme'] = cmap
    elif isinstance(cmap, list):
        option['colors'] = cmap
    else:
        raise ValueError(
            """`cmap` must be a string (name of a color scheme)
                         or a list of colors, but a value of {} was given
                         """
            .format(cmap))
    return option


def remove_old_countdowns_messages(apps, schema_editor):
    """
    Remove old countdowns and messages created by 2.0 from projector elements which are unusable in 2.1.
    """
    Projector = apps.get_model('core', 'Projector')
    projector = Projector.objects.get(pk=1)
    projector_config = projector.config
    for key, value in list(projector.config.items()):
        if value.get('name') in ('core/countdown', 'core/message'):
            del projector_config[key]
    projector.config = projector_config
    projector.save(skip_autoupdate=True)


def linebreaker(i, break_pt=16, sep=' '):
    """
    used for adding labels in plots.

    :param l: list of strings
    :param break_pt: number, insert new line after this many letters
    """
    if len(i) > break_pt:
        i_words = i.split(sep)
        i_out = ''
        line_len = 0
        for w in i_words:
            line_len += len(w) + 1
            if i_words.index(w) == 0:
                i_out = w
            elif line_len > break_pt:
                line_len = 0
                i_out = '%s\n%s' % (i_out, w)
            else:
                i_out = '%s %s' % (i_out, w)
        return i_out
    else:
        return i


def new(name: str=''):
    """Create new mask

    :param name: Name, Name of new mask
    :type name: str
    """
    pass


def link(model, resource_type):
    """Return fhir URL for `model` which is a `resource_type`.
        """


@classmethod
def getChildPids(cls, pid):
    """
            getChildPids - Get pids of children of a given process.

            Note -- this is on the order of 100x faster than using psutil, so that's why it's reimplemented.

            @param pid <int> - A process pid

            @return list<int> - List of children pids
        """
    myPids = cls.getMyRunningPids()
    pid = int(pid)
    childPids = []
    for myPid in myPids:
        try:
            statInfo = cls.getStatInfo(myPid)
        except:
            continue
        if pid == statInfo['ppid']:
            childPids.append(myPid)
    return childPids


def rpx_identifier_is_unique():
    """ check if rpx id has not been added to a different user before """


def drop_category_exeeding_limit(df, var_name, category_limit):
    """ Drops category if its # of unique variables exceed the limit.
        INPUT:
            df:
                A dataframe of independent features and one dependent y feature
            var_name:
                string, the column name of the dependent y variable in the dataframe
        OUTPUT:
            df:
                A dataframe with one less feature if it exeeds the limit.
    """
    if len(df[var_name].unique()) > category_limit:
        df.drop(var_name, axis=1)
    return df


def hide(unselected: bool=False):
    """Tag selected bones to not be visible in Pose Mode

    :param unselected: Unselected
    :type unselected: bool
    """
    pass


def lambd_tris_trisH_GT17simopt(T, P):
    """n-c: tris trisH [GT17simopt]."""
    lambd = 0.06306
    valid = T == 298.15
    return lambd, valid


def _getstatusoutput(args):
    """Execute bash command returning output and exit status."""
    import subprocess
    process = subprocess.Popen(args, executable='bash', shell=True, stderr=
        subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True)
    output = process.stdout.read().strip()
    status = process.wait()
    return status, output


def put_gps_long(row):
    """
    Format longitude as a float.

    :param row: a data frame row
    :type row: pandas.Series
    :returns: processed value.

    """
    if row['lat'] == 0 and row['long'] == 0:
        row['long'] = 0
    else:
        row['long'] = row['long'] / 100000.0
    return row['long']


def get_total_n_points(d):
    """
    Returns the total number of data points in values of dict.

    Paramters
    ---------
    d : dict
    """
    n = 0
    for di in d.values():
        n += len(di)
    return n


@staticmethod
def _shorten_version(ver, num_components=2):
    """
        If ``ver`` is a dot-separated string with at least (num_components +1)
        components, return only the first two. Else return the original string.

        :param ver: version string
        :type ver: str
        :return: shortened (major, minor) version
        :rtype: str
        """
    parts = ver.split('.')
    if len(parts) <= num_components:
        return ver
    return '.'.join(parts[:num_components])


def setLogFormat(f_format):
    """Set the log format. (Has to be set before logToSomething is called)."""
    global FANCYLOG_LOGGING_FORMAT
    FANCYLOG_LOGGING_FORMAT = f_format


def find_phis(func):
    """Map blocks to phis found in the block"""
    phis = {}
    for block in func.blocks:
        phis[block] = []
        for op in block.leaders:
            if op.opcode == 'phi':
                phis[block].append(op)
    return phis


def drop_named_image(name: str='Image', filepath: str='Path', relative_path:
    bool=True):
    """Assign Image to active UV Map, or create an UV Map

    :param name: Name, Image name to assign
    :type name: str
    :param filepath: Filepath, Path to image file
    :type filepath: str
    :param relative_path: Relative Path, Select the file relative to the blend file
    :type relative_path: bool
    """
    pass


def mean_axis0(x, axis=0):
    """Equivalent to the numpy.mean function but with axis=0 by default."""
    return x.mean(axis=axis)


def parseDate(date):
    """
    Parse the date into year, month, and day
    :param date: Lunar date or Solar date
    :return: year, month, day
    """
    if type(date).__name__ == 'LunarDate':
        year = date.lunar_year
        month = date.lunar_month
        day = date.lunar_day
    elif type(date).__name__ == 'datetime':
        year = date.year
        month = date.month
        day = date.day
    else:
        raise ValueError("'date' invalid!")
    return year, month, day


def _text_to_text_conversion(vector, cc_ref):
    """ apply text to text conversion to data

    Parameters
    ----------------
    vector : numpy 1D array
        raw data to be converted to physical value
    cc_ref : cc_ref from mdfinfo4.info4 conversion block ('CCBlock') dict

    Returns
    -----------
    converted data to physical value
    """
    ref_count = len(cc_ref) - 2
    for l_index in range(len(vector)):
        key_index = ref_count + 1
        for i in range(0, ref_count, 2):
            if vector[l_index] == cc_ref[i]:
                key_index = i
                break
        vector[l_index] = cc_ref[key_index]
    return vector


@classmethod
def find(cls, id_):
    """Find record by the id
        :param id_: the primary key
        """
    return cls.query.get(id_)


def _countNumberOfAparitions(array, number):
    """Number of aparitions of a number in an array

    Parameters
    ----------
    array : array of numbers

    number : number to search for

    Returns
    -------
    aparaitions : int
        Number of aparitions of the number in the given array
    """
    aparitions = 0
    for i in range(0, len(array)):
        if array[i] == number:
            aparitions += 1
    return aparitions


def get_num_params(vocab_size, num_layers, num_neurons):
    """Returns the number of trainable parameters of an LSTM.

    Args:
        vocab_size (int): The vocabulary size
        num_layers (int): The number of layers in the LSTM
        num_neurons (int): The number of neurons / units per layer

    Returns:
        int: The number of trainable parameters
    """
    num_first_layer = 4 * (num_neurons * (vocab_size + num_neurons) +
        num_neurons)
    num_other_layer = 4 * (num_neurons * 2 * num_neurons + num_neurons)
    num_softmax = vocab_size * num_neurons + vocab_size
    return num_first_layer + (num_layers - 1) * num_other_layer + num_softmax


def safedel_message(key):
    """
    Create safe deletion log message.

    :param hashable key: unmapped key for which deletion/removal was tried
    :return str: message to log unmapped key deletion attempt.
    """
    return 'No key {} to delete'.format(key)


def _build_robovac_command(mode, command):
    """ Compile the given mode and command into the bytes data sent to the RoboVac. """
    mcu_ota_header_0xa5 = 165
    cmd_data = mode.value + command.value
    return bytes([mcu_ota_header_0xa5, mode.value, command.value, cmd_data,
        250])


def select_more():
    """Select control points directly linked to already selected ones

    """
    pass


def smart_truncate(text, max_length=100, suffix='...'):
    """
    Returns a string of at most `max_length` characters, cutting
    only at word-boundaries. If the string was truncated, `suffix`
    will be appended.
    """
    if text is None:
        return ''
    if len(text) <= max_length:
        return text
    value = text[:max_length]
    words = value.split(' ')[:-1]
    return ' '.join(words) + suffix


def error_msg_from_exception(e):
    """Translate exception into error message

    Database have different ways to handle exception. This function attempts
    to make sense of the exception object and construct a human readable
    sentence.

    TODO(bkyryliuk): parse the Presto error message from the connection
                     created via create_engine.
    engine = create_engine('presto://localhost:3506/silver') -
      gives an e.message as the str(dict)
    presto.connect('localhost', port=3506, catalog='silver') - as a dict.
    The latter version is parsed correctly by this function.
    """
    msg = ''
    if hasattr(e, 'message'):
        if isinstance(e.message, dict):
            msg = e.message.get('message')
        elif e.message:
            msg = '{}'.format(e.message)
    return msg or '{}'.format(e)


def _round_sig(x, sig=3):
    """
    Rounds x to sig significant digits
    :param x: The value to round
    :param sig: Number of significant digits
    :return: rounded value
    """
    from math import floor, log10
    if abs(x) < 1e-12:
        return 0
    else:
        return round(x, sig - int(floor(log10(abs(x)))) - 1)


def substructure_vec_to_substructure_dict(substructure_vec):
    """convert the substructure vector to dictionary with degree as key"""
    substructure_dict = {}
    for i in substructure_vec:
        if str(len(i)) not in substructure_dict.keys():
            substructure_dict[str(len(i))] = [i]
        else:
            substructure_dict[str(len(i))].append(i)
    return substructure_dict


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 strtoint(s, default=''):
    """Return int from string s interpreting ``default`` as 0.
    """
    return 0 if s == default else int(s)


@classmethod
def from_tokens(cls, tokens, **init_kwargs):
    """
        Create a new TMPreproc instance by loading `tokens` in the same format as they are returned by
        :attr:`~TMPreproc.tokens` or :attr:`~TMPreproc.tokens_with_metadata`, i.e. as dict with mapping: document
        label -> document tokens array or document data frame.

        :param tokens: dict of tokens as returned by :attr:`~TMPreproc.tokens` o
                       :attr:`~TMPreproc.tokens_with_metadata`
        :param init_kwargs: dict of arguments passed to :meth:`~TMPreproc.__init__`
        :return: new instance with passed tokens
        """
    if 'docs' in init_kwargs.keys():
        raise ValueError(
            '`docs` cannot be passed as argument when loading tokens')
    init_kwargs['docs'] = None
    return cls(**init_kwargs).load_tokens(tokens)


def _rename_amino_acid(df):
    """ 3 letter to single letter amino-acid code"""
    STY = {'Ser': 'S', 'Thr': 'T', 'Tyr': 'Y'}
    amino_acid = STY.get(df['ORIGINAL'].iloc[0], float('NaN'))
    df['Amino.Acid'] = amino_acid
    return df


def rot_clear():
    """Reset rotations of selected bones to their default values

    """
    pass


def parseDeviceName(deviceName):
    """ Parse the device name, which is of the format card#.

    Parameters:
    deviceName -- DRM device name to parse
    """
    return deviceName[4:]


def describe_instance_associations_status(InstanceId=None, MaxResults=None,
    NextToken=None):
    """
    The status of the associations for the instance(s).
    See also: AWS API Documentation

    :example: response = client.describe_instance_associations_status(
        InstanceId='string',
        MaxResults=123,
        NextToken='string'
    )

    :type InstanceId: string
    :param InstanceId: [REQUIRED]
            The instance IDs for which you want association status information.

    :type MaxResults: integer
    :param MaxResults: The maximum number of items to return for this call. The call also returns a token that you can specify in a subsequent call to get the next set of results.

    :type NextToken: string
    :param NextToken: The token for the next set of items to return. (You received this token from a previous call.)

    :rtype: dict
    :return: {
        'InstanceAssociationStatusInfos': [
            {
                'AssociationId': 'string',
                'Name': 'string',
                'DocumentVersion': 'string',
                'InstanceId': 'string',
                'ExecutionDate': datetime(2015, 1, 1),
                'Status': 'string',
                'DetailedStatus': 'string',
                'ExecutionSummary': 'string',
                'ErrorCode': 'string',
                'OutputUrl': {
                    'S3OutputUrl': {
                        'OutputUrl': 'string'
                    }
                }
            },
        ],
        'NextToken': 'string'
    }

    """
    pass


def utsb(event, server, view):
    """ This method is called to set who has set the topic"""
    chan = event['channel'].lower()
    nickb = event['nickb']
    win = view.get_win((server.getName(), chan))
    packet = 'Topic on %s set by %s\n' % (chan, nickb)
    win.update_screen(packet)


def banners_count():
    """
        Get banners count
        """


def remove_hdmx_table(tt):
    """Removes hdmx table from a fontTools.ttLib.TTFont object"""
    try:
        del tt['hdmx']
    except KeyError:
        pass


def unpack_boolean(data, pointer=0):
    """
    Unpacks a boolean value.
    """
    if data[pointer]:
        return pointer + 1, True
    return pointer + 1, False


def _convert_logical(builder, node, graph, err):
    """
    convert to CoreML Logical And/Or/Xor/Not Layer:
    https://github.com/apple/coremltools/blob/655b3be5cc0d42c3c4fa49f0f0e4a93a26b3e492/mlmodel/format/NeuralNetwork.proto#L1013
    """
    mode = node.op_type.upper()
    builder.add_logical(name=node.name, input_names=node.inputs,
        output_name=node.outputs[0], mode=mode)


def model_from_json(json_string, custom_objects=None):
    """Parses a JSON model configuration file
    and returns a model instance.
    """
    import json
    from keras.utils.layer_utils import layer_from_config
    config = json.loads(json_string)
    return layer_from_config(config, custom_objects=custom_objects)


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


def substitute_half_a_bitvector(pattern: str, args: 'List[int]') ->int:
    """
    Helper function for `substitute_bitvector`. Takes an 8-bit pattern and returns a
    single byte.
    """
    ret = 0
    for shift, pattern_bit in enumerate(reversed(pattern)):
        if pattern_bit == '0':
            real_bit = 0
        elif pattern_bit == '1':
            real_bit = 1
        else:
            index = ord(pattern_bit.lower()) - ord('a')
            real_bit = args[index] & 1
            args[index] >>= 1
        ret += real_bit << shift
    return ret


def fix_bounds(start, end, min_span):
    """Adjust end point to ensure span of at least `min_span`"""
    return start, max(end, start + min_span)


def __del(collection, item, _sa_initiator=None):
    """Run del events, may eventually be inlined into decorators."""
    if _sa_initiator is not False:
        executor = collection._sa_adapter
        if executor:
            executor.fire_remove_event(item, _sa_initiator)


@staticmethod
def metadata_updated_on(item):
    """Extracts the update time from a Jenkins item.

        The timestamp is extracted from 'timestamp' field.
        This date is a UNIX timestamp but needs to be converted to
        a float value.

        :param item: item generated by the backend

        :returns: a UNIX timestamp
        """
    return float(item['timestamp'] / 1000)


def test_one_bit_set(arg):
    """
    Return True if arg has form 1 << X
    """
    return arg != 0 and arg & arg - 1 == 0


def truncate_str(v: str, max_length: int=80) ->str:
    """Trim the given text if too long."""
    if len(v) <= max_length:
        return v
    head = max_length * 2 // 3
    tail = max_length - head - 3
    return v[:head] + '...' + v[-tail:]


def objects_remove():
    """Remove selected objects from Rigid Body simulation

    """
    pass


@classmethod
def parse(cls, name, data_size, reader, parsers):
    """given a 4 byte name, data_size int, BitstreamReader
        and dict of {"atom":handler} sub-parsers,
        returns an atom of this class"""
    return cls(name, reader.read_bytes(data_size))


def action_unlink(force_delete: bool=False):
    """Unlink this action from the active action slot (and/or exit Tweak Mode)

    :param force_delete: Force Delete, Clear Fake User and remove copy stashed in this datablock’s NLA stack
    :type force_delete: bool
    """
    pass


def get_compare_func(value: str):
    """Use mini-language to allow for profile setting value comparison."""
    if value.startswith('>='):
        f_value = float(value[2:])
        return lambda v: v >= f_value
    if value.startswith('<='):
        f_value = float(value[2:])
        return lambda v: v <= f_value
    if value.startswith('>'):
        f_value = float(value[1:])
        return lambda v: v > f_value
    if value.startswith('<'):
        f_value = float(value[1:])
        return lambda v: v < f_value
    if value.startswith('!'):
        return lambda v: v != value
    return lambda v: str(v) == value


def nmap(a, b, c, d, curvefn=None, normfn=None):
    """
    Returns a function that maps a number n from range (a, b) onto a range
    (x, y). If no curvefn is given, linear mapping will be used. Optionally a
    normalisation function normfn can be provided to transform output.
    """
    if not curvefn:
        curvefn = lambda x: x

    def map(n):
        r = 1.0 * (n - a) / (b - a)
        out = curvefn(r) * (d - c) + c
        if not normfn:
            return out
        return normfn(out)
    return map


def int_or_none(x, limit):
    """Returns `int(x)` if `x` is a valid `int` or `None` otherwise.

    `x` is valid if `1 <= x <= limit`.
    """
    try:
        value = int(x)
        if 1 <= value <= limit:
            return value
        else:
            return None
    except ValueError:
        return None


@classmethod
def make_attributes(cls, args, ui, tokgen):
    """
        Called to have this Group generate attributes (possibly by prompting the user for them)
        :rtype : dict
        """
    return {}


def enableSyndication(obj):
    """ Enable syndication for the passed-in object

        o raises 'Syndication is Disabled' if syndication is now allowed

        o raises 'Syndication Information Exists' if used repeatedly
        """


def get_content_type(mimetype, charset):
    """Returns the full content type string with charset for a mimetype.

    If the mimetype represents text the charset will be appended as charset
    parameter, otherwise the mimetype is returned unchanged.

    :param mimetype: the mimetype to be used as content type.
    :param charset: the charset to be appended in case it was a text mimetype.
    :return: the content type.
    """
    if mimetype.startswith('text/'
        ) or mimetype == 'application/xml' or mimetype.startswith(
        'application/') and mimetype.endswith('+xml'):
        mimetype += '; charset=' + charset
    return mimetype


def add_expid_arg(parser, required=False):
    """Add '-i' / '--id' for 'experiment_id' option."""
    parser.add_argument('-i', '--id', dest='experiment_id', type=int,
        required=required, help='experiment id submission')


@classmethod
def fromSections(cls, sections, ramAddress):
    """
        Create a main code file from a list of sections.
        """
    self = cls(b'', ramAddress)
    self.sections = sections
    return self


def _set_tree(value):
    """Set the shared tree to a specific value (for testing)."""
    global _tree
    _tree = value


def close_hook(player, container):
    """
        The ``player`` a Player's protocol
        The ``container`` is a 0x65 message
        """
    pass


def explode_refresh(modifier: str=''):
    """Refresh data in the Explode modifier

    :param modifier: Modifier, Name of the modifier to edit
    :type modifier: str
    """
    pass


def user_active_directory_enabled(user, attributes, created, updated):
    """
    Activate/deactivate user accounts based on Active Directory's
    userAccountControl flags. Requires 'userAccountControl'
    to be included in LDAP_SYNC_USER_EXTRA_ATTRIBUTES.
    """
    try:
        user_account_control = int(attributes['userAccountControl'][0])
        if user_account_control & 2:
            user.is_active = False
        else:
            user.is_active = True
    except KeyError:
        pass


def enumarg(enum, arg):
    """Return enum member from its name or value.

    >>> enumarg(TIFF.PHOTOMETRIC, 2)
    <PHOTOMETRIC.RGB: 2>
    >>> enumarg(TIFF.PHOTOMETRIC, 'RGB')
    <PHOTOMETRIC.RGB: 2>

    """
    try:
        return enum(arg)
    except Exception:
        try:
            return enum[arg.upper()]
        except Exception:
            raise ValueError('invalid argument %s' % arg)


def set_axis_tick_width(params):
    """Set the axis width

    Args:
        params (dict): plotting parameter dictionary

    Returns:
        same as input
    """
    for panel_id, p in params['local'].items():
        obj_axis = params['internal']['canvas']['axes'][panel_id]
        for k in ['x', 'y']:
            attr = 'get_{}axis'.format(k)
            ax = getattr(obj_axis, attr)()
            for m in ['major', 'minor']:
                ax.set_tick_params(which=m, width=p['tick'][m]['width'][k])
    return params


@classmethod
def to_route_short_names_as_string(cls, short_names, sep=', '):
    """
        :return a string representing all short names (e.g., good for a tooltip on a stop popup)
        """
    ret_val = None
    for s in short_names:
        rsn = s.get('route_short_name')
        if rsn:
            if ret_val is None:
                ret_val = rsn
            else:
                ret_val = '{}{}{}'.format(ret_val, sep, rsn)
    return ret_val


@classmethod
def from_json(cls, data):
    """ Loads a JSON-serializable representation into the model state.

        The input of this function is a dict which can be the result
        of :any:`json.loads`.
        """
    c = cls(data.get('segment_name'), None, data.get('formula'), data.get(
        'model_params'), warnings=data.get('warnings'))
    return c


@staticmethod
def disconnect(workers, verbosity):
    """Interrupt connection."""
    workers.Disconnect()


def save_tag_dict(filename, tag_dict):
    """
    Save the given tag dictionary to the given file. Dictionary
    is saved with one tag per line, in the order of their codes.
    """
    ordered_keys = sorted(tag_dict, key=tag_dict.get)
    text = '\n'.join(ordered_keys)
    with open(filename, 'wb') as f:
        f.write(text.encode('utf-8'))


def pose_add(frame: int=1, name: str='Pose'):
    """Add the current Pose to the active Pose Library

    :param frame: Frame, Frame to store pose on
    :type frame: int
    :param name: Pose Name, Name of newly added Pose
    :type name: str
    """
    pass


@classmethod
def _load(cls, path):
    """
        Returns a readable file-like object for the given path. If the path refers to a regular
        file, this method returns the result of invoking open() on the given path. If the path
        refers to a directory, this method returns a ZIP file with all files and subdirectories
        in the directory at the given path.

        :type path: str
        :rtype: io.FileIO
        """
    raise NotImplementedError()


def get_pmin(survey):
    """
   A function to get the pmin value for the aplpy chart, as a function of the instrument.

   Args:
      fc_params: the parameters of the finding charts (a dictionary)
   Returns:
      pmin (float): the pmin value
   """
    if survey in ['2MASS-J', '2MASS-H', '2MASS-K']:
        return 30.0
    else:
        return 10.0


@staticmethod
def construct_code_tab(contents, active=False):
    """
        This convenience method wraps contents in the proper markup

        Parameters:
        contents: The contents of the tab
        active: Whether or not the tab should be marked as active
        """
    return '
%s
' % (' active' if active else
        '', contents)


def auto_increment(start_value=0):
    """Returns an iterator over an auto increment value."""
    value = start_value - 1
    while True:
        value += 1
        yield value


def flip_normals():
    """Flip the direction of selected faces’ normals (and of their vertices)

    """
    pass


def isTestModule(modulename):
    """
    Determine whether a module is a test module
    by given module name.
    """
    filename = modulename.split('.')[-1]
    return '.test.' in modulename and filename.startswith('test')


def get_servers_responding():
    """Return a list of IServer objects, one for each server that
        responded to the share query (even if they said they didn't have
        shares, and even if they said they did have shares but then didn't
        send them when asked, or dropped the connection, or returned a
        Failure, and even if they said they did have shares and sent
        incorrect ones when asked)"""


@classmethod
def ExternalDepFailed(cls, name, failmsg):
    """Inform that an optional dependency was not found.

        A new `_ExternalDep` object will be created and stored
        in `config`.

        :Parameters:
          name
            identifier of the optional dependency. This should
            be a valid python identifier, because it will be
            accessible as ``mdp.config.has_<name>`` attribute.
          failmsg
            an object convertible to ``str``, which will be displayed in
            ``mdp.config.info()`` output. This will usually be either an
            exception (e.g. ``ImportError``), or a message string.
        """
    return cls._ExternalDep(name, failmsg=failmsg)


def clear():
    """Clear the queue.

        This method can return a deferred. """


def reverse_enumerate(iterable):
    """Enumerate over an iterable in reverse order while retaining proper indexes, without creating any copies.
    """
    return zip(reversed(range(len(iterable))), reversed(iterable))


def _edge_sign(K, edge):
    """Returns the sign (+/- 1) associated to given edge in the black graph."""
    crossing = edge[2]
    if set(((crossing, 0), (crossing, 1))).issubset(set(edge[0])) or set(((
        crossing, 0), (crossing, 1))).issubset(set(edge[1])):
        return +1
    return -1


def get_deformation_field_scales(reg_params):
    """
    Calculates the scaling of the deformation field from real space
    to voxels
    :param reg_params:
    :return:
    """
    x_scale = 1000 / float(reg_params.atlas_x_pix_size)
    y_scale = 1000 / float(reg_params.atlas_y_pix_size)
    z_scale = 1000 / float(reg_params.atlas_z_pix_size)
    return x_scale, y_scale, z_scale


def _values(obj):
    """Use iter-/generator, preferably.
    """
    return getattr(obj, 'itervalues', obj.values)()


def get_padding(north, south, west, east, padding=10):
    """
    Calculate a reasonable amount of padding for the map
    :param north:
    :type north:
    :param south:
    :type south:
    :param west:
    :type west:
    :param east:
    :type east:
    :param padding:
    :type padding:
    :return: The amount of padding to apply
    :rtype: int, int
    """
    padding /= 100
    lat_padding = abs(north - south) * padding
    lon_padding = abs(east - west) * padding
    if lat_padding < 5:
        lat_padding = 5
    if lon_padding < 5:
        lon_padding = 5
    return round(lat_padding), round(lon_padding)


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 are_aligned(shape1, shape2):
    """Check if two numpy arrays are aligned.

    Parameters
    ----------
    shape1, shape2 : iterable

    Returns
    -------
    isaligned : bool

    """
    isaligned = True
    shape1 = list(shape1)
    shape2 = list(shape2)
    try:
        while isaligned is True:
            dim1 = shape1.pop()
            dim2 = shape2.pop()
            if dim1 != dim2 and (dim1 != 1 and dim2 != 1):
                isaligned = False
    except IndexError:
        return isaligned
    return isaligned


@staticmethod
def lengthen(vowel):
    """
        Returns a lengthened copy of the vowel argument.
        """
    return vowel.lengthen()


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 get_seq_GC(seq):
    """
    From a nucleotide sequence return the GC content
    """
    seq = seq.lower()
    n_C = seq.count('c')
    n_G = seq.count('g')
    GC_content = (n_C + n_G) / float(len(seq))
    return GC_content


def padding_string(pad, pool_size):
    """Get string defining the border mode.

    Parameters
    ----------

    pad: tuple[int]
        Zero-padding in x- and y-direction.
    pool_size: list[int]
        Size of kernel.

    Returns
    -------

    padding: str
        Border mode identifier.
    """
    if isinstance(pad, str):
        return pad
    if pad == (0, 0):
        padding = 'valid'
    elif pad == (pool_size[0] // 2, pool_size[1] // 2):
        padding = 'same'
    elif pad == (pool_size[0] - 1, pool_size[1] - 1):
        padding = 'full'
    else:
        raise NotImplementedError(
            'Padding {} could not be interpreted as any of the '.format(pad
            ) + "supported border modes 'valid', 'same' or 'full'.")
    return padding


def cleanCurlyAround(s: str) ->str:
    """Removes curly braces"""
    if s and s[0] == '{' and s[-1] == '}':
        return s[1:-1]
    return s


def report_issue():
    """Used when errors are really f*cked up"""
    return (
        'report an issue please?         ( https://github.com/agamm/comeback/issues )'
        )


def quote(string):
    """Surround string with single quotes."""
    return "'{0}'".format(string)


def split_models(baseline, *models):
    """ Seperate the effect of models from the baseline.

    Seperate the effect of model and risidual on the baseline,
    base on precalculated effects of each model.
    It is assumed that the models combine linearly with each
    other and a residual (meaning modelA + modelB + residual = baseline,
    but not modelA * modelB + residual = baseline or other such variations).

    Parameters
    ----------
    baseline : ndarray
        An array of the base measurements.
    *models : ndarray
        Arrays of the effects of each model to be removed.
        all models must have the same length as baseline.

    Returns
    -------
    tuple of ndarray
        A tuple, with the first component being an ndarray of the residual
        and the second component being an ndarray of the combined model.
        The result statisfies that the sum of the components
        is equal to the baseline.

    Examples
    --------
    >>> from pyfac.fac import *  # doctest: +SKIP
    >>> modelA = np.arange(15).reshape(5,3)**2
    >>> modelB = sw.as_3d(np.arange(7,2,-1))
    >>> data = (np.random.randn(5,3)*0.1 + modelA + modelB
    ...         + sw.pack_3d(np.sin(np.arange(5)*0.5),
    ...                      np.cos(np.arange(5)*0.5),
    ...                      np.tan(np.arange(5)*0.5)))
    >>> split_models(data,modelA,modelB) # doctest: +ELLIPSIS
    (array([[...,...,...],
           [...,...,...],
           [...,...,...],
           [...,...,...],
           [...,...,...]]), array([[  7.,   8.,  11.],
           [ 15.,  22.,  31.],
           [ 41.,  54.,  69.],
           [ 85., 104., 125.],
           [147., 172., 199.]]))
    """
    model = sum(models)
    return baseline - model, model


def dates_to_fits(date_begin, date_end):
    """Convert two dates into FITS form.

    Parameters
    ----------
    date_begin : `astropy.time.Time`
        Date representing the beginning of the observation.
    date_end  : `astropy.time.Time`
        Date representing the end of the observation.

    Returns
    -------
    cards : `dict` of `str` to `str` or `float`
        Header card keys and values following the FITS standard.
        If neither date is defined this may be empty.
    """
    cards = {}
    if date_begin is None and date_end is None:
        return cards
    cards['TIMESYS'] = 'TAI'
    date_avg = None
    if date_begin is not None and date_end is not None:
        date_avg = date_begin + (date_end - date_begin) / 2.0
    for fragment, date in (('OBS', date_begin), ('END', date_end), ('AVG',
        date_avg)):
        if date is not None:
            tai = date.tai
            cards[f'DATE-{fragment}'] = tai.isot
            cards[f'MJD-{fragment}'] = tai.mjd
    return cards


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 coinc_inspiral_end_time(events, offset_vector):
    """
	Compute the end time of an inspiral coincidence.  events is an
	iterable of sngl_inspiral triggers, offset_vector is a dictionary
	mapping instrument to offset.

	This function returns the time shifted end time of the trigger with
	the highest SNR.  The end time reported by this function gets used
	for things like plot titles, alert messages, and so on.  It is not
	meant to be an accurate estimate of the time at which the
	gravitational wave passed through the geocentre, or any other such
	thing.

	This end time is also used to parallelize thinca by allowing a
	single lock stretch to be split across several jobs without missing
	or double counting any coincs.  This is achieved by using a
	definition that is guaranteed to return a bit-identical "end time"
	for a given set of triggers.  Guaranteeing that allows thinca to
	clip coincs to a sequence of contiguous segments and know that no
	coinc will missed or double counted.
	"""
    event = max(events, key=lambda event: event.snr)
    return event.end + offset_vector[event.ifo]


def add_jardiff_optgroup(parser):
    """
    option group specific to the tests in jardiff
    """
    og = parser.add_argument_group('JAR Checking Options')
    og.add_argument('--ignore-jar-entry', action='append', default=[])
    og.add_argument('--ignore-jar-signature', action='store_true', default=
        False, help='Ignore JAR signing changes')
    og.add_argument('--ignore-manifest', action='store_true', default=False,
        help='Ignore changes to manifests')
    og.add_argument('--ignore-manifest-subsections', action='store_true',
        default=False, help='Ignore changes to manifest subsections')
    og.add_argument('--ignore-manifest-key', action='append', default=[],
        help='case-insensitive manifest keys to ignore')


@classmethod
def getQtDesignerPluginInfo(cls):
    """we don't want this widget in designer"""
    return None


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

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

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


def union(other, self_weight, other_weight):
    """Given BTrees.IFBTree data structure, return weighted union"""


def __call__():
    """ Returns whether the object is in the offer phase or not
        """


def weighting_syntactic_role(entity_role):
    """Return weight given an entity grammatical role.

    Weighting scheme for syntactic role of an entity. This uses the heuristic
    from :cite:`guinaudeau2013graph`, which is:

    +-----------+--------+
    | EGrid Tag | Weight |
    +===========+========+
    | S         | 3      |
    +-----------+--------+
    | O         | 2      |
    +-----------+--------+
    | X         | 1      |
    +-----------+--------+
    | dash      | 0      |
    +-----------+--------+

    :param entity_role: Entity grammatical role (S, O, X, -)
    :type entity_role: string
    :return: Role weight
    :rtype: int
    """
    if entity_role == u'S':
        return 3
    elif entity_role == u'O':
        return 2
    elif entity_role == u'X':
        return 1
    return 0


@classmethod
def unbuild(cls):
    """ Recover all the map unbuilding the things """
    for thing in cls.things:
        thing.unbuild()


def commas(iterable):
    """
    Turn an iterable into a sorted comma-separated string.

    @param iterable: An iterable of things to be put into the return string.
    @return: A sorted comma-separated C{str} of the things in C{iterable}.
    """
    return ', '.join(map(str, sorted(iterable)))


@classmethod
def _load_related_objects(cls, response, client):
    """
        The relationships of the ImageUpload are not first-class CatalogObjects,
        so we need slightly different handling here.
        """
    related_objects = {}
    related_objects_serialized = response.get('included')
    if related_objects_serialized:
        for serialized in related_objects_serialized:
            model_class = cls._upload_model_classes[serialized['type']]
            if model_class:
                related = model_class(validate=False, id=serialized['id'],
                    **serialized['attributes'])
                related_objects[serialized['type'], serialized['id']] = related
    return related_objects


def decode_utf16le(s):
    """
    decode_utf16le attempts to decode a bytestring as UTF-16LE.
      If the string has an odd length, or some unexpected feature,
      this function does its best to handle the data. It does not
      catch any Unicode-related exceptions, such as UnicodeDecodeError,
      so these should be handled by the caller.

    @type s: bytes
    @param s: a bytestring to pase
    @rtype: unicode
    @return: the unicode string decoded from `s`
    @raises: this function does not attempt to catch any Unicode-related exception, so the caller should handle these.
    """
    if b'\x00\x00' in s:
        index = s.index(b'\x00\x00')
        if index > 2:
            if s[index - 2] != b'\x00'[0]:
                s = s[:index + 2]
            else:
                s = s[:index + 3]
    if len(s) % 2 != 0:
        s = s + b'\x00'
    s = s.decode('utf16')
    s = s.partition('\x00')[0]
    return s


def p_parameters_2(p):
    """parameters : LPAR varargslist RPAR"""
    p[0] = p[2]


def get_aif_shift(time_series, bolus_arrival_index):
    """
    Calculates the arterial input function offset as:

    *t*\\ :sub:`arrival` - *t*\\ :sub:`0`

    where *t*\\ :sub:`0` is the first slice acquisition time
    and *t*\\ :sub:`arrival` averages the acquisition times at
    and immediately following bolus arrival.

    :param time_series: the modeling input 4D NIfTI image file path
    :param bolus_arrival_index: the bolus uptake series index
    :return: the parameter CSV file path
    """
    import os
    import csv
    import nibabel as nb
    import numpy as np
    from dcmstack.dcmmeta import NiftiWrapper
    from dcmstack import dcm_time_to_sec
    ts_nii = nb.load(time_series)
    ts_nw = NiftiWrapper(ts_nii)
    acq_time0 = dcm_time_to_sec(ts_nw.get_meta('AcquisitionTime', (0, 0, 0, 0))
        )
    acq_time1 = dcm_time_to_sec(ts_nw.get_meta('AcquisitionTime', (0, 0, 0,
        bolus_arrival_index)))
    acq_time2 = dcm_time_to_sec(ts_nw.get_meta('AcquisitionTime', (0, 0, 0,
        bolus_arrival_index + 1)))
    return (acq_time1 + acq_time2) / 2.0 - acq_time0


@classmethod
def preferred_ordinal(cls, attr_name):
    """
        Returns an ordering value for a particular attribute key.

        Unrecognized attributes and OIDs will be sorted lexically at the end.

        :return:
            An orderable value.

        """
    attr_name = cls.map(attr_name)
    if attr_name in cls.preferred_order:
        ordinal = cls.preferred_order.index(attr_name)
    else:
        ordinal = len(cls.preferred_order)
    return ordinal, attr_name


def _expand_params(solver, params=None, timing=None):
    """Expand a limited set of user-provided params to a full set, substituting
    missing values with solver defaults.
    """
    if params is None:
        params = {}
    if timing is None:
        timing = {}
    default_annealing_time = solver.properties['default_annealing_time']
    default_programming_thermalization = solver.properties[
        'default_programming_thermalization']
    default_readout_thermalization = solver.properties[
        'default_readout_thermalization']
    if 'qpu_anneal_time_per_sample' in timing:
        annealing_time = timing['qpu_anneal_time_per_sample']
    elif 'annealing_time' in params:
        annealing_time = params['annealing_time']
    elif 'anneal_schedule' in params:
        anneal_schedule = params['anneal_schedule']
        annealing_time = anneal_schedule[-1][0]
    else:
        annealing_time = default_annealing_time
    if 'anneal_schedule' in params:
        anneal_schedule = params['anneal_schedule']
    else:
        anneal_schedule = [[0, 0], [annealing_time, 1]]
    flux_biases = params.get('flux_biases')
    initial_state = params.get('initial_state')
    return {'anneal_offsets': params.get('anneal_offsets'),
        'anneal_schedule': anneal_schedule, 'annealing_time':
        annealing_time, 'answer_mode': params.get('answer_mode',
        'histogram'), 'auto_scale': params.get('auto_scale', True if not
        flux_biases else False), 'beta': params.get('beta', 10 if solver.
        is_vfyc else 1), 'chains': params.get('chains'), 'flux_biases':
        flux_biases, 'flux_drift_compensation': params.get(
        'flux_drift_compensation', True), 'h_gain_schedule': params.get(
        'h_gain_schedule', [[0, 1], [annealing_time, 1]]), 'initial_state':
        initial_state, 'max_answers': params.get('max_answers'),
        'num_reads': params.get('num_reads', 1),
        'num_spin_reversal_transforms': params.get(
        'num_spin_reversal_transforms', 0), 'postprocess': params.get(
        'postprocess', 'sampling' if solver.is_vfyc else ''),
        'programming_thermalization': params.get(
        'programming_thermalization', default_programming_thermalization),
        'readout_thermalization': params.get('readout_thermalization',
        default_readout_thermalization), 'reduce_intersample_correlation':
        params.get('reduce_intersample_correlation', False),
        'reinitialize_state': params.get('reinitialize_state', True if
        initial_state else False)}


def assume_role_with_web_identity(RoleArn=None, RoleSessionName=None,
    WebIdentityToken=None, ProviderId=None, Policy=None, DurationSeconds=None):
    """
    Returns a set of temporary security credentials for users who have been authenticated in a mobile or web application with a web identity provider, such as Amazon Cognito, Login with Amazon, Facebook, Google, or any OpenID Connect-compatible identity provider.
    Calling AssumeRoleWithWebIdentity does not require the use of AWS security credentials. Therefore, you can distribute an application (for example, on mobile devices) that requests temporary security credentials without including long-term AWS credentials in the application, and without deploying server-based proxy services that use long-term AWS credentials. Instead, the identity of the caller is validated by using a token from the web identity provider. For a comparison of AssumeRoleWithWebIdentity with the other APIs that produce temporary credentials, see Requesting Temporary Security Credentials and Comparing the AWS STS APIs in the IAM User Guide .
    The temporary security credentials returned by this API consist of an access key ID, a secret access key, and a security token. Applications can use these temporary security credentials to sign calls to AWS service APIs.
    The credentials are valid for the duration that you specified when calling AssumeRoleWithWebIdentity , which can be from 900 seconds (15 minutes) to a maximum of 3600 seconds (1 hour). The default is 1 hour.
    The temporary security credentials created by AssumeRoleWithWebIdentity can be used to make API calls to any AWS service with the following exception: you cannot call the STS service's GetFederationToken or GetSessionToken APIs.
    Optionally, you can pass an IAM access policy to this operation. If you choose not to pass a policy, the temporary security credentials that are returned by the operation have the permissions that are defined in the access policy of the role that is being assumed. If you pass a policy to this operation, the temporary security credentials that are returned by the operation have the permissions that are allowed by both the access policy of the role that is being assumed, * and * the policy that you pass. This gives you a way to further restrict the permissions for the resulting temporary security credentials. You cannot use the passed policy to grant permissions that are in excess of those allowed by the access policy of the role that is being assumed. For more information, see Permissions for AssumeRole, AssumeRoleWithSAML, and AssumeRoleWithWebIdentity in the IAM User Guide .
    Before your application can call AssumeRoleWithWebIdentity , you must have an identity token from a supported identity provider and create a role that the application can assume. The role that your application assumes must trust the identity provider that is associated with the identity token. In other words, the identity provider must be specified in the role's trust policy.
    For more information about how to use web identity federation and the AssumeRoleWithWebIdentity API, see the following resources:
    See also: AWS API Documentation

    Examples
    Expected Output:

    :example: response = client.assume_role_with_web_identity(
        RoleArn='string',
        RoleSessionName='string',
        WebIdentityToken='string',
        ProviderId='string',
        Policy='string',
        DurationSeconds=123
    )

    :type RoleArn: string
    :param RoleArn: [REQUIRED]
            The Amazon Resource Name (ARN) of the role that the caller is assuming.

    :type RoleSessionName: string
    :param RoleSessionName: [REQUIRED]
            An identifier for the assumed role session. Typically, you pass the name or identifier that is associated with the user who is using your application. That way, the temporary security credentials that your application will use are associated with that user. This session name is included as part of the ARN and assumed role ID in the AssumedRoleUser response element.
            The regex used to validate this parameter is a string of characters consisting of upper- and lower-case alphanumeric characters with no spaces. You can also include underscores or any of the following characters: =,.@-

    :type WebIdentityToken: string
    :param WebIdentityToken: [REQUIRED]
            The OAuth 2.0 access token or OpenID Connect ID token that is provided by the identity provider. Your application must get this token by authenticating the user who is using your application with a web identity provider before the application makes an AssumeRoleWithWebIdentity call.

    :type ProviderId: string
    :param ProviderId: The fully qualified host component of the domain name of the identity provider.
            Specify this value only for OAuth 2.0 access tokens. Currently www.amazon.com and graph.facebook.com are the only supported identity providers for OAuth 2.0 access tokens. Do not include URL schemes and port numbers.
            Do not specify this value for OpenID Connect ID tokens.

    :type Policy: string
    :param Policy: An IAM policy in JSON format.
            The policy parameter is optional. If you pass a policy, the temporary security credentials that are returned by the operation have the permissions that are allowed by both the access policy of the role that is being assumed, * and * the policy that you pass. This gives you a way to further restrict the permissions for the resulting temporary security credentials. You cannot use the passed policy to grant permissions that are in excess of those allowed by the access policy of the role that is being assumed. For more information, see Permissions for AssumeRoleWithWebIdentity in the IAM User Guide .
            The format for this parameter, as described by its regex pattern, is a string of characters up to 2048 characters in length. The characters can be any ASCII character from the space character to the end of the valid character list (u0020-u00FF). It can also include the tab (u0009), linefeed (u000A), and carriage return (u000D) characters.
            Note
            The policy plain text must be 2048 bytes or shorter. However, an internal conversion compresses it into a packed binary format with a separate limit. The PackedPolicySize response element indicates by percentage how close to the upper size limit the policy is, with 100% equaling the maximum allowed size.

    :type DurationSeconds: integer
    :param DurationSeconds: The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) to 3600 seconds (1 hour). By default, the value is set to 3600 seconds.
            Note
            This is separate from the duration of a console session that you might request using the returned credentials. The request to the federation endpoint for a console sign-in token takes a SessionDuration parameter that specifies the maximum length of the console session, separately from the DurationSeconds parameter on this API. For more information, see Creating a URL that Enables Federated Users to Access the AWS Management Console in the IAM User Guide .

    :rtype: dict
    :return: {
        'Credentials': {
            'AccessKeyId': 'string',
            'SecretAccessKey': 'string',
            'SessionToken': 'string',
            'Expiration': datetime(2015, 1, 1)
        },
        'SubjectFromWebIdentityToken': 'string',
        'AssumedRoleUser': {
            'AssumedRoleId': 'string',
            'Arn': 'string'
        },
        'PackedPolicySize': 123,
        'Provider': 'string',
        'Audience': 'string'
    }

    :returns:
    RoleArn (string) -- [REQUIRED]
    The Amazon Resource Name (ARN) of the role that the caller is assuming.

    RoleSessionName (string) -- [REQUIRED]
    An identifier for the assumed role session. Typically, you pass the name or identifier that is associated with the user who is using your application. That way, the temporary security credentials that your application will use are associated with that user. This session name is included as part of the ARN and assumed role ID in the AssumedRoleUser response element.
    The regex used to validate this parameter is a string of characters consisting of upper- and lower-case alphanumeric characters with no spaces. You can also include underscores or any of the following characters: =,.@-

    WebIdentityToken (string) -- [REQUIRED]
    The OAuth 2.0 access token or OpenID Connect ID token that is provided by the identity provider. Your application must get this token by authenticating the user who is using your application with a web identity provider before the application makes an AssumeRoleWithWebIdentity call.

    ProviderId (string) -- The fully qualified host component of the domain name of the identity provider.
    Specify this value only for OAuth 2.0 access tokens. Currently www.amazon.com and graph.facebook.com are the only supported identity providers for OAuth 2.0 access tokens. Do not include URL schemes and port numbers.
    Do not specify this value for OpenID Connect ID tokens.

    Policy (string) -- An IAM policy in JSON format.
    The policy parameter is optional. If you pass a policy, the temporary security credentials that are returned by the operation have the permissions that are allowed by both the access policy of the role that is being assumed, * and * the policy that you pass. This gives you a way to further restrict the permissions for the resulting temporary security credentials. You cannot use the passed policy to grant permissions that are in excess of those allowed by the access policy of the role that is being assumed. For more information, see Permissions for AssumeRoleWithWebIdentity in the IAM User Guide .
    The format for this parameter, as described by its regex pattern, is a string of characters up to 2048 characters in length. The characters can be any ASCII character from the space character to the end of the valid character list (u0020-u00FF). It can also include the tab (u0009), linefeed (u000A), and carriage return (u000D) characters.

    Note
    The policy plain text must be 2048 bytes or shorter. However, an internal conversion compresses it into a packed binary format with a separate limit. The PackedPolicySize response element indicates by percentage how close to the upper size limit the policy is, with 100% equaling the maximum allowed size.

    DurationSeconds (integer) -- The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) to 3600 seconds (1 hour). By default, the value is set to 3600 seconds.

    Note
    This is separate from the duration of a console session that you might request using the returned credentials. The request to the federation endpoint for a console sign-in token takes a SessionDuration parameter that specifies the maximum length of the console session, separately from the DurationSeconds parameter on this API. For more information, see Creating a URL that Enables Federated Users to Access the AWS Management Console in the IAM User Guide .

    """
    pass


def _total_seconds(td):
    """Wrapper to work around lack of .total_seconds() method in Python 3.1.
    """
    if hasattr(td, 'total_seconds'):
        return td.total_seconds()
    return td.days * 3600 * 24 + td.seconds + td.microseconds / 100000.0


def merge_dicts(*dict_args):
    """
    Given any number of dicts, shallow copy and merge into a new dict,
    precedence goes to key value pairs in latter dicts.

    >>> merge_dicts( {1:2, 2:3, 3:4}, {2:4, 3:6, 4:8} )
    {1: 2, 2: 4, 3: 6, 4: 8}

    >>> merge_dicts( {} )
    {}

    >>> merge_dicts ( {}, {} )
    {}

    >>> merge_dicts ( {1:2}, {} )
    {1: 2}

    >>> merge_dicts ( {1:2} )
    {1: 2}

    """
    result = {}
    for dictionary in dict_args:
        result.update(dictionary)
    return result


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


@classmethod
def from_file(cls, file_obj):
    """ Create a packet instance from bytes read from a file-like object.
        This class method is only meant to be called on subclasses that
        define _bytes and _type class properties.
        Note: file_obj position will be changed after calling this function.

        Keyword arguments:
        file_obj -- file-like object to read bytes from

        Return new packet instance.
        """
    instance = cls()
    for name, data_type in cls._bytes:
        val = data_type.get(file_obj, instance)
        setattr(instance, name, val)
    return instance


def outgroup(tree, outgroups):
    """Root the provided tree by the provided outgroups, given that at least
    one of the outgroups are present within the tree and that the OTUs that are
    present are non-repetetive and form a monophyletic group. Returns the
    rooted tree and True if the conditions are met or the input tree and False
    if the conditions were not met.

    Parameters
    ----------
    tree : TreeNode object
        The node you wish to root.
    outgroups : list of strings
        Root the provided TreeNode object using the OTUs within this list.

    Returns
    -------
    tree : TreeNode object
        Tree rerooted at outgroups if conditions are met, input tree if not.
    rooted : bool
        True if conditions are met, False if not.
    """
    rooted = False
    outgroups_in_tree = tree.outgroups_present(outgroups)
    if not outgroups_in_tree:
        return tree, rooted
    if len(set(outgroups_in_tree)) < len(outgroups_in_tree):
        return tree, rooted
    if len(outgroups_in_tree) == 1:
        outgroup_otu = outgroups_in_tree[0]
        for leaf in tree.iter_leaves():
            otu = leaf.otu()
            if otu == outgroup_otu:
                rooted = True
                return tree.reroot(leaf), rooted
    for branch in tree.iter_branches():
        if branch.is_monophyletic_outgroup(outgroups_in_tree):
            rooted = True
            return tree.reroot(branch), rooted
    return tree, rooted


def ratioTerminatorToStar(H_p, R_p, R_s):
    """Calculates the ratio of the terminator to the star assuming 5 scale
    heights large. If you dont know all of the input try
    :py:func:`calcRatioTerminatorToStar`

    .. math::
        \\Delta F = \\frac{10 H R_p + 25 H^2}{R_\\star^2}

    Where :math:`\\Delta F` is the ration of the terminator to the star,
    H scale height planet atmosphere, :math:`R_p` radius of the planet,
    :math:`R_s` radius of the star

    :param H_p:
    :param R_p:
    :param R_s:
    :return: ratio of the terminator to the star
    """
    deltaF = (10 * H_p * R_p + 25 * H_p ** 2) / R_s ** 2
    return deltaF.simplified


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

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


def add_marker(location: float=(0.0, 0.0)):
    """Place new marker at specified location

    :param location: Location, Location of marker on frame
    :type location: float
    """
    pass


@staticmethod
def p_attribute_name(p):
    """attribute_name : STRING"""
    p[0] = p[1]


@classmethod
def getFirstInteractionShape(cls):
    """Returns the shape kind which will be used by the very first
        interaction with the plot.

        This interactions are hardcoded inside the plot

        :rtype: str
        """
    return cls._plotShape


def delay_invoke(name, wait):
    """
        invoke method `name` on each incoming thing with passed arguments,
        keywords after delay `wait` but return incoming thing instead if method
        returns `None`

        @param name: name of method
        @param wait: time in seconds
        """


def ReplaceCapitals(string):
    """
    Replaces the capital letter in a string with an underscore plus the
    corresponding lowercase character.

    **Parameters:**

    * `string`: the string to be analyzed.
    """
    newString = ''
    for char in string:
        if char.isupper():
            newString += '_%s' % char.lower()
        else:
            newString += char
    return newString


def count_tup(tupl, value, start=None, end=None):
    """
    Counts the number of times ``value`` occurs in ``tupl[start:end]``.

    Optional arguments start and end are interpreted as in slice notation.

    :param tupl: The tuple to search
    :type tupl:  ``tuple``

    :param value: The value to count
    :type value:  ``any``

    :param start: The start of the search range
    :type start:  ``int``

    :param end: The end of the search range
    :type end:  ``int``

    :return: The number of times ``value`` occurs in ``tupl[start:end]``.
    :rtype:  ``int``
    """
    assert type(tupl) == tuple, '%s is not a tuple' % tupl
    return tupl[start:end].count(value)


def is_atom(unknown_object):
    """Determines whether an object is an atom or a collection"""
    if hasattr(unknown_object, 'shape'):
        return True
    if hasattr(unknown_object, '__len__') and not hasattr(unknown_object,
        'keys'):
        return False
    return True


def print_scientific_16(value: float) ->str:
    """
    Prints a value in 16-character scientific notation.
    This is a sub-method and shouldnt typically be called

    .. seealso:: print_float_16 for a better method
    """
    if value == 0.0:
        return '%16s' % '0.'
    python_value = '%16.14e' % value
    svalue, sexponent = python_value.strip().split('e')
    exponent = int(sexponent)
    if abs(value) < 1.0:
        sign = '-'
    else:
        sign = '+'
    sexp2 = str(exponent).strip('-+')
    value2 = float(svalue)
    len_sexp = len(sexp2) + 1
    leftover = 16 - len_sexp
    if value < 0:
        fmt = '%%1.%sf' % (leftover - 3)
    else:
        fmt = '%%1.%sf' % (leftover - 2)
    svalue3 = fmt % value2
    svalue4 = svalue3.strip('0')
    field = '%16s' % (svalue4 + sign + sexp2)
    return field


def camel_to_underscore(name):
    """Convert camelcase style naming to underscore style naming

    e.g. SpamEggs -> spam_eggs """
    import string
    for c in string.ascii_uppercase:
        name = name.replace(c, '_%c' % c)
    return name.strip('_').lower()


def strjoin(s):
    """
    Return a function to join sequences using `s` as the separator. Intended
    for use with :func:`petl.transform.conversions.convert`.

    """
    return lambda l: s.join(map(str, l))


def to_ordinal(a_date):
    """
    Calculate number of days from 0000-00-00.
    """
    return a_date.toordinal()


@classmethod
def none(cls):
    """A factory method that creates a :class:`Permissions` with all
        permissions set to False."""
    return cls(0)


@staticmethod
def _patch_for_win_winapi(orig_file, patch_file):
    """ Both _winapi.c and overlapped.c define a C structure with the name
        OverlappedType.  We rename the former.
        """
    for line in orig_file:
        patch_file.write(line.replace('OverlappedType', 'OverlappedType_'))


def underscore_host(host):
    """
    replace periods in a url with underscores for valid folder name
    """
    return host.replace('.', '_')


@classmethod
def _adjust_kwargs(cls, **kwargs):
    """Extension point for custom kwargs adjustment."""
    return kwargs


@classmethod
def create_qos_policy(cls, name, description=None, shared=False, project_id
    =None, is_default=False):
    """Wrapper utility that returns a test QoS policy."""
    body = cls.admin_client.create_qos_policy(name, description, shared,
        project_id, is_default)
    qos_policy = body['policy']
    cls.qos_policies.append(qos_policy)
    return qos_policy


def tipo(x):
    """
    Retorna o tipo do objeto.

    Examples
    --------

    >>> tipo(2) == inteiro
    Verdadeiro
    """
    return type(x)


@classmethod
def available(cls):
    """returns True if the AudioOutput is available on the system"""
    try:
        from audiotools.output import CoreAudio
        return True
    except ImportError:
        return False


@staticmethod
def _sync_base_clf_probability(base_clf, probability):
    """ Enable or disable probability estimation for the base classifiers

        Parameters
        ----------
        base_clf : list[SklearnClassifier]
        probability : bool
        """
    for clf in base_clf:
        if hasattr(clf, 'probability'):
            clf.set_params(probability=probability)


def bayesian(p_h, p_o_h, p_o_not_h):
    """Calculate the probability of hypothesis `h` given the new observation
       `o`, where ::

       - `p_h` is the probability before the new observation was made,

       - `p_o_h` is the probability of the observation when the
         hypothesis `h` is true,

       - `p_o_not_h` is the probability of the observation when the
         hypothesis `h` is false.

       Consider a disease that appears in 1% of the population and a test for
       that disease is positive 80% (or 85%, or 90%) of the time when the
       disease is present and 10% (or 5%, or 1%) of the time when the disease
       is not present:

       >>> print ("%5.3f" % bayesian (0.01, 0.80, 0.10))
       0.075
       >>> print ("%5.3f" % bayesian (0.01, 0.85, 0.05))
       0.147
       >>> print ("%5.3f" % bayesian (0.01, 0.90, 0.01))
       0.476
       >>> print ("%5.3f" % bayesian (0.01, 0.99, 0.01))
       0.500

       Because so many people don't have the disease, the false positives far
       exceed the small percentage of those tested who actually have the
       disease.

       >>> print ("%5.3f" % bayesian (0.50, 0.80, 0.10))
       0.889
       >>> print ("%5.3f" % bayesian (0.50, 0.85, 0.05))
       0.944
       >>> print ("%5.3f" % bayesian (0.50, 0.90, 0.01))
       0.989
       >>> print ("%5.3f" % bayesian (0.50, 0.99, 0.01))
       0.990
    """
    p_not_h = 1.0 - p_h
    p_h_times_p_o_h = p_h * p_o_h
    return p_h_times_p_o_h / (p_h_times_p_o_h + p_not_h * p_o_not_h)


def to_uuid(uuid):
    """Return the UUID from the string representation.

        :param uuid: A UUID, or the string representation of the UUID.
        :type uuid: UUID or str
        :return: The UUID, converted if needed as appropriate for the
            API version.  In 3.0, the string representation is
            interpreted as an integer, while in 3.1 it is the hex
            string.
        :rtype: UUID
        """


@staticmethod
def get_elastic_mappings(es_major):
    """Get Elasticsearch mapping.

        :param es_major: major version of Elasticsearch, as string
        :returns:        dictionary with a key, 'items', with the mapping
        """
    mapping = """
        {
            "properties": {
                "description_analyzed": {
                  "type": "text",
                  "index": true
                },
                "geolocation": {
                    "type": "geo_point"
                }
           }
        } """
    return {'items': mapping}


@classmethod
def compute_info(cls, val):
    """
        Compute the new information for this provider

        The computed value should be returned and will then be accessible directly as cls.INFO.
        This information will be printed by the client when describing this metadata provider

        Parameters
        ----------
        val : str
            Provider specific information used in computing the new information. For example, this
            can be a path.

        Returns
        -------
        str :
            Value to be set to INFO
        """
    return ''


def filter_title(title, target_words, filter_words, filter_mode):
    """
    :param title is string of announcement's title
    :param target_words
    :param filter_words
    :param filter_mode can take 'AND' or 'OR'
    """
    if filter_mode == 'OR':
        for w_positive in target_words:
            if w_positive in title:
                for w_negative in filter_words:
                    if w_negative in title:
                        return False
                return True
        return False
    elif filter_mode == 'AND':
        for w_positive in target_words:
            if w_positive not in title:
                return False
        for w_negative in filter_words:
            if w_negative in title:
                return False
        return True


def getAttributes():
    """Return a list of 2-tuple attribute information.

        The first entry of the 2-tuple is the name of the attribute, the
        second is the attribute object itself.
        """


def _get_paginated_url(url, page):
    """Add a page number to the url

    Args:
        url:
        page:

    Returns:

    """
    return '{0}/?page={1}'.format(url, page)


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

    The ".dev0" means dirty.

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


def find_first_listed_qtr(quarterly_submissions, s):
    """
    Finds the first qtr for which the company published at least one report.

    :param quarterly_submissions: dictionary of submissions indexes by qtr
    :param s: Settings dictionary
    :return: bool for success and first qtr when the company was listed.
    """
    flag_listed = False
    for qtr in s['list_qtr']:
        if len(quarterly_submissions[qtr]) == 0:
            continue
        else:
            flag_listed = True
            break
    return flag_listed, qtr


def join_formatted_lines(lines):
    """Return the finished output"""
    return '\n'.join(lines)


def remove_raw_object(cls):
    """
    Decorator for Record class.
    If a Record class is decorated, raw_object will be removed once all mark properties are cached.
    """
    cls._remove_raw_object = True
    return cls


def set_config_motifs(config, params):
    """process the Motifs section"""
    params['sequence_types'] = config.get('Motifs', 'sequence_types').split(','
        )
    params['search_distances'] = {}
    params['scan_distances'] = {}
    for seqtype in params['sequence_types']:
        cat = 'SequenceType-%s' % seqtype
        params['search_distances'][seqtype] = tuple(map(int, config.get(cat,
            'search_distance').split(',')))
        params['scan_distances'][seqtype] = tuple(map(int, config.get(cat,
            'scan_distance').split(',')))


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 isCurrentYear():
    """Return true if this object represents a date/time that
        falls within the current year, in the context of this
        object's timezone representation"""


def batch_put_attributes(DomainName=None, Items=None):
    """
    The BatchPutAttributes operation creates or replaces attributes within one or more items. By using this operation, the client can perform multiple  PutAttribute operation with a single call. This helps yield savings in round trips and latencies, enabling Amazon SimpleDB to optimize requests and generally produce better throughput.
    The client may specify the item name with the Item.X.ItemName parameter. The client may specify new attributes using a combination of the Item.X.Attribute.Y.Name and Item.X.Attribute.Y.Value parameters. The client may specify the first attribute for the first item using the parameters Item.0.Attribute.0.Name and Item.0.Attribute.0.Value , and for the second attribute for the first item by the parameters Item.0.Attribute.1.Name and Item.0.Attribute.1.Value , and so on.
    Attributes are uniquely identified within an item by their name/value combination. For example, a single item can have the attributes { "first_name", "first_value" } and { "first_name", "second_value" } . However, it cannot have two attribute instances where both the Item.X.Attribute.Y.Name and Item.X.Attribute.Y.Value are the same.
    Optionally, the requester can supply the Replace parameter for each individual value. Setting this value to true will cause the new attribute values to replace the existing attribute values. For example, if an item I has the attributes { 'a', '1' }, { 'b', '2'} and { 'b', '3' } and the requester does a BatchPutAttributes of {'I', 'b', '4' } with the Replace parameter set to true, the final attributes of the item will be { 'a', '1' } and { 'b', '4' } , replacing the previous values of the 'b' attribute with the new value.
    You can execute multiple BatchPutAttributes operations and other operations in parallel. However, large numbers of concurrent BatchPutAttributes calls can result in Service Unavailable (503) responses.
    The following limitations are enforced for this operation:
    See also: AWS API Documentation

    :example: response = client.batch_put_attributes(
        DomainName='string',
        Items=[
            {
                'Name': 'string',
                'Attributes': [
                    {
                        'Name': 'string',
                        'Value': 'string',
                        'Replace': True|False
                    },
                ]
            },
        ]
    )

    :type DomainName: string
    :param DomainName: [REQUIRED] The name of the domain in which the attributes are being stored.

    :type Items: list
    :param Items: [REQUIRED] A list of items on which to perform the operation.
            (dict) --
            Name (string) -- [REQUIRED] The name of the replaceable item.
            Attributes (list) -- [REQUIRED] The list of attributes for a replaceable item.
            (dict) --
            Name (string) -- [REQUIRED] The name of the replaceable attribute.
            Value (string) -- [REQUIRED] The value of the replaceable attribute.
            Replace (boolean) -- A flag specifying whether or not to replace the attribute/value pair or to add a new attribute/value pair. The default setting is false .

    :returns:
    DomainName (string) -- [REQUIRED] The name of the domain in which the attributes are being stored.
    Items (list) -- [REQUIRED] A list of items on which to perform the operation.

    (dict) --
    Name (string) -- [REQUIRED] The name of the replaceable item.
    Attributes (list) -- [REQUIRED] The list of attributes for a replaceable item.
    (dict) --
    Name (string) -- [REQUIRED] The name of the replaceable attribute.
    Value (string) -- [REQUIRED] The value of the replaceable attribute.
    Replace (boolean) -- A flag specifying whether or not to replace the attribute/value pair or to add a new attribute/value pair. The default setting is false .

    """
    pass


@classmethod
def fromkeys(cls, iterable, value=None):
    """OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
        and values equal to v (which defaults to None).

        """
    d = cls()
    for key in iterable:
        d[key] = value
    return d


def dispatch_hook(key, hooks, hook_data, **kwargs):
    """Dispatches a hook dictionary on a given piece of data."""
    hooks = hooks or dict()
    if key in hooks:
        hooks = hooks.get(key)
        if hasattr(hooks, '__call__'):
            hooks = [hooks]
        for hook in hooks:
            _hook_data = hook(hook_data, **kwargs)
            if _hook_data is not None:
                hook_data = _hook_data
    return hook_data


def get_input_list(input_val, default_val):
    """
    Method to get a list from a comma separated string.
    :param input_val: Input string or list
    :param default_val: Default value (generally used for a spider)
    :return: listified string or default_val if input is not a list or string.
    """
    if isinstance(input_val, list):
        return input_val
    elif isinstance(input_val, str):
        return input_val.split(',')
    else:
        return default_val


def get_ver():
    """
    Gather the version number from git
    """
    import subprocess
    proc = subprocess.run(['git', 'describe'], stdout=subprocess.PIPE,
        stderr=subprocess.PIPE)
    if not proc.returncode == 0:
        return
    v = proc.stdout.decode().strip()
    if '-' not in v:
        ret = v
    else:
        csum = v[v.rindex('-') + 1:]
        base = v[:v.rindex('-')]
        count = base[base.rindex('-') + 1:]
        tag = base[:base.rindex('-')]
        ret = f'{tag}.post{count}+{csum}'
    return ret


def gen_monospace(text):
    """Creates a monospace typed text.

    This is often used for source code formatting.

    Args:
      text (string): The text to be formatted with
        monospace.

    Returns:
      string: The monospace formatted text.

    """
    return '`' + text + '`'


def view_frame():
    """Reset viewable area to show range around current frame

    """
    pass


def reference_suffix(metric, reference):
    """
    Return the suffix for a metric displayed for a reference (or no Reference)

    :return:
        A string that is used as the suffix for a reference metric.
    """
    if reference is not None and reference.delta_percent:
        return '%'
    return metric.suffix


def white_listed(url, white_listed_urls=None, white_listed_patterns=None):
    """
    Check if link is in the white listed URLs or patterns to ignore.

    Args:
        - url                    (str) : link to check.
        - white_listed_urls     (list) : list of white-listed urls.
        - white_listed_patterns (list) : list of white-listed patterns.

    Returns:
        (bool) boolean for whether link is white-listed or not.
    """
    white_listed_urls = white_listed_urls or []
    white_listed_patterns = white_listed_patterns or []
    if url in white_listed_urls:
        return True
    for white_listed_pattern in white_listed_patterns:
        if white_listed_pattern in url:
            return True
    return False


def is_model_abstract(model):
    """True if abstract is True in Meta class"""
    return model._meta.abstract


def retransmit_timeout(group_state: 'GroupState'):
    """
    retransmit timer associated with group GroupState object has expired
    """
    group_state.group_state_logger.debug(
        'NonQuerier NoMembersPresent: retransmit_timeout')
    return


@staticmethod
def properties_proactively_reported():
    """Return True if properties asynchronously reported."""
    return False


def norm(angle):
    """ Normalizes an angle between 0 and 360. """
    return angle % 360


def RGB(red, green, blue):
    """
    Given integer values of Red, Green, Blue, return a color string "#RRGGBB"
    :param red:  Red portion from 0 to 255
    :type red: (int)
    :param green:  Green portion from 0 to 255
    :type green: (int)
    :param blue:  Blue portion from 0 to 255
    :type  blue: (int)
    :return:  A single RGB String in the format "#RRGGBB" where each pair is a hex number.
    :rtype: (str)
    """
    red = min(int(red), 255) if red > 0 else 0
    blue = min(int(blue), 255) if blue > 0 else 0
    green = min(int(green), 255) if green > 0 else 0
    return '#%02x%02x%02x' % (red, green, blue)


def __material_cr(d):
    """ Fixed length data fields for continuing resources. """
    return d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7:10], d[10], d[11], d[
        12:15], d[15], d[16]


def add_common_arguments(parser, nargs=1):
    """Populate the given argparse.ArgumentParser with arguments.

    This function can be used to centralize the definition of commons argparse
    arguments and avoid the duplication of these definitions among the
    executable scripts.

    The following arguments are added to the parser:

    - **verbose** (boolean): verbose mode
    - **debug** (boolean): debug mode
    - **plot** (boolean): plot images
    - **saveplot** (string): the output file where to save plotted images
    - **fileargs** (file paths): the files image to process

    Parameters
    ----------
    parser : argparse.ArgumentParser
        The parser to populate.

    Returns
    -------
    argparse.ArgumentParser
        Return the populated ArgumentParser object.
    """
    parser.add_argument('--verbose', '-v', action='store_true', help=
        'Verbose mode.')
    parser.add_argument('--debug', action='store_true', help='Debug mode.')
    parser.add_argument('--plot', action='store_true', help='Plot images.')
    parser.add_argument('--saveplot', default=None, metavar='FILE', help=
        'The output file where to save plotted images.')
    parser.add_argument('fileargs', nargs=nargs, metavar='FILE', help=
        'The files image to process.')
    return parser


def invalid_json_schema():
    """
    Verified 2015-06-16 for creating a LB, changing a node, adding nodes:

    - when providing invalid fields in the JSON request
    - when providing invalid JSON
    - this schema validation happens even before checking whether a LB and/or
      node exists

    :return: a `tuple` of (dict body message, 400 http status code)
    """
    return {'message': ['JSON does not match the expected schema']}, 400


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

    :return: rst string
    :rtype: str
    """
    return """
    The ``alignak`` model is used to store the global configuration of an Alignak instance.

    """


def testAssociate(id_, key, requestor):
    """Test that keepass has the given identifier and key"""
    input_data = {'RequestType': 'test-associate'}
    return requestor(key, input_data, id_)


def droplet_volume(length=100, diameter=250):
    """
    convert the length of a plug to volume in 250 um capillary.

    Parameters
    ----------
    l : float
        droplet or plug length
    d : float
        channel diameter

    Returns
    -------
    v : float
        volume of the object

    Examples
    --------
    the example of usage

    >>> droplet_volume(250,250)
    """


def lauegroup_to_lattice(lauegroup):
    """Convert a Laue group representation (from pointless, e.g. I m m m)
    to something useful, like the implied crystal lattice (in this
    case, oI.)"""
    lauegroup_to_lattice = {'Ammm': 'oA', 'C2/m': 'mC', 'I2/m': 'mI',
        'Cmmm': 'oC', 'Fm-3': 'cF', 'Fm-3m': 'cF', 'Fmmm': 'oF', 'H-3':
        'hR', 'H-3m': 'hR', 'R-3:H': 'hR', 'R-3m:H': 'hR', 'R-3': 'hR',
        'R-3m': 'hR', 'I4/m': 'tI', 'I4/mmm': 'tI', 'Im-3': 'cI', 'Im-3m':
        'cI', 'Immm': 'oI', 'P-1': 'aP', 'P-3': 'hP', 'P-3m': 'hP', 'P2/m':
        'mP', 'P4/m': 'tP', 'P4/mmm': 'tP', 'P6/m': 'hP', 'P6/mmm': 'hP',
        'Pm-3': 'cP', 'Pm-3m': 'cP', 'Pmmm': 'oP'}
    updated_laue = ''
    for l in lauegroup.split():
        if not l == '1':
            updated_laue += l
    return lauegroup_to_lattice[updated_laue]


def _maybe_shift_opspec(args):
    """Moves opspec to flags if it looks like a flag assignment.
    """
    if args.opspec and '=' in args.opspec:
        args.flags = (args.opspec,) + args.flags
        args.opspec = None


def build_content_type(format, encoding='utf-8'):
    """
    Appends character encoding to the provided format if not already present.
    """
    if 'charset' in format:
        return format
    if format in ('application/json', 'text/javascript'):
        return format
    return '%s; charset=%s' % (format, encoding)


def datestamp():
    """Datetime of creation, last modification or deletion of the record.

        This can be used for selective harvesting.
        """


def write_video_cluster_metrics(metrics, add_summary_fn):
    """Writes average video cluster metrics using add_summary_fn."""
    add_summary_fn('CTR', metrics['click'] / metrics['impression'])
    if metrics['click'] > 0:
        add_summary_fn('AverageQuality', metrics['quality'] / metrics['click'])
    for k in metrics:
        prefix = 'cluster_watch_count_cluster_'
        if k.startswith(prefix):
            add_summary_fn('cluster_watch_count_frac/cluster_%s' % k[len(
                prefix):], metrics[k] / metrics['impression'])
    add_summary_fn('cluster_watch_count_frac/no_click', metrics[
        'cluster_watch_count_no_click'] / metrics['impression'])


def update(*args, **kwds):
    """od.update(E, **F) -> None.  Update od from dict/iterable E and F.

        If E is a dict instance, does:           for k in E: od[k] = E[k]
        If E has a .keys() method, does:         for k in E.keys(): od[k] = E[k]
        Or if E is an iterable of items, does:   for k, v in E: od[k] = v
        In either case, this is followed by:     for k, v in F.items(): od[k] = v

        """
    if len(args) > 2:
        raise TypeError(
            'update() takes at most 2 positional arguments (%d given)' % (
            len(args),))
    elif not args:
        raise TypeError('update() takes at least 1 argument (0 given)')
    self = args[0]
    other = ()
    if len(args) == 2:
        other = args[1]
    if isinstance(other, dict):
        for key in other:
            self[key] = other[key]
    elif hasattr(other, 'keys'):
        for key in other.keys():
            self[key] = other[key]
    else:
        for key, value in other:
            self[key] = value
    for key, value in kwds.items():
        self[key] = value


def to_bytes(s):
    """convert str to bytes for py 2/3 compat
    """
    if isinstance(s, bytes):
        return s
    return s.encode('utf-8', 'ignore')


@staticmethod
def validate_messages_for_send(message, app):
    """
        Makes sure that one or more messages have required fields for
        sending them by the sender.
        """
    if isinstance(message, (list, tuple, set)):
        result = True
        for m_one in message:
            result = result and m_one.valid_for_send(app)
    else:
        result = message.valid_for_send(app)
    return result


@classmethod
def apply_up_to(cls, revisions, cost_price, date):
    """Apply revision to cost price up to date
        revisions list is modified"""
    try:
        while True:
            revision = revisions.pop(0)
            if revision.date <= date:
                cost_price = revision.get_cost_price(cost_price)
            else:
                revisions.insert(0, revision)
                break
    except IndexError:
        pass
    return cost_price


@staticmethod
def format_file_size(size_of_file: int, suffix: str='B') ->str:
    """Humanize file size.
        :param size_of_file: Size of file in bytes
        :param suffix: Suffix which will be added to size format
        :type size_of_file: int
        :type suffix: str
        :return: Humanized file size
        :rtype: str
        """
    for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']:
        if abs(size_of_file) < 1024.0:
            return '{0}{1:s}{2:s}'.format(round(size_of_file, 3), unit, suffix)
        size_of_file /= 1024.0


@staticmethod
def _create_ports_per_numa(node, interfaces):
    """
        Create a dictionary or ports per numa node
        :param node: Node dictionary
        :param interfaces: All the interfaces to be used by vpp
        :type node: dict
        :type interfaces: dict
        :returns: The ports per numa dictionary
        :rtype: dict
        """
    ports_per_numa = {}
    for item in interfaces.items():
        i = item[1]
        if i['numa_node'] not in ports_per_numa:
            ports_per_numa[i['numa_node']] = {'interfaces': []}
            ports_per_numa[i['numa_node']]['interfaces'].append(i)
        else:
            ports_per_numa[i['numa_node']]['interfaces'].append(i)
    node['cpu']['ports_per_numa'] = ports_per_numa
    return ports_per_numa