def _create_cfn_parameters(parameters_dict: dict) ->list:
    """
    Converts a dict of key/value pairs into cloud formation list of dicts
    :parm dict parameters_dict: parameters_dict dictionary to be converted to cfn parameters_dict
    :return: list of dicts formatted for cloud formation Parameters
    """
    result = list()
    if not parameters_dict:
        return result
    for key in parameters_dict.keys():
        result.append({'ParameterKey': key, 'ParameterValue':
            parameters_dict[key]})
    return result


def _import_module(name, package=None, warn=True, prefix='_py_', ignore='_'):
    """Try import all public attributes from module into global namespace.

    Existing attributes with name clashes are renamed with prefix.
    Attributes starting with underscore are ignored by default.

    Return True on successful import.

    """
    import warnings
    from importlib import import_module
    try:
        if not package:
            module = import_module(name)
        else:
            module = import_module('.' + name, package=package)
    except ImportError:
        if warn:
            warnings.warn('failed to import module %s' % name)
    else:
        for attr in dir(module):
            if ignore and attr.startswith(ignore):
                continue
            if prefix:
                if attr in globals():
                    globals()[prefix + attr] = globals()[attr]
                elif warn:
                    warnings.warn('no Python implementation of ' + attr)
            globals()[attr] = getattr(module, attr)
        return True


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

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

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


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


@classmethod
def find(cls, db, name):
    """Find a service by name.

        Returns None if not found.
        """
    return db.query(cls).filter(cls.name == name).first()


@staticmethod
def isPunctuationSymbol(surfaceForm: str) ->bool:
    """
        The isPunctuationSymbol method takes a String surfaceForm as an input and returns true if it is a punctuation,
        False otherwise.
        Grave accent : `
        Left quotation mark : “
        Right quotation mark : ”
        Left single quotation mark : ‘
        Horizontal ellipsis : …

        PARAMETERS
        ----------
        surfaceForm : str
            String input to check.

        RETURNS
        -------
        bool
            true if it is a punctuation, false otherwise.
        """
    return (surfaceForm == '.' or surfaceForm == '...' or surfaceForm ==
        '[' or surfaceForm == ']' or surfaceForm == '…' or surfaceForm ==
        '%' or surfaceForm == '&' or surfaceForm == '=' or surfaceForm ==
        '``' or surfaceForm == '`' or surfaceForm == "''" or surfaceForm ==
        '$' or surfaceForm == '!' or surfaceForm == '?' or surfaceForm ==
        ',' or surfaceForm == ':' or surfaceForm == '--' or surfaceForm ==
        ';' or surfaceForm == '(' or surfaceForm == ')' or surfaceForm ==
        "'" or surfaceForm == '"' or surfaceForm == '“' or surfaceForm ==
        '‘' or surfaceForm == '”' or surfaceForm == '…' or surfaceForm ==
        '●' or surfaceForm == '/' or surfaceForm == '-' or surfaceForm ==
        '+' or surfaceForm == '-LRB-' or surfaceForm == '-RRB-' or
        surfaceForm == '-LCB-' or surfaceForm == '-RCB-' or surfaceForm ==
        '-LSB-' or surfaceForm == '-RSB-')


def _get_redis_commands(redis_client):
    """
    Retrieves a set of commands from Redis
    """
    commands = redis_client.execute_command('COMMAND')
    redis_commands = set()
    for command in commands:
        redis_commands.add(command[0])
    return redis_commands


def _range_checker(ip_check, first, last):
    """
    Tests whether an ip address is within the bounds of the first and last address.

    :param ip_check: The ip to test if it is within first and last.
    :param first: The first IP in the range to test against.
    :param last: The last IP in the range to test against.

    :return: bool
    """
    if ip_check >= first and ip_check <= last:
        return True
    else:
        return False


def get_cplex_version(context):
    """Submits a minimal job on DOCplexcloud and get the CPLEX version from
    logs
    Args:
        context: The context to use to connect
    Returns:
        A tuple (major, minor, micro), for instance (12, 7, 1)
    """
    import re
    from docplex.mp.compat23 import StringIO
    from docplex.mp.model import Model
    logs = StringIO()
    model = Model()
    model.solve(url=context.solver.docloud.url, key=context.solver.docloud.
        key, log_output=logs)
    v = re.search(
        'CPLEX version ([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])',
        logs.getvalue())
    try:
        major = int(v.group(1))
        minor = int(v.group(2))
        micro = int(v.group(3))
        return major, minor, micro
    except IndexError:
        raise RuntimeError('Could not find CPLEX version in resulting logs')
    except:
        raise ValueError('Could not determine version from %s' % v.group(0))


def show_active():
    """Open up the tree and adjust the view so that the active Object is shown centered

    """
    pass


@classmethod
def from_coefficients(cls, coefficients):
    """ Initiate polynomial from list of coefficients """
    pass


def __rred(r_1, r_2):
    """

    Calculate the reduced (effective) radius of two radii according to Hertzian
    contact theory.

    Parameters
    ----------
    r_1: scalar
        The first radius.
    r_2: scalar
        The second radius.

    Returns
    -------
    r_red: scalar
        The reduced (effective) radius.

    """
    if (r_1 == 0 or abs(r_1) == float('inf')) and r_2 != 0:
        r_red = r_2
    elif (r_2 == 0 or abs(r_2) == float('inf')) and r_1 != 0:
        r_red = r_1
    elif (r_1 == 0 or abs(r_1) == float('inf')) and (r_2 == 0 or abs(r_2) ==
        float('inf')):
        r_red = 0
    elif r_1 == -r_2:
        r_red = 0
    else:
        r_red = 1 / (1 / r_1 + 1 / r_2)
    return r_red


def find_base_domain(base_transform):
    """Given a base domain transform class, find the base domain that
    it transform."""
    for base in base_transform.__bases__:
        if hasattr(base, '_parameters') and not hasattr(base, 'domain'):
            return base
    name = base_transform.__name__
    raise TypeError('{} is not a base domain transform'.format(name))


def setfacl(ctx, path, acl, modify=False):
    """Sets/modifies ACL for a directory/file.

    :param ctx:
    :param path:
    :param acl:
        * u:www-data:--x
        * u::rwX,g::-,o::-,u:idlesign:rwx
        * u::rwx,g::---,o::---,u:idlesign:r-x
    :param modify: Modify or set.

    """
    mode = 'm' if modify else ' --set'
    ctx.sudo('setfacl -R%(mode)s "%(acl)s" %(path)s' % {'mode': mode, 'acl':
        acl, 'path': path})


def get_largest_fragment(fragments):
    """Return the largest connected component in a list of components.

    Parameters
    ----------
    fragments : list
        A list of strongly connected instances of NetworkX DiGraph each of
        which represents a component in the graph.

    Returns
    -------
    fragment : NetworkX DiGraph
        A strongly connected instance of NetworkX DiGraph that represents the
        largest component in the graph.
    """
    fragments.sort(key=lambda f: len(f.nodes()), reverse=True)
    return fragments[0]


def populate():
    """Populate the extent based on the current content of the database.

        After a successful call, `populated` will be True.  Unsuccessful calls
        must raise exceptions.

        If `populated` is true when called, this is a no-op.  After the
        initial population, updates should be maintained via other mechanisms.

        """


def taskname(*items):
    """A task name consisting of items."""
    s = '_'.join('{}' for _ in items)
    return s.format(*items)


def _function2(value):
    """function2(value)"""
    return value % 100


def pre_upgrade():
    """Pre-upgrade checks."""
    pass


def get_page_limit(request, default):
    """Return page and limit as integers."""
    try:
        limit = int(request.GET.get('limit', default))
    except ValueError:
        limit = default
    limit = min(max(10, limit), 2000)
    try:
        page = int(request.GET.get('page', 1))
    except ValueError:
        page = 1
    page = max(1, page)
    return page, limit


@staticmethod
def _constraint_wrapper(func, x_meas, kwargs, p):
    """
        Wrapper function that point to constraint function.

        :param func: constraint function.
        :param kwargs: key arguments to pass on to constraint function
        :param p: particle used to calculate constraint function
        :return: If this particle is feasable or not.
        """
    return func(p.pos, x_meas, **kwargs)


def zero_or_greater(name, value):
    """Verify that value is zero or greater. If not, 'name'
    will be used in error message

    :raises: ValueError

    """
    if int(value) < 0:
        errmsg = '{} must be >= 0, but got {}'.format(name, value)
        raise ValueError(errmsg)


def findzc(x, thresh, t_max=None):
    """
    Find cues to each zero-crossing in vector x.

    To be accepted as a zero-crossing, the signal must pass from below
    -thresh to above thresh, or vice versa, in no more than t_max samples.

    Args
    ----
    thresh: (float)
        magnitude threshold for detecting a zero-crossing.
    t_max: (int)
        maximum duration in samples between threshold crossings.

    Returns
    -------
    zc: ndarray
        Array containing the start **zc_s**, finish **zc_f** and direction **S**
        of zero crossings

        where:

        * zc_s: the cue of the first threshold-crossing in samples
        * zc_f: the cue of the second threshold-crossing in samples
        * S: the sign of each zero-crossing (1 = positive-going, -1 = negative-going).

    Notes
    -----
    This routine is a reimplementation of Mark Johnson's Dtag toolbox method
    and tested against the Matlab version to be sure it has the same result.
    """
    import numpy
    pt_p = x > thresh
    pt_n = ~pt_p
    nt_n = x < -thresh
    nt_p = ~nt_n
    pt_np = (pt_p[:-1] & pt_n[1:]).nonzero()[0]
    pt_pn = (pt_n[:-1] & pt_p[1:]).nonzero()[0] + 1
    nt_np = (nt_p[:-1] & nt_n[1:]).nonzero()[0] + 1
    nt_pn = (nt_n[:-1] & nt_p[1:]).nonzero()[0]
    ind_all = numpy.hstack((pt_np, nt_np, pt_pn, nt_pn))
    ind_all.sort()
    crossing_mask = ~(numpy.diff(numpy.sign(x[ind_all])) == 0)
    crossing_mask = numpy.hstack((crossing_mask, False))
    ind_1stx = ind_all[crossing_mask]
    ind_2ndx = ind_all[numpy.where(crossing_mask)[0] + 1]
    del_ind = numpy.where(ind_2ndx > len(x) - 1)[0]
    for i in del_ind:
        ind_1stx = numpy.delete(ind_1stx, i)
        ind_2ndx = numpy.delete(ind_1stx, i)
    signs = numpy.sign(x[ind_1stx]) * -1
    zc = numpy.vstack((ind_1stx, ind_2ndx, signs)).T
    if t_max:
        zc = zc[(zc[:, (1)] - zc[:, (0)] <= t_max), :]
    return zc.astype(int)


def implementer(*interfaces):
    """Create a decorator for declaring interfaces implemented by a facory

        A callable is returned that makes an implements declaration on
        objects passed to it.
        """


def _win_path_to_bytes(path):
    """Encode Windows paths to bytes. Only used on Python 2.

    Motivation is to be consistent with other operating systems where paths
    are also returned as bytes. This avoids problems mixing bytes and Unicode
    elsewhere in the codebase. For more details and discussion see
    <https://github.com/pypa/pip/issues/3463>.

    If encoding using ASCII and MBCS fails, return the original Unicode path.
    """
    for encoding in ('ASCII', 'MBCS'):
        try:
            return path.encode(encoding)
        except (UnicodeEncodeError, LookupError):
            pass
    return path


@staticmethod
def user_input(text):
    """Wrap input() making testing support of py2 and py3 easier."""
    return input(text).strip()


def SizeBenefitOther(t):
    """Other benefit per policy"""
    return 0


def getUserDN():
    """ Retrieve the user object's Distinguished Name attribute.

        Permission - Access contents information
        """


def in_scope(graph, node, parent):
    """ Returns True if `node` is in the scope of `parent`. """
    scope_dict = graph.scope_dict()
    scope = scope_dict[node]
    while scope is not None:
        if scope == parent:
            return True
        scope = scope_dict[scope]
    return False


@classmethod
def header_hash(cls, header):
    """Given a header return the hash."""
    import x11_hash
    return x11_hash.getPoWHash(header)


def get_help(command_name, configuration_file):
    """
        Returns the cli help string.

        :param command_name: Name of the cli call (usually sys.argv[0]).
        :type command_name: str
        :param configuration_file: Name of the default configuration file.
        :type configuration_file: str
        :return: The formatted help string ready to be displayed.
        :rtype: str

        .. seealso:: backupper.cli.main
    """
    help_string = (
        """Usage: {} [OPTIONS...]

  -h, --help			Displays the current help and exits.
  -f, --config-file		Specifies an alternative YAML config file (default: {}).
  -b, --backup-dir		Specifies an alternative backup directory (overrides the one set in the YAML config file).
  -d, --delete_old_backups	If true, will delete old backups (overrides the one set in the YAML config file).
"""
        .format(command_name, configuration_file))
    return help_string


def skip(s, substr):
    """
        >>> skip('0123456789','45')
        '6789'
        """
    idx = s.index(substr)
    return s[idx + len(substr):]


@staticmethod
def _to_bytes(str_value: str):
    """
        Convert string to bytes
        :param str_value: str
        :return: bytes
        """
    length = len(str_value).bit_length() // 8 + 1
    res = len(str_value).to_bytes(length, byteorder='little')
    return res


def __new__(cls, *args, **kwargs):
    """Return possibly existing instance."""
    if not '_instance' in cls.__dict__:
        cls._instance = object.__new__(cls, *args, **kwargs)
    return cls._instance


def makeBiDirectional(d):
    """
    Helper for generating tagNameConverter
    Makes dict that maps from key to value and back
    """
    dTmp = d.copy()
    for k in d:
        dTmp[d[k]] = k
    return dTmp


def kurtosis(a, axis=None):
    """Kurtosis of input"""
    raise NotImplementedError


def get_named_graph(ont):
    """
    Ontobee uses NGs such as http://purl.obolibrary.org/obo/merged/CL
    """
    if ont.startswith('http://'):
        return ont
    namedGraph = 'http://purl.obolibrary.org/obo/merged/' + ont.upper()
    return namedGraph


def namespace(api, name, description):
    """Return namespace name for the given module."""
    return api.namespace(name.split('.')[-1].replace('_', '-'), description
        =description)


def helical_transition_Re_Kutateladze_Borishanskii(Di, Dc):
    """Calculates the transition Reynolds number for flow inside a curved or
    helical coil between laminar and turbulent flow, using the method of [1]_,
    also shown in [2]_.

    .. math::
        Re_{crit} = 2300 + 1.05\\times 10^4 \\left(\\frac{D_i}{D_c}\\right)^{0.3}

    Parameters
    ----------
    Di : float
        Inner diameter of the coil, [m]
    Dc : float
        Diameter of the helix/coil measured from the center of the tube on one
        side to the center of the tube on the other side, [m]

    Returns
    -------
    Re_crit : float
        Transition Reynolds number between laminar and turbulent [-]

    Notes
    -----
    At very low curvatures, converges to Re = 2300.
    Recommended for :math:`0.0417 < d_i/D_c < 0.1667`

    Examples
    --------
    >>> helical_transition_Re_Kutateladze_Borishanskii(1, 7.)
    7121.143774574058

    References
    ----------
    .. [1] Kutateladze, S. S, and V. M Borishanskiĭ. A Concise Encyclopedia of
       Heat Transfer. Oxford; New York: Pergamon Press, 1966.
    .. [2] El-Genk, Mohamed S., and Timothy M. Schriener. "A Review and
       Correlations for Convection Heat Transfer and Pressure Losses in
       Toroidal and Helically Coiled Tubes." Heat Transfer Engineering 0, no. 0
       (June 7, 2016): 1-28. doi:10.1080/01457632.2016.1194693.
    """
    return 2300.0 + 10500.0 * (Di / Dc) ** 0.4


def __repr__(A):
    """For `print` and `pprint`"""
    return A.to_str()


def last_arg_byref(args):
    """Return the last C argument's value by reference."""
    return args[-1]._obj.value


def _convert_pooling_param(param):
    """Convert the pooling layer parameter
    """
    param_string = "pooling_convention='full', "
    if param.global_pooling:
        param_string += 'global_pool=True, kernel=(1,1)'
    else:
        param_string += 'pad=(%d,%d), kernel=(%d,%d), stride=(%d,%d)' % (param
            .pad, param.pad, param.kernel_size, param.kernel_size, param.
            stride, param.stride)
    if param.pool == 0:
        param_string += ", pool_type='max'"
    elif param.pool == 1:
        param_string += ", pool_type='avg'"
    else:
        raise ValueError('Unknown Pooling Method!')
    return param_string


@staticmethod
def is_allocation_required(jira):
    """ sets the allocation restrictions rules for jira """
    not_required_setups = ['Demo', 'UserTest', 'Multi AP']
    for setup in not_required_setups:
        if setup in jira.summary:
            return False
    return True


def tensorrt_bind(symbol, ctx, all_params, type_dict=None, stype_dict=None,
    group2ctx=None, **kwargs):
    """Bind current symbol to get an optimized trt executor.

    Parameters
    ----------
    symbol : Symbol
        The symbol you wish to bind, and optimize with TensorRT.

    ctx : Context
        The device context the generated executor to run on.

    all_params : Dict of str->ndarray
        A dictionary of mappings from parameter names to parameter NDArrays.

    type_dict  : Dict of str->numpy.dtype
        Input type dictionary, name->dtype

    stype_dict  : Dict of str->str
        Input storage type dictionary, name->storage_type

    group2ctx : Dict of string to mx.Context
        The dict mapping the `ctx_group` attribute to the context assignment.

    kwargs : Dict of str->shape
        Input shape dictionary, name->shape

    Returns
    -------
    executor : mxnet.Executor
        An optimized TensorRT executor.
    """
    kwargs['shared_buffer'] = all_params
    return symbol.simple_bind(ctx, type_dict=type_dict, stype_dict=
        stype_dict, group2ctx=group2ctx, **kwargs)


def select_less():
    """Deselect spline points at the boundary of each selection region

    """
    pass


def get_arn(vpc_id, region, account_id):
    """Creates a vpc ARN."""
    return f'arn:aws:ec2:{region}:{account_id}:vpc/{vpc_id}'


def get_config_params(properties):
    """Extract the set of configuration parameters from the properties attached
    to the schedule
    """
    param = []
    wdef = 'full'
    for prop in properties.split('\n'):
        if prop.startswith('org.opencastproject.workflow.config'):
            key, val = prop.split('=', 1)
            key = key.split('.')[-1]
            param.append((key, val))
        elif prop.startswith('org.opencastproject.workflow.definition'):
            wdef = prop.split('=', 1)[-1]
    return wdef, param


def count_char(tokens, char):
    """Counts how many times a given character appears in a list of tokens"""
    return sum(1 for token in tokens if token.string == char)


def logical_not(data=None, out=None, name=None, **kwargs):
    """Returns the result of logical NOT (!) function

    Example:
      logical_not([-2., 0., 1.]) = [0., 1., 0.]

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

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

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


def list_datasets(socrata_client, domain):
    """List all datasets on a portal using the Socrata API"""
    all_metadata = socrata_client.datasets(domains=[domain], only=['dataset'])
    key_fields = []
    for dataset in all_metadata:
        key_fields.append({'Name': dataset['resource']['name'], 'Category':
            dataset['classification'].get('domain_category'), 'ID': dataset
            ['resource']['id'], 'URL': dataset['permalink']})
    return sorted(key_fields, key=lambda _: _['Name'].lower())


def print_task_headers():
    """Print the column headers"""
    print('ID       Pri  Owner                State    Arch       Name')


def emotionV(frequencyVec, scoreVec):
    """Given the frequency vector and the score vector, compute the happs.

    Doesn't use numpy, but equivalent to `np.dot(freq,happs)/np.sum(freq)`."""
    tmpSum = sum(frequencyVec)
    if tmpSum > 0:
        happs = 0.0
        for i in range(len(scoreVec)):
            happs += frequencyVec[i] * float(scoreVec[i])
        happs = float(happs) / float(tmpSum)
        return happs
    else:
        return -1


@staticmethod
def parse_uri(uri):
    """Return the real URI with any protocol prefix stripped."""
    return uri


def p_macro_call_arg_list_atom(p):
    """macro_arg_list : ATOM macro_arg_list"""
    p[0] = [('atom', p[1])] + p[2]


def get_new_mean(value, current_mean, count):
    """Given a value, current mean, and count, return new mean"""
    summed = current_mean * count
    return (summed + value) / (count + 1)


@staticmethod
def get_parser_settings_key():
    """Return the key that contains the optional parser options in the `settings` input node."""
    return 'parser_options'


def get_connection_info(pool_id, node_id, batch_client):
    """
    Get connection info of specified node in pool
    :param batch_client: The batch client to use.
    :type batch_client: `batchserviceclient.BatchServiceClient`
    :param str pool_id: The pool id to look up
    :param str node_id: The node id to look up
    """
    rls = batch_client.compute_node.get_remote_login_settings(pool_id, node_id)
    remote_ip = rls.remote_login_ip_address
    ssh_port = str(rls.remote_login_port)
    return remote_ip, ssh_port


@classmethod
def get_object(cls, obj, transposed: bool):
    """ return the data for this obj """
    return obj


def fmt(docstr):
    """Format a docstring for use as documentation in sample config."""
    docstr = docstr.replace('\n', ' ')
    docstr = docstr.strip()
    return docstr


def product_from_name(name):
    """
    Return a product name from this tag name or target name.

    :param name: eg. "ceph-3.0-rhel-7"
    :returns: eg. "ceph"
    """
    if name.startswith('guest-'):
        name = name[6:]
    parts = name.split('-', 1)
    return parts[0]


def isTop(pid):
    """Determine if the PID is that of a t/tbar"""
    return abs(pid) == 6


def add_align(vstruct, vector='a', direction=(1, 0, 0)):
    """align all elements (locally) in a cartesian direction
    vector : ['a','b','c']
    direction : (x,y,z)
    """
    vstruct['transforms'].append({'type': 'local_align', 'cvector': vector,
        'direction': direction})


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

        :param SfTeamGrantAccessDetails val:
        :rtype: EventDetails
        """
    return cls('sf_team_grant_access_details', val)


def clean_line(line):
    """Remove comments and parentheses from the input line."""
    comment_begin = line.find('#')
    line = line[:comment_begin]
    line = line.replace('[', '').replace(']', '')
    line = line.replace('(', '').replace(')', '')
    return line


def merge_logs(bet_logs, bet_results_logs):
    """Merges bet logs (LogBet) with bet results logs (LogResult)."""
    merged_logs = ()
    bet_results_dict = {}
    for bet_result in bet_results_logs:
        bet_id = bet_result['bet_id']
        bet_results_dict = dict(bet_results_dict, **{bet_id: bet_result})
    for bet_log in bet_logs:
        bet_id = bet_log['bet_id']
        bet_result = bet_results_dict.get(bet_id)
        merged_log = {'bet_log': bet_log, 'bet_result': bet_result}
        merged_logs += merged_log,
    return merged_logs


def _is_int(int_as_str: str) ->bool:
    """
    Returns true if the given string can be parsed as an int.
    :param int_as_str: String to test.
    :return: True if it is an int, False otherwise.
    """
    try:
        int(int_as_str)
        return True
    except ValueError:
        return False


@classmethod
def for_point(cls, point, zoom):
    """Creates a tile for given point"""
    latitude, longitude = point.latitude_longitude
    return cls.for_latitude_longitude(latitude=latitude, longitude=
        longitude, zoom=zoom)


def all_sprite_scripts(state):
    """
    Finds all scripts in sprites DOES NOT include stage
    returns a list of lists, each sublist is a list of scripts for each sprite
    """
    json_data = state.data.get('json')
    sprite_scripts = []
    if json_data != None:
        for child in json_data.get('children'):
            if 'scripts' in child:
                sprite_scripts.append(child.get('scripts', []))
    return sprite_scripts


def multiply(intf, ints):
    """
    overpython.multiply(intf, ints)

    Multiply intf by ints. Raises ValueError if intf/ints is a string.
    """
    try:
        return float(intf) * float(ints)
    except ValueError:
        raise ValueError('%s/%s is not a number' % (intf, ints))


def clear_line():
    """Clear the line and store in history

    """
    pass


def tag_prefix():
    """Present for backwards compatibility with older versions of ctl-lib"""
    return ''


def nearestPoint(pos):
    """
    Finds the nearest grid point to a position (discretizes).
    """
    current_row, current_col = pos
    grid_row = int(current_row + 0.5)
    grid_col = int(current_col + 0.5)
    return grid_row, grid_col


@staticmethod
def _update_status(old_status, new_status):
    """
        Set status messages.
        :param old_status: original status
        :param new_status: changed status
        :return: status dictionary
        """
    old_status['catalogs']['valid'] += new_status['catalogs']['valid']
    old_status['catalogs']['invalid'] += new_status['catalogs']['invalid']
    old_status['collections']['valid'] += new_status['collections']['valid']
    old_status['collections']['invalid'] += new_status['collections']['invalid'
        ]
    old_status['items']['valid'] += new_status['items']['valid']
    old_status['items']['invalid'] += new_status['items']['invalid']
    old_status['unknown'] += new_status['unknown']
    return old_status


def last(iterable, default=None):
    """
	Return the last item from the iterable. If the iterator doesn't produce any
	items ``default`` will be returned.
	"""
    item = default
    for item in iterable:
        pass
    return item


def VStack_Calc(N, Vcell):
    """
    Calculate VStack.

    :param N: number of single cells
    :type N  :int
    :param Vcell: cell voltage [V}
    :type Vcell:float
    :return: VStack [V] as float
    """
    try:
        result = N * Vcell
        return result
    except TypeError:
        print('[Error] VStack Calculation Error (N:%s, Vcell:%s)' % (str(N),
            str(Vcell)))


def _generateSpecialOrthoOptsCentre(displayCtx, xax, yax, canvas):
    """Used by the generation functions for the ``xcentre``, ``ycentre``,
    and ``zcentre`` options.
    """
    x, y = canvas.getDisplayCentre()
    xlo = displayCtx.bounds.getLo(xax)
    ylo = displayCtx.bounds.getLo(yax)
    xlen = displayCtx.bounds.getLen(xax)
    ylen = displayCtx.bounds.getLen(yax)
    x = -1 + 2 * (x - xlo) / xlen
    y = -1 + 2 * (y - ylo) / ylen
    return ['{: 0.5f}'.format(x), '{: 0.5f}'.format(y)]


def smse(y_true, y_pred):
    """
    Standardised mean squared error.

    Parameters
    ----------
    y_true: ndarray
        vector of true targets
    y_pred: ndarray
        vector of predicted targets

    Returns
    -------
    float:
        SMSE of predictions vs truth (scalar)

    Example
    -------
    >>> y_true = np.random.randn(100)
    >>> smse(y_true, y_true)
    0.0
    >>> smse(y_true, np.random.randn(100)) >= 1.0
    True
    """
    N = y_true.shape[0]
    return ((y_true - y_pred) ** 2).sum() / (N * y_true.var())


def detect_filetype(header):
    """Returns Kepler and TESS file types given their primary header.

    This function will detect the file type by looking at both the TELESCOP and
    CREATOR keywords in the first extension of the FITS header. If the file is
    recognized as a Kepler or TESS data product, one of the following strings
    will be returned:

        * `'KeplerTargetPixelFile'`
        * `'TessTargetPixelFile'`
        * `'KeplerLightCurveFile'`
        * `'TessLightCurveFile'`

    If the file is not recognized as a Kepler or TESS data product, then
    `None` will be returned.

    Parameters
    ----------
    header : astropy.io.fits.Header object
        The primary header of a FITS file.

    Returns
    -------
    filetype : str or None
        A string describing the detected filetype. If the filetype is not
        recognized, `None` will be returned.
    """
    try:
        if 'TELESCOP' in header.keys():
            telescop = header['telescop'].lower()
        else:
            telescop = header['mission'].lower()
        creator = header['creator'].lower()
        origin = header['origin'].lower()
        if telescop == 'kepler':
            if 'targetpixel' in creator:
                return 'KeplerTargetPixelFile'
            elif 'fluxexporter' in creator or 'lightcurve' in creator or 'lightcurve' in creator:
                return 'KeplerLightCurveFile'
        elif telescop == 'tess':
            if 'targetpixel' in creator:
                return 'TessTargetPixelFile'
            elif 'lightcurve' in creator:
                return 'TessLightCurveFile'
            elif 'stsci' in origin:
                return 'TessTargetPixelFile'
    except (KeyError, AttributeError):
        return None


def SetVersionNumber(RevString):
    """Set the subversion version number

    :param str RevString: something like "$Revision: 4155 $"
      that is set by subversion when the file is retrieved from subversion.

    Place ``GSASIIpath.SetVersionNumber("$Revision: 4155 $")`` in every python
    file.
    """
    try:
        RevVersion = int(RevString.split(':')[1].split()[0])
        global version
        version = max(version, RevVersion)
    except:
        pass


def iter_http_requests(server, player):
    """Repeatedly accept HTTP connections on a server.

    Forever if the serving externally, or while a player is running if it is not
    empty.
    """
    while not player or player.running:
        try:
            yield server.open(timeout=2.5)
        except OSError:
            continue


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

        :param LegalHoldsChangeHoldDetailsDetails val:
        :rtype: EventDetails
        """
    return cls('legal_holds_change_hold_details_details', val)


def pers_update(label_ids, activate):
    """Activate or deactivate personal label_ids (by user) on the current context."""


@classmethod
def launch_instance(cls, argv=None, **kwargs):
    """Launch a global instance of this Application

        If a global instance already exists, this reinitializes and starts it
        """
    app = cls.instance(**kwargs)
    app.initialize(argv)
    app.start()


@classmethod
def vol_type(cls):
    """The type of volume supported by this type."""
    return 'npiv'


def generate_primes(upper=0):
    """
    Generate a list of primes from 2 to a set limit
    It reuses the sieve of Eratosthenes

    Returns a list of integer.

    """
    primes = [2]
    for n in range(3, upper + 1):
        k = 0
        while primes[k] <= pow(n, 0.5) and n % primes[k] != 0:
            k += 1
        if pow(n, 0.5) < primes[k]:
            primes.append(n)
    return primes


def heading_to_md(cell):
    """turn heading cell into corresponding markdown"""
    cell.cell_type = 'markdown'
    level = cell.pop('level', 1)
    cell.source = '#' * level + ' ' + cell.source


@staticmethod
def p_a2l_optional_list(p):
    """a2l_optional_list : a2l_optional
                             | a2l_optional a2l_optional_list"""
    try:
        p[0] = [p[1]] + p[2]
    except IndexError:
        p[0] = [p[1]]


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 is_definition(cursor):
    """Test if a cursor refers to a definition

    This occurs when the cursor has a definition, and shares the location of that definiton
    """
    defn = cursor.get_definition()
    return defn is not None and cursor.location == defn.location


@classmethod
def from_dict(cls, dictionary):
    """
        Instantiates a Sortinfo object from dictionary,
        normalising as necessary
        """
    normalised = cls.normalise_dict(dictionary)
    return cls.from_normalised_dict(normalised)


def volume(R):
    """Returns the first number/word of the volume field, hopefully trimming something like: `'49 Suppl 20'` to `49`"""
    return R['VI'].split(' ')[0]


def prime_sieve(n):
    """
    Return a list of prime numbers from 2 to a prime < n. Very fast (n<10,000,000) in 0.4 sec.

    Example:
    >>>prime_sieve(25)
    [2, 3, 5, 7, 11, 13, 17, 19, 23]

    Algorithm & Python source: Robert William Hanks
    http://stackoverflow.com/questions/17773352/python-sieve-prime-numbers
    """
    sieve = [True] * (n // 2)
    for i in range(3, int(n ** 0.5) + 1, 2):
        if sieve[i // 2]:
            sieve[i * i // 2::i] = [False] * ((n - i * i - 1) // (2 * i) + 1)
    return [2] + [(2 * i + 1) for i in range(1, n // 2) if sieve[i]]


def portlet_assignable():
    """Whether or not the context is capable of having locally assigned
        portlets.
        """


@classmethod
def iter_items(cls, client, common_path=None):
    """Find all references in the repository."""
    refs_path = path = client.renku_path / cls.REFS
    if common_path:
        path = path / common_path
    for name in path.rglob('*'):
        if name.is_dir():
            continue
        yield cls(client=client, name=str(name.relative_to(refs_path)))


@staticmethod
def add(store_track):
    """Build a track add event.

		Parameters:
			store_track (dict): A store track dict.

		Returns:
			dict: A mutation dict.
		"""
    store_track['trackType'] = 8
    return {'create': store_track}


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 scale_Isos(Isos, Gcamp):
    """
    Takes inputs Isos, and Gcamp and returns scaled_Isos
    """
    import scipy.stats as stats
    slope, intercept, r_val, p_val, stderr = stats.linregress(Isos, Gcamp)
    scaled_Isos = Isos * slope + intercept
    return scaled_Isos


def read_id(id_path):
    """
    Reads the ID from the specified ID file.

    :param id_path: the ID file to read
    :type id_path: str
    :return: the ID
    """
    with open(id_path, 'r') as id_file:
        id = id_file.readline()
        return id.strip()


def _end_of_set_index(string, start_index):
    """
    Returns the position of the appropriate closing bracket for a glob set in
    string.

    :param string:      Glob string with wildcards
    :param start_index: Index at which the set starts, meaning the position
                        right behind the opening bracket
    :return:            Position of appropriate closing bracket
    """
    length = len(string)
    closing_index = start_index
    if closing_index < length and string[closing_index] == '!':
        closing_index += 1
    if closing_index < length:
        closing_index += 1
    while closing_index < length and string[closing_index] != ']':
        closing_index += 1
    return closing_index


def _endpoint_from_view_func(view_func):
    """Internal helper that returns the default endpoint for a given
    function.  This always is the function name.
    """
    assert view_func is not None, 'expected view func if endpoint is not provided.'
    return view_func.__name__


def _format_names(name: str) ->str:
    """Format dictionary key names to be human friendly.

    Args:
        name (str): The Unicode type name.

    Returns:
        str: The formatted Unicode type name.
    """
    return name[0].upper() + name[1:].replace('_', ' ')


def _assert_possible_cover_size(n, x, fol):
    """Raise `AssertionError` if size `u` not of a cover."""
    assert n >= 0, n
    assert (n == 0) is (x == fol.false), n


def domain_to_filename(domain):
    """All '/' are turned into '-', no trailing. schema's
    are gone, only the raw domain + ".txt" remains
    """
    filename = domain.replace('/', '-')
    if filename[-1] == '-':
        filename = filename[:-1]
    filename += '.txt'
    return filename


def prepare_arguments(arguments):
    """Set proper maximum track length. Convert length arguments to seconds."""
    if 'max_tracklist_length' in arguments:
        if 0 < arguments['max_tracklist_length'] < arguments['max']:
            arguments['max'] = arguments['max_tracklist_length']
        arguments['max_tracklist_length'] *= 60
    arguments['max'] *= 60
    arguments['min'] *= 60


def printSyntax():
    """
    Display the syntax of the command line
    """
    print(__doc__)


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

        :param SfExternalInviteWarnType val:
        :rtype: EventType
        """
    return cls('sf_external_invite_warn', val)


def prompt(zelf):
    """ virtual handler to display a prompt. """
    pass


def by_one_gen():
    """Generator for trade in rewards starting at 3 and increasing by 1"""
    num = 2
    while True:
        num += 1
        yield num


def _validate_l1_method(method):
    """
    As of 0.10.0, the supported values for `method` in `fit_regularized`
    are "l1" and "l1_cvxopt_cp".  If an invalid value is passed, raise
    with a helpful error message

    Parameters
    ----------
    method : str

    Raises
    ------
    ValueError
    """
    if method not in ['l1', 'l1_cvxopt_cp']:
        raise ValueError(
            '`method` = {method} is not supported, use either "l1" or "l1_cvxopt_cp"'
            .format(method=method))


def formatLog(source='', level='', title='', data={}):
    """ Similar to format, but takes additional reserved params to promote logging best-practices

  :param level - severity of message - how bad is it?
  :param source - application context - where did it come from?
  :param title - brief description - what kind of event happened?
  :param data - additional information - what details help to investigate?
  """
    source = '' if source is None else source
    level = '' if level is None else level
    title = '' if title is None else title
    if not type(data) is dict:
        data = {}
    data['source'] = source
    data['level'] = level
    data['title'] = title
    return format(data)


def t_quoted_STRING(t):
    """"([^"\\n\\\\]|\\\\.)*\""""
    t.type = 'STRING'
    t.value = t.value[1:-1]
    return t


def __miles_to_meters(miles: float) ->float:
    """Convert miles to meters."""
    return miles * 1609.344


def date_to_str(d):
    """Convert date and datetime objects to a string

    Note, this does not do any timezone conversion.

    :param d: The :class:`datetime.date` or :class:`datetime.datetime` to
              convert to a string
    :returns: The string representation of the date
    """
    return d.strftime('%Y-%m-%dT%H:%M:%SZ')


@staticmethod
def decompress(tensor, ctx):
    """Decompress the tensor with the given context."""
    pass


@staticmethod
def set_fragment_temporary_id(fragment, temporary_id, P1_array,
    index_individual_fragment):
    """Given a P1 array relative to a global fragment sets to 0 the row relative to fragment
        which is temporarily identified with identity temporary_id

        Parameters
        ----------
        fragment : Fragment
            Fragment object containing images associated with a single individual
        temporary_id : int
            temporary identifier associated to fragment
        P1_array  : nd.array
            P1 vector of fragment
        index_individual_fragment : int
            Index of fragment with respect to a global fragment in which it is contained

        Returns
        -------
        P1_array  : nd.array
            updated P1 array
        """
    fragment._temporary_id = int(temporary_id)
    P1_array[(index_individual_fragment), :] = 0.0
    P1_array[:, (temporary_id)] = 0.0
    return P1_array


@staticmethod
def get_params(img, output_size):
    """Get parameters for ``crop`` for center crop.
        Args:
            img (PIL Image): Image to be cropped.
            output_size (tuple): Expected output size of the crop.
        Returns:
            tuple: params (i, j, h, w) to be passed to ``crop`` for center crop.
        """
    w, h = img.size
    th, tw = output_size
    i = int(round((h - th) / 2.0))
    j = int(round((w - tw) / 2.0))
    return i, j, th, tw


def sizeof_fmt(num, suffix='B', standard='SI'):
    """Humanized size modified from link below
    Link: https://stackoverflow.com/questions/1094841/reusable-library-to-get-human-readable-version-of-file-size#1094933
    """
    if standard.lower() == 'si':
        unit_list = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']
        last_unit_value = 'Y'
        divisor = 1000.0
    elif standard.lower() == 'iec':
        unit_list = ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']
        last_unit_value = 'Yi'
        divisor = 1024.0
    else:
        raise NotImplementedError('Unknow `standard`')
    for unit in unit_list:
        if abs(num) < 1024.0:
            return '{:3.2f} {}{}'.format(num, unit, suffix)
        num /= divisor
    return '{:.2f} {}{}'.format(num, last_unit_value, suffix)


def paginate(client, paginator, **kwargs):
    """
    Returns pages for given AWS paginator client and type.
    Example: iam client and "list_policies" paginator
    """
    marker = None
    while True:
        pages = client.get_paginator(paginator).paginate(**kwargs,
            PaginationConfig={'MaxItems': 10, 'PageSize': 10,
            'StartingToken': marker})
        for page in pages:
            yield page
        if 'NextMarker' not in page:
            break
        marker = page['NextMarker']


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

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

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


def formula_2015_01_01(foyer_fiscal, period, parameters):
    """
        Les dépenses de travaux dépendent d'un bouquet de travaux (sur 2 ans)
        2015
        """
    f7rn = foyer_fiscal('f7rn', period)
    f7rp = foyer_fiscal('f7rp', period)
    f7rq = foyer_fiscal('f7rq', period)
    f7rr = foyer_fiscal('f7rr', period)
    f7rs = foyer_fiscal('f7rs', period)
    f7rt = foyer_fiscal('f7rt', period)
    f7sa = foyer_fiscal('f7sa', period)
    f7sb = foyer_fiscal('f7sb', period)
    f7sd = foyer_fiscal('f7sd', period)
    f7se = foyer_fiscal('f7se', period)
    f7sf = foyer_fiscal('f7sf', period)
    f7sg = foyer_fiscal('f7sg', period)
    f7sh = foyer_fiscal('f7sh', period)
    f7si = foyer_fiscal('f7si', period)
    f7sj = foyer_fiscal('f7sj', period)
    f7sk = foyer_fiscal('f7sk', period)
    f7sl = foyer_fiscal('f7sl', period)
    f7sn = foyer_fiscal('f7sn', period)
    f7sp = foyer_fiscal('f7sp', period)
    f7sq = foyer_fiscal('f7sq', period)
    f7sr = foyer_fiscal('f7sr', period)
    f7ss = foyer_fiscal('f7ss', period)
    f7st = foyer_fiscal('f7st', period)
    f7sv = foyer_fiscal('f7sv', period)
    f7sw = foyer_fiscal('f7sw', period)
    f7ta = foyer_fiscal('f7ta', period)
    f7tb = foyer_fiscal('f7tb', period)
    f7tn = foyer_fiscal('f7tn', period)
    f7tp = foyer_fiscal('f7tp', period)
    f7tq = foyer_fiscal('f7tq', period)
    f7tr = foyer_fiscal('f7tr', period)
    f7ts = foyer_fiscal('f7ts', period)
    f7tt = foyer_fiscal('f7tt', period)
    f7vg = foyer_fiscal('f7vg', period)
    f7vh = foyer_fiscal('f7vh', period)
    f7wb = foyer_fiscal('f7wb', period)
    f7wc = foyer_fiscal('f7wc', period)
    f7wh = foyer_fiscal('f7wh', period)
    f7wt = foyer_fiscal('f7wt', period)
    f7wu = foyer_fiscal('f7wu', period)
    f7wv = foyer_fiscal('f7wv', period)
    f7xb = foyer_fiscal('f7xb', period)
    depense_2014_eligible = (f7sd + f7se + f7wc + f7vg + f7wt + f7sn + f7sp +
        f7sr + f7ss + f7sq + f7st + f7sf + f7sg + f7sh + f7si + f7sj + f7sk +
        f7sl + f7sv + f7sw)
    depense_2015_eligible = (f7ta + f7tb + f7xb + f7wh + f7wv + f7tn + f7tp +
        f7tr + f7ts + f7tq + f7tt)
    t1 = (f7wt + f7wu + f7wv > 0) * 1
    t2 = (f7wc + f7wb + f7xb > 0) * 1
    t3 = (f7vg + f7vh + f7wh > 0) * 1
    t4 = (f7sn + f7rn + f7tn > 0) * 1
    t5 = (f7sr + f7rr + f7tr + f7ss + f7rs + f7ts > 0) * 1
    t6 = (f7sd + f7sa + f7ta + f7se + f7sb + f7tb + f7sp + f7rp + f7tp +
        f7sq + f7rq + f7tq + f7st + f7rt + f7tt > 0) * 1
    bouquet = (t1 + t2 + t3 + t4 + t5 + t6 > 1) * (depense_2014_eligible > 0
        ) * (depense_2015_eligible > 0)
    return bouquet


def _ordinal(n):
    """Returns the ordinal string for a given integer

    See https://stackoverflow.com/a/20007730/1307974

    Parameters
    ----------
    n : `int`
        the number to convert to ordinal

    Examples
    --------
    >>> _ordinal(11)
    '11th'
    >>> _ordinal(102)
    '102nd'
    """
    idx = int((n // 10 % 10 != 1) * (n % 10 < 4) * n % 10)
    return '{}{}'.format(n, 'tsnrhtdd'[idx::4])


def a2lsbi(array):
    """ array to int (LSB first) """
    integer = 0
    for i in range(len(array) - 1, -1, -1):
        integer *= 256
        integer += array[i]
    return integer


def address_type(address):
    """
    Return the types of the address

    This can be 'AF_INET', 'AF_UNIX', or 'AF_PIPE'
    """
    if type(address) == tuple:
        return 'AF_INET'
    elif type(address) is str and address.startswith('\\\\'):
        return 'AF_PIPE'
    elif type(address) is str:
        return 'AF_UNIX'
    else:
        raise ValueError('address type of %r unrecognized' % address)


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


def _merge_observation(accum_observation, observation):
    """
    Old visual observation is discarded, because it is outdated frame.
    Text observations are merged, because they are messages sent from the rewarder.
    """
    if observation is None:
        return None
    elif accum_observation is None:
        return observation
    accum_observation['vision'] = observation.get('vision')
    accum_observation['text'] = accum_observation.get('text', []
        ) + observation.get('text', [])
    return accum_observation


def get_client_cluster():
    """
    Separated out the imports to make it easier to mock during testing
    """
    from distributed import Client, LocalCluster
    return Client, LocalCluster


def select_docker_file(files):
    """Ask user which docker file to use and return a PurePath object."""
    num = 0
    n = len(files)
    if n > 1:
        print('Available docker files:')
        for i, f in enumerate(files):
            print(i + 1, f.name)
        while True:
            end = len(files)
            input_str = input('which docker file to use? [1-{}] '.format(end))
            try:
                num = int(input_str) - 1
                if num < 0 or num >= end:
                    raise ValueError
                break
            except (TypeError, ValueError):
                print('Invalid input: {}. Please choose from [1-{}]'.format
                    (input_str, end))
                continue
    return files[num]


def center_text(text, length=80, left_edge='|', right_edge='|', text_length
    =None):
    """Center text with specified edge chars.

    You can pass in the length of the text as an arg, otherwise it is computed
    automatically for you.  This can allow you to center a string not based
    on it's literal length (useful if you're using ANSI codes).
    """
    if text_length is None:
        text_length = len(text)
    output = []
    char_start = length // 2 - text_length // 2 - 1
    output.append(left_edge + ' ' * char_start + text)
    length_so_far = len(left_edge) + char_start + text_length
    right_side_spaces = length - len(right_edge) - length_so_far
    output.append(' ' * right_side_spaces)
    output.append(right_edge)
    final = ''.join(output)
    return final


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


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 pk_names(cls):
    """
        Primary key column name list.
        """
    if cls._cache_pk_names is None:
        cls._cache_pk_names = cls._get_primary_key_names()
    return cls._cache_pk_names


def knot_insertion_kv(knotvector, u, span, r):
    """ Computes the knot vector of the rational/non-rational spline after knot insertion.

    Part of Algorithm A5.1 of The NURBS Book by Piegl & Tiller, 2nd Edition.

    :param knotvector: knot vector
    :type knotvector: list, tuple
    :param u: knot
    :type u: float
    :param span: knot span
    :type span: int
    :param r: number of knot insertions
    :type r: int
    :return: updated knot vector
    :rtype: list
    """
    kv_size = len(knotvector)
    kv_updated = [(0.0) for _ in range(kv_size + r)]
    for i in range(0, span + 1):
        kv_updated[i] = knotvector[i]
    for i in range(1, r + 1):
        kv_updated[span + i] = u
    for i in range(span + 1, kv_size):
        kv_updated[i + r] = knotvector[i]
    return kv_updated


def GetClassForUnboundMethod(method):
    """
    On Python 3 there are no unbound methods anymore. They are only regular functions.

    This function abstracts that difference and implements a workaround for Python 3.

    However this has a drawback: callback to method of local classes AREN'T SUPPORTED anymore,
    as it is impossible to retrieve their class object just by method object alone.
    """
    locals_name = '<locals>'
    names = method.__qualname__.split('.')
    names.pop()
    method_class = method.__globals__[names.pop(0)]
    while names:
        name = names.pop(0)
        if name == locals_name:
            raise NotImplementedError(
                'Impossible to retrieve class object for unbound methods in local classes.'
                )
        method_class = getattr(method_class, name)
    return method_class


@classmethod
def uploaded_file(cls, request, study, ppm_id, document_type, uuid,
    location, content_type='application/octect-stream'):
    """
        Make a request to P2MD to create a file upload
        """
    data = {'study': study, 'uuid': uuid, 'location': location, 'type':
        document_type, 'content_type': content_type}
    return cls.patch(request, f'/sources/api/file/{ppm_id}', data)


def maybe_unroll_group(group):
    """Unroll group with only one member."""
    try:
        size = len(group.tasks)
    except TypeError:
        try:
            size = group.tasks.__length_hint__()
        except (AttributeError, TypeError):
            return group
        else:
            return list(group.tasks)[0] if size == 1 else group
    else:
        return group.tasks[0] if size == 1 else group


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


def get_all(isamAppliance, check_mode=False, force=False):
    """
    Get all current host records
    """
    return isamAppliance.invoke_get('Retrieving current host records',
        '/isam/host_records')


def fix_id(fid):
    """As a temporary measure, escapes certain special characters in a name.

       Right now, a measure like this is required to make Vega* work properly
       with various field names.

       See https://github.com/vega/vega-lite/issues/4965.
    """
    new_id = ''
    for c in fid:
        if c == '.':
            new_id += ':'
        elif c == ']':
            new_id += ')'
        elif c == '[':
            new_id += '('
        elif c == "'" or c == '"':
            pass
        elif c == '\\':
            new_id += '|'
        else:
            new_id += c
    return new_id


def mean_grad(x, beta):
    """gradient/Jacobian for d (x*beta)/ d beta
    """
    return x


@classmethod
def ddb_load_(cls, engine, data):
    """ Load a model from DynamoDB data """
    obj = cls.__new__(cls)
    with obj.loading_(engine):
        for key, val in data.items():
            obj.set_ddb_val_(key, val)
    return obj


def layer_duplicate():
    """Make a copy of the active Grease Pencil layer

    """
    pass


def dbh_cad_model_viewer(path, contenttype, extension, roottag, nsurl):
    """ Generic Checklist Handler - Returns checlist for Checklist Files """
    if extension.lower() in ['stl', 'obj', 'x3d']:
        return 'db_cad_model_viewer'
    else:
        return False


def clean_utf8(s):
    """
    aiohttp uses surrogatescape all over the header processing.
    try to stop it from leaking any farther.
    """
    try:
        s.encode()
    except UnicodeEncodeError:
        s = s.encode('utf-8', 'replace').decode()
    return s


def int2ap(num):
    """Convert integer to A-P string representation."""
    val = ''
    ap = 'ABCDEFGHIJKLMNOP'
    num = int(abs(num))
    while num:
        num, mod = divmod(num, 16)
        val += ap[mod:mod + 1]
    return val


@classmethod
def workbench_scenarios(cls):
    """A canned scenario for display in the workbench."""
    return [('UBC Peer Rationale Reflection: Basic', cls.resource_string(
        'static/xml/basic_scenario.xml'))]


def delCorrtagWCS(thdr):
    """Delete table WCS keywords.

    The function returns a copy of the header with table-specific WCS keywords
    deleted.  This is appropriate when creating an x1d table from a corrtag
    table.

    Parameters
    ----------
    thdr: pyfits Header object
        A header for a BINTABLE extension.

    Returns
    -------
    hdr: pyfits Header object
        A copy of thdr, with certain table WCS keywords deleted.
    """
    hdr = thdr.copy()
    tkey = ['TCTYP2', 'TCRVL2', 'TCRPX2', 'TCDLT2', 'TCUNI2', 'TC2_2',
        'TC2_3', 'TCTYP3', 'TCRVL3', 'TCRPX3', 'TCDLT3', 'TCUNI3', 'TC3_2',
        'TC3_3']
    for keyword in tkey:
        if keyword in hdr:
            del hdr[keyword]
    return hdr


def xyz_to_rgb(cs, xc, yc, zc):
    """
    Given an additive tricolour system CS, defined by the CIE x
    and y chromaticities of its three primaries (z is derived
    trivially as 1-(x+y)), and a desired chromaticity (XC, YC,
    ZC) in CIE space, determine the contribution of each
    primary in a linear combination which sums to the desired
    chromaticity.  If the  requested chromaticity falls outside
    the Maxwell  triangle (colour gamut) formed by the three
    primaries, one of the r, g, or b weights will be negative.

    Caller can use constrain_rgb() to desaturate an
    outside-gamut colour to the closest representation within
    the available gamut and/or norm_rgb to normalise the RGB
    components so the largest nonzero component has value 1.
    """
    xr = cs['xRed']
    yr = cs['yRed']
    zr = 1 - (xr + yr)
    xg = cs['xGreen']
    yg = cs['yGreen']
    zg = 1 - (xg + yg)
    xb = cs['xBlue']
    yb = cs['yBlue']
    zb = 1 - (xb + yb)
    xw = cs['xWhite']
    yw = cs['yWhite']
    zw = 1 - (xw + yw)
    rx = yg * zb - yb * zg
    ry = xb * zg - xg * zb
    rz = xg * yb - xb * yg
    gx = yb * zr - yr * zb
    gy = xr * zb - xb * zr
    gz = xb * yr - xr * yb
    bx = yr * zg - yg * zr
    by = xg * zr - xr * zg
    bz = xr * yg - xg * yr
    rw = (rx * xw + ry * yw + rz * zw) / yw
    gw = (gx * xw + gy * yw + gz * zw) / yw
    bw = (bx * xw + by * yw + bz * zw) / yw
    rx = rx / rw
    ry = ry / rw
    rz = rz / rw
    gx = gx / gw
    gy = gy / gw
    gz = gz / gw
    bx = bx / bw
    by = by / bw
    bz = bz / bw
    r = rx * xc + ry * yc + rz * zc
    g = gx * xc + gy * yc + gz * zc
    b = bx * xc + by * yc + bz * zc
    return r, g, b


def quaternion_real(quaternion):
    """Return real part of quaternion.

    >>> quaternion_real([3, 0, 1, 2])
    3.0

    """
    return float(quaternion[0])


def Cross3(a, b):
    """Return the cross product of two vectors, a x b."""
    ax, ay, az = a
    bx, by, bz = b
    return ay * bz - az * by, az * bx - ax * bz, ax * by - ay * bx


def _get_color_list(annotations=False):
    """Get the current color list from matplotlib rcParams.

    Parameters
    ----------
    annotations : boolean
        Has no influence on the function if false. If true, check if color
        "red" (#ff0000) is in the cycle and remove it.

    Returns
    -------
    colors : list
    """
    import matplotlib.pyplot as plt
    color_cycle = plt.rcParams.get('axes.prop_cycle')
    if not color_cycle:
        colors = plt.rcParams.get('axes.color_cycle')
    else:
        colors = color_cycle.by_key()['color']
    if annotations and '#ff0000' in colors:
        colors.remove('#ff0000')
    return colors


def atan2h(x, y):
    """
    Hyperbolic arctangent
    >>> arctanh(z) = 1/2 Log((1+z)/(1-z))

    real:
        the following must be true: |x1| > |x2| and x2 ≠ 0.

    complex:
        x1 = a + bi
        x2 = b + di
        a = b = 0 and (sign of c) = (sign of d):
             the result is 0.
        a = b = 0 and (sign of c) ≠ (sign of d):
             the result is π.
        c = d = 0 and (sign of a) = (sign of b):
             the result is π/2.
        c = d = 0 and (sign of a) ≠ (sign of b):
             the result is −π/2
    """
    raise NotImplementedError()


def cut():
    """Used within a Seq parser (p1, p2, p3,...) to commit the Seq to that
    alternative.

    After the Seq passes the `cut`, any failure becomes fatal, and backtracking
    is not performed. This improves performance and improves the quality
    of the error messages."""


def _fuzzy_date_formatter(date, format='%d-%m-%Y'):
    """
    Dateconverter to convert date or datetime objects to strings in a specific format

    Implemented because of the problems of datetime.strftime method with years before 1900
    :param date:
    :param format: The format to print the date in. (must be a predefined format)
                    '%d-%m-%Y' or '%m-%Y' or '%Y'
    :return: The formatted date, eg. `07-09-2014`
    """
    if format == '%d-%m-%Y':
        return '{0.day:02d}-{0.month:02d}-{0.year:4d}'.format(date)
    elif format == '%m-%Y':
        return '{0.month:02d}-{0.year:4d}'.format(date)
    elif format == '%Y':
        return '{0.year:4d}'.format(date)
    else:
        return '{0.day:02d}-{0.month:02d}-{0.year:4d}'.format(date)


def printable_name(element):
    """Returns a string 'namespace:local_name' for the given element."""
    return '%s:%s' % (element.namespaceURI, element.localName)


def lookup_module(filename):
    """Helper function for break/clear parsing -- may be overridden.

    lookupmodule() translates (possibly incomplete) file or module name
    into an absolute file name.
    """
    import os
    import sys
    if os.path.isabs(filename) and os.path.exists(filename):
        return filename
    f = os.path.join(sys.path[0], filename)
    if os.path.exists(f):
        return f
    root, ext = os.path.splitext(filename)
    if ext == '':
        filename = filename + '.py'
    if os.path.isabs(filename):
        return filename
    for dirname in sys.path:
        while os.path.islink(dirname):
            dirname = os.readlink(dirname)
        fullname = os.path.join(dirname, filename)
        if os.path.exists(fullname):
            return fullname
    return None


@staticmethod
def _write_longtable_end(buf):
    """
        Write the end of a longtable environment.

        Parameters
        ----------
        buf : string or file handle
            File path or object. If not specified, the result is returned as
            a string.

        """
    buf.write('\\end{longtable}\n')


@classmethod
def getAppRefByLocalizedName(cls, name):
    """Get the top level element for the application with the specified
        localized name, such as VMware Fusion.

        Wildcards are also allowed.
        """
    return cls.from_localized_name(name)


def subdivide(number_cuts: int=1):
    """Break selected bones into chains of smaller bones

    :param number_cuts: Number of Cuts
    :type number_cuts: int
    """
    pass


def send_digest():
    """
        Retrieves digested messages, constructs digest, and sends the
        digest to any digest subscribers.
        """


def _print_with_line_no(text):
    """
    docstring for _print_with_line_no
    """
    for i, line in enumerate(text.split('\n')):
        line_no = i + 1
        print('{:>3}'.format(line_no), '|', line)
    print(' ')


@staticmethod
def _add_tid(xs, x_map, tid):
    """Add tid to the relevant map.
        """
    for x in xs:
        if x in x_map:
            x_map[x].add(tid)
        else:
            x_map[x] = {tid}


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 parse_values_to_append(options):
    """Manual parsing of --append arguments.

    :param options: list of arguments following --append argument.
    :return: dictionary containing key paths with values to be added
    :rtype: dict
    """
    parsed = {}
    for argument in options:
        if len(argument.split('=')) == 2:
            section, values = argument.split('=')
            if len(section.split('.')) != 2:
                raise Exception(
                    "Missing dot. The option --append has to come in the format 'section.key=value[,value]', but got '%s'."
                     % argument)
            if values == '':
                raise Exception(
                    "No values to append specified. The option --append has to come in the format 'section.key=value[, value]', but got '%s'"
                     % values)
            parsed[section] = values.split(',')
        else:
            raise Exception('Missing equal sign or more than just one found.')
    return parsed


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 normhash(cls, hash):
    """helper to normalize hash, correcting any bcrypt padding bits"""
    if cls.identify(hash):
        return cls.from_string(hash).to_string()
    else:
        return hash


def parse_url(url):
    """
    Parse a 'swift://CONTAINER/OBJECT' style URL
    :param url:
    :return: dictionary with "container" and "obj" keys
    """
    url = url.replace('swift://', '')
    if url.find('/') == -1:
        raise ValueError("Swift url must be 'swift://container/object'")
    pieces = url.split('/')
    containername = pieces[0]
    objname = '/'.join(pieces[1:])
    return {'container': containername, 'obj': objname}


def verify_trust(TrustId=None):
    """
    AWS Directory Service for Microsoft Active Directory allows you to configure and verify trust relationships.
    This action verifies a trust relationship between your Microsoft AD in the AWS cloud and an external domain.
    See also: AWS API Documentation

    :example: response = client.verify_trust(
        TrustId='string'
    )

    :type TrustId: string
    :param TrustId: [REQUIRED]
            The unique Trust ID of the trust relationship to verify.

    :rtype: dict
    :return: {
        'TrustId': 'string'
    }

    """
    pass


@staticmethod
def _strip_prefix(path_, parent='/'):
    """Strips 'file:' prefix and (optional) parent dir from file path."""
    stripped = path_.split(':')[-1]
    if not parent.endswith('/'):
        parent = parent + '/'
    if stripped.startswith(parent):
        stripped = stripped[len(parent):]
    return stripped


def get_class(class_name):
    """Get a class from the class name throuth the 'reflection' property."""
    parts = class_name.split('.')
    module = '.'.join(parts[:-1])
    m = __import__(module)
    for comp in parts[1:]:
        m = getattr(m, comp)
    return m


def listify(data):
    """ Make sure data is a list """
    if data is None:
        return []
    if isinstance(data, (set, list, tuple)):
        return list(data)
    return [data]


@classmethod
def from_identity(cls, gidc):
    """ Loads an unpacked gidc into a SecondParty. Note that this
        does not select the correct SecondParty for any given gidc's
        ciphersuite.
        """
    ghid = gidc.ghid
    keys = cls._unpack_keys({'signature': gidc.signature_key, 'encryption':
        gidc.encryption_key, 'exchange': gidc.exchange_key})
    self = cls(keys=keys, ghid=ghid)
    return self


@classmethod
def from_num(cls, num):
    """
    Factory that creates an IPAddr6 from a large integer
    """
    o = b''
    for i in range(16):
        o = chr(num & 255) + o
        num >>= 8
    return cls.from_raw(o)


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


@classmethod
def get_factory(cls, *args, **kw):
    """
        A class function which returns a runnable which calls the factory function (i.e. the
        constructor) of the class with the arguments provided.
        This should makes it easy to bind GrowlerProtocol construction explicitly. All
        arguments are forwarded to the constructor.
        """
    return lambda : cls.factory(*args, **kw)


def cCopy():
    """
    Return the kernel source for cCopy
    """
    code_text = """
    KERNEL void cCopy(
             GLOBAL_MEM  const float2 *CX,
             GLOBAL_MEM             float2 *CY)
    {
    // Copy x to y: y = x;
    //CX: input array (float2)
    // CY output array (float2)
    unsigned long gid=get_global_id(0);
    CY[gid]=CX[gid];
    };
    """
    return code_text


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 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 execute_http_call(session, url):
    """Executes an http call with the given session and url"""
    return session.get(url)


def getArgs(parser):
    """
   Get arguments corresponding to parser.
   """
    return parser.parse_args()


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


def GetTBProcess(DUTName):
    """
	Return VHDL code for the read of textio stimuli file.
	"""
    return (
        """
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
TEST: process
	--file TestFile : text is in "./stimValues.txt";
	file TestFile : text open read_mode is "./stimValues.txt";
	variable L           : line;
	variable TimeVector  : time;
	variable R           : integer;--real
	variable good_number : boolean := True;
	variable index       : integer;
	variable TooMuchStim : boolean := True;

begin  -- process Test

	--WRITE_STRING (OUTPUT, "*** {0} test ***");
	write(output, "*** Start {0} test ***");

	while not endfile(TestFile) loop
		readline(TestFile, L);
		--writeline(output, L);

		read(L, R, GOOD => good_number);-- read the time from the beginning of the line
		if not good_number then
			write(output, "Skip line:");
			writeline(output, L);
		end if;
		next when not good_number;-- skip the line if it doesn't start with a number

		TimeVector := natural(R) * 1 ns; -- convert real number to time
		if (now < TimeVector) then -- wait until vector time
			wait for TimeVector - now;
			write(output, "Time : " & integer'image(R));
		end if;
		index := NbStimuli-1;
		TooMuchStim := False;
		--write(output, "NbStimuli=" & integer'image(NbStimuli));

		--For each caracter in line:
		for i in L'range loop
			if index<0 then -- wait until vector time
				if L(i)='0' or  L(i)='1' or L(i)='H' or  L(i)='L' or L(i)='X' then
					write(output, "Error parsing line:");
					writeline(output, L);
					assert false report "Given stimuli bit number exceeds the number of stimuli signals." severity ERROR;
					exit;
				end if;
			end if;
			--write(output, "index : " & integer'image(index));
			--write(output, "Stimuli length : " & integer'image(Stimuli'length));
			case L(i) is
				when '0' => -- Drive 0
					Stimuli(index) <= '0';
				when '1' => -- Drive 1
					Stimuli(index) <= '1';
				when 'H' => -- Test for 1
					assert Stimuli(index) = '1';
				when 'L' => -- Test for 0
					assert Stimuli(index) = '0';
				when 'X' => -- Don't care
					null;
				when ' ' | HT => -- Skip white space
					next;
				when others =>
					-- Illegal character
					assert false report "Illegal char in vector file: " & L(i);
				exit;
			end case;
			index := index-1;
		end loop;  -- end of line

	end loop;  -- end of file

assert false report "*** Test complete ***";
wait;

end process TEST;"""
        .format(DUTName))


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


@classmethod
def has_resuming(cls):
    """Returns whether it supports to resume the fetch process.

        :returns: this backend supports items resuming
        """
    return True


def append(a, vancestors):
    """
    Append ``a`` to the list of the virtual ancestors, unless it is already
    included.
    """
    add = True
    for j, va in enumerate(vancestors):
        if issubclass(va, a):
            add = False
            break
        if issubclass(a, va):
            vancestors[j] = a
            add = False
    if add:
        vancestors.append(a)


@staticmethod
def p_bit_operation_optional(p):
    """bit_operation_optional : left_shift
                                  | right_shift
                                  | sign_extend"""
    p[0] = p.slice[1].type, p[1]


def flatten_list(list_of_list):
    """Input a list of list, return a list that all items are in a list.

    Parameters
    ----------
    list_of_list : a list of list

    Examples
    --------
    >>> tl.utils.flatten_list([[1, 2, 3],[4, 5],[6]])
    [1, 2, 3, 4, 5, 6]

    """
    return sum(list_of_list, [])


@classmethod
def _java_loader_class(cls, clazz):
    """
        Returns the full class name of the Java ML instance. The default
        implementation replaces "pyspark" by "org.apache.spark" in
        the Python full class name.
        """
    java_package = clazz.__module__.replace('pyspark', 'org.apache.spark')
    if clazz.__name__ in ('Pipeline', 'PipelineModel'):
        java_package = '.'.join(java_package.split('.')[0:-1])
    return java_package + '.' + clazz.__name__


def handle_python_strings(string):
    """handles py2/3 incompatiblities"""
    if not isinstance(string, bytes):
        string = string.encode('UTF-8')
    return string


def create_data(data):
    """
    Create glue data array (return data)
    """
    return data


@classmethod
def DeregisterAnalyzer(cls, analyzer_class):
    """Deregisters a analyzer class.

    The analyzer classes are identified based on their lower case name.

    Args:
      analyzer_class (type): class object of the analyzer.

    Raises:
      KeyError: if analyzer class is not set for the corresponding name.
    """
    analyzer_name = analyzer_class.NAME.lower()
    if analyzer_name not in cls._analyzer_classes:
        raise KeyError('analyzer class not set for name: {0:s}'.format(
            analyzer_class.NAME))
    del cls._analyzer_classes[analyzer_name]


def unload_ipython_extension(ipython):
    """Unload the extension in IPython."""
    pass


@staticmethod
def get_highest_enmax(vasp_potcar):
    """Make a list of all ENMAX values in the POTCAR, return the highest among them.

        :param vasp_potcar: VASP POTCAR file
        :type vasp_potcar: str (with linebreaks)
        :return: highest ENMAX value from the POTCAR
        :rtype: float
        """
    list_of_enmax = []
    for line in vasp_potcar.split('\n'):
        if 'ENMAX' in line:
            list_of_enmax.append(float(line.strip().split()[2].strip(';')))
    return max(list_of_enmax)


@staticmethod
def _get_filter_from_rule(rule):
    """Parse the firewall rule to a tuple

        :param rule: firewall rule
        :return: a tuple of parsed information
        """
    rule_filter = []
    keys = ['ip_version', 'protocol', 'source_port', 'destination_port',
        'source_ip_address', 'destination_ip_address']
    for key in keys:
        if key in ['source_port', 'destination_port']:
            port_range = rule.get(key, [])
            if port_range:
                port_lower, sep, port_upper = port_range.partition(':')
                port_upper = port_upper if sep else port_lower
                port_range = [port_lower, port_upper]
            rule_filter.append(port_range or [])
        else:
            rule_filter.append(rule.get(key, []))
    return tuple(rule_filter)


@classmethod
def pattern_to_regex(cls, pattern):
    """
		Convert the pattern into an uncompiled regular expression.

		*pattern* (:class:`str`) is the pattern to convert into a regular
		expression.

		Returns the uncompiled regular expression (:class:`str` or :data:`None`),
		and whether matched files should be included (:data:`True`),
		excluded (:data:`False`), or is a null-operation (:data:`None`).

			.. NOTE:: The default implementation simply returns *pattern* and
			   :data:`True`.
		"""
    return pattern, True


def get(key, *, expunge=False):
    """Return the contents cached under the given key.

        :param key: The key identifying the contents you want to retrieve.
        :type key: str
        :param expunge: A flag indicating whether the file contents should
            also be removed from the cache.
        :type expunge: bool
        :return: The contents of the cached file or None if the given id isn't
            in the cache (or it's already expired).
        :rtype: bytes or str, depending on the original contents.
        """


def get_simple_split(branchfile):
    """Splits the branchfile argument and assuming branch is
       the first path component in branchfile, will return
       branch and file else None."""
    index = branchfile.find('/')
    if index == -1:
        return None, None
    branch, file = branchfile.split('/', 1)
    return branch, file


def hex_to_color(color):
    """Convert color in the "#rrggbb" format to a color tuple."""
    red = color[1:3]
    green = color[3:5]
    blue = color[5:7]
    return int(red, 16), int(green, 16), int(blue, 16)


def compute_ratios(df_dict, df_str, gridclimname1, gridclimname2, prefix1,
    prefix2='meanmonth', comp_dict=None):
    """
    Compute fold-difference between monthly means (e.g,. Temp) for two different gridded datasets (e.g., Liv, WRF)
    """
    if isinstance(comp_dict, type(None)):
        comp_dict = {}
    for each1 in prefix1:
        for each2 in prefix2:
            ratios = df_dict['_'.join([each2, each1, gridclimname1])
                ] / df_dict['_'.join([each2, each1, gridclimname2])]
            comp_dict['_'.join([str(each1), df_str])] = ratios
    return comp_dict


def eotvos(target, k, temperature='pore.temperature', critical_temperature=
    'pore.critical_temperature', molar_density='pore.molar_density'):
    """
    Missing description

    Parameters
    ----------
    target : OpenPNM Object
        The object for which these values are being calculated.  This
        controls the length of the calculated array, and also provides
        access to other necessary thermofluid properties.

    k : float
        Constant parameter specific to fluid

    temperature : string
        The dictionary key containing the temperature values (K)

    critical_temperature : string
        The dictionary key containing the critical temperature values (K)

    molar_density : string
        The dictionary key containing the molar density values (K)

    Returns
    -------
    value : NumPy ndarray
        Array containing surface tension values [N/m]

    TODO: Needs description, and improve definition of k

    """
    Tc = target[critical_temperature]
    T = target[temperature]
    Vm = 1 / target[molar_density]
    value = k * (Tc - T) / Vm ** (2 / 3)
    return value


def arcgiscache_path(tile_coord):
    """
   >>> arcgiscache_path((1234567, 87654321, 9))
   'L09/R05397fb1/C0012d687'
   """
    return 'L%02d/R%08x/C%08x' % (tile_coord[2], tile_coord[1], tile_coord[0])


def predict_alternator_status(alternator_status_model, time, prev_status,
    battery_state_of_charge, gear_box_power_in):
    """
    Predicts the alternator status(0: off, 1: on, due to state of charge, 2: on
    due to BERS) [-].

    :param alternator_status_model:
         Function that predicts the alternator status.
    :type alternator_status_model: callable

    :param time:
        Time [s].
    :type time: float

    :param prev_status:
        Previous alternator status [-].
    :type prev_status: int

    :param battery_state_of_charge:
        State of charge of the battery [%].

        .. note::

            `battery_state_of_charge` = 99 is equivalent to 99%.
    :type battery_state_of_charge: float

    :param gear_box_power_in:
        Gear box power [kW].
    :type gear_box_power_in: float

    :return:
        Alternator status(0: off, 1: on, due to state of charge, 2: on due to
        BERS) [-].
    :rtype: int
    """
    args = time, prev_status, battery_state_of_charge, gear_box_power_in
    return alternator_status_model(*args)


def isBrowserIdFromForm():
    """Return true if browser id comes from a form variable.

        o Variable may come from either the query string or a post.

        o Permission required: Access contents information

        o Raise BrowserIdManagerErr if there is no current browser id.
        """


def filter_bash_shellshock(df, process_time):
    """
    A function that filters out the BASH SHELLSHOCK alert data obtained from FireEye
    :param df: a DataFrame object
    :param process_time:
    :return:
    """
    result = []
    track = []
    for o in df:
        if 'BASH [Shellshock HTTP]' in o['message']:
            track.append(o)
        else:
            result.append(o)
    trackfile = open('tracking_bashShellShock_' + process_time + '.txt', 'w')
    numskip = 1
    for item in track:
        trackfile.write('\n\n**** {:d}: Display ID {} ****\n\n{}'.format(
            numskip, item['displayId'], item))
        numskip += 1
    return result


def not_found(start_response):
    """Called if Url not found."""
    start_response('404 Not Found', [('Content-Type', 'text/plain')])
    return [b'Error 404: Not Found']


@classmethod
def createFromDict(cls, dct):
    """ Create an object of type cls with the dct as the kwargs
        """
    return cls(**dct)


def _iter_axes_subartists(ax):
    """Yield all child `Artist`\\s (*not* `Container`\\s) of *ax*."""
    yield from ax.collections
    yield from ax.images
    yield from ax.lines
    yield from ax.patches
    yield from ax.texts


def list_buckets():
    """
    Returns a list of all buckets owned by the authenticated sender of the request.
    See also: AWS API Documentation

    :example: response = client.list_buckets()

    :rtype: dict
    :return: {
        'Buckets': [
            {
                'Name': 'string',
                'CreationDate': datetime(2015, 1, 1)
            },
        ],
        'Owner': {
            'DisplayName': 'string',
            'ID': 'string'
        }
    }

    """
    pass


def NXM_IS_NX_REG(o):
    """
  Simulates macro from OVS
  """
    return o.is_reg


def _ignorefileandline(f):
    """Given a file `f`, return the ignore file and line that ignores it."""


def crop_img(img, crop):
    """Extract a center crop of the input image.

    Parameters
    ----------
    img : PIL.Image.Image
        Image to be cropped.
    crop : tuple
        Dimensions of the desired crop (height, width).

    Returns
    -------
    PIL.Image
        Cropped image.

    Notes
    -----
    The image center will be computed by rounding the coordinates
    if necessary. Python round default behavior is toward the
    closest even decimal.

    """
    w, h = img.size
    if crop[1] >= w or crop[0] >= h:
        raise ValueError('crop dimensions cannot be higher than {:}'.format
            (img.size))
    x1 = int(round((w - crop[1]) / 2.0))
    y1 = int(round((h - crop[0]) / 2.0))
    return img.crop((x1, y1, x1 + crop[1], y1 + crop[0]))


def body_open():
    """open the main logic"""
    return '    def __query(__connection):'


def get_global_option(checker, option, default=None):
    """ Retrieve an option defined by the given *checker* or
    by all known option providers.

    It will look in the list of all options providers
    until the given *option* will be found.
    If the option wasn't found, the *default* value will be returned.
    """
    try:
        return getattr(checker.config, option.replace('-', '_'))
    except AttributeError:
        pass
    for provider in checker.linter.options_providers:
        for options in provider.options:
            if options[0] == option:
                return getattr(provider.config, option.replace('-', '_'))
    return default


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

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


@classmethod
def resume(cls):
    """Resumes JavaScript execution.
        """
    return cls.build_send_payload('resume', {}), None


def fixedBoundary(eq, Jtor, psi):
    """
    Set psi=0 on all boundaries

    Inputs
    ------

    eq    Equilibrium object (not used)
    Jtor  2D array of toroidal current (not used)
    psi   2D array of psi values (modified by call)

    Returns
    -------
    None
    """
    psi[(0), :] = 0.0
    psi[:, (0)] = 0.0
    psi[(-1), :] = 0.0
    psi[:, (-1)] = 0.0


def first(*args):
    """return first not None argument or None"""
    for arg in args:
        if not arg is None:
            return arg
    return None


def consecutive(data):
    """
    Find sections of data with consecutive indices in a list of tuples with (index, value) representing candidates for
    ori and ter
    :param data: list of tuples
    :return: a list of the middle tuples of each found section of consecutives
    """
    if len(data) == 1:
        return [data[0]]
    data.sort(key=lambda x: x[0])
    ret = []
    current_seq = [data[0]]
    for i in range(1, len(data)):
        if data[i][0] == data[i - 1][0] + 1:
            current_seq.append(data[i])
        elif len(current_seq) != 0:
            current_seq.append(data[i])
            ret.append(current_seq[(len(current_seq) - 1) // 2])
            current_seq = []
        else:
            current_seq.append(data[i])
    if len(current_seq) != 0:
        ret.append(current_seq[(len(current_seq) - 1) // 2])
    return ret


def _get_seq(string):
    """
    Return the input string or an empty string with np.nan.

    >>> _get_seq('QVQQ')
    'QVQQ'
    >>> import numpy as np
    >>> _get_seq(np.nan)
    ''
    """
    if isinstance(string, str):
        return string
    return ''


def magic_timeit(setup, stmt, ncalls=None, repeat=3, force_ms=False):
    """Time execution of a Python statement or expression
    Usage:\\
      %timeit [-n<N> -r<R> [-t|-c]] statement
    Time execution of a Python statement or expression using the timeit
    module.
    Options:
    -n<N>: execute the given statement <N> times in a loop. If this value
    is not given, a fitting value is chosen.
    -r<R>: repeat the loop iteration <R> times and take the best result.
    Default: 3
    -t: use time.time to measure the time, which is the default on Unix.
    This function measures wall time.
    -c: use time.clock to measure the time, which is the default on
    Windows and measures wall time. On Unix, resource.getrusage is used
    instead and returns the CPU user time.
    -p<P>: use a precision of <P> digits to display the timing result.
    Default: 3
    Examples:
      In [1]: %timeit pass
      10000000 loops, best of 3: 53.3 ns per loop
      In [2]: u = None
      In [3]: %timeit u is None
      10000000 loops, best of 3: 184 ns per loop
      In [4]: %timeit -r 4 u == None
      1000000 loops, best of 4: 242 ns per loop
      In [5]: import time
      In [6]: %timeit -n1 time.sleep(2)
      1 loops, best of 3: 2 s per loop
    The times reported by %timeit will be slightly higher than those
    reported by the timeit.py script when variables are accessed. This is
    due to the fact that %timeit executes the statement in the namespace
    of the shell, compared with timeit.py, which uses a single setup
    statement to import function or create variables. Generally, the bias
    does not matter as long as results from timeit.py are not mixed with
    those from %timeit."""
    import timeit
    import math
    units = ['s', 'ms', 'us', 'ns']
    scaling = [1, 1000.0, 1000000.0, 1000000000.0]
    timer = timeit.Timer(stmt, setup)
    if ncalls is None:
        number = 1
        for _ in range(1, 10):
            if timer.timeit(number) >= 0.1:
                break
            number *= 10
    else:
        number = ncalls
    best = min(timer.repeat(repeat, number)) / number
    if force_ms:
        order = 1
    elif best > 0.0 and best < 1000.0:
        order = min(-int(math.floor(math.log10(best)) // 3), 3)
    elif best >= 1000.0:
        order = 0
    else:
        order = 3
    return {'loops': number, 'repeat': repeat, 'timing': best * scaling[
        order], 'units': units[order]}


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

        :param ResellerLogInfo val:
        :rtype: ActorLogInfo
        """
    return cls('reseller', val)


def decode_mixed(x):
    """Convert bytes in Numpy arrays into strings.  Leave other stuff alone.

    Parameters
    ----------
    x : object
        Input object.

    Returns
    -------
    object
        If `x` has a ``decode()`` method, ``x.decode()`` will be returned.
        Otherwise `x` will be returned unchanged.
    """
    try:
        return x.decode()
    except:
        return x


def outlier_removal_mean(dataframe, colname, low_cut, high_cut):
    """Replace outliers with the mean on dataframe[colname]"""
    col = dataframe[colname]
    col_numerics = col.loc[col.apply(lambda x: isinstance(x, (int, float)) and
        (x >= low_cut and x <= high_cut))]
    dataframe.loc[col.apply(lambda x: isinstance(x, (int, float)) and (x <
        low_cut or x > high_cut)), colname] = col_numerics.mean()
    return dataframe


def length(b):
    """
    Returns the length of the first netstring in the provided bytes object without decoding it.
    WARNING: This function doesn't check for netstring validity.
  """
    try:
        return int(b[:b.find(b':')].decode('ascii'))
    except:
        raise ValueError


def str2bool(str_val):
    """ Convert a boolean-like string into bool

    :param str_val: a boolean-like string
    :return: bool
    """
    assert isinstance(str_val, str)
    str_val = str_val.lower()
    if str_val in ['true', 'yes', '1']:
        return True
    elif str_val in ['false', 'no', '0']:
        return False
    else:
        raise ValueError('Unknown boolean-like string %r' % str_val)


def _whole_basis_types(basis):
    """
    Get a list of all the types of features in this basis set.

    """
    all_types = set()
    for v in basis['elements'].values():
        if 'electron_shells' in v:
            for sh in v['electron_shells']:
                all_types.add(sh['function_type'])
        if 'ecp_potentials' in v:
            for pot in v['ecp_potentials']:
                all_types.add(pot['ecp_type'])
    return sorted(list(all_types))


@staticmethod
def init_pagination():
    """ Update request params to allow pagination
        Returns: dict of params
        """
    return {'page': 1, 'per_page': 100}


def denormalize(tensor, stats):
    """
    denormalize a tensor using a running mean and std

    :param tensor: (TensorFlow Tensor) the normalized tensor
    :param stats: (RunningMeanStd) the running mean and std of the input to normalize
    :return: (TensorFlow Tensor) the restored tensor
    """
    if stats is None:
        return tensor
    return tensor * stats.std + stats.mean


def price_to_cash_flow(price_per_share, cash_flow_per_share):
    """Computes price to cash flow ratio.

    @params
    -------
    price_per_share: share price
    cash_flow_per_share: cash flow per share

    returns
    -------
    Price to cash flow ratio, int or float

    explanation
    -----------

    """
    return price_per_share / cash_flow_per_share


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

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

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


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


def avg_sum(x, y):
    """Average of x and y.
    """
    return (x + y) / 2


def bufr_specific_handling(sounding):
    """
    Apply bufr message specific functions

    Depending on the BUFR format, that data
    has to be prepared differently

    BUFR309053 (dropsonde)
    BUFR309056 (radiosonde descent)
    BUFR309057 (radiosonde ascent)
    - Remove last entries of time, latitude, longitude because those
        belong to the 'absoluteWindShearIn1KmLayerAbove'/
        'absoluteWindShearIn1KmLayerBelow' entries

    """
    variables = ['latitude', 'longitude', 'pressure', 'windspeed',
        'winddirection', 'temperature', 'dewpoint', 'gpm', 'time']
    if sounding.meta_data['bufr_msg'] == 309053:
        pass
    elif sounding.meta_data['bufr_msg'] == 309056:
        pass
    elif sounding.meta_data['bufr_msg'] == 309057:
        pass
    return sounding


def add_script(nc, line):
    """Add one-liner script or several lines (newline separated)"""
    assert type(nc) == dict
    nc['startup'] = nc.get('startup') or ''
    if not nc['startup'].endswith('\n'):
        nc['startup'] += '\n'
    nc['startup'] += line + '\n'


def step(sys, T=None, X0=0.0, input=0, output=None, return_x=False):
    """
    Step response of a linear system

    If the system has multiple inputs or outputs (MIMO), one input has
    to be selected for the simulation.  Optionally, one output may be
    selected. If no selection is made for the output, all outputs are
    given. The parameters `input` and `output` do this. All other
    inputs are set to 0, all other outputs are ignored.

    Parameters
    ----------
    sys: StateSpace, or TransferFunction
        LTI system to simulate

    T: array-like object, optional
        Time vector (argument is autocomputed if not given)

    X0: array-like or number, optional
        Initial condition (default = 0)

        Numbers are converted to constant arrays with the correct shape.

    input: int
        Index of the input that will be used in this simulation.

    output: int
        If given, index of the output that is returned by this simulation.

    Returns
    -------
    yout: array
        Response of the system

    T: array
        Time values of the output

    xout: array (if selected)
        Individual response of each x variable

    See Also
    --------
    lsim, initial, impulse

    Examples
    --------
    >>> yout, T = step(sys, T, X0)
    """
    from ..timeresp import step_response
    T, yout, xout = step_response(sys, T, X0, input, output, transpose=True,
        return_x=True)
    if return_x:
        return yout, T, xout
    return yout, T


def change_indexes_0_to_1(key):
    """('RU') Функция используется в drange в __getitem__().
	a[1] > a[0]
	Она смещает в последовательностях номер первого элемента с [0] на [1] чтобы показать вам.
	если при a[arg] передается один аргумент, он int и пишется в keys
	если пытаешься брать срез, keys присваивается объект среза вида: slice(1, None, None)
	rev. 5
	"""
    if type(key) == int:
        if key >= 0:
            key += 1
    elif type(key) == slice:
        if key.step and key.step < 0:
            if key.start and key.start >= 0:
                start = key.start + 1
            else:
                start = key.start
            if key.stop != None:
                if key.stop >= 0:
                    stop = key.stop + 2
                else:
                    stop = key.stop
            else:
                stop = None
            key = slice(start, stop, key.step)
        else:
            if key.start >= 0:
                start = key.start + 1
            key = slice(start, key.stop, key.step)
    return key


def _gcd(a, b):
    """Euclidean algorithm for calculating the GCD of two numbers a, b.
    This algoritm also works for real numbers:
    Find the greatest number h such that a and b are integer multiples of h.
    """
    while a > 1e-05:
        a, b = b % a, a
    return b


@staticmethod
def _deduce_system_type(**kwargs):
    """Based on the combination of arguments this returns which ODE
        description has been provided.

        full rhs
            x' = f(x, t, r, p)
        full mass matrix
            M(x, p) * x' = f(x, t, r, p)
        min mass matrix
            M(q, p) * u' = f(q, u, t, r, p)
            q' = g(q, u, t)

        """
    if kwargs.pop('coordinate_derivatives') is not None:
        system_type = 'min mass matrix'
    elif kwargs.pop('mass_matrix') is not None:
        system_type = 'full mass matrix'
    else:
        system_type = 'full rhs'
    return system_type