def make_namedtuple_tf_ngram(unischema, ngram, *args, **kargs):
    """Creates a dictionary of timestep keys and namedtuple values from args and kargs.

    :param ngram: The ngram definition.
    :param args: args.
    :param kargs: kargs.
    :return: A dictionary of timestep keys and namedtuple values.
    """
    ngram_result = {}
    previous_args_end = 0
    for timestep in range(min(ngram.fields.keys()), max(ngram.fields.keys()
        ) + 1):
        current_field_names = ngram.get_field_names_at_timestep(timestep)
        new_schema = ngram.get_schema_at_timestep(schema=unischema,
            timestep=timestep)
        new_args_end = previous_args_end + len(current_field_names)
        args_timestep = args[previous_args_end:new_args_end]
        previous_args_end = new_args_end
        kargs_timestep = kargs[str(timestep)] if str(timestep) in kargs else {}
        ngram_result[timestep] = new_schema._get_namedtuple()(*
            args_timestep, **kargs_timestep)
    return ngram_result


@classmethod
def prettify(cls, my_dict):
    """
        Removes the name mangling caused by private
        instance attributes by removing the class name
        and the 3 underscores
        """
    my_items = my_dict.copy()
    for key in my_items.keys():
        if '_{}__'.format(my_dict['__class__']) in key:
            mangled = len(my_dict['__class__']) + 3
            new_key = key[mangled:]
            my_dict[new_key] = my_items[key]
            del my_dict[key]
    return my_dict


def update(resource_id: str, updated_path: str) ->None:
    """
        Update a resource with a new object. Preserves UUID and all other metadata (levels, etc.)

        :param r_id - the UUID of the object you'd like to update
        :param updated_path - path to the contents of the updated object.

        """
    pass


def any(name, alternates):
    """Return a named group pattern matching list of alternates."""
    return '(?P<%s>' % name + '|'.join(alternates) + ')'


@classmethod
def get_short_name(cls):
    """Return A short name for the workflow used to subdivide.

        The short name is used by CombinedWorkflows and the argparser to
        subdivide the commandline parameters avoiding the trouble of having
        subworkflows parameters with the same name.

        For example, a combined workflow with dti reconstruction and csd
        reconstruction might en up with the b0_threshold parameter. Using short
        names, we will have dti.b0_threshold and csd.b0_threshold available.

        Returns class name by default but it is strongly advised to set it to
        something shorter and easier to write on commandline.

        """
    return cls.__name__


def t_BIN(t):
    """(%[01]+)|([01]+[bB])"""
    if t.value[0] == '%':
        t.value = t.value[1:]
    else:
        t.value = t.value[:-1]
    t.value = int(t.value, 2)
    t.type = 'NUMBER'
    return t


@classmethod
def GetHasherClasses(cls, hasher_names=None):
    """Retrieves the registered hashers.

    Args:
      hasher_names (list[str]): names of the hashers to retrieve.

    Yields:
        tuple: containing:

         str: parser name
         type: next hasher class.
    """
    for hasher_name, hasher_class in iter(cls._hasher_classes.items()):
        if not hasher_names or hasher_name in hasher_names:
            yield hasher_name, hasher_class


def nodeid(node):
    """Given a node, tries to return a way to see where it was in the
    source text"""
    fname = 'UNKNOWN'
    line = 'UNKNOWN'
    try:
        if node.line:
            line = str(node.line)
    except:
        pass
    try:
        if node.source:
            fname = str(node.source)
    except:
        pass
    return 'near line %s in file %s' % (line, fname)


def o2d(obj):
    """
    把对象(支持单个对象、list、set)转换成字典
    :param obj: obj, list, set
    :return:
    """
    is_list = isinstance(obj, list)
    is_set = isinstance(obj, set)
    if is_list or is_set:
        obj_arr = []
        for o in obj:
            if o:
                dict1 = {}
                dict1.update(o.__dict__)
                obj_arr.append(dict1)
        return obj_arr
    else:
        dict1 = {}
        dict1.update(obj.__dict__)
        return dict1


def _bcc(recipient):
    """
    Returns a query item matching messages that have certain recipients in
    the bcc field.

    Args:
        recipient (str): The recipient in the bcc field to match.

    Returns:
        The query string.

    """
    return f'bcc:{recipient}'


def _py2ro(obj):
    """ Dummy function for py2ro.

    This function will convert Python objects into rpy2.robjects
    (ro) objects.
    """
    raise NotImplementedError(
        "Conversion 'py2ro' not defined for objects of type '%s'" % str(
        type(obj)))


def repeat_to_length(string_to_expand, length):
    """Repeat a string (partial) to a given length"""
    return (string_to_expand * int(length / len(string_to_expand) + 1))[:length
        ]


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 generate_url(query, num, start, recent, country_code):
    """(str, str, str) -> str
    A url in the required format is generated.
    """
    query = '+'.join(query.split())
    url = ('https://www.google.com/search?q=' + query + '&num=' + num +
        '&start=' + start)
    if recent in ['h', 'd', 'w', 'm', 'y']:
        url += '&tbs=qdr:' + recent
    if country_code is not None:
        url += '&gl=' + country_code
    return url


def is_ascii(s):
    """
    Check if a "bytes" contains all ascii characters
    :param s: the string to check
    :return: true if the string is entirely ascii characters
    """
    try:
        s.decode('ascii')
    except UnicodeDecodeError:
        return False
    return True


def timespan(counter, ago=False):
    """Return approximate timespan for a number of seconds."""
    counter = int(counter)
    if counter == 0:
        return 'just now'
    for unit, count in (('second', 60), ('minute', 60), ('hour', 24), (
        'day', 7), ('week', 4), ('month', 12), ('year', 0)):
        if count > 0 and counter >= count * 2:
            counter /= count
        else:
            break
    return '%d %s%s%s' % (counter, unit, 's' if counter > 1 else '', ' ago' if
        ago else '')


@classmethod
def exact(cls, amount):
    """
        Return a :class:`.Dimension` with an exact size. (min, max and
        preferred set to ``amount``).
        """
    return cls(min=amount, max=amount, preferred=amount)


def estimate():
    """Estimate running time of upgrade in seconds (optional)."""
    return 1


def put_char(memory):
    """Print current cell's ASCII character on stdout."""
    if memory.cell == ord('\n'):
        print()
    else:
        print(chr(memory.cell), end='')


@staticmethod
def _dump_condition_name(flow_name, idx):
    """Create condition name for a dump.

        :param flow_name: flow name
        :type flow_name: str
        :param idx: index of condition within the flow
        :type idx: int
        :return: condition function representation
        """
    assert idx >= 0
    return '_condition_{}_{}'.format(flow_name, idx)


@classmethod
def convert_lines(cls, lines):
    """multiple lines for one entry"""
    new_lines = list()
    for line in lines:
        if line[1] in ['MONTHLY', 'DAILY', 'HOURLY', 'WEEKEND']:
            new_lines.append(line)
        else:
            new_lines[-1] += line[1:]
    for line in new_lines:
        yield cls(*line)


def test(func):
    """
    :type func function
    mark function as test
    """
    func.__test__ = True
    func.desc = func.__doc__.strip()
    func.name = func.__name__
    return func


def _z_order_mask_set(swizzler_mask, c_blocks, x_blocks, y_blocks, z_blocks,
    c_mask, x_mask, y_mask, z_mask):
    """THIS FUNCTION WILL SWIZZLE AN ARRAY OF x, y, AND z OFFSETS
    TOGETHER IN z-ORDER STYLE. THE COLOR CHANNELS CAN ALSO BE SWIZZLED"""
    c_mask.extend([0] * c_blocks)
    i = c_blocks
    for size in range(max(x_blocks, y_blocks, z_blocks)):
        """WE CHECK IF THERE ARE STILL ANY BITS FOR EACH AXIS"""
        if x_blocks > size:
            x_mask.append(i)
            i += 1
        if y_blocks > size:
            y_mask.append(i)
            i += 1
        if z_blocks > size:
            z_mask.append(i)
            i += 1
        i -= 1


def beautifySize(size):
    """Returns a string representing the size in bytes in a more human readable way."""
    if size / 1073741824:
        return '%(size)0.2f GBytes' % {'size': float(size) / 1073741824.0}
    elif size / 1048576:
        return '%(size)0.2f MBytes' % {'size': float(size) / 1048576.0}
    elif size / 1024:
        return '%(size)0.2f KBytes' % {'size': float(size) / 1024.0}
    else:
        return '%(size)s Bytes' % {'size': size}


def convert_to_json_value(column_attrs, attr, value):
    """
    将资源的字段转换成json的格式输出
    :param column_attrs: inspect_.mapper.column_attrs
    :param attr:
    :param value:
    :return:
    """
    from sqlalchemy import Integer, DateTime, Date, Numeric, JSON
    try:
        type_ins = column_attrs[attr].columns[0].type
        if isinstance(type_ins, DateTime):
            return value.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(type_ins, Date):
            return str(value)
        elif isinstance(type_ins, Numeric):
            return value
        elif isinstance(type_ins, JSON):
            return value
    except:
        pass
    return value


def convert(celsius: float) ->float:
    """Convert Celsius to Fahrenheit"""
    fahrenheit = celsius * 1.8 + 32
    return fahrenheit


def move_up():
    """Move selected strips up a track if there’s room

    """
    pass


def compute_cutline(projection, only_one=False):
    """x0, x1 all included"""
    state = 'start'
    break_pos = []
    x0 = None
    x1 = None
    zero_count = 0
    for i, n in enumerate(projection):
        if state == 'start':
            if n == 0:
                state = 'zero'
            else:
                state = 'none-zero'
                x0 = i
        elif state == 'zero':
            if n != 0:
                state = 'none-zero'
                x0 = i
        elif state == 'none-zero':
            if n == 0:
                state = 'zero'
                x1 = i
                break_pos.append((x0, x1))
    if only_one and len(break_pos) > 1:
        break_pos = [(break_pos[0][0], break_pos[-1][1])]
    return break_pos


def get_upgraders(version, meta_type):
    """Return the registered upgrade_handlers of meta_type.
        """


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

        :param FileCommentsChangePolicyType val:
        :rtype: EventType
        """
    return cls('file_comments_change_policy', val)


@classmethod
def _get_fitting_schema(cls):
    """return the schema to validate input data
        should be overridden by subclass

        Returns
        -------
        dict

        """
    raise NotImplementedError


def poll(cache, conn, cursor):
    """
        Poll for invalidations since the last taken state of the viewer.

        Update the state of the viewer and update the global state maintained
        in this coordinator.

        This should be the first thing done after the *conn* is opened or
        a transaction has begun: in fact, to ensure that the global
        state never accidentally goes backwards, no snapshot of the database
        should have been taken with the connection yet. The queries we execute
        in this method should establish the snapshot for the first time.
        """


def subarray_specs(subarr):
    """
    Get the pixel information for a NIRISS subarray

    The returned dictionary defines the extent ('x' and 'y'),
    the starting pixel ('xloc' and 'yloc'), and the number
    of reference pixels at each subarray edge ('x1', 'x2',
    'y1', 'y2) as defined by SSB/DMS coordinates shown below:
        ___________________________________
       |               y2                  |
       |                                   |
       |                                   |
       | x1                             x2 |
       |                                   |
       |               y1                  |
       |___________________________________|
    (1,1)

    Parameters
    ----------
    subarr: str
        The subarray name

    Returns
    -------
    dict
        The dictionary of the specified subarray
        or a nested dictionary of all subarrays
    """
    pix = {'FULL': {'xloc': 1, 'x': 2048, 'x1': 4, 'x2': 4, 'yloc': 1, 'y':
        2048, 'y1': 4, 'y2': 4, 'tfrm': 10.737, 'tgrp': 10.737},
        'SUBSTRIP96': {'xloc': 1, 'x': 2048, 'x1': 4, 'x2': 4, 'yloc': 1803,
        'y': 96, 'y1': 0, 'y2': 0, 'tfrm': 2.213, 'tgrp': 2.213},
        'SUBSTRIP256': {'xloc': 1, 'x': 2048, 'x1': 4, 'x2': 4, 'yloc':
        1793, 'y': 256, 'y1': 0, 'y2': 4, 'tfrm': 5.491, 'tgrp': 5.491}}
    return pix[subarr]


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 getAxisTuple(axis):
    """Returns the tuple on axis with name <axis>, usually 'Axis0', 'Axis1', 'SlicerAxis'.
        If axis is a number return tuples on the <axis>-th axis."""


def unique_with_order_preserved(items):
    """
    Return a list of unique items in the list provided, preserving the order
    in which they are found.
    """
    new_items = []
    for item in items:
        if item not in new_items:
            new_items.append(item)
    return new_items


@staticmethod
def _reshape_sparse_matrix(frmdat, dim):
    """
        Return 3D full matrix representation from 2D representation

        If the 2D matrix has the shape (width*height,channels) then the
        returned matrix has shape (channel, y, x)
        """
    cs, ys, xs = dim
    return frmdat.T.toarray().reshape(cs, ys, xs)


def writeErzsolOut2cmd(cmd_file: str, erzsol_seismo_out: str):
    """
    writeErzsolOut2cmd(cmd_file, seisOut)

    This function writes the Path to the erzsol seimogram output to the
    cmd file.

    Parameters
    ----------
    cmd_file: str
        Path to cmd file
    erzsol_seismo_out: str
        Path/name of erzsol3 output file

    Returns
    -------
    Modified cmd_file including path to erzsol3 output file

    """
    file = open(cmd_file, 'r')
    lines = file.read().splitlines()
    file.close()
    lines[1] = (
        '"{}"                                  File for T-X seismogram output'
        .format(erzsol_seismo_out))
    file = open(cmd_file, 'w')
    file.write('\n'.join(lines))
    file.close()


def create_application(ApplicationName=None, ApplicationDescription=None,
    Inputs=None, Outputs=None, ApplicationCode=None):
    """
    Creates an Amazon Kinesis Analytics application. You can configure each application with one streaming source as input, application code to process the input, and up to five streaming destinations where you want Amazon Kinesis Analytics to write the output data from your application. For an overview, see How it Works .
    In the input configuration, you map the streaming source to an in-application stream, which you can think of as a constantly updating table. In the mapping, you must provide a schema for the in-application stream and map each data column in the in-application stream to a data element in the streaming source, with the option of renaming, casting and dropping columns as desired.
    Your application code is one or more SQL statements that read input data, transform it, and generate output. Your application code can create one or more SQL artifacts like SQL streams or pumps.
    In the output configuration, you can configure the application to write data from in-application streams created in your applications to up to five streaming destinations.
    To read data from your source stream or write data to destination streams, Amazon Kinesis Analytics needs your permissions. You grant these permissions by creating IAM roles. This operation requires permissions to perform the kinesisanalytics:CreateApplication action.
    For introductory exercises to create an Amazon Kinesis Analytics application, see Getting Started .
    See also: AWS API Documentation

    :example: response = client.create_application(
        ApplicationName='string',
        ApplicationDescription='string',
        Inputs=[
            {
                'NamePrefix': 'string',
                'KinesisStreamsInput': {
                    'ResourceARN': 'string',
                    'RoleARN': 'string'
                },
                'KinesisFirehoseInput': {
                    'ResourceARN': 'string',
                    'RoleARN': 'string'
                },
                'InputParallelism': {
                    'Count': 123
                },
                'InputSchema': {
                    'RecordFormat': {
                        'RecordFormatType': 'JSON'|'CSV',
                        'MappingParameters': {
                            'JSONMappingParameters': {
                                'RecordRowPath': 'string'
                            },
                            'CSVMappingParameters': {
                                'RecordRowDelimiter': 'string',
                                'RecordColumnDelimiter': 'string'
                            }
                        }
                    },
                    'RecordEncoding': 'string',
                    'RecordColumns': [
                        {
                            'Name': 'string',
                            'Mapping': 'string',
                            'SqlType': 'string'
                        },
                    ]
                }
            },
        ],
        Outputs=[
            {
                'Name': 'string',
                'KinesisStreamsOutput': {
                    'ResourceARN': 'string',
                    'RoleARN': 'string'
                },
                'KinesisFirehoseOutput': {
                    'ResourceARN': 'string',
                    'RoleARN': 'string'
                },
                'DestinationSchema': {
                    'RecordFormatType': 'JSON'|'CSV'
                }
            },
        ],
        ApplicationCode='string'
    )

    :type ApplicationName: string
    :param ApplicationName: [REQUIRED]
            Name of your Amazon Kinesis Analytics application (for example, sample-app ).

    :type ApplicationDescription: string
    :param ApplicationDescription: Summary description of the application.

    :type Inputs: list
    :param Inputs: Use this parameter to configure the application input.
            You can configure your application to receive input from a single streaming source. In this configuration, you map this streaming source to an in-application stream that is created. Your application code can then query the in-application stream like a table (you can think of it as a constantly updating table).
            For the streaming source, you provide its Amazon Resource Name (ARN) and format of data on the stream (for example, JSON, CSV, etc). You also must provide an IAM role that Amazon Kinesis Analytics can assume to read this stream on your behalf.
            To create the in-application stream, you need to specify a schema to transform your data into a schematized version used in SQL. In the schema, you provide the necessary mapping of the data elements in the streaming source to record columns in the in-app stream.
            (dict) --When you configure the application input, you specify the streaming source, the in-application stream name that is created, and the mapping between the two. For more information, see Configuring Application Input .
            NamePrefix (string) -- [REQUIRED]Name prefix to use when creating in-application stream. Suppose you specify a prefix 'MyInApplicationStream'. Kinesis Analytics will then create one or more (as per the InputParallelism count you specified) in-application streams with names 'MyInApplicationStream_001', 'MyInApplicationStream_002' and so on.
            KinesisStreamsInput (dict) --If the streaming source is an Amazon Kinesis stream, identifies the stream's Amazon Resource Name (ARN) and an IAM role that enables Amazon Kinesis Analytics to access the stream on your behalf.
            ResourceARN (string) -- [REQUIRED]ARN of the input Amazon Kinesis stream to read.
            RoleARN (string) -- [REQUIRED]ARN of the IAM role that Amazon Kinesis Analytics can assume to access the stream on your behalf. You need to grant the necessary permissions to this role.
            KinesisFirehoseInput (dict) --If the streaming source is an Amazon Kinesis Firehose delivery stream, identifies the Firehose delivery stream's ARN and an IAM role that enables Amazon Kinesis Analytics to access the stream on your behalf.
            ResourceARN (string) -- [REQUIRED]ARN of the input Firehose delivery stream.
            RoleARN (string) -- [REQUIRED]ARN of the IAM role that Amazon Kinesis Analytics can assume to access the stream on your behalf. You need to make sure the role has necessary permissions to access the stream.
            InputParallelism (dict) --Describes the number of in-application streams to create.
            Data from your source will be routed to these in-application input streams.
            (see Configuring Application Input .
            Count (integer) --Number of in-application streams to create. For more information, see Limits .
            InputSchema (dict) -- [REQUIRED]Describes the format of the data in the streaming source, and how each data element maps to corresponding columns in the in-application stream that is being created.
            Also used to describe the format of the reference data source.
            RecordFormat (dict) -- [REQUIRED]Specifies the format of the records on the streaming source.
            RecordFormatType (string) -- [REQUIRED]The type of record format.
            MappingParameters (dict) --When configuring application input at the time of creating or updating an application, provides additional mapping information specific to the record format (such as JSON, CSV, or record fields delimited by some delimiter) on the streaming source.
            JSONMappingParameters (dict) --Provides additional mapping information when JSON is the record format on the streaming source.
            RecordRowPath (string) -- [REQUIRED]Path to the top-level parent that contains the records.
            For example, consider the following JSON record:
            In the RecordRowPath , '$' refers to the root and path '$.vehicle.Model' refers to the specific 'Model' key in the JSON.
            CSVMappingParameters (dict) --Provides additional mapping information when the record format uses delimiters (for example, CSV).
            RecordRowDelimiter (string) -- [REQUIRED]Row delimiter. For example, in a CSV format, 'n' is the typical row delimiter.
            RecordColumnDelimiter (string) -- [REQUIRED]Column delimiter. For example, in a CSV format, a comma (',') is the typical column delimiter.

            RecordEncoding (string) --Specifies the encoding of the records in the streaming source. For example, UTF-8.
            RecordColumns (list) -- [REQUIRED]A list of RecordColumn objects.
            (dict) --Describes the mapping of each data element in the streaming source to the corresponding column in the in-application stream.
            Also used to describe the format of the reference data source.
            Name (string) -- [REQUIRED]Name of the column created in the in-application input stream or reference table.
            Mapping (string) --Reference to the data element in the streaming input of the reference data source.
            SqlType (string) -- [REQUIRED]Type of column created in the in-application input stream or reference table.

    :type Outputs: list
    :param Outputs: You can configure application output to write data from any of the in-application streams to up to five destinations.
            These destinations can be Amazon Kinesis streams, Amazon Kinesis Firehose delivery streams, or both.
            In the configuration, you specify the in-application stream name, the destination stream Amazon Resource Name (ARN), and the format to use when writing data. You must also provide an IAM role that Amazon Kinesis Analytics can assume to write to the destination stream on your behalf.
            In the output configuration, you also provide the output stream Amazon Resource Name (ARN) and the format of data in the stream (for example, JSON, CSV). You also must provide an IAM role that Amazon Kinesis Analytics can assume to write to this stream on your behalf.
            (dict) --Describes application output configuration in which you identify an in-application stream and a destination where you want the in-application stream data to be written. The destination can be an Amazon Kinesis stream or an Amazon Kinesis Firehose delivery stream.
            You can configure your application to write output to up to five destinations.
            Name (string) -- [REQUIRED]Name of the in-application stream.
            KinesisStreamsOutput (dict) --Identifies an Amazon Kinesis stream as the destination.
            ResourceARN (string) -- [REQUIRED]ARN of the destination Amazon Kinesis stream to write to.
            RoleARN (string) -- [REQUIRED]ARN of the IAM role that Amazon Kinesis Analytics can assume to write to the destination stream on your behalf. You need to grant the necessary permissions to this role.
            KinesisFirehoseOutput (dict) --Identifies an Amazon Kinesis Firehose delivery stream as the destination.
            ResourceARN (string) -- [REQUIRED]ARN of the destination Amazon Kinesis Firehose delivery stream to write to.
            RoleARN (string) -- [REQUIRED]ARN of the IAM role that Amazon Kinesis Analytics can assume to write to the destination stream on your behalf. You need to grant the necessary permissions to this role.
            DestinationSchema (dict) -- [REQUIRED]Describes the data format when records are written to the destination. For more information, see Configuring Application Output .
            RecordFormatType (string) --Specifies the format of the records on the output stream.

    :type ApplicationCode: string
    :param ApplicationCode: One or more SQL statements that read input data, transform it, and generate output. For example, you can write a SQL statement that reads input data and generates a running average of the number of advertisement clicks by vendor.
            You can also provide a series of SQL statements, where output of one statement can be used as the input for the next statement.
            Note that the application code must create the streams with names specified in the Outputs . For example, if your Outputs defines output streams named ExampleOutputStream1 and ExampleOutputStream2 , then your application code must create these streams.

    :rtype: dict
    :return: {
        'ApplicationSummary': {
            'ApplicationName': 'string',
            'ApplicationARN': 'string',
            'ApplicationStatus': 'DELETING'|'STARTING'|'STOPPING'|'READY'|'RUNNING'|'UPDATING'
        }
    }

    """
    pass


def window_bartlett(N):
    """Bartlett window (wrapping of numpy.bartlett) also known as Fejer

    :param int N: window length

    The Bartlett window is defined as

    .. math:: w(n) = \\frac{2}{N-1} \\left(
              \\frac{N-1}{2} - \\left|n - \\frac{N-1}{2}\\right|
              \\right)

    .. plot::
        :width: 80%
        :include-source:

        from spectrum import window_visu
        window_visu(64, 'bartlett')

    .. seealso:: numpy.bartlett, :func:`create_window`, :class:`Window`.
    """
    from numpy import bartlett
    return bartlett(N)


def _get_dims(data):
    """Get primary x-y dimensions of dataset

    """
    if 'XC' in data.dims:
        xdim = 'XC'
    elif 'XG' in data.dims:
        xdim = 'XG'
    else:
        xdim = 'x_km'
    if 'YC' in data.dims:
        ydim = 'YC'
    elif 'YG' in data.dims:
        ydim = 'YG'
    else:
        ydim = 'y_km'
    return ydim, xdim


def get_scaled_distance(distance_tpl):
    """Scale distances from 0 to 1.

    Given tuple of (seq length, Hamming distance)
    return proportion of different sites
    unless one of the sequences was missing.
    """
    eff_seq_len, distance = distance_tpl
    if distance != 'NaN':
        if eff_seq_len > 0 and distance > 0:
            scaled_distance = distance / eff_seq_len
        else:
            scaled_distance = 0
    else:
        scaled_distance = 'NaN'
    return scaled_distance


def return_segments(shape, break_points):
    """Break a shape into segments between stops using break_points.

    This function can use the `break_points` outputs from
    `find_segments`, and cuts the shape-sequence into pieces
    corresponding to each stop.
    """
    segs = []
    bp = 0
    bp2 = 0
    for i in range(len(break_points) - 1):
        bp = break_points[i] if break_points[i] is not None else bp2
        bp2 = break_points[i + 1] if break_points[i + 1] is not None else bp
        segs.append(shape[bp:bp2 + 1])
    segs.append([])
    return segs


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

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

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

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

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

    """
    pass


def get_letter_font_prop():
    """ get the properties of the subplot letters to add """
    from matplotlib.font_manager import FontProperties
    font = FontProperties()
    font.set_family('C:\\WINDOWS\\Fonts\\HelveticaNeue-CondensedBold.ttf')
    font.set_weight('heavy')
    font.set_size(10)
    font.letter_format = 'a'
    return font


@classmethod
def apply_filter_regexp(cls, queryset, options, value):
    """Apply `reexp` filter.

         Syntax:

            /endpoint/?field_name__regexp={regexp}

        Example:

            http://localhost:8000/api/users/?age__regexp=1[6-9]
            http://localhost:8000/api/users/?age__regexp=2.*

        :param queryset: Original queryset.
        :param options: Filter options.
        :param value: value to filter on.
        :type queryset: elasticsearch_dsl.search.Search
        :type options: dict
        :type value: str
        :return: Modified queryset.
        :rtype: elasticsearch_dsl.search.Search
        """
    return cls.apply_filter(queryset=queryset, options=options, args=[
        'regexp'], kwargs={options['field']: value})


def std(series, n):
    """
    标准差: 求series序列每n个周期的标准差

        注意: n为0的情况下, 或当n为有效值但当前的series序列元素个数不足n个, 函数返回 NaN 序列

    Args:
        series (pandas.Series): 数据序列

        n (int): 标准差的周期

    Returns:
        pandas.Series: 标准差序列

    Example::

        from tqsdk import TqApi, TqSim, tafunc

        api = TqApi(TqSim())
        klines = api.get_kline_serial("CFFEX.IF1908", 24 * 60 * 60)
        std = tafunc.std(klines.close, 5)  # 收盘价序列每5项计算一个标准差
        print(list(std))
    """
    m = series.rolling(n).std()
    return m


def rescale(a, v1):
    """Return `v1` multiplied by a scalar `a`, as a new vector."""
    x1, y1, z1 = v1
    return a * x1, a * y1, a * z1


def select_less():
    """Deselect keyframes on ends of selection islands

    """
    pass


def _get_digits(mantissa, n_digits, remove_trailing):
    """Get the digits for an int."""
    digitstr = (b'%d' % abs(mantissa)).rjust(n_digits, b'0')
    if remove_trailing:
        return digitstr.rstrip(b'0')
    else:
        return digitstr


def _getdate(idsect):
    """return yyyy,mm,dd,min,ss from section 1"""
    yyyy = idsect[5]
    mm = idsect[6]
    dd = idsect[7]
    hh = idsect[8]
    min = idsect[9]
    ss = idsect[10]
    return yyyy, mm, dd, hh, min, ss


def layer_prev():
    """Switch to editing action in animation layer below the current action in the NLA Stack

    """
    pass


def truncator(name, chars):
    """Shortens a name to chars and replaces '|' with a comma
    and gets rid of leading and trailing spaces"""
    name = ' '.join(name.split())
    truncated_name = name[:chars] + '...' if len(name) > chars else name
    return truncated_name.replace('|', ', ')


def clean_text(text, findings):
    """clean_text will remove phi findings from a text object
    :param text: the original text sent to the content.inspect DLP endpoint
    :param findings: the full response for the text.
    """
    if 'findings' in findings:
        for finding in findings['findings']:
            label = '**%s**' % finding['infoType']['name']
            text = text.replace(finding['quote'], label)
    return text


def _fd(f):
    """Get a filedescriptor from something which could be a file or an fd."""
    return f.fileno() if hasattr(f, 'fileno') else f


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

			# Return value

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


@classmethod
def create(cls, **kwargs: dict) ->'Meta.Model':
    """
        Shortcut for create method of model
        return: Model
        """
    return cls.Meta.model.objects.create(**kwargs)


def swidth(s):
    """terminal output width of string <s>

    For western scripts, this is just len(s), but for cjk glyphs, 2 cells are used.
    """
    return len(s)


def map_coords_to_xy(coords, dxy, x_min, y_min, copy=True):
    """
    The reverse of point_xy_to_map_coords.
    """
    if copy:
        coords1 = coords.copy().astype(float)
    else:
        coords1 = coords.astype(float)
    coords1[0] = coords1[0] * dxy + x_min
    coords1[1] = coords1[1] * dxy + y_min
    return coords1.T


def right_d_threshold_sequence(n, m):
    """
    Create a skewed threshold graph with a given number
    of vertices (n) and a given number of edges (m).

    The routine returns an unlabeled creation sequence
    for the threshold graph.

    FIXME: describe algorithm

    """
    cs = ['d'] + ['i'] * (n - 1)
    if m < n:
        cs[m] = 'd'
        return cs
    if m > n * (n - 1) / 2:
        raise ValueError('Too many edges for this many nodes.')
    ind = n - 1
    sum = n - 1
    while sum < m:
        cs[ind] = 'd'
        ind -= 1
        sum += ind
    ind = m - (sum - ind)
    cs[ind] = 'd'
    return cs


def get_image(hires=True, webformat=False):
    """Return image raw data. If ``hires`` is set to True, the
        original image data is returned. If ``webformat`` is set to
        True, the web version image raw data is returned.
        """


def makeresponsecacher(repo, proto, command, args, objencoderfn,
    redirecttargets, redirecthashes):
    """Construct a cacher for a cacheable command.

    Returns an ``iwireprotocolcommandcacher`` instance.

    Extensions can monkeypatch this function to provide custom caching
    backends.
    """
    return None


def cols_to_negative(df, columns):
    """Convert selected column values to negative and return dataframe.

    Args:
        df: Pandas dataframe.
        columns: List of columns to convert.

    Returns:
        Original dataframe with converted column data.
    """
    for col in columns:
        df[col] = df[col] * -1
    return df


def iterate_attributes(cls):
    """iterate all the keys and attributes associated
       with a class, without using getattr().

       Does not use getattr() so that class-sensitive
       descriptors (i.e. property.__get__()) are not called.

    """
    keys = dir(cls)
    for key in keys:
        for c in cls.__mro__:
            if key in c.__dict__:
                yield key, c.__dict__[key]
                break


@classmethod
def from_xml(cls, node):
    """
        Construct a DesignRules instance from an EAGLE XML ``<designrules>``
        node.
        """
    name = node.attrib.get('name')
    descriptions = {}
    for desc_node in node.xpath('description'):
        lang = desc_node.attrib['language']
        descriptions[lang] = desc_node.text
    params = {}
    for param_node in node.xpath('param'):
        params[param_node.attrib['name']] = param_node.attrib['value']
    return cls(name=name, descriptions=descriptions, params=params)


def updateEofZFinal(EofZ, EofX, L):
    """
	TODO: rewrite docstring
	"""
    EofWeight = EofX * L
    return EofZ + EofWeight, EofWeight


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


@classmethod
def get_classname(cls, my_instance):
    """
        Return the class name of my_instance, or "Instance.None".
        :param cls: Our class.
        :param my_instance: Instance to use.
        :return: Return the class name of my_instance, or "Instance.None" in case of error/None value.
        """
    if my_instance is None:
        return 'Instance.None'
    else:
        return my_instance.__class__.__name__


def get_tables():
    """
    Returns hardcoded list of tables which have ``tenant_id`` column.

    DB head can be changed. To prevent possible problems, when models will be
    updated, return hardcoded list of tables, up-to-date for this day.

    Output retrieved by using:

    >>> metadata = head.get_metadata()
    >>> all_tables = metadata.sorted_tables
    >>> tenant_tables = []
    >>> for table in all_tables:
    ...     for column in table.columns:
    ...         if column.name == 'tenant_id':
    ...             tenant_tables.append((table, column))

    """
    tables = ['vips', 'members', 'pools', 'healthmonitors', 'lbaas_members',
        'lbaas_healthmonitors', 'lbaas_loadbalancers', 'lbaas_pools',
        'lbaas_l7rules', 'lbaas_l7policies', 'lbaas_listeners']
    return tables


def select_word():
    """Select word under cursor

    """
    pass


def get_md_cell(source, metadata=None):
    """Markdown cell containing `source` with `metadata`."""
    return {'cell_type': 'markdown', 'metadata': {} if metadata is None else
        metadata, 'source': source}


def gen_pager_bootstrap_url(cat_slug, page_num, current):
    """
    pager for searching results.
    """
    pager = ''
    if page_num == 1 or page_num == 0:
        pager = ''
    elif page_num > 1:
        pager_mid, pager_pre, pager_next, pager_last, pager_home = ('', '',
            '', '', '')
        pager = '
'
        if current > 1:
            pager_home = (
                """

                首页
"""
                .format('', cat_slug, 1))
            pager_pre = (
                """

                上一页
"""
                .format('', cat_slug, current - 1))
        if current > 5:
            cur_num = current - 4
        else:
            cur_num = 1
        if page_num > 10 and cur_num < page_num - 10:
            show_num = cur_num + 10
        else:
            show_num = page_num + 1
        for num in range(cur_num, show_num):
            if num == current:
                checkstr = 'active'
            else:
                checkstr = ''
            tmp_str_df = (
                """

                  {2}
"""
                .format(checkstr, cat_slug, num))
            pager_mid += tmp_str_df
        if current < page_num:
            pager_next = (
                """

下一页
"""
                .format('', cat_slug, current + 1))
            pager_last = (
                """

末页
"""
                .format('', cat_slug, page_num))
        pager += pager_home + pager_pre + pager_mid + pager_next + pager_last
        pager += '
'
    else:
        pass
    return pager


def evalDisp(coeff, wl):
    """Return the pixel corresponding to wavelength wl.

    Notes
    -----
    The expression in the calstis code is::

      x = coeff[0] +
          coeff[1] * m * wl +
          coeff[2] * m**2 * wl**2 +
          coeff[3] * m +
          coeff[4] * wl +
          coeff[5] * m**2 * wl +
          coeff[6] * m * wl**2 +
          coeff[7] * m**3 * wl**3

    This version of the function to evaluate the dispersion relation
    assumes that the grating is first order, i.e. m = 1.  The dispersion
    coefficients give one-indexed pixel coordinates (reference pixels),
    but this function converts to zero-indexed pixels.

    Parameters
    -----------
    coeff : array_like object
        a list of eight elements containing the
        dispersion coefficients as read from a STIS _dsp.fits table

    wl : float or ndarray
        a single wavelength or an array (numarray) of wavelengths,
        in Angstroms

    Returns
    --------
    pix_number : float or ndarray
        the pixel number (or array of pixel numbers) corresponding
        to the input wavelength(s); note that these are zero indexed
    """
    c = [0.0, 0.0, 0.0, 0.0]
    c[0] = coeff[0] + coeff[3]
    c[1] = coeff[1] + coeff[4] + coeff[5]
    c[2] = coeff[2] + coeff[6]
    c[3] = coeff[7]
    x = c[3] * wl
    x = (c[2] + x) * wl
    x = (c[1] + x) * wl
    x = c[0] + x
    return x - 1.0


def _search_layer_backwards(model, condition):
    """
    Search for a layer in ``model``, backwards (starting from the output layer),
    checking if the layer is suitable with the callable ``condition``,
    """
    for layer in model.layers[::-1]:
        if condition(model, layer):
            return layer
    raise ValueError('Could not find a suitable target layer automatically.')


@classmethod
def items(cls):
    """
        All values for this enum
        :return: list of str

        """
    return [cls.OWM_API_POLLING]


@staticmethod
def _suffix_for(req):
    """
        For a requirement, return the 'extras_require' suffix for
        that requirement.
        """
    return ':' + str(req.marker) if req.marker else ''


def last(coll):
    """
    Return the last item in ``coll``, in linear time.
    """
    e = None
    for item in coll:
        e = item
    return e


def create_regex_string(inputseq):
    """ adds '-*' between each aa or nt/aa in a DNA or protein sequence, so that a particular
    aligned sequence can be identified via a regex search, even if it contains gaps
    inputseq : 'LQQLWNA'
    output   : 'L-*Q-*Q-*L-*W-*N-*A'
    """
    search_string = ''
    for letter in inputseq:
        letter_with_underscore = letter + '-*'
        search_string += letter_with_underscore
    return search_string[:-2]


def sorting_func(package_info):
    """
    A sorting order for (package, codec_class) tuples. Example ordering:

    application/coreapi+json  (highest priority)
    application/openapi+json  (lower as not a coreapi package built-in)
    application/json          (lower as more general subtype)
    text/*                    (lower as sub type is wildcard)
    */*                       (lowest as main type is wildcard)
    """
    package, codec_class = package_info
    media_type = getattr(codec_class, 'media_type')
    main_type, _, sub_type = media_type.partition('/')
    sub_type = sub_type.split(';')[0]
    is_builtin = package.dist.project_name == 'coreapi'
    return (main_type == '*', sub_type == '*', '+' not in sub_type, not
        is_builtin, media_type)


def voc_label_indices(colormap, colormap2label):
    """Assign label indices for Pascal VOC2012 Dataset."""
    colormap = colormap.astype('int32')
    idx = (colormap[:, :, (0)] * 256 + colormap[:, :, (1)]) * 256 + colormap[:,
        :, (2)]
    return colormap2label[idx]


def patch(patch_data):
    """JSON Patch implementation: https://tools.ietf.org/html/rfc6902"""


def _transform_spherical_displacement(inode, data, coord, xyz_cid0,
    cid_transform, is_global_cid):
    """helper method for transform_displacement_to_global"""
    xyzi = xyz_cid0[(inode), :]
    for itime in range(data.shape[0]):
        translation = data[(itime), (inode), :3]
        rotation = data[(itime), (inode), 3:]
        translation = coord.coord_to_xyz_array(translation)
        rotation = coord.coord_to_xyz_array(rotation)
        if is_global_cid:
            data[(itime), (inode), :3] = translation
            data[(itime), (inode), 3:] = rotation
            return
        data[(itime), (inode), :3] = translation.dot(cid_transform)
        data[(itime), (inode), 3:] = rotation.dot(cid_transform)


def split_artifact_filename(s):
    """
    split_artifact_filename('artifact::filename') -> ('artifact', 'filename')

    Raises ValueError if "::" is not found.
    """
    index = s.index('::')
    return s[:index], s[index + 2:]


@classmethod
def _from_toml(cls, filepath: str, **options) ->'Namespace':
    """Load a namespace from a TOML file."""
    import toml
    with open(filepath, mode='r', **options) as source:
        return cls(toml.load(source))


def qual(c):
    """Return full import path of a class."""
    return c.__module__ + '.' + c.__name__


def get_time_stamp() ->int:
    """Returns the system time stamp.

    :return:  The system time stamp.
    """
    pass


@classmethod
def _test_boundaries(cls, value):
    """Test if value is within defined range for this object."""
    return cls.value_min <= value <= cls.value_max


def to_unicode(s):
    """Return string as unicode.

    :param s: A string (bytestring or unicode string).
        If s is a bytestring, it is assumed that it is utf-8 encoded text"""
    if hasattr(s, 'decode'):
        return s.decode('utf-8')
    return s


def _reverse_annotations(old_record, new_record):
    """
    Copy annotations form old_record to new_record, reversing any
    lists / tuples / strings.
    """
    for k, v in list(old_record.annotations.items()):
        if isinstance(v, (tuple, list)) and len(v) == len(old_record):
            assert len(v) == len(old_record)
            v = v[::-1]
        new_record.annotations[k] = v
    for k, v in list(old_record.letter_annotations.items()):
        assert len(v) == len(old_record)
        new_record.letter_annotations[k] = v[::-1]


def lerp(a, b, t):
    """ Returns the linear interpolation between a and b at time t between 0.0-1.0.
        For example: lerp(100, 200, 0.5) => 150.
    """
    if t < 0.0:
        return a
    if t > 1.0:
        return b
    return a + (b - a) * t


@classmethod
def stop(cls):
    """Unschedules all watchdogs."""
    cls.observer.unschedule_all()
    cls.running = False


@staticmethod
def _check_label(label):
    """
        check that label doesn't contain chars forbidden by KeyURI spec
        """
    if label and ':' in label:
        raise ValueError("label may not contain ':'")


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 _prov_mapping(reg, etype):
    """Register RDF mapping for PROV-O entity types related to some entity type (prov:Agent).
    """
    reg.register_prefix('prov', 'http://www.w3.org/ns/prov#')
    reg.register_etype_equivalence('Activity', 'prov:Activity')
    reg.register_attribute_equivalence('Activity', 'type', 'prov:type')
    reg.register_attribute_equivalence('Activity', 'description', 'prov:label')
    reg.register_attribute_equivalence('Activity', 'start',
        'prov:startedAtTime')
    reg.register_attribute_equivalence('Activity', 'end', 'prov:endedAtTime')
    reg.register_relation_equivalence('Activity', 'associated_with',
        'CWUser', 'prov:wasAssociatedWith')
    reg.register_relation_equivalence('Activity', 'generated', etype,
        'prov:generated')
    reg.register_relation_equivalence('Activity', 'used', etype, 'prov:used')


def display_new_ruleset(name):
    """display function for creating a new ruleset"""
    print('Created new ruleset "%s"' % name)


def faces_select_linked_flat(sharpness: float=0.0174533):
    """Select linked faces by angle

    :param sharpness: Sharpness
    :type sharpness: float
    """
    pass


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

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

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

        """
    return cls(**kw)


@classmethod
def retrieve(cls, region, mpis):
    """
            Helper to get multiple mpis from a region
            Allows some nice declarativity below....
        """
    return tuple(cls.parse(region) for mpi in mpis)


def getRootTopicSpec():
    """If using kwargs protocol, then root topic takes no args."""
    argsDocs = {}
    reqdArgs = ()
    return argsDocs, reqdArgs


@classmethod
def get_type_name(cls):
    """Returns the class name unless the __type_name__ attribute is defined.
        """
    retval = cls.__type_name__
    if retval is None:
        retval = cls.__name__
    return retval


def drivers_delete_selected():
    """Delete drivers assigned to selected items

    """
    pass


@classmethod
def base_url(klass, *args, **kwargs):
    """
        Returns the URI for the organization.
        """
    return 'organizations'


def is_classifier(estimator):
    """Returns True if the given estimator is (probably) a classifier.
    Parameters
    ----------
    estimator : object
        Estimator object to test.
    Returns
    -------
    out : bool
        True if estimator is a classifier and False otherwise.
    """
    return getattr(estimator, '_estimator_type', None) == 'classifier'


def print_warning(msg):
    """Print warning message within jinja2 template.

    :param:
        The warning message as a string
    """
    import logging
    logger = logging.getLogger(__name__)
    logger.warn(msg)
    return ''


@conf
def gxx_modifier_aix(conf):
    """Configuration flags for executing g++ on AIX"""
    v = conf.env
    v.LINKFLAGS_cxxprogram = ['-Wl,-brtl']
    v.LINKFLAGS_cxxshlib = ['-shared', '-Wl,-brtl,-bexpfull']
    v.SHLIB_MARKER = []


def lists_differs(a: list, b: list) ->bool:
    """
    Checks if a and b differs
    :param a:
    :param b:
    :return:
    """
    a.sort()
    b.sort()
    return a != b


def remove_leading(needle, haystack):
    """Remove leading needle string (if exists).

    >>> remove_leading('Test', 'TestThisAndThat')
    'ThisAndThat'
    >>> remove_leading('Test', 'ArbitraryName')
    'ArbitraryName'
    """
    if haystack[:len(needle)] == needle:
        return haystack[len(needle):]
    return haystack


@classmethod
def fromcache(cls, cache, *args, **kwargs):
    """Initialize index using `cache` and update items.

        >>> cache = Cache('/tmp/diskcache/index')
        >>> _ = cache.clear()
        >>> index = Index.fromcache(cache, {'a': 1, 'b': 2, 'c': 3})
        >>> len(index)
        3
        >>> 'b' in index
        True
        >>> index['c']
        3

        :param Cache cache: cache to use
        :param args: mapping or sequence of items
        :param kwargs: mapping of items
        :return: initialized Index

        """
    self = cls.__new__(cls)
    self._cache = cache
    self.update(*args, **kwargs)
    return self


def fix_line_breaks(text):
    """
    Convert all line breaks to Unix style.

    This will convert the following sequences into the standard \\\\n
    line break:

        - CRLF (\\\\r\\\\n), used on Windows and in some communication
          protocols
        - CR (\\\\r), once used on Mac OS Classic, and now kept alive
          by misguided software such as Microsoft Office for Mac
        - LINE SEPARATOR (\\\\u2028) and PARAGRAPH SEPARATOR (\\\\u2029),
          defined by Unicode and used to sow confusion and discord
        - NEXT LINE (\\\\x85), a C1 control character that is certainly
          not what you meant

    The NEXT LINE character is a bit of an odd case, because it
    usually won't show up if `fix_encoding` is also being run.
    \\\\x85 is very common mojibake for \\\\u2026, HORIZONTAL ELLIPSIS.

        >>> print(fix_line_breaks(
        ...     "This string is made of two things:\\u2029"
        ...     "1. Unicode\\u2028"
        ...     "2. Spite"
        ... ))
        This string is made of two things:
        1. Unicode
        2. Spite

    For further testing and examples, let's define a function to make sure
    we can see the control characters in their escaped form:

        >>> def eprint(text):
        ...     print(text.encode('unicode-escape').decode('ascii'))

        >>> eprint(fix_line_breaks("Content-type: text/plain\\r\\n\\r\\nHi."))
        Content-type: text/plain\\n\\nHi.

        >>> eprint(fix_line_breaks("This is how Microsoft \\r trolls Mac users"))
        This is how Microsoft \\n trolls Mac users

        >>> eprint(fix_line_breaks("What is this \\x85 I don't even"))
        What is this \\n I don't even
    """
    return text.replace('\r\n', '\n').replace('\r', '\n').replace('\u2028',
        '\n').replace('\u2029', '\n').replace('\x85', '\n')


def sub_pixel_fractions(x, y):
    """
    Makes a list of pixel coordinates and weights to reflect sub-pixel shifts
    A point source which isn't centred on a pixel can be modelled by a centred
    PSF convolved with a shifted delta function. A fraction of the delta
    function in moved into each of the adjoining pixels. For example, a star
    at ``(x,y)=(0.2, 0.2)`` would be represented by a following pixel weights::
       ---------------
       | 0.16 | 0.04 |
       ---------------
       | 0.64 | 0.16 |
       ---------------
    where (0,0) is the centre of the bottom-left pixel
    Given (x,y) pixel coordinates, this function returns the fractions of flux
    that should go into the surrounding pixels, as well as the coordinates of
    those neighbouring pixels.
    Parameters
    ----------
    x, y : float
    Returns
    -------
    x_pix, y_pix, fracs : list of (int, int, float)
       The x and y pixel coordinates and their corresponding flux fraction
    """
    x0, dx = divmod(x, 1)
    y0, dy = divmod(y, 1)
    xi0 = int(x0)
    xi1 = xi0 + bool(dx)
    yi0 = int(y0)
    yi1 = yi0 + bool(dy)
    f00 = (1.0 - dx) * (1.0 - dy)
    f01 = (1.0 - dx) * dy
    f10 = dx * (1 - dy)
    f11 = dx * dy
    x_pix = [xi0, xi1, xi0, xi1]
    y_pix = [yi0, yi0, yi1, yi1]
    fracs = [f00, f10, f01, f11]
    return x_pix, y_pix, fracs


def units_to_msec(units, resolution):
    """Convert BLE specific units to milliseconds."""
    time_ms = units * float(resolution) / 1000
    return time_ms


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

    Like 'git describe --tags --dirty --always'.

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


def printRho(SGLaue, rho, rhoMax):
    """default doc string

    :param type name: description

    :returns: type name: description

    """
    dim = len(rho.shape)
    if dim == 2:
        ix, jy = rho.shape
        for j in range(jy):
            line = ''
            if SGLaue in ['3', '3m1', '31m', '6/m', '6/mmm']:
                line += (jy - j) * '  '
            for i in range(ix):
                r = int(100 * rho[i, j] / rhoMax)
                line += '%4d' % r
            print(line + '\n')
    else:
        ix, jy, kz = rho.shape
        for k in range(kz):
            print('k = %d' % k)
            for j in range(jy):
                line = ''
                if SGLaue in ['3', '3m1', '31m', '6/m', '6/mmm']:
                    line += (jy - j) * '  '
                for i in range(ix):
                    r = int(100 * rho[i, j, k] / rhoMax)
                    line += '%4d' % r
                print(line + '\n')


def unsqueeze(data, axis, oldshape):
    """
    Unsqueeze a collapsed array.

    Parameters
    ----------
    data : ndarray
        The data to unsqueeze.
    axis : int
        The axis to unsqueeze.
    oldshape : tuple[int]
        The original shape before the squeeze or reduce operation.

    Returns
    -------
    ndarray
        The unsqueezed array.

    Examples
    --------
    >>> from numpy import mean
    >>> from numpy.random import standard_normal
    >>> x = standard_normal((3,4,5))
    >>> m = mean(x, axis=1)
    >>> m.shape
    (3, 5)
    >>> m = unsqueeze(m, 1, x.shape)
    >>> m.shape
    (3, 1, 5)
    >>>
    """
    newshape = list(oldshape)
    newshape[axis] = 1
    return data.reshape(newshape)


def chunks(l, n):
    """
    Yield successive n-sized chunks from l.
    """
    for i in range(0, len(l), n):
        yield l[i:i + n]


@classmethod
def __initialize_states(cls):
    """ Initializes a class-scoped states dictionary to store named
            states.
        """
    if not hasattr(cls, '_SharedState__states'):
        cls.__states = {}


def bytes_to_int_py3(byte_arr):
    """transform multi-byte values into integers, python3 version"""
    return int.from_bytes(byte_arr, byteorder='little', signed=False)


def SSMT2text(Opr):
    """From superspace group matrix/translation operator returns text version"""
    XYZS = 'x', 'y', 'z', 't'
    TRA = ('   ', 'ERR', '1/6', '1/4', '1/3', 'ERR', '1/2', 'ERR', '2/3',
        '3/4', '5/6', 'ERR')
    Fld = ''
    M, T = Opr
    for j in range(4):
        IJ = ''
        for k in range(4):
            txt = str(int(round(M[j][k])))
            txt = txt.replace('1', XYZS[k]).replace('0', '')
            if '2' in txt:
                txt += XYZS[k]
            if IJ and M[j][k] > 0:
                IJ += '+' + txt
            else:
                IJ += txt
        IK = int(round(T[j] * 12)) % 12
        if IK:
            if not IJ:
                break
            if IJ[0] == '-':
                Fld += (TRA[IK] + IJ).rjust(8)
            else:
                Fld += (TRA[IK] + '+' + IJ).rjust(8)
        else:
            Fld += IJ.rjust(8)
        if j != 3:
            Fld += ', '
    return Fld


def accumulate(l, sumval=0):
    """Return cumulative sums of @l, starting at @sumval."""
    for el in l:
        yield sumval
        sumval += el


@classmethod
def getRecord(cls, node):
    """ fetches record name or query from datasource node

        :param node: datasource node
        :type node: :class:`lxml.etree.Element`
        :returns: record name or query
        :rtype: :obj:`str`
        """
    withRec = ['CLIENT', 'TANGO']
    withQuery = ['DB']
    if node.tag == 'datasource':
        dsource = node
    else:
        dsource = node.find('.//datasource')
    dstype = dsource.attrib['type']
    res = ''
    if dstype and dstype in withRec:
        host = None
        port = None
        dname = None
        rname = None
        member = None
        device = dsource.findall('device')
        if device is not None and len(device) > 0:
            host = device[0].get('hostname')
            port = device[0].get('port')
            dname = device[0].get('name')
            member = device[0].get('member')
        surfix = ''
        prefix = ''
        if member or member != 'attribute':
            if member == 'property':
                prefix = '@'
            elif member == 'command':
                surfix = '()'
        record = dsource.findall('record')
        if record is not None and len(record) > 0:
            rname = record[0].get('name')
            if rname:
                if dname:
                    if host:
                        if not port:
                            port = '10000'
                        res = '%s:%s/%s/%s%s%s' % (host, port, dname,
                            prefix, rname, surfix)
                    else:
                        res = '%s/%s%s%s' % (dname, prefix, rname, surfix)
                else:
                    res = rname
            return res
    elif dstype and dstype in withQuery:
        query = dsource.find('.//query')
        if len(query) and query.strip():
            return query.strip() or ''
    return res


def database_url(url):
    """Parse a string as a Heroku-style database URL."""
    if url.startswith('postgres://'):
        url = 'postgresql+psycopg2://' + url[len('postgres://'):]
    return url


def downgrade():
    """ Downgrade from 2 to 1 """


@staticmethod
def _get_resource_path(resource_type, resource_id=None, relationship=None):
    """
        Build and return API path.
        """
    path = '/' + resource_type
    if resource_id is not None:
        path += '/' + str(resource_id)
    if relationship is not None:
        path += '/relationships/' + relationship
    return path


def atse_init():
    """ only for compat reasons """


def id(response):
    """ Returns a generated id for the current response object.
        This can be helpful when specified as a `--label` argument.
       :param response: A :class:`wex.response.Response` object.
    """
    return response.id


@staticmethod
def _normalize_compare_config(diff):
    """Filter out strings that should not show up in the diff."""
    ignore_strings = ['Contextual Config Diffs', 'No changes were found',
        'file prompt quiet', 'ntp clock-period']
    new_list = []
    for line in diff.splitlines():
        for ignore in ignore_strings:
            if ignore in line:
                break
        else:
            new_list.append(line)
    return '\n'.join(new_list)


def get_calculations():
    """Get a list of LNG Ageing calculations

     # noqa: E501

    :rtype: List[Calculation]
    """
    return 'do some magic!'


def url_is_secure(url):
    """Check if given url is secure (https).

	:param url: url to check
	:type url: str
	:return: True if url is secure

	"""
    return url.startswith('https')


def has_perm(action):
    """Return True if permission for `action` is granted."""
    return False


def _normalise_whitespace(s):
    """Normalise the whitespace in a bytestring to spaces."""
    if s is None:
        return None
    return b' '.join(s.split())


def region_2d_to_vector_3d(region: 'bpy.types.Region', rv3d:
    'bpy.types.RegionView3D', coord) ->'mathutils.Vector':
    """Return a direction vector from the viewport at the specific 2d region coordinate.

    :param region: region of the 3D viewport, typically bpy.context.region.
    :type region: 'bpy.types.Region'
    :param rv3d: 3D region data, typically bpy.context.space_data.region_3d.
    :type rv3d: 'bpy.types.RegionView3D'
    :param coord: 2d coordinates relative to the region: (event.mouse_region_x, event.mouse_region_y) for example.
    :return:  normalized 3d vector.
    """
    pass


def get_to_binary(decimal_number, length=32):
    """ Given a decimal number, returns a string bitfield of length = len """
    bitstr = ''.join(map(lambda y: str(decimal_number >> y & 1), range(
        length - 1, -1, -1)))
    return bitstr


def _yield_finished_futures(fs, waiter, ref_collect):
    """
    Iterate on the list *fs*, yielding finished futures one by one in
    reverse order.
    Before yielding a future, *waiter* is removed from its waiters
    and the future is removed from each set in the collection of sets
    *ref_collect*.

    The aim of this function is to avoid keeping stale references after
    the future is yielded and before the iterator resumes.
    """
    while fs:
        f = fs[-1]
        for futures_set in ref_collect:
            futures_set.remove(f)
        with f._condition:
            f._waiters.remove(waiter)
        del f
        yield fs.pop()


def stripped_string_concat(str1, str2):
    """Concatenates passed strings and truncates spaces in the result.

    :param str1: First string
    :type str1: str
    :param str2: Second string
    :type str2: str
    :return: A string with truncated spaces
    :rtype: str
    """
    return f'{str1} {str2}'.strip()


def nub(iterable):
    """
    nub :: [a] -> [a]
    O(n^2). The nub function removes duplicate elements from a list. In particular, it keeps only the first occurrence of each element. (The name nub means `essence'.) It is a special case of nubBy, which allows the programmer to supply their own equality test.
    """
    rs = []
    for x in iterable:
        if not x in rs:
            rs.append(x)
    return rs


def set_aes_src(lucid, srcval):
    """Call lucid8824.set_aes_src"""
    lucid.set_aes_src(srcval)


def strip_blank_lines(l):
    """Remove leading and trailing blank lines from a list of lines"""
    while l and not l[0].strip():
        del l[0]
    while l and not l[-1].strip():
        del l[-1]
    return l


def groupfinder(userid, request):
    """Fetch principals from permission backend for the specified `userid`.

    This is plugged by default using the ``multiauth.groupfinder`` setting.
    """
    backend = getattr(request.registry, 'permission', None)
    if not backend:
        return []
    if request.prefixed_userid:
        userid = request.prefixed_userid
    reify_key = userid + '_principals'
    if reify_key not in request.bound_data:
        principals = backend.user_principals(userid)
        request.bound_data[reify_key] = principals
    return request.bound_data[reify_key]


def whitespace_tokenize(text):
    """Runs basic whitespace cleaning and splitting on a piece of text."""
    text = text.strip()
    if not text:
        return []
    tokens = text.split()
    return tokens


def parse_covmetrics(covmetrics_file, stats):
    """
    Parse covmetrics report and write content to ``stats``.

    Covmetrics report is a one-line file with three colunmns::

        mean_coverage   mean_coverage*0.2   coverage_uniformity

    """
    with open(covmetrics_file) as handle:
        cov_data = handle.readline().strip().split('\t')
        stats['mean_coverage'] = float(cov_data[0])
        stats['mean_coverage_20'] = float(cov_data[1])
        stats['coverage_uniformity'] = float(cov_data[2]) / 100


def return_pyvpc_objects_string(pyvpc_objects):
    """
    Documentation https://github.com/astanin/python-tabulate
    :param pyvpc_objects: list of PyVPCBlock
    :return: string
    """
    from tabulate import tabulate
    table = []
    for pyvpc_object in pyvpc_objects:
        table.append([pyvpc_object.get_start_address(), pyvpc_object.
            get_end_address(), pyvpc_object.get_num_addresses(),
            pyvpc_object.get_network_prefix(), pyvpc_object.block_available,
            pyvpc_object.get_id(), pyvpc_object.get_name()])
    headers = ['Lowest IP', 'Upper IP', 'Num of Addr', 'Prefix',
        'Available', 'ID', 'Name']
    return tabulate(table, headers, tablefmt='github')


def to_netcdf(volume, filename, timestep=None):
    """ Save XRadVolume to netcdf compliant file.

    Parameters
    ----------
    volume : XRadVolume object
    filename : str
        output filename
    timestep : int, slice
        timestep/slice of wanted volume
    """
    volume.root.load()
    root = volume.root.copy(deep=True)
    root.attrs['Conventions'] = 'Cf/Radial'
    root.attrs['version'] = '2.0'
    root.to_netcdf(filename, mode='w', group='/')
    for idx, key in enumerate(root.sweep_group_name.values):
        swp = volume[idx].data.isel(time=timestep)
        swp.to_netcdf(filename, mode='a', group=key)


def nosym(calc, val):
    """https://www.quantum-espresso.org/Doc/INPUT_PW.html#nosym
    """
    assert isinstance(val, bool)


@classmethod
def from_httplib(cls, message):
    """Read headers from a Python 2 httplib message object."""
    headers = []
    for line in message.headers:
        if line.startswith((' ', '\t')):
            key, value = headers[-1]
            headers[-1] = key, value + '\r\n' + line.rstrip()
            continue
        key, value = line.split(':', 1)
        headers.append((key, value.strip()))
    return cls(headers)


def query_yes_no(question, default='no'):
    """
    (From https://gist.github.com/hrouault/1358474)
    Ask a yes/no question via raw_input() and return their answer.

    "question" is a string that is presented to the user.
    "default" is the presumed answer if the user just hits <Enter>.
        It must be "yes" (the default), "no" or None (meaning
        an answer is required of the user).

    The "answer" return value is True for "yes" or False for "no".
    """
    valid = {'yes': True, 'y': True, 'ye': True, 'no': False, 'n': False}
    if default is None:
        prompt = ' [y/n] '
    elif default == 'yes':
        prompt = ' [Y/n] '
    elif default == 'no':
        prompt = ' [y/N] '
    else:
        raise ValueError("invalid default answer: '%s'" % default)
    while True:
        print(question + prompt)
        choice = input().lower()
        if default and choice == '':
            return valid[default]
        elif choice in valid:
            return valid[choice]
        else:
            print("Please respond with 'yes' or 'no' (or 'y' or 'n').\n")


def get_eval_metric_values(events):
    """Filter TensorBoard events to only include those for eval metrics.

  Args:
    events: dict of list of (step, value) tuples where keys are tags.

  Returns:
    Dict where key is task_name/metric_name and value is (step, value) tuple.
  """
    eval_values = {}
    for tag, event_values in events.items():
        if tag.startswith('eval'):
            _, task_name, metric_name = tag.split('/')
            eval_values['{}/{}'.format(task_name, metric_name)] = event_values
    return eval_values


def split_after(iterable, pred, maxsplit=-1):
    """Yield lists of items from *iterable*, where each list ends with an
    item where callable *pred* returns ``True``:

        >>> list(split_after('one1two2', lambda s: s.isdigit()))
        [['o', 'n', 'e', '1'], ['t', 'w', 'o', '2']]

        >>> list(split_after(range(10), lambda n: n % 3 == 0))
        [[0], [1, 2, 3], [4, 5, 6], [7, 8, 9]]

    At most *maxsplit* splits are done. If *maxsplit* is not specified or -1,
    then there is no limit on the number of splits:

        >>> list(split_after(range(10), lambda n: n % 3 == 0, maxsplit=2))
        [[0], [1, 2, 3], [4, 5, 6, 7, 8, 9]]

    """
    if maxsplit == 0:
        yield list(iterable)
        return
    buf = []
    it = iter(iterable)
    for item in it:
        buf.append(item)
        if pred(item) and buf:
            yield buf
            if maxsplit == 1:
                yield list(it)
                return
            buf = []
            maxsplit -= 1
    if buf:
        yield buf


def fly():
    """Interactively fly around the scene

    """
    pass


@classmethod
def allowed_to_disconnect(cls, user, backend_name, association_id=None):
    """Return if it's safe to disconnect the social account for the
        given user"""
    raise NotImplementedError('Implement in subclass')


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


def reduce_reflex_angle_deg(angle):
    """ Given an angle in degrees, normalises in [-179, 180] """
    new_angle = angle % 360
    if new_angle > 180:
        new_angle -= 360
    return new_angle


def validate_format(*_arg):
    """
    This method can be overridden with format validation logic.
    """
    return True


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

        :param MemberAccessLevelResult val:
        :rtype: RemoveMemberJobStatus
        """
    return cls('complete', val)


def scale_scores(scores):
    """Scale scores in-place."""
    scores[...] /= scores[...].max()


def __click(perform_dict):
    """Click on element."""
    perform_dict.get('element').click()
    return True, None


def add_occurrences(events, count):
    """
    Adds an occurrence key to the event object w/ a list of occurrences
    and adds a popover (for use with twitter bootstrap).
    The occurrence is added so that each event can be aware of what
    day(s) it occurs in the month.
    """
    for day in count:
        for item in count[day]:
            for event in events:
                if event.pk == item[1]:
                    try:
                        event.occurrence.append(day)
                    except AttributeError:
                        event.occurrence = []
                        event.occurrence.append(day)


def relative_to(path, target):
    """Return the relative path of the input to the target path.

    For example:
        path = /a/b/d/c/Y
        target = /a/b/c/X
    Then this function will return:
        '../../c/X'

    Args:
        path (pathlib.Path):
        target (pathlib.Path):

    Returns:
        str: the path of 'path' relative to 'target'.
    """
    for n, p in enumerate(path.parents):
        try:
            q = target.relative_to(p)
        except ValueError:
            continue
        return '../' * n + str(q)
    return str(target)


def asDict():
    """Return the state expressed as an attribute dictionary.

        The state should combine the attributes and items somehow, to present
        a complete picture for the purpose of comparing these dictionaries
        while looking for changes.
        """


def maxBit(int_val):
    """Return power of 2 for highest bit set for integer"""
    length = 0
    count = 0
    while int_val:
        count += int_val & 1
        length += 1
        int_val >>= 1
    return length - 1


@staticmethod
def println(*args):
    """
        Print the specified arguments to the screen, including an appended newline character.

        Args:
            *args: Variable length argument list.
        """
    print(*args)


def get_default_chunksize(length, num_splits):
    """Creates the most equal chunksize possible based on length and number of splits.

    Args:
        length: The integer length to split (number of rows/columns).
        num_splits: The integer number of splits.

    Returns:
        An integer chunksize.
    """
    return (length // num_splits if length % num_splits == 0 else length //
        num_splits + 1)


def get_pairs(word):
    """Return set of symbol pairs in a word.

    Word is represented as tuple of symbols (symbols being variable-length strings).
    """
    pairs = set()
    prev_char = word[0]
    for char in word[1:]:
        pairs.add((prev_char, char))
        prev_char = char
    return pairs


def pytest_bdd_before_step_call(request, feature, scenario, step, step_func,
    step_func_args):
    """Called before step function is executed."""


def make_key(*criteria):
    """Make a string key out of many criteria."""
    parts = []
    for criterion in criteria:
        if criterion is None:
            continue
        criterion = str(criterion)
        criterion = criterion.replace(':', '#')
        parts.append(criterion)
    return ':'.join(parts)


def identify_max_gear(speed_velocity_ratios):
    """
    Identifies the maximum gear of the gear box [-].

    :param speed_velocity_ratios:
        Speed velocity ratios of the gear box [h*RPM/km].
    :type speed_velocity_ratios: dict[int | float]

    :return:
        Maximum gear of the gear box [-].
    :rtype: int
    """
    return int(max(speed_velocity_ratios))


def _check_mod_11_2(numeric_string):
    """
    Validate numeric_string for its MOD-11-2 checksum.

    Any "-" in the numeric_string are ignored.

    The last digit of numeric_string is assumed to be the checksum, 0-9 or X.

    See ISO/IEC 7064:2003 and
    https://support.orcid.org/knowledgebase/articles/116780-structure-of-the-orcid-identifier
    """
    nums = numeric_string.replace('-', '')
    total = 0
    for num in nums[:-1]:
        digit = int(num)
        total = (total + digit) * 2
    remainder = total % 11
    result = (12 - remainder) % 11
    if result == 10:
        checkdigit = 'X'
    else:
        checkdigit = str(result)
    return nums[-1].upper() == checkdigit


@staticmethod
def fromconfig(repo):
    """current value of the variant in the configuration"""
    raise NotImplementedError()


def select_next():
    """Select control points following already selected ones along the curves

    """
    pass


def x2cx(x, e):
    """Transform from *x* value to column *x* index value, using the
    *e.css('cw')* (column width) as column measure."""
    gw = e.gw
    cw = e.css('cw', 0)
    if cw + gw:
        return (x - e.parent.pl) / (cw + gw)
    return 0


def assign_valence(mol):
    """Assign pi electron and hydrogens"""
    for u, v, bond in mol.bonds_iter():
        if bond.order == 2:
            mol.atom(u).pi = 1
            mol.atom(v).pi = 1
            if mol.atom(u).symbol == 'O' and not mol.atom(u).charge:
                mol.atom(v).carbonyl_C = 1
            if mol.atom(v).symbol == 'O' and not mol.atom(v).charge:
                mol.atom(u).carbonyl_C = 1
        elif bond.order == 3:
            mol.atom(u).pi = mol.atom(v).pi = 2
    max_nbr = {'C': 4, 'Si': 4, 'N': 3, 'P': 3, 'As': 3, 'O': 2, 'S': 2,
        'Se': 2, 'F': 1, 'Cl': 1, 'Br': 1, 'I': 1}
    for i, nbrs in mol.neighbors_iter():
        atom = mol.atom(i)
        if len(nbrs) == 2 and all(bond.order == 2 for bond in nbrs.values()):
            atom.pi = 2
        if atom.symbol in max_nbr:
            h_cnt = max_nbr[atom.symbol] - len(nbrs) - atom.pi + atom.charge
            if h_cnt > 0:
                mol.atom(i).add_hydrogen(h_cnt)
    mol.descriptors.add('Valence')


def inch(cm: float=None, mm: float=None) ->float:
    """ Either cm or mm to inch """
    if cm is not None and mm is None:
        return cm / 2.54
    elif mm is not None and cm is None:
        return mm / 10 / 2.54
    else:
        raise ValueError('Either cm or mm should be provided.')


def generateDeviceNames(prefix, first, last, minimal=False):
    """ generates device names

    :param prefix: device name prefix
    :type prefix: :obj:`str`
    :param first: first device index
    :type first: :obj:`int`
    :param last: last device index
    :type last: :obj:`int`
    :returns: device names
    :rtype: :obj:`list` <:obj:`str`>
    """
    names = []
    if prefix.strip():
        for i in range(first, last + 1):
            if not minimal:
                names.append(prefix + ('0' if len(str(i)) == 1 else '') +
                    str(i))
            else:
                names.append(prefix + str(i))
    return names


def dequote(s):
    """ Remove outer quotes from string

    If a string has single or double quotes around it, remove them.
    todo: Make sure the pair of quotes match.
    If a matching pair of quotes is not found, return the string unchanged.
    """
    if s.startswith(("'", '"', '<')):
        return s[1:-1]
    return s


def asint(val, default=None):
    """Convert string representation of integer value to integer type."""
    try:
        v = int(val)
    except:
        v = default
    return v


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


def decode_bytes_array(arr):
    """Convert an array of bytes objects to an array of Unicode strings."""
    if arr.dtype.hasobject and type(arr.item(0)) is bytes:
        return arr.astype(str)
    else:
        return arr


@classmethod
def get(cls, channel: int):
    """
        Get the attribute for an input number.

        :param channel: the channel number (1..4)
        :return: the enum for the desired channel.
        """
    return getattr(cls, 'input_{}'.format(channel))


def getToplevelMessages(start=None, end=None, recent_first=True, sort_on=
    'date', filter_on='date', reversed=False):
    """Get a list of proxies for all messages that are at the top of a
           thread in order by date, optionally restricted to a specific date
           range and/or sorted by or filtered on the most recently responded
           to message using the sort_on and filter_on arguments.

           The recent_first argument is deprecated and should no longer be used.
           It will be removed in a later version of the code."""


def transfer_syntax(UID=None, description=None):
    """ Transfer Syntax UID <-> Description lookup.

    :param UID: Transfer Syntax UID, returns description
    :param description: Take the description of a transfer syntax and return its UID
    """
    transfer_syntax = {'1.2.840.10008.1.2':
        'Implicit VR Endian: Default Transfer Syntax for DICOM',
        '1.2.840.10008.1.2.1': 'Explicit VR Little Endian',
        '1.2.840.10008.1.2.1.99': 'Deflated Explicit VR Big Endian',
        '1.2.840.10008.1.2.2': 'Explicit VR Big Endian',
        '1.2.840.10008.1.2.4.50':
        'JPEG Baseline (Process 1): Default Transfer Syntax for Lossy JPEG 8-bit Image Compression'
        , '1.2.840.10008.1.2.4.51':
        'JPEG Baseline (Processes 2 & 4): Default Transfer Syntax for Lossy JPEG 12-bit Image Compression (Process 4 only)'
        , '1.2.840.10008.1.2.4.57':
        'JPEG Lossless, Nonhierarchical (Processes 14)',
        '1.2.840.10008.1.2.4.70':
        'JPEG Lossless, Nonhierarchical, First-Order Prediction (Processes 14 [Selection Value 1])'
        , '1.2.840.10008.1.2.4.80': 'JPEG-LS Lossless Image Compression',
        '1.2.840.10008.1.2.4.81':
        'JPEG-LS Lossy (Near- Lossless) Image Compression',
        '1.2.840.10008.1.2.4.90':
        'JPEG 2000 Image Compression (Lossless Only)',
        '1.2.840.10008.1.2.4.91': 'JPEG 2000 Image Compression',
        '1.2.840.10008.1.2.4.92':
        'JPEG 2000 Part 2 Multicomponent Image Compression (Lossless Only)',
        '1.2.840.10008.1.2.4.93':
        'JPEG 2000 Part 2 Multicomponent Image Compression',
        '1.2.840.10008.1.2.4.94': 'JPIP Referenced',
        '1.2.840.10008.1.2.4.95': 'JPIP Referenced Deflate',
        '1.2.840.10008.1.2.5': 'RLE Lossless', '1.2.840.10008.1.2.6.1':
        'RFC 2557 MIME Encapsulation', '1.2.840.10008.1.2.4.100':
        'MPEG2 Main Profile Main Level', '1.2.840.10008.1.2.4.102':
        'MPEG-4 AVC/H.264 High Profile / Level 4.1',
        '1.2.840.10008.1.2.4.103':
        'MPEG-4 AVC/H.264 BD-compatible High Profile / Level 4.1'}
    assert UID or description, 'Either Transfer syntax UID or description required'
    if UID in transfer_syntax:
        return transfer_syntax[UID]
    for key, value in transfer_syntax.iteritems():
        if description == value:
            return key
    return None


def keyingset_button_remove():
    """Remove current UI-active property from current keying set

    """
    pass


def is_tuple(obj):
    """Helper method to see if the object is a Python tuple.

    >>> is_tuple((1,))
    True
    """
    return type(obj) is tuple


def islist(x):
    """Is an object a python list"""
    return type(x) is list


def extract_prev_block_le(header: bytes) ->bytes:
    """Extracts the previous block's hash from a header (little-endian)"""
    return header[4:36]


def unique_name(key: 'bpy.context.object', name: str, name_dict: dict,
    name_max=-1, clean_func=None, sep: str='.'):
    """Helper function for storing unique names which may have special characters stripped and restricted to a maximum length.

    :param key: unique item this name belongs to, name_dict[key] will be reused when available. This can be the object, mesh, material, etc instance its self.
    :type key: 'bpy.context.object'
    :param name: The name used to create a unique value in name_dict.
    :type name: str
    :param name_dict: This is used to cache namespace to ensure no collisions occur, this should be an empty dict initially and only modified by this function.
    :type name_dict: dict
    :param clean_func: Function to call on name before creating a unique value.
    :param sep: Separator to use when between the name and a number when a duplicate name is found.
    :type sep: str
    """
    pass


def RMI(df, n, price='Close'):
    """
    Relative Momentum Index
    Returns: list of floats = jhta.RMI(df, n, price='Close')
    Source: https://www.fmlabs.com/reference/default.htm?url=RMI.htm
    """
    rmi_list = []
    upavg = 0.0
    dnavg = 0.0
    for i in range(len(df[price])):
        if i + 1 < n:
            rmi = float('NaN')
        else:
            if df[price][i] > df[price][i - n]:
                up = df[price][i] - df[price][i - n]
                dn = 0
            else:
                up = 0
                dn = df[price][i - n] - df[price][i]
            upavg = (upavg * (n - 1) + up) / n
            dnavg = (dnavg * (n - 1) + dn) / n
        if upavg + dnavg == 0:
            rmi = float('NaN')
        else:
            rmi = 100 * upavg / (upavg + dnavg)
        rmi_list.append(rmi)
    return rmi_list


def extendlist(lst, i, value=''):
    """extend the list so that you have i-th value"""
    if i == None:
        pass
    elif i < len(lst):
        pass
    else:
        lst.extend([value] * (i - len(lst) + 1))


def type_unpack(type):
    """ return the struct and the len of a particular type """
    type = type.lower()
    s = None
    l = None
    if type == 'short':
        s = 'h'
        l = 2
    elif type == 'ushort':
        s = 'H'
        l = 2
    elif type == 'int':
        s = 'i'
        l = 4
    elif type == 'uint':
        s = 'I'
        l = 4
    elif type == 'long':
        s = 'l'
        l = 4
    elif type == 'ulong':
        s = 'L'
        l = 4
    elif type == 'float':
        s = 'f'
        l = 4
    elif type == 'double':
        s = 'd'
        l = 8
    else:
        raise TypeError('Unknown type %s' % type)
    return '<' + s, l


def write_cert(filename, content):
    """Writes certificate body to the given file path."""
    with open(filename, 'w') as cert_file:
        cert_file.write(content)


def getAllQuestions():
    """Return all the questions in the survey"""


@staticmethod
def build_image(client, **kwargs):
    """
		Builds a container image, printing progress output as it is received
		"""
    events = client.api.build(decode=True, **kwargs)
    imageID = None
    for event in events:
        output = event.get('stream', event.get('status', '')).strip()
        details = event.get('progress', '').strip()
        if output != '':
            print('{}{}'.format(output, ' ' + details if details != '' else
                ''), flush=True)
        elif output == '' and len(event.get('stream', '')) > 0:
            pass
        elif 'error' in event:
            raise RuntimeError('Docker build failed with error: {}'.format(
                event['error']))
        elif 'aux' in event and 'ID' in event['aux']:
            imageID = event['aux']['ID']
        else:
            print(event, flush=True)
    return imageID


@staticmethod
def _line_is_comment(line):
    """Check whether a given line is a comment or not"""
    if not line:
        return False
    return line.startswith('#')


@classmethod
def register(cls, pkg, mgr):
    """Class method used internally by the Jetfactory manager to register a Service

        :param pkg: instance of :class:`jetfactory.Jetpack`
        :param mgr: instance of :class:`Jetfactory.JetManager`
        """
    cls.loop = mgr.loop
    cls.app = mgr.sanic
    cls._pkg_bind(pkg)


def clipboard(action, target, destination):
    """Clipboard actions... copy, cut and paste. paste is implied from
        either copy or cut action."""


def getQuery(store):
    """
        Return an SQL string with ?-style bind parameter syntax thingies.
        """


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

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

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


def filepath_drop(filepath='Path'):
    """Undocumented contribute <https://developer.blender.org/T51061>

    """
    pass


def monthCode(month):
    """
    perform month->code and back conversion

    Input: either month nr (int) or month code (str)
    Returns: code or month nr

    """
    codes = 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'Q', 'U', 'V', 'X', 'Z'
    assert month > 0, 'Month number must be positive and >0'
    if isinstance(month, int):
        return codes[month - 1]
    elif isinstance(month, str):
        return codes.index(month) + 1
    else:
        raise ValueError('Function accepts int or str')


def is_help_command(command) ->bool:
    """
     Checks that the user inputted command is a help command, which will not go over the wire.
      This is a command with -h or --help.
      The help functionality is triggered no matter where the -h appears in the command (arg ordering)
    """
    for part in command:
        if part in ('-h', '--help'):
            return True
    return False


@staticmethod
def events2seq(events):
    """turn events into a nt sequence based on the 'move' column

        Args:
            events: list of events (dictionaries)
        """
    seq = list()
    seq.append(next(events)['kmer'])
    for ev in events:
        move = ev['move']
        kmer = ev['kmer']
        seq.append(kmer[len(kmer) - move:])
    return ''.join(seq)


@staticmethod
def _clean_license_in_item(item_description: dict) ->None:
    """
        Remove license information from item_description

        :param item_description: feature properties or collection item into which license
                                 information is stored.
        """
    if 'license' in item_description:
        del item_description['license']
    if 'license_info' in item_description:
        del item_description['license_info']


def success_headers(headers):
    """
    Updates headers for a message when a process succeeds

    Resets the kafka_retry_count to 0,
    or adds if it didn't originally exist
    """
    try:
        headers = dict(headers)
    except TypeError:
        headers = {}
    headers['kafka_retry_count'] = '0'
    return headers


def validate_hparams(hparams):
    """
    Limited number of checks performed on the validity of the hyperparameters.
    The file is generally considered to follow the semantics of the
    mpunet.bin.defaults hyperparameter files.

    Args:
        hparams: A YAMLHParams object
    """
    if hparams['fit'].get('class_weights') and hparams['fit']['loss'] not in (
        'SparseFocalLoss',):
        raise ValueError(
            "Invalid loss function '{}' used with the 'class_weights' parameter"
            .format(hparams['fit']['loss']))
    if hparams['fit']['loss'] == 'WeightedCrossEntropyWithLogits':
        if not bool(hparams['fit']['class_weights']):
            raise ValueError(
                "Must specify 'class_weights' argument with loss'WeightedCrossEntropyWithLogits'."
                )
        if not hparams['build']['out_activation'] == 'linear':
            raise ValueError(
                "Must use out_activation: linear parameter with loss 'WeightedCrossEntropyWithLogits'"
                )
    if not hparams['train_data']['base_dir']:
        raise ValueError('No training data folder specified in parameter file.'
            )


def nba_league(x):
    """Takes in initials of league and returns numeric API Code

    Input Values: "NBA", "WNBA", or "NBADL"

    Used in: _Draft.Anthro(), _Draft.Agility(), _Draft.NonStationaryShooting(),
    _Draft.SpotUpShooting(), _Draft.Combine()

    """
    leagues = {'NBA': '00', 'WNBA': '10', 'NBADL': '20'}
    try:
        return leagues[x.upper()]
    except:
        raise ValueError(
            "Please use one of the following values for League: 'NBA', 'WNBA', 'NBADL'"
            )


def split_streams(streams: list, max_items: int):
    """Split a list of streams into chunks

    :param streams: List to be split
    :param max_items: Max number of items
    :return: Generator
    """
    for item in range(0, len(streams), max_items):
        yield streams[item:item + max_items]


def __get_elements(driver, params):
    """Get elements using Selenium.

    Parameters:
    - driver [selenium] : Selenium driver
    - params [dict] : A dict that contains elements to search the element for
    Returns:
    - output [WebElement list] : A list of found WebElements
    """
    if params.get('id'):
        return [driver.find_element_by_id(params.get('id'))]
    if params.get('name'):
        return driver.find_elements_by_name(params.get('name'))
    elif params.get('xpath'):
        return driver.find_elements_by_xpath(params.get('xpath'))
    elif params.get('link_text'):
        return driver.find_elements_by_link_text(params.get('link_text'))
    elif params.get('partial_link_text'):
        return driver.find_elements_by_partial_link_text(params.get(
            'partial_link_text'))
    elif params.get('tag_name'):
        return driver.find_elements_by_tag_name(params.get('tag_name'))
    elif params.get('class_name'):
        return driver.find_elements_by_class_name(params.get('class_name'))
    elif params.get('css_selector'):
        return driver.find_elements_by_css_selector(params.get('css_selector'))


def remove_feed_fetch_op(program):
    """ remove feed and fetch operator and variable for fine-tuning
    """
    block = program.global_block()
    need_to_remove_op_index = []
    for i, op in enumerate(block.ops):
        if op.type == 'feed' or op.type == 'fetch':
            need_to_remove_op_index.append(i)
    for index in need_to_remove_op_index[::-1]:
        block._remove_op(index)
    need_to_remove_var = []
    for var in block.vars:
        if var.endswith('feed'):
            need_to_remove_var.append(var)
        if var.endswith('fetch'):
            need_to_remove_var.append(var)
    for var in need_to_remove_var:
        block._remove_var(var)
    program.desc.flush()


def session_started(method):
    """Apply this decorator to a method of class :class:`.HermesSnipsComponent`
    to register it as a callback to be triggered when the dialogue manager
    queues starts a new session.
    """
    method.subscribe_method = 'subscribe_session_started'
    return method


def flatten(sequence):
    """
    A simple generator which flattens a sequence.

    Only one level is flattened.

    .. code-block:: python

        (1, (2, 3), 4) -> (1, 2, 3, 4)

    """
    for item in sequence:
        if hasattr(item, '__iter__') and not isinstance(item, str
            ) and not isinstance(item, bytes):
            for i in item:
                yield i
        else:
            yield item


def sample_size(dataframe):
    """Return the sample size in coordinate space.

    Args:
      dataframe (GeoDataFrame): dataframe containing samples

    Returns:
      tuple(float, float): tuple with width and height in map units
    """
    left, bottom, right, top = dataframe.iloc[0].geometry.bounds
    return abs(left - right), abs(top - bottom)


def clip_args(func, arg1, arg2, bounds=(0.0, 1.0)):
    """
    Clip the arguments to bounds

    Return the results of the function where the clipped arguments have been used.
    Arguments below the lower bound are set to the lower bound and the arguments
    above the upper bound are set to the upper bound.

    Parameters
    ----------
    func : func(arg1,arg2)
        The function which the clipped arguments are passed to
    arg1 : ndarray
        1D array with floats.
    arg2 : ndarray.
        1D array with floats.
    bounds : tuple, optional
        The bounds that the arguments are limited to.

    Returns
    -------
    clipped_func : func(arg1_clipped,arg2_clipped)
        The results of the function where the clipped agruments have been applied.

    Notes
    -----
    This function does not do any type of typechecking
    """
    upper_bound = bounds[1]
    lower_bound = bounds[0]
    arg1_inbound = arg1.copy()
    arg2_inbound = arg2.copy()
    arg1_inbound[arg1 < lower_bound] = lower_bound
    arg1_inbound[arg1 > upper_bound] = upper_bound
    arg2_inbound[arg2 < lower_bound] = lower_bound
    arg2_inbound[arg2 > upper_bound] = upper_bound
    return func(arg1_inbound, arg2_inbound)


@classmethod
def iter_nodes(cls, cluster):
    """
        Iterates through all nodes.

        :param cluster: Cluster instance
        :type cluster: Cluster
        :return: Generator for all nodes
        :rtype: generator
        """
    info = cluster.es.nodes.info(metric='settings')
    for node_id, node in info['nodes'].items():
        yield cls(cluster, node_id)


def onlywhite(line):
    """Return true if the line does only consist of whitespace characters."""
    for c in line:
        if c is not ' ' and c is not '  ':
            return c is ' '
    return line