def check_cached(name):
    """Check cache status for the given file
    :return Bool True if exists, False if not"""
    pass


def assert_not_called(_mock_self):
    """assert that the mock was never called."""
    self = _mock_self
    if self.call_count != 0:
        msg = "Expected '%s' to not have been called. Called %s times." % (
            self._mock_name or 'mock', self.call_count)
        raise AssertionError(msg)


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 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 _a_decode_int(stream, offset, count, _):
    """
    'a2i42',3,2 --> 5,42
    """
    return offset + count, int(stream[offset:offset + count])


def assert_equal_arrays(a1, a2):
    """
    Check that two arrays are equal.

    This is a simplified method useful when the arrays to be compared may
    not be numeric. It simply compares the shapes of the two arrays and then
    does a value by value comparison.

    Parameters
    ----------
    a1 : array
        The first array to compare.
    a2 : array
        The second array to compare.
    """
    assert a1.shape == a2.shape
    for x, y in zip(a1.flat, a2.flat):
        assert x == y


def filter_migration_segment_len(x, hmin=0, hmax=float('inf'), dmin=0, dmax
    =float('inf')):
    """
    Filter migration segment by home segment length and destination length.
    x: ['migration_list']
    hmin: min_home_segment_len
    hmax: max_home_segment_len
    dmin: min_des_segment_len
    dmax: max_des_segment_len
    """
    home_segment = x[0]
    des_segment = x[1]
    home_len = home_segment[1] - home_segment[0] + 1
    des_len = des_segment[1] - des_segment[0] + 1
    if hmin <= home_len <= hmax and dmin <= des_len <= dmax:
        return 1
    else:
        return 0


def appendColumnIfNotExist(ws, columnHeader):
    """
    Check whether a column with the given header already exists in ws, and append it if not.

    Input:
    ws (xl.worksheet.worksheet.worksheet): Worksheet to append column to
    columnHeader (str): Header of new column

    Output:
    If column with columnHeader does not exist, append it to ws. Return index of column with columnHeader.
    """
    maxHeaderIdx = 0
    for headerIdx, cell in enumerate(list(ws.rows)[0]):
        if cell.value == columnHeader:
            return headerIdx
        maxHeaderIdx = max(headerIdx, maxHeaderIdx)
    newColIdx = maxHeaderIdx + 1
    ws.cell(1, 1).offset(column=newColIdx).value = columnHeader
    return newColIdx


@classmethod
def FromBuffer(cls, buffer):
    """Instantiate an EndCentralDirectory from this buffer."""
    if len(buffer) > cls.sizeof():
        end = len(buffer) - cls.sizeof() + 4
        while True:
            index = buffer.rfind(cls.magic_string, 0, end)
            if index < 0:
                break
            end_cd = cls(buffer[index:])
            if end_cd.IsValid():
                return end_cd, index
            end = index
    raise IOError('Unable to find EndCentralDirectory')


def get_chunks(seq, num):
    """split seq in chunks of size num,
	used to divide tasks for workers
	"""
    avg = len(seq) / float(num)
    out = []
    last = 0.0
    while last < len(seq):
        out.append(seq[int(last):int(last + avg)])
        last += avg
    return out


def unpack(*arg):
    """Unpacks a 2D array. Input must be unpack(*arg.T) for column unpacking and
    unpack(*arg) for row unpacking."""
    return arg


def remove_range(file_contents, source_range):
    """
    removes the chars covered by the sourceRange from the file

    :param file_contents: list of lines in the file
    :param source_range:  Source Range
    :return:              list of file contents without specified chars removed
    """
    if not file_contents:
        return []
    newfile = list(file_contents)
    source_range = source_range.expand(file_contents)
    if source_range.start.line == source_range.end.line:
        newfile[source_range.start.line - 1] = newfile[source_range.start.
            line - 1][:source_range.start.column - 1] + newfile[
            source_range.start.line - 1][source_range.end.column:]
        if newfile[source_range.start.line - 1] == '':
            del newfile[source_range.start.line - 1]
    else:
        newfile[source_range.start.line - 1] = newfile[source_range.start.
            line - 1][:source_range.start.column - 1]
        newfile[source_range.end.line - 1] = newfile[source_range.end.line - 1
            ][source_range.end.column:]
        for i in reversed(range(source_range.start.line, source_range.end.
            line - 1)):
            del newfile[i]
        if newfile[source_range.start.line] == '':
            del newfile[source_range.start.line]
        if newfile[source_range.start.line - 1] == '':
            del newfile[source_range.start.line - 1]
    return newfile


def process_stats_perc(proc):
    """
    Get process statistics for the percentage memory option
    """
    return proc.cpu_percent(), proc.memory_percent(), proc.create_time()


def print_optional(string, print_in_log):
    """Print a statement based on a string and a boolean wheter to really print or not.

    Parameters
    ----------
        string : str
            string to be printed

        print_in_log : bool
            boolean on whether the string should really be printed
    """
    if print_in_log:
        print(string)


def p_variable_without_objects(p):
    """variable_without_objects : simple_indirect_reference"""
    p[0] = p[1]


def getSurveyId():
    """Return the userid for the survey"""


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 approximate_xswap_prior(source_degree, target_degree, num_edges):
    """
    Approximate the XSwap prior by assuming that the XSwap Markov Chain is stationary.
    While this is not the case in reality, some networks' priors can be estimated
    very well using this equation.

    Parameters
    ----------
    source_degree : int, float, numpy.array, or pandas.Series
        The source degree for a single node pair or a number of source degrees.
        The type of object passed should match `target_degree`.
    target_degree : int, float, numpy.array, or pandas.Series
        The target degree for a single node pair or a number of target degrees.
        The type of object passed should match `source_degree`.
    num_edges : int or float
        The total number of edges in the network

    Returns
    -------
    approximate_prior : float, numpy.array, or pandas.Series
        Output type matches the types of `source_degree` and `target_degree`.
    """
    return source_degree * target_degree / ((source_degree * target_degree) **
        2 + (num_edges - source_degree - target_degree + 1) ** 2) ** 0.5


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

        :param FolderOverviewItemPinnedType val:
        :rtype: EventType
        """
    return cls('folder_overview_item_pinned', val)


def sortLocations(locations):
    """ Sort the locations by ranking:
            1.  all on-axis points
            2.  all off-axis points which project onto on-axis points
                these would be involved in master to master interpolations
                necessary for patching. Projecting off-axis masters have
                at least one coordinate in common with an on-axis master.
            3.  non-projecting off-axis points, 'wild' off axis points
                These would be involved in projecting limits and need to be patched.
    """
    onAxis = []
    onAxisValues = {}
    offAxis = []
    offAxis_projecting = []
    offAxis_wild = []
    for l in locations:
        if l.isOrigin():
            continue
        if l.isOnAxis():
            onAxis.append(l)
            for axis in l.keys():
                if axis not in onAxisValues:
                    onAxisValues[axis] = []
                onAxisValues[axis].append(l[axis])
        else:
            offAxis.append(l)
    for l in offAxis:
        ok = False
        for axis in l.keys():
            if axis not in onAxisValues:
                continue
            if l[axis] in onAxisValues[axis]:
                ok = True
        if ok:
            offAxis_projecting.append(l)
        else:
            offAxis_wild.append(l)
    return onAxis, offAxis_projecting, offAxis_wild


def get(key, default=None):
    """Get a value for a key

        The default is returned if there is no value for the key.
        """


@classmethod
def clear_instance(cls):
    """unset _instance for this class and singleton parents.
        """
    if not cls.initialized():
        return
    for subclass in cls._walk_mro():
        if isinstance(subclass._instance, cls):
            subclass._instance = None


def arn_has_slash(arn):
    """Given an ARN, determine if the ARN has a stash in it. Just useful for the hacky methods for
    parsing ARN namespaces. See
    http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html for more details on ARN namespacing."""
    if arn.count('/') > 0:
        return True
    else:
        return False


def inspect(obj):
    """Inspect object obj. Works on Sound and Picture objects."""
    obj.inspect()


@staticmethod
def map_list(lst, field_name):
    """
        Create hashtable from list

        map_list([{a: 1, b: 2}, {a: 3, b: 4}], 'a') => {1: {a: 1, b:2}, 3: {a: 3, b: 4}}
        """
    ret = {}
    for item in lst:
        if field_name in item:
            ret[item[field_name]] = item
    return ret


def int_shape(x):
    """Returns the shape of a Keras tensor or a Keras variable as a tuple of
    integers or None entries.

    # Arguments
        x: Tensor or variable.

    # Returns
        A tuple of integers (or None entries).
    """
    if hasattr(x, '_keras_shape'):
        return x._keras_shape
    else:
        return None


def _gen_unzip(it, elem_len):
    """Helper for unzip which checks the lengths of each element in it.
    Parameters
    ----------
    it : iterable[tuple]
        An iterable of tuples. ``unzip`` should map ensure that these are
        already tuples.
    elem_len : int or None
        The expected element length. If this is None it is infered from the
        length of the first element.
    Yields
    ------
    elem : tuple
        Each element of ``it``.
    Raises
    ------
    ValueError
        Raised when the lengths do not match the ``elem_len``.
    """
    elem = next(it)
    first_elem_len = len(elem)
    if elem_len is not None and elem_len != first_elem_len:
        raise ValueError('element at index 0 was length %d, expected %d' %
            (first_elem_len, elem_len))
    else:
        elem_len = first_elem_len
    yield elem
    for n, elem in enumerate(it, 1):
        if len(elem) != elem_len:
            raise ValueError(
                'element at index %d was length %d, expected %d' % (n, len(
                elem), elem_len))
        yield elem


@staticmethod
def get_expr(expr, follow, nofollow):
    """Update @follow/@nofollow according to insteresting nodes
        Returns same expression (non modifier visitor).

        @expr: expression to handle
        @follow: set of nodes to follow
        @nofollow: set of nodes not to follow
        """
    if expr.is_id():
        follow.add(expr)
    elif expr.is_int():
        nofollow.add(expr)
    elif expr.is_mem():
        follow.add(expr)
    return expr


@classmethod
def get_image_info(cls, name):
    """
        Gets an image's info.

        It is not required to prefix the name with ``File:``, but the extension is required.

        Parameters
        ----------
        name: :class:`str`
            The name of the image.

        Returns
        -------
        :class:`Image`
            The image's information.
        """
    gen = cls.get_images_info([name])
    return next(gen)


def _cga_colour_names():
    """The basic CGA colours are in a slightly different order"""
    return 'red green yellow blue magenta cyan'.split()


def reload():
    """Reload active text data-block from its file

    """
    pass


@classmethod
def new(cls, expression=None, **kwargs):
    """
        Create a :class:`~crython.expression.CronExpression` instance from the given expression string or field values.

        :param expression: (Optional) A string that can be converted to a cron expression.
        :param kwargs: (Optional) A dict that maps field names to values.
        :return: A :class:`~crython.expression.CronExpression` that represents the given string or field values.
        """
    return cls.from_str(expression) if expression else cls.from_kwargs(**kwargs
        )


def last_written_resolver(riak_object):
    """
    A conflict-resolution function that resolves by selecting the most
    recently-modified sibling by timestamp.

    :param riak_object: an object-in-conflict that will be resolved
    :type riak_object: :class:`RiakObject <riak.riak_object.RiakObject>`
    """
    riak_object.siblings = [max(riak_object.siblings, key=lambda x: x.
        last_modified)]


def min_edit_distance_align(source, target, ins_cost=lambda _x: 1, del_cost
    =lambda _x: 1, sub_cost=lambda x, y: 0 if x == y else 1):
    """Finds a minimum cost alignment between two strings.

    Uses the Levenshtein weighting as a default, but offers keyword arguments
    to supply functions to measure the costs for editing with different
    characters. Note that the alignment may not be unique.

    Args:
        ins_cost: A function describing the cost of inserting a given char
        del_cost: A function describing the cost of deleting a given char
        sub_cost: A function describing the cost of substituting one char for

    Returns:
        A sequence of tuples representing character level alignments between
        the source and target strings.
    """
    n = len(target)
    m = len(source)
    dist = [([0] * (n + 1)) for _ in range(m + 1)]
    bptrs = [([[]] * (n + 1)) for _ in range(m + 1)]
    for i in range(1, m + 1):
        dist[i][0] = i
        bptrs[i][0] = i - 1, 0
    for j in range(1, n + 1):
        dist[0][j] = j
        bptrs[0][j] = 0, j - 1
    for j in range(1, n + 1):
        for i in range(1, m + 1):
            options = [(dist[i - 1][j] + ins_cost(target[j - 1]), (i - 1, j
                )), (dist[i - 1][j - 1] + sub_cost(source[i - 1], target[j -
                1]), (i - 1, j - 1)), (dist[i][j - 1] + del_cost(source[i -
                1]), (i, j - 1))]
            minimum, pointer = sorted(options)[0]
            dist[i][j] = minimum
            bptrs[i][j] = pointer
    bt = [(m, n)]
    cell = bptrs[m][n]
    while True:
        if not cell:
            break
        bt.append(cell)
        if bptrs[cell[0]][cell[1]]:
            cell = bptrs[cell[0]][cell[1]]
        else:
            break
    trace = list(reversed(bt))
    alignment = []
    for i in range(1, len(trace)):
        current = trace[i]
        prev = trace[i - 1]
        if current[0] - prev[0] == 1 and current[1] - prev[1] == 1:
            alignment.append((source[current[0] - 1], target[current[1] - 1]))
        elif current[0] - prev[0] == 1:
            alignment.append((source[current[0] - 1], ''))
        elif current[1] - prev[1] == 1:
            alignment.append(('', target[current[1] - 1]))
    return alignment


def get_prefix_from_proxy_group(proxy_group):
    """
    Return prefix by analyzing proxy_group name

    Args:
        proxy_group (str): proxy group name

    Returns:
        str: prefix if exists, empty string if not
    """
    split_name = proxy_group.split('@')[0].split('-')
    if len(split_name) <= 2:
        return ''
    return proxy_group.split('@')[0].split('-')[-3].strip()


@classmethod
def iconize(cls, directory: str, icon_path_no_ext):
    """
        Doesn't do anything
        :param directory: The directory to iconize
        :param icon_path_no_ext: The icon file without a file extension.
                                 .png will be appended
        :return: None
        """
    pass


def graph_view_all():
    """View all curves in editor

    """
    pass


def normalize_hex(hex_color):
    """Transform a xxx hex color to xxxxxx.
    """
    hex_color = hex_color.replace('#', '').lower()
    length = len(hex_color)
    if length in (6, 8):
        return '#' + hex_color
    if length not in (3, 4):
        return None
    strhex = u'#%s%s%s' % (hex_color[0] * 2, hex_color[1] * 2, hex_color[2] * 2
        )
    if length == 4:
        strhex += hex_color[3] * 2
    return strhex


def _get_first_tag_pos(base, tag, xmlkeys):
    """Returns a position were to add a subelement with the given tag.

    Args:
        base: The base node element. (lxml node)
        tag: The id to search for. (string)
        xmlkeys: The list of possible keys in the right order for xml (list strings)

    Returns:
        The int number of were to add the element with the tag.
    """
    listrest = xmlkeys[xmlkeys.index(tag):]
    counter = 0
    for node in base:
        if node.tag.replace('{http://www.rdml.org}', '') in listrest:
            return counter
        counter += 1
    return counter


def empty(x):
    """Returns the empty value of its argument's type. Ramda defines the empty
value of Array ([]), Object ({}), String (''), and Arguments. Other
types are supported if they define <Type>.empty,
<Type>.prototype.empty or implement the
FantasyLand Monoid spec.
Dispatches to the empty method of the first argument, if present"""
    if x:
        return False
    else:
        return True


@staticmethod
def p_if_data_measurement_unsupported_element(p):
    """if_data_measurement_unsupported_element : begin IDENT generic_parameter_list end IDENT"""
    p[0] = p[1]


def network_name(nid):
    """
    Lookup the friendly name for a network ID.
    :param int nid: The network ID to look up.
    :return: The friendly name for the network.
    :rtype: str
    """
    networks = {(1): 'HSCAN', (2): 'MSCAN', (3): 'SWCAN', (4): 'LSFTCAN'}
    return networks.get(nid, 'Unknown')


def QuotedString(value):
    """Return the value quoted as needed."""
    return "'%s'" % value.replace("'", "''")


def p_attr_name(p):
    """attr_name : term"""
    p[0] = p[1]


def maybe_parentheses(obj, operator: str=' ') ->str:
    """
    Wrap the string (or object's string representation) in parentheses, but only if required.
    :param obj:
        The object to (potentially) wrap up in parentheses. If it is not a string, it is converted
        to a string first.
    :param operator:
        The operator that needs precedence rules clarified. The default is ``' '`` (a space).
    :return: The (possibly) parenthesized string.
    """
    s = str(obj)
    if operator not in s:
        return s
    open_mark = s[0]
    if open_mark in '([{':
        groupings = [s[0]]
        for c in s[1:-1]:
            if c in '([{':
                groupings.append(c)
            elif c == '}':
                if groupings[-1] == '{':
                    groupings.pop()
                else:
                    groupings.clear()
            elif c == ']':
                if groupings[-1] == '[':
                    groupings.pop()
                else:
                    groupings.clear()
            elif c == ')':
                if groupings[-1] == '(':
                    groupings.pop()
                else:
                    groupings.clear()
            if not groupings:
                return '(' + s + ')'
        if groupings[0] == '(' and groupings[-1] == ')' or groupings[0
            ] == '[' and groupings[-1] == ']' or groupings[0
            ] == '{' and groupings[-1] == '}':
            return s
    return '(' + s + ')' if operator in s else s


@classmethod
def get_last_id(cls):
    """ Return the last primary key ``id`` value
        """
    res = cls.query('id').order_by(cls.id.desc()).limit(1).first()
    if res:
        return res[0]
    return 0


def put_dic(f, dic, dataset='spectrum'):
    """
    Put a dictionary to the dataset in a HDF5 File
    """
    dset = f[dataset]
    for key, value in dic.items():
        if type(key) == int and type(value) == dict:
            axis = key
            for axiskey, axisvalue in value.items():
                fullkey = str(axis) + '_' + axiskey
                dset.attrs[fullkey] = axisvalue
        else:
            dset.attrs[key] = value
    return


def _pipe_segment_with_colons(align, colwidth):
    """Return a segment of a horizontal line with optional colons which
    indicate column's alignment (as in `pipe` output format)."""
    w = colwidth
    if align in ['right', 'decimal']:
        return '-' * (w - 1) + ':'
    elif align == 'center':
        return ':' + '-' * (w - 2) + ':'
    elif align == 'left':
        return ':' + '-' * (w - 1)
    else:
        return '-' * w


@staticmethod
def _grad_f_w(x, d_l=None):
    """
        Derivative of the classifier decision function w.r.t. the
        weights
        """
    d = x.T
    if d_l is not None:
        d *= d_l
    return d


@classmethod
def create_conntrack_helper(cls, router_id, helper, protocol, port, client=None
    ):
    """Create a conntrack helper

        Create a conntrack helper and schedule it for later deletion. If a
        client is passed, then it is used for deleteing the CTH too.

        :param router_id: The ID of the Neutron router associated to the
        conntrack helper.

        :param helper: The conntrack helper module alias

        :param protocol: The conntrack helper IP protocol used in the conntrack
        helper.

        :param port: The conntrack helper IP protocol port number for the
        conntrack helper.

        :param client: network client to be used for creating and cleaning up
        the conntrack helper.
        """
    client = client or cls.client
    cth = client.create_conntrack_helper(router_id, helper, protocol, port)[
        'conntrack_helper']
    cth['router_id'] = router_id
    cth['client'] = client
    cls.conntrack_helpers.append(cth)
    return cth


@staticmethod
def _bool_status(status: str) ->bool:
    """
        Converts a status string from DBus to a bool, to keep consistency
        with the other API status variables.
        """
    return status.lower() == 'playing'


@staticmethod
def calculate_item_height(text_font_size):
    """Calculate the item height"""
    return max(2.5 * text_font_size, 10)


def writeTemperatures(temp, model):
    """Gas and dust temperatures."""
    temp.append('void temperature(double x, double y, double z, ')
    temp.append('double *temperature) {\n\n')
    temp.append('\ttemperature[0] = findvalue(x, y, z, temp);\n')
    if model.rescaletemp:
        temp.append('\ttemperature[0] *= %.3f;\n' % model.rescaletemp)
    temp.append('\tif (temperature[0] < %.2f) ' % model.tcmb)
    temp.append('{\n\t\ttemperature[0] = %.2f;\n\t}\n\n' % model.tcmb)
    if type(model.dtemp) is float:
        temp.append('\ttemperature[1] = %.3f * temperature[0];' % model.dtemp)
        temp.append('\n\n')
    else:
        temp.append('\ttemperature[1] = findvalue(x, y, z, dtemp);\n')
        temp.append('\tif (temperature[1] < %.2f) ' % model.tcmb)
        temp.append('{\n\t\ttemperature[1] = %.2f;\n\t}\n' % model.tcmb)
    temp.append('}\n\n\n')
    return


def null_distance_results(string1, string2, max_distance):
    """Determines the proper return value of an edit distance function
    when one or both strings are null.

    Parameters
    ----------
    string_1 : str
        Base string.
    string_2 : str
        The string to compare.
    max_distance : int
        The maximum distance allowed.

    Returns
    -------
    int
        -1 if the distance is greater than the max_distance, 0 if the
        strings are equivalent (both are None), otherwise a positive
        number whose magnitude is the length of the string which is not
        None.
    """
    if string1 is None:
        if string2 is None:
            return 0
        else:
            return len(string2) if len(string2) <= max_distance else -1
    return len(string1) if len(string1) <= max_distance else -1


@staticmethod
def _class_name(clas, parts=0):
    """Given a class object, return a fully-qualified name.

        This works for things I've tested in matplotlib so far, but may not be
        completely general.
        """
    module = clas.__module__
    if module == '__builtin__':
        fullname = clas.__name__
    else:
        fullname = '%s.%s' % (module, clas.__name__)
    if parts == 0:
        return fullname
    name_parts = fullname.split('.')
    return '.'.join(name_parts[-parts:])


def register_class(cls_name, cls, is_unique=False):
    """
    This function registers given class into tpRigToolkit module
    :param cls_name: str, name of the class we want to register
    :param cls: class, class we want to register
    :param is_unique: bool, Whether if the class should be updated if new class is registered with the same name
    """
    import tpRigToolkit
    if is_unique:
        if cls_name in tpRigToolkit.__dict__:
            setattr(tpRigToolkit.__dict__, cls_name, getattr(tpRigToolkit.
                __dict__, cls_name))
    else:
        tpRigToolkit.__dict__[cls_name] = cls


def GetNode(Mapping, X, Y):
    """
	Return Node mapped at given coordinates.
	"""
    for Node, Coord in Mapping.items():
        if Coord == (X, Y):
            return Node
    return None


def sym(dim=1):
    """
    Symmetrical matrix
    """
    from ..C_funcs.constructors import symzerone
    return symzerone(dim)


def raise_error():
    """Raise any error associated with this node."""


def rsplit1(s, sep):
    """The same as s.rsplit(sep, 1), but works in 2.3"""
    parts = s.split(sep)
    return sep.join(parts[:-1]), parts[-1]


def getStatus():
    """Return an IBuildStatus object for the Build that I control."""


def update_master_list(master_list, layer_obj):
    """Given a master list of package objects and a layer object containing a
    list of package objects, append to the master list all the package objects
    that are not in the master list and remove the duplicate packages from the
    layer object"""
    unique = []
    for _ in range(len(layer_obj.packages)):
        item = layer_obj.packages.pop(0)
        exists = False
        for pkg in master_list:
            if item.is_equal(pkg):
                exists = True
                break
        if not exists:
            unique.append(item)
    for u in unique:
        master_list.append(u)
    while unique:
        layer_obj.packages.append(unique.pop(0))
    del unique


def segregate(str):
    """3.1 Basic code point segregation"""
    base = bytearray()
    extended = set()
    for c in str:
        if ord(c) < 128:
            base.append(ord(c))
        else:
            extended.add(c)
    extended = sorted(extended)
    return bytes(base), extended


def _encode_asn1_utf8_str(backend, string):
    """
    Create an ASN1_UTF8STRING from a Python unicode string.
    This object will be an ASN1_STRING with UTF8 type in OpenSSL and
    can be decoded with ASN1_STRING_to_UTF8.
    """
    s = backend._lib.ASN1_UTF8STRING_new()
    res = backend._lib.ASN1_STRING_set(s, string.encode('utf8'), len(string
        .encode('utf8')))
    backend.openssl_assert(res == 1)
    return s


def string_bool(argument):
    """
    Converts True, true, False, False in python boolean values
    """
    if argument is None:
        msg = (
            'argument required but none supplied; choose from "True" or "False"'
            )
        raise ValueError(msg)
    elif argument.lower() == 'true':
        return True
    elif argument.lower() == 'false':
        return False
    else:
        raise ValueError('"%s" unknown; choose from "True" or "False"' %
            argument)


@staticmethod
def graph_generation(result_dict):
    """
        Graph generaiton
        :return: nothing
        """
    return []


@classmethod
def get_repo_notifications(cls, repository_id, event=None):
    """Returns a queryset with the notifications for a given repository
        and event.

        :param repository_id: The id of the repository that sent an event.
        :param event: The event that will trigger notifications."""
    if event:
        events_kw = {'_events': event}
    else:
        events_kw = {'_events': []}
    return cls.objects.filter(repository_id=repository_id, **events_kw)


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

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


@classmethod
def from_dict(cls, d):
    """Create class entirely from dictonary.
        """
    atoms = d.pop('_atoms')
    lattice = d.pop('_lattice')
    density = d.pop('_density')
    file_info = d.pop('_file_info')
    cls(density, lattice, atoms, file_info, **d)


@staticmethod
def map_phrases_in_venue(phrase_mapper, partial_event):
    """Map place phrases in the venue and find us fields of a partial
        event."""
    return phrase_mapper.map_phrases(partial_event.venue_name
        ) + phrase_mapper.map_phrases(partial_event.find_us)


def sizeForSorting():
    """Returns a tuple (basic_unit, amount)

        Used for sorting among different kinds of sized objects.
        'amount' need only be sortable among things that share the
        same basic unit."""


@classmethod
def get_carrier_methods_for_domain(cls):
    """
        Return the list of carrier methods that can be used for
        address validation
        """
    return []


def get_library(gi, lib_name, lib_desc='', lib_synopsis='', create=True):
    """
    Get the id corresponding to given library, and create it if it doesn't exist yet
    """
    print("Looking for lib '" + lib_name + "'")
    libs = gi.libraries.get_libraries()
    found_lib = None
    for lib in libs:
        if not found_lib and lib['name'] == lib_name and lib['deleted'
            ] is False:
            print("Found library '" + lib_name + "'")
            found_lib = lib['id']
    if not found_lib:
        if create:
            print("Did not find library '" + lib_name + "', creating it")
            create = gi.libraries.create_library(lib_name, lib_desc,
                lib_synopsis)
            found_lib = create['id']
        else:
            raise Exception("Did not find library '" + lib_name + "'")
    return found_lib


def get_current_scene_db(scene_root, history_db):
    """calls the function to get the location of the history db"""
    import os
    from src.praxxis.sqlite import sqlite_scene
    scene = sqlite_scene.get_current_scene(history_db)
    return os.path.join(scene_root, scene, '%s.db' % scene)


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

        :param MemberDeleteProfilePhotoDetails val:
        :rtype: EventDetails
        """
    return cls('member_delete_profile_photo_details', val)


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

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


def get_state_id_for_port(port):
    """This method returns the state ID of the state containing the given port

    :param port: Port to check for containing state ID
    :return: State ID of state containing port
    """
    parent = port.parent
    from rafcon.gui.mygaphas.items.state import StateView
    if isinstance(parent, StateView):
        return parent.model.state.state_id


def parse_json(request):
    """
    Default content parser for JSON
    """
    return request.json


def __init__(cls, name, bases, namespace, **kwargs):
    """Perform some additional class object initialization."""
    super().__init__(name, bases, namespace)
    try:
        cls._with_context = kwargs.pop('with_context')
    except KeyError:
        pass


@staticmethod
def _fix_statistics_keys(statistics):
    """
        Helper function to clean up the response from the statistics endpoint by removing
        misspelled statistics keys.

        :param statistics: Dictionary containing statistics, modified by reference
        :return:
        """
    if 'numberOf' in statistics:
        number_of = statistics['numberOf']
        if 'unsendtNotifications' in number_of:
            number_of['unsentNotifications'] = number_of['unsendtNotifications'
                ]
            del number_of['unsendtNotifications']


def compression_ratio(initial_edge, final_edge, poweredge, _):
    """Compute data compression ratio"""
    try:
        return initial_edge / (final_edge + poweredge)
    except ZeroDivisionError:
        return 1.0


@staticmethod
def get_subtype(object_dictionary):
    """
        Given the hash representation of a subtype of this class,
        use the info in the hash to return the class of the subtype.
        """
    type = object_dictionary['type']
    if type == 'NFS':
        return 'CreateNFSBackupDestinationDetails'
    if type == 'RECOVERY_APPLIANCE':
        return 'CreateRecoveryApplianceBackupDestinationDetails'
    else:
        return 'CreateBackupDestinationDetails'


@classmethod
def _convert_to_style(cls, style_dict):
    """
        converts a style_dict to an openpyxl style object
        Parameters
        ----------
        style_dict: style dictionary to convert
        """
    from openpyxl.style import Style
    xls_style = Style()
    for key, value in style_dict.items():
        for nk, nv in value.items():
            if key == 'borders':
                xls_style.borders.__getattribute__(nk).__setattr__(
                    'border_style', nv)
            else:
                xls_style.__getattribute__(key).__setattr__(nk, nv)
    return xls_style


def get_app_label_from_import_path(import_path):
    """App authors must not override AppConfig.label"""
    return import_path.split('.')[-2]


@classmethod
def startRuleUsageTracking(cls):
    """Enables the selector recording.
        """
    return cls.build_send_payload('startRuleUsageTracking', {}), None


def Pathlen_ULdigraph_Intermediate(N):
    """
    Largest possible pathlength for a digraph with L = (N-1) + 1/2 N(N-1) arcs.

    Calculates the pathlength of a digraph consisting of the superposition of
    a directed ring with a complete directed acyclic graph whose arcs are
    pointing in the opposite orientations as the ring. That is, each vertex j
    points to all other vertices with i < j.

    Reference and citation
    ^^^^^^^^^^^^^^^^^^^^^^
    G. Zamora-López & R. Brasselet "Sizing complex networks" Commun Phys 2:144 (2019)

    Parameters
    ----------
    N : integer
        Number of nodes in the digraph.

    Returns
    -------
    avpathlen : float
        The average pathlength of the digraph.

    See Also
    --------
    Pathlen_ULdigraph :
    Pathlen_ULdigraph_Range1_MBS :
    Pathlen_ULdigraph_Range1_Approx :
    Pathlen_ULdigraph_Range2 :
    """
    if N < 2:
        raise ValueError('Network needs at least two nodes, N > 1')
    avpathlen = float(N + 4) / 6
    return avpathlen


def flexint(v):
    """Convert strings to integer values.

    The block read/write commands accept integer values as either
    decimal or hexadecimal. This function converts either format into
    integer values."""
    if isinstance(v, int):
        return v
    else:
        return int(v, 0)


def di(obj):
    """Returns dependency injector used to construct class

    This instance is useful to propagate dependencies
    """
    try:
        return obj.__zorro_di__
    except AttributeError:
        raise RuntimeError('No dependency injector found')


def compare_strictly(histo1, histo2):
    """Check if two histograms (1D numpy arrays) or two sets of histograms (2D
    numpy arrays) are identical.

    Only suitable to check the results of double precision computations.
    """
    assert (histo1 == histo2).all()


def iso8601_repr(timedelta, format=None):
    """
    Represent a timedelta as an ISO8601 duration.
    http://en.wikipedia.org/wiki/ISO_8601#Durations
    """
    years = int(timedelta.days / 365)
    weeks = int(timedelta.days % 365 / 7)
    days = timedelta.days % 7
    hours = int(timedelta.seconds / 3600)
    minutes = int(timedelta.seconds % 3600 / 60)
    seconds = timedelta.seconds % 60
    if format == 'alt':
        if years or weeks or days:
            raise ValueError(
                'Does not support `alt` format for durations more then 1 day')
        return 'PT{0:02d}:{1:02d}:{2:02d}'.format(hours, minutes, seconds)
    formatting = ('P', (('Y', years), ('W', weeks), ('D', days))), ('T', ((
        'H', hours), ('M', minutes), ('S', seconds)))
    result = []
    for category, subcats in formatting:
        result += category
        for format, value in subcats:
            if value:
                result.append('%d%c' % (value, format))
    if result[-1] == 'T':
        result = result[:-1]
    return ''.join(result)


def nack(messageid, subscriptionid, transactionid=None):
    """STOMP negative acknowledge command.

    NACK is the opposite of ACK. It is used to tell the server that the client
    did not consume the message. The server can then either send the message to
    a different client, discard it, or put it in a dead letter queue. The exact
    behavior is server specific.

    messageid:
        This is the id of the message we are acknowledging,
        what else could it be? ;)

    subscriptionid:
        This is the id of the subscription that applies to the message.

    transactionid:
        This is the id that all actions in this transaction
        will have. If this is not given then a random UUID
        will be generated for this.

    """
    header = 'subscription:%s\nmessage-id:%s' % (subscriptionid, messageid)
    if transactionid:
        header += '\ntransaction:%s' % transactionid
    return 'NACK\n%s\n\n\x00\n' % header


def p_definition_list(t):
    """definition_list : definition definition_list
                       | empty"""


def print_seq_names(outfile, euk_ids, prok_ids, prokarya):
    """
    Write predicted euk and predicted prok scaffolds names to their respective output files
    """
    for line in euk_ids:
        outfile.write(line + '\n')
    if prokarya is not None:
        for line in prok_ids:
            prokarya.write(line + '\n')


def filter_by_user(model, user):
    """
    helper function to filter queryset by user or all if superuser
    """
    m = model.objects
    return m.all() if user.is_superuser else m.filter(user=user.id)


def select_prev_item():
    """Select the previous element (using selection order)

    """
    pass


@classmethod
def _get_column_by_db_name(cls, name):
    """
        Returns the column, mapped by db_field name
        """
    return cls._columns.get(cls._db_map.get(name, name))


def shader_script_update():
    """Update shader script node with new sockets and options from the script

    """
    pass


@classmethod
def show_general(cls, orders_pd, action_pd, capital, benchmark, returns_cmp
    =False, only_info=False, only_show_returns=False,
    enable_stocks_full_rate_factor=False):
    """
        类方法，针对输入执行度量后执行主要度量可视化及度量结果信息输出
        :param orders_pd: 回测结果生成的交易订单构成的pd.DataFrame对象
        :param action_pd: 回测结果生成的交易行为构成的pd.DataFrame对象
        :param capital: 资金类AbuCapital实例化对象
        :param benchmark: 交易基准对象，AbuBenchmark实例对象
        :param returns_cmp: 是否只度量无资金管理的情况下总体情况
        :param only_info: 是否只显示文字度量结果，不显示图像
        :param only_show_returns: 透传plot_returns_cmp，默认False, True则只显示收益对比不显示其它可视化
        :param enable_stocks_full_rate_factor: 是否开启满仓乘数
        :return AbuMetricsBase实例化类型对象
        """
    metrics = cls(orders_pd, action_pd, capital, benchmark,
        enable_stocks_full_rate_factor=enable_stocks_full_rate_factor)
    metrics.fit_metrics()
    if returns_cmp:
        metrics.plot_order_returns_cmp(only_info=only_info)
    else:
        metrics.plot_returns_cmp(only_info=only_info, only_show_returns=
            only_show_returns)
        if not only_show_returns:
            metrics.plot_sharp_volatility_cmp(only_info=only_info)
    return metrics


def convert_column(column, conversion):
    """
    Convert column with conversion.
    Return converted column.
    """
    target, convert = conversion
    origin = column.dtype.kind
    return convert[target][origin](column)


@classmethod
def modify_url_for_impersonation(cls, url, impersonate_user: bool, username:
    str):
    """
        Modify the SQL Alchemy URL object with the user to impersonate if applicable.
        :param url: SQLAlchemy URL object
        :param impersonate_user: Flag indicating if impersonation is enabled
        :param username: Effective username
        """
    if impersonate_user is not None and username is not None:
        url.username = username


def transforms_clear():
    """Reset location, rotation, and scaling of selected bones to their default values

    """
    pass


def copy_service_to_services_backward(apps, schema_editor):
    """Copy the first service from ManyToManyField to ForeignKeyField."""
    Incident = apps.get_model('statusboard', 'incident')
    db_alias = schema_editor.connection.alias
    for i in Incident.objects.using(db_alias).all():
        s = i.services.first()
        if s is not None:
            i.service = s
            i.save()


def _splitdict(tk, v, cut_minus=True, conv=None):
    """Return a properly formatted dict built from Tcl list pairs.
    If cut_minus is True, the supposed '-' prefix will be removed from
    keys. If conv is specified, it is used to convert values.
    Tcl list is expected to contain an even number of elements.
    """
    t = tk.splitlist(v)
    if len(t) % 2:
        raise RuntimeError(
            'Tcl list representing a dict is expected to contain an even number of elements'
            )
    it = iter(t)
    dict = {}
    for key, value in zip(it, it):
        key = str(key)
        if cut_minus and key[0] == '-':
            key = key[1:]
        if conv:
            value = conv(value)
        dict[key] = value
    return dict


def poly_compare(poly1, poly2, area):
    """Calculate the ratio of overlap between two polygons and the given area

    :param poly1: polygon specified by its verticies
    :type poly1: list
    :param poly2: polygon specified by its verticies
    :type poly2: list
    :param area: the area to compare the overlap of poly1 and poly2
    :type area: float
    :return: the ratio of overlap of poly1 and poly2 to the area  e.g. overlap(poly1, poly2)/area
    :rtype: float
    """
    assert area > 0
    intersection_area = help.polygon_intersection_area([poly1, poly2])
    return intersection_area / area


def velocity(vo2):
    """
    A regression equation relating VO2 with running velocity. Used in conjuction with the "vO2" equation to create the Jack Daniel's VDOT tables. Initially retrieved from "Oxygen Power: Performance Tables for Distance Runners" by Jack Daniels.

    J., Daniels, and J. Daniels. Conditioning for Distance Running: The Scientific Aspects. New York: John Wiley and Sons., n.d. Print.

    args:
        vo2 (float): VO2, given in mL/kg/minute

    Returns:
        float: velocity, in meters/minute
    """
    return 29.54 + 5.000663 * vo2 - 0.007546 * pow(vo2, 2)


def optical_laser_active(event):
    """
    Retrieves from Karabo the status of the optical laser at XFEL.

    Returns whether, in pump probe experiments, the optical laser is active for the
    current frame. Currently Karabo provides no information about the status of
    optical lasers at XFEL. Hence, this function determines the status of the laser
    according to information provided in the OnDA configuration file.

    * The file must include a entry called 'karabo_frame_ids_with_optical_laser_active'
      in the 'DataRetrievalLayer' parameter group.

    * The entry must contain a list of frame indexes for which the optical laser is
      supposed to be active.

    * If the index of the current frame within the event is included in the list, the
      optical laser is considered to be active.

    Arguments:

        event (:class:`~onda.utils.data_event.DataEvent`): an object storing the event
            data.

    Returns:

        bool: True if the optical laser is active, False otherwise.
    """
    frame_cell_id = event.data[event.framework_info['data_label']][
        'image.pulseId'][event.current_frame]
    return frame_cell_id in event.framework_info['frames_with_optical_laser']


def update_template_strings(variable, quote_results):
    """
    The following function will replace all {{ tag }} variables in the template with the results from the quote
    results. The current variables are;

    Groups
    ~~~~~~
    1.) Quotes
    2.) Organisatiions
    3.) Quote Billing Address
    """
    variable = variable.replace('{{ customer_id }}', str(quote_results.
        customer_id))
    variable = variable.replace('{{ customer_notes }}', quote_results.
        customer_notes)
    variable = variable.replace('{{ is_invoice }}', quote_results.is_invoice)
    variable = variable.replace('{{ opportunity_id }}', str(quote_results.
        opportunity_id))
    variable = variable.replace('{{ organisation_id }}', str(quote_results.
        organisation_id))
    variable = variable.replace('{{ project_id }}', str(quote_results.
        project_id))
    variable = variable.replace('{{ quote_billing_address }}', str(
        quote_results.quote_billing_address))
    variable = variable.replace('{{ quote_id }}', str(quote_results.quote_id))
    variable = variable.replace('{{ quote_stage_id }}', str(quote_results.
        quote_stage_id))
    variable = variable.replace('{{ quote_terms }}', quote_results.quote_terms)
    variable = variable.replace('{{ quote_title }}', quote_results.quote_title)
    variable = variable.replace('{{ quote_valid_till }}', str(quote_results
        .quote_valid_till))
    variable = variable.replace('{{ task_id }}', str(quote_results.task_id))
    if quote_results.organisation_id:
        variable = variable.replace('{{ organisation_name }}',
            quote_results.organisation_id.organisation_name)
        variable = variable.replace('{{ organisation_website }}',
            quote_results.organisation_id.organisation_website)
        variable = variable.replace('{{ organisation_email }}',
            quote_results.organisation_id.organisation_email)
    else:
        variable = variable.replace('{{ organisation_name }}', '')
        variable = variable.replace('{{ organisation_website }}', '')
        variable = variable.replace('{{ organisation_email }}', '')
    if quote_results.quote_billing_address:
        variable = variable.replace('{{ billing_address1 }}', quote_results
            .quote_billing_address.campus_address1)
        variable = variable.replace('{{ billing_address2 }}', quote_results
            .quote_billing_address.campus_address2)
        variable = variable.replace('{{ billing_address3 }}', quote_results
            .quote_billing_address.campus_address3)
        variable = variable.replace('{{ campus_id }}', str(quote_results.
            quote_billing_address.campus_id))
        variable = variable.replace('{{ campus_nickname }}', quote_results.
            quote_billing_address.campus_nickname)
        variable = variable.replace('{{ campus_phone }}', quote_results.
            quote_billing_address.campus_phone)
        variable = variable.replace('{{ campus_region_id }}', str(
            quote_results.quote_billing_address.campus_region_id))
        variable = variable.replace('{{ billing_suburb }}', quote_results.
            quote_billing_address.campus_suburb)
        if quote_results.quote_billing_address.campus_postcode == None:
            variable = variable.replace('{{ billing_postcode }}', '')
        else:
            variable = variable.replace('{{ billing_postcode }}', str(
                quote_results.quote_billing_address.campus_postcode))
        variable = variable.replace('{{ billing_region }}', str(
            quote_results.quote_billing_address.campus_region_id))
        variable = variable.replace('{{ billing_country }}', str(
            quote_results.quote_billing_address.campus_country_id))
    else:
        variable = variable.replace('{{ billing_address1 }}', '')
        variable = variable.replace('{{ billing_address2 }}', '')
        variable = variable.replace('{{ billing_address3 }}', '')
        variable = variable.replace('{{ billing_postcode }}', '')
        variable = variable.replace('{{ campus_id }}', '')
        variable = variable.replace('{{ campus_nickname }}', '')
        variable = variable.replace('{{ campus_phone }}', '')
        variable = variable.replace('{{ campus_region_id }}', '')
        variable = variable.replace('{{ billing_suburb }}', '')
        variable = variable.replace('{{ billing_region }}', '')
        variable = variable.replace('{{ billing_country }}', '')
    return variable


@classmethod
def get_name(cls):
    """Return a human-readable (one or two word) name for this plugin.

        Subclasses should set the class attribute NAME, which is
        returned by the default implementation.
        """
    if not cls.NAME:
        raise NotImplementedError
    return cls.NAME


@classmethod
def start_recording_skipped(cls):
    """
        Start collecting OptionErrors for all skipped options recorded
        with the record_skipped_option method
        """
    cls._errors_recorded = []


def getKnownGroupEffects(fulldata, batchfilename):
    """ Check the input file for KNOWN possible group effects
    Exclude those that may not exist such as TREATMENT. Make no
    assumptions about order or sorting. Return list in arbitrary
    order. Independent of list provided by the user
    """
    foundColumns = list()
    listOneHotEncoded = list()
    if batchfilename == False:
        print('Using hard coded batch effect names')
        currentPossibleColumnEffects = ['TREATMENT', 'MOUSE', 'SEX', 'DATE',
            'NODEID']
        allColumns = fulldata.columns.values
        listOneHotEncoded = ['MOUSE']
        foundColumns = list(set(allColumns) & set(currentPossibleColumnEffects)
            )
    else:
        foundColumnsCombined = list()
        with open(batchfilename) as f:
            tempColumns = f.read().splitlines()
            for effect in tempColumns:
                foundColumnsCombined.append(effect)
            for ipair in foundColumnsCombined:
                name, typeEnc = ipair.strip().split(' ')
                foundColumns.append(name)
                if typeEnc == 'ONEHOT':
                    listOneHotEncoded.append(name)
    print('Number of Possible batch effects found/specified is ' + str(len(
        foundColumns)))
    print('Number of groupeffect columns in data is ' + str(foundColumns))
    print('They have been converted to UPPER CASE: ' + str(foundColumns))
    return foundColumns, listOneHotEncoded


def post_install(context):
    """Post install script"""
    if context.readDataFile('cciaapdportletbandi_default.txt') is None:
        return


def calc_system_ndof(natoms, nmolecs, nbonds, stop_com_tra, stop_com_rot):
    """
    Calculates the total / translational / rotational & internal /
    rotational / internal degrees of freedom of the system.

    Parameters
    ----------
    natoms : int
        Total number of atoms in the system
    nmolecs : int
        Total number of molecules in the system
    nbonds : int
        Total number of bonds in the system
    stop_com_tra : bool
        Was the center-of-mass translation removed during the simulation?
    stop_com_rot : bool
        Was the center-of-mass translation removed during the simulation?

    Returns
    -------
    ndof : dict
        Dictionary containing the degrees of freedom.
        Keys: ['tot', 'tra', 'rni', 'rot', 'int']
    """
    ndof_tot = 3 * natoms - nbonds
    if stop_com_tra:
        ndof_tot -= 3
    if stop_com_rot:
        ndof_tot -= 3
    ndof_tot_tra = 3 * nmolecs
    if stop_com_tra:
        ndof_tot -= 3
    ndof_tot_rni = ndof_tot - ndof_tot_tra
    ndof_tot_rot = 3 * nmolecs
    if stop_com_tra:
        ndof_tot -= 3
    ndof_tot_int = ndof_tot_rni - ndof_tot_rot
    ndof = {'tot': ndof_tot, 'tra': ndof_tot_tra, 'rni': ndof_tot_rni,
        'rot': ndof_tot_rot, 'int': ndof_tot_int}
    return ndof


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

        :param TeamSelectiveSyncPolicyChangedDetails val:
        :rtype: EventDetails
        """
    return cls('team_selective_sync_policy_changed_details', val)


def get_election_summary(election, request, url=None):
    """ Returns some basic informations about the given election as a JSON
    seriazable dict. """
    last_modified = election.last_modified
    if last_modified:
        last_modified = last_modified.isoformat()
    return {'completed': election.completed, 'date': election.date.
        isoformat(), 'domain': election.domain, 'elected': election.
        elected_candidates, 'last_modified': last_modified, 'progress': {
        'counted': election.progress[0] or 0, 'total': election.progress[1] or
        0}, 'title': election.title_translations, 'type': 'election', 'url':
        url or request.link(election)}


@classmethod
def keys(cls, name, hash_key, range_key=None, throughput=None):
    """ Create an index that projects only key attributes """
    return cls(cls.KEYS, name, hash_key, range_key, throughput=throughput)


def historical_player_salary_values(html_text):
    """ historical_player_salary_values returns a dictionary of
    salary information keyed by Hoopshype player ID

    @param **html_text** (*str*): String of the HTML response
    from a Hoopshype team URL

    Returns:

        **player_salaries** (*dict*): Dictionary keyed by Hoopshype
            player ID with a list of salary and inflation-adjusted
            salary (followed by player salary URL) as values
    """
    value_str = 'data-value="'
    option_str = 'style="'
    player_salaries = {}
    url_val = html_text.find('Totals	')
    while url_val < total_val:
        player_list = []
        start_ind = html_text.find('<a')
        end_ind = html_text.find('')
        play_key = html_text[start_ind + 2:end_ind]
        play_key = play_key[play_key.find('href="') + 6:play_key.find('">\n')]
        player_key = play_key.split('/')[-3]
        html_text = html_text[end_ind + 4:]
        for col_count in range(0, 2):
            start_ind = html_text.find(option_str) + len(option_str)
            end_ind = html_text.find('" ')
            html_text = html_text[end_ind + 2:]
            start_ind = html_text.find(value_str) + len(value_str)
            end_ind = html_text.find('">')
            try:
                salary_value = int(html_text[start_ind:end_ind])
            except:
                salary_value = 0
            player_list.append(salary_value)
            html_text = html_text[end_ind + 2:]
        player_list.append(play_key)
        player_salaries[player_key] = {}
        player_salaries[player_key]['salary'] = player_list
        total_val = html_text.find('class="name">Totals	')
        url_val = html_text.find('<a')
    return player_salaries


def delete_model(restApiId=None, modelName=None):
    """
    Deletes a model.
    See also: AWS API Documentation

    :example: response = client.delete_model(
        restApiId='string',
        modelName='string'
    )

    :type restApiId: string
    :param restApiId: [REQUIRED]
            The RestApi under which the model will be deleted.

    :type modelName: string
    :param modelName: [REQUIRED]
            The name of the model to delete.

    """
    pass


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

        :param ShowcaseFileAddedType val:
        :rtype: EventType
        """
    return cls('showcase_file_added', val)


def is_success(status):
    """
    Check if HTTP status code is successful.

    :param status: http status code
    :returns: True if status is successful, else False
    """
    return 200 <= status <= 299


@classmethod
def register(cls, key, default):
    """Register individual defaults by calling this method"""
    cls._defaults[cls.prefixed(key)] = default


def extract_ace(archive, compression, cmd, verbosity, interactive, outdir):
    """Extract an ACE archive."""
    cmdlist = [cmd, 'x']
    if not outdir.endswith('/'):
        outdir += '/'
    cmdlist.extend([archive, outdir])
    return cmdlist


@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 {'required_addresses': {'replyer': str}, 'optional_addresses': {}}


def isProduct(filename):
    """Return True if 'filename' is a "product" name.

    Parameters
    ----------
    filename: str
        Name of an output file.

    Returns
    -------
    is_product: boolean
        True if the root part (before the suffix) of 'filename' ends in '0',
        implying that it is a product name.
    """
    is_product = False
    i = filename.rfind('_')
    if i > 0 and filename[i:] == '_a.fits' or filename[i:] == '_b.fits':
        i = filename[0:i - 1].rfind('_')
    if i > 0 and filename[i - 1] == '0':
        is_product = True
    return is_product


def context_set_float(data_path: str='', value: float=0.0, relative: bool=False
    ):
    """Set a context value

    :param data_path: Context Attributes, RNA context string
    :type data_path: str
    :param value: Value, Assignment value
    :type value: float
    :param relative: Relative, Apply relative to the current value (delta)
    :type relative: bool
    """
    pass


@classmethod
def from_db(cls, db, force=False):
    """Make instance from database.

        For performance, this caches the episode types for the database.  The
        `force` parameter can be used to bypass this.

        """
    if force or db not in cls._cache:
        cls._cache[db] = cls._new_from_db(db)
    return cls._cache[db]


@staticmethod
def get_reverse_state(state):
    """Do a symmetry around 1 of the state ::

        * 0 -> 2
        * 1 -> 1
        * 2 -> 0
        * else -> else

        :param state: state to reverse
        :type state: int
        :return: Integer from 0 to 2 (usually)
        :rtype: int
        """
    if state == 1:
        return 1
    if state == 0:
        return 2
    if state == 2:
        return 0
    return state


def is_class_method(f):
    """Returns whether the given method is a class_method."""
    return hasattr(f, '__self__') and f.__self__ is not None


def primes(imax):
    """
    Returns prime numbers up to imax.

    Parameters
    ----------
    imax: int
        The number of primes to return. This should be less or equal to 10000.

    Returns
    -------
    result: list
        The list of prime numbers.
    """
    p = list(range(10000))
    result = []
    k = 0
    n = 2
    if imax > 10000:
        raise ValueError('imax should be <= 10000')
    while len(result) < imax:
        i = 0
        while i < k and n % p[i] != 0:
            i = i + 1
        if i == k:
            p[k] = n
            k = k + 1
            result.append(n)
            if k > 10000:
                break
        n = n + 1
    return result


def get_extent(iterator):
    """returns (min, max) of iterator"""
    iterator = iter(iterator)
    m = M = next(iterator)
    for elem in iterator:
        if elem < m:
            m = elem
        elif elem > M:
            M = elem
    return m, M


@classmethod
def get_row_permission(cls, obj, ar, state, ba):
    """Returns True or False whether the given action request
        ActionRequest `ar` is allowed on the given row instance `row`.

        """
    if ba.action.readonly:
        return True
    if ar.get_user().user_type.readonly:
        return False
    return cls.editable


def dpf_flags_osr(parser, flags=None):
    """
    Add generic OS/radio/software flags to parser.

    :param parser: Parser to modify.
    :type parser: argparse.ArgumentParser

    :param flags: Tuple of sections to add.
    :type flags: tuple(str)
    """
    if 'osr' in flags:
        parser.add_argument('os', help='OS version')
        parser.add_argument('radio', help='Radio version, 10.x.y.zzzz',
            nargs='?', default=None)
        parser.add_argument('swrelease', help=
            'Software version, 10.x.y.zzzz', nargs='?', default=None)
    return parser


def p_visibility_modifier(p):
    """visibility_modifier : PUBLIC
                           | PROTECTED
                           | PRIVATE"""
    p[0] = p[1].lower()


def read_file(file_path):
    """
    Reads the contents of the given file.
    :param file_path: the file path to read
    :return: the contents of the file
    """
    with open(file_path) as f:
        return f.read()


def plural(n):
    """Utility function to optionally pluralize words based on the value of n.
    """
    if n == 1:
        return ''
    else:
        return 's'


def plugins_enabled():
    """List of plugins enabled."""


def RemoveDominated(Candidates, Constraints):
    """
	List candidate modules for each task.
	"""
    return Candidates


def codegen_reload_data():
    """Parameters to codegen used to generate the algosec_resilient package"""
    reload_params = {'package': u'algosec_resilient', 'incident_fields': [],
        'action_fields': [], 'function_params': [u'algosec_hostname'],
        'datatables': [u'algosec_associated_applications',
        u'algosec_internet_connectivity_queries',
        u'algosec_isolation_requests'], 'message_destinations': [u'algosec'
        ], 'functions': [u'algosec_check_host_internet_connectivity',
        u'algosec_isolate_host_from_network',
        u'algosec_list_associated_applications'], 'phases': [],
        'automatic_tasks': [], 'scripts': [], 'workflows': [
        u'example_algosec_check_host_internet_connectivity',
        u'example_algosec_isolate_host_from_network',
        u'example_algosec_list_associated_applications'], 'actions': [
        u'Example: AlgoSec: Check Host Internet Connectivity',
        u'Example: AlgoSec: List Associated Applications',
        u'Isolate from Network (AlgoSec)']}
    return reload_params


@classmethod
def set_purge(cls, value):
    """
        sets the default for all clouds to refresh
        :param value:
        :return:
        """
    if str(value) in ['on', 'True']:
        cls.set('purge', 'True')
    else:
        cls.set('purge', 'False')


@staticmethod
def transform(input_value):
    """Transform input value to string representation."""
    return str(input_value)


def __iter__():
    """Iterator returning the versions.

        The iterators ``next`` method returns ``IVersionData`` objects.
        """


@classmethod
def construct_from_other(cls, other):
    """
        Construct API-based client from another API-based client

        :param other: API-based client to get connection options from
        :return: self -- new client
        """
    return cls(other._base_url, other._token, other._retries, other.timeout)


def tag_check(tags, rating, score, score_range=[-1000000000000000.0,
    1000000000000000.0], included_ratings=set(), banned_tags=set(),
    required_tags=set(), atleast_tags=set(), atleast_num=0):
    """
    checks if tags and rating match requirements
    """
    if banned_tags & tags:
        return False
    if required_tags & tags != required_tags:
        return False
    if len(atleast_tags & tags) < atleast_num:
        return False
    if rating not in included_ratings:
        return False
    if int(score) < score_range[0]:
        return False
    if int(score) > score_range[1]:
        return False
    return True


@staticmethod
def handle_swagger_array(item_swagger_type, shape):
    """
        Converts a dtype type representing a sub-array to a swagger valid type

        :param item_swagger_type:
        :type item_swagger_type: dict
        :param shape:
        :type shape: numpy.dtype.shape
        :return: the converted swagger type.
        :rtype: dict
        """
    swag_array = {'type': 'array', 'items': item_swagger_type}
    if len(shape) > 1:
        for dim in range(len(shape) - 1):
            swag_array = {'type': 'array', 'items': swag_array}
    return swag_array


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 num2julian(n):
    """
    Convert a Julian days to a matplotlib date.

    Parameters
    ----------
    n : numpy.ndarray : int32
        Number of days since 0001-01-01 00:00:00 UTC *plus* *one*.

    Returns
    -------
    j : numpy.ndarray : int32
        Julian days.
    """
    return n + 1721424.5


def math_commands():
    """Provides list with math commands - we need this when using eval"""
    from math import acos, asin, atan, atan2, ceil, cos, cosh, exp, floor, log, pi, pow, sin, sinh, sqrt, tan, tanh
    functions = ['acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh',
        'exp', 'floor', 'log', 'pi', 'pow', 'sin', 'sinh', 'sqrt', 'tan',
        'tanh']
    mathdefinitions = {}
    for f in functions:
        mathdefinitions[f] = locals().get(f, None)
    return mathdefinitions


@staticmethod
def supportedViews():
    """Overrides :meth:`.ControlMixin.supportedViews`. The
        ``TimeSeriesControlPanel`` is only intended to be added to
        :class:`.TimeSeriesPanel` views.
        """
    from fsleyes.views.timeseriespanel import TimeSeriesPanel
    return [TimeSeriesPanel]


@classmethod
def facing_user(cls, audio=True, **kwargs):
    """Convenience method to get the camera facing the user (often front)

        Parameters
        ----------
        audio: bool
            Capture audio or not
        kwargs:
            Extra keyword arguments passed to the `CameraStream`
        """
    return cls._facing(facing_mode='user', audio=audio, **kwargs)


def briconToScaleOffset(brightness, contrast, drange):
    """Used by the :func:`briconToDisplayRange` and the :func:`applyBricon`
    functions.

    Calculates a scale and offset which can be used to transform a display
    range of the given size so that the given brightness/contrast settings
    are applied.

    :arg brightness: Brightness, between 0.0 and 1.0.
    :arg contrast:   Contrast, between 0.0 and 1.0.
    :arg drange:     Data range.
    """
    offset = (brightness * 2 - 1) * drange
    if contrast <= 0.5:
        scale = contrast * 2
    else:
        scale = 20 * contrast ** 4 - 0.25
    return scale, offset


def get_post_fields(request):
    """parse through a request, and return fields from post in a dictionary
    """
    fields = dict()
    for field, value in request.form.items():
        fields[field] = value
    return fields


def core_specs2count(core_spec_str):
    """Determine the number of cores from a speciciatoin such as, e.g.,
    0-5,7,9-11

    >>> core_specs2count('0-5')
    6
    >>> core_specs2count('1-9,15-18')
    13
    >>> core_specs2count('5')
    1
    >>> core_specs2count('0-4,7,9-14,3')
    13
    """
    core_count = 0
    for core_spec in core_spec_str.split(','):
        if core_spec.isdigit():
            core_count += 1
        elif '-' in core_spec:
            low, high = core_spec.split('-')
            core_count += int(high) - int(low) + 1
    return core_count


def describe_table_restore_status(ClusterIdentifier=None,
    TableRestoreRequestId=None, MaxRecords=None, Marker=None):
    """
    Lists the status of one or more table restore requests made using the  RestoreTableFromClusterSnapshot API action. If you don't specify a value for the TableRestoreRequestId parameter, then DescribeTableRestoreStatus returns the status of all table restore requests ordered by the date and time of the request in ascending order. Otherwise DescribeTableRestoreStatus returns the status of the table specified by TableRestoreRequestId .
    See also: AWS API Documentation

    :example: response = client.describe_table_restore_status(
        ClusterIdentifier='string',
        TableRestoreRequestId='string',
        MaxRecords=123,
        Marker='string'
    )

    :type ClusterIdentifier: string
    :param ClusterIdentifier: The Amazon Redshift cluster that the table is being restored to.

    :type TableRestoreRequestId: string
    :param TableRestoreRequestId: The identifier of the table restore request to return status for. If you don't specify a TableRestoreRequestId value, then DescribeTableRestoreStatus returns the status of all in-progress table restore requests.

    :type MaxRecords: integer
    :param MaxRecords: The maximum number of records to include in the response. If more records exist than the specified MaxRecords value, a pagination token called a marker is included in the response so that the remaining results can be retrieved.

    :type Marker: string
    :param Marker: An optional pagination token provided by a previous DescribeTableRestoreStatus request. If this parameter is specified, the response includes only records beyond the marker, up to the value specified by the MaxRecords parameter.

    :rtype: dict
    :return: {
        'TableRestoreStatusDetails': [
            {
                'TableRestoreRequestId': 'string',
                'Status': 'PENDING'|'IN_PROGRESS'|'SUCCEEDED'|'FAILED'|'CANCELED',
                'Message': 'string',
                'RequestTime': datetime(2015, 1, 1),
                'ProgressInMegaBytes': 123,
                'TotalDataInMegaBytes': 123,
                'ClusterIdentifier': 'string',
                'SnapshotIdentifier': 'string',
                'SourceDatabaseName': 'string',
                'SourceSchemaName': 'string',
                'SourceTableName': 'string',
                'TargetDatabaseName': 'string',
                'TargetSchemaName': 'string',
                'NewTableName': 'string'
            },
        ],
        'Marker': 'string'
    }

    """
    pass


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 network_builder(topology, op_sets, input_dropout=None, dropout=None,
    regularizer=None, constraint=None, output_activation=None, use_bias=True):
    """Building Keras model using given topology and parameters

    Args:
        topology (list): Data about network topology
        op_sets (dict): Operator sets of each block
        input_dropout (float): Dropout applied to input layer, default None
        dropout (float): Dropout applied to hidden layers, default None
        regularizer (float): Weight decay coefficient, default None
        constraint (float): Max-norm constraint of weights, default None
        output_activation (str): Optional activation applied to output layer, default None
        use_bias (bool): Allow using bias if True

    Returns:
        Keras model without compilation

    """
    from ..layers import gop
    from keras.layers import Dropout, Input, Dense, BatchNormalization as BN, Concatenate
    from keras.models import Model
    from keras import regularizers, constraints
    inputs = Input((topology[0],))
    if input_dropout:
        hiddens = Dropout(input_dropout, name='input_dropout')(inputs)
    else:
        hiddens = inputs
    no_layer = len(topology)
    for layer_idx in range(1, no_layer - 1):
        layer_blocks = []
        layer_output_dim = 0
        no_block = len(topology[layer_idx])
        for block_idx in range(no_block):
            suffix = '_' + str(layer_idx - 1) + '_' + str(block_idx)
            block_type, units = topology[layer_idx][block_idx]
            layer_output_dim += units
            if block_type == 'gop':
                hiddens_ = gop.GOP(units, op_sets[block_type + suffix],
                    regularizer, constraint, use_bias, name='gop' + suffix)(
                    hiddens)
                hiddens_ = BN(name='bn' + suffix)(hiddens_)
            elif block_type == 'mem':
                hiddens_ = BN(name='mem_pre_bn' + suffix)(hiddens)
                hiddens_ = Dense(units, use_bias=use_bias, name='mem' + suffix
                    )(hiddens_)
                hiddens_ = BN(name='bn' + suffix)(hiddens_)
            else:
                raise ('Invalid block type ´´%s´´' % block_type)
            layer_blocks.append(hiddens_)
        if len(layer_blocks) > 1:
            hiddens = Concatenate(axis=-1, name='concat_' + str(layer_idx - 1)
                )(layer_blocks)
        else:
            hiddens = layer_blocks[0]
        if dropout:
            hiddens = Dropout(dropout, name='dropout_' + str(layer_idx - 1))(
                hiddens)
    output_type, output_units = topology[-1]
    if output_type == 'dense':
        outputs = Dense(output_units, kernel_regularizer=regularizers.l2(
            regularizer) if regularizer else None, kernel_constraint=
            constraints.max_norm(constraint, axis=0) if constraint else
            None, activation=output_activation, use_bias=use_bias, name=
            'output')(hiddens)
    elif output_type == 'gop':
        outputs = gop.GOP(output_units, op_sets['output'], regularizer,
            constraint, use_bias, name='output')(hiddens)
    model = Model(inputs=inputs, outputs=outputs)
    return model


def check_domain_state(conn, guestname, logger):
    """ if a guest with the same name exists, remove it """
    running_guests = []
    ids = conn.listDomainsID()
    for id in ids:
        obj = conn.lookupByID(id)
        running_guests.append(obj.name())
    if guestname in running_guests:
        logger.info('A guest with the same name %s is running!' % guestname)
        logger.info('destroy it...')
        domobj = conn.lookupByName(guestname)
        domobj.destroy()
    defined_guests = conn.listDefinedDomains()
    if guestname in defined_guests:
        logger.info('undefine the guest with the same name %s' % guestname)
        domobj = conn.lookupByName(guestname)
        domobj.undefine()


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

        :param DeviceApprovalsChangeDesktopPolicyDetails val:
        :rtype: EventDetails
        """
    return cls('device_approvals_change_desktop_policy_details', val)


def filter_saturated(observations):
    """
    bool index for unsaturated obserervations between 0..10,000

    Useful for efficiently filtering noisy-data from arrays.

    Arguments:
        observations: spectra nd-array, assumed to be shaped as
            (6,n-moments) of unscaled data.

    Returns:
        1-d bool ndarray

    """
    unsaturated = (0 < observations[(1), :]) & (observations[(1), :] < 10000
        ) & (0 < observations[(2), :]) & (observations[(2), :] < 10000) & (
        0 < observations[(3), :]) & (observations[(3), :] < 10000) & (0 <
        observations[(4), :]) & (observations[(4), :] < 10000) & (0 <
        observations[(5), :]) & (observations[(5), :] < 10000) & (0 <
        observations[(0), :]) & (observations[(0), :] < 10000)
    return unsaturated


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

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


@staticmethod
def build_slo(window, slo_config):
    """Get SLO JSON representation in Service Monitoring API from SLO
        configuration.

        Args:
            window (int): Window (in seconds).
            slo_config (dict): SLO Configuration.

        Returns:
            dict: SLO JSON configuration.
        """
    measurement = slo_config['backend'].get('measurement', {})
    method = slo_config['backend']['method']
    description = slo_config['slo_description']
    target = slo_config['slo_target']
    minutes, _ = divmod(window, 60)
    hours, _ = divmod(minutes, 60)
    display_name = f'{description} ({hours}h)'
    slo = {'display_name': display_name, 'goal': target, 'rolling_period':
        {'seconds': window}}
    filter_valid = measurement.get('filter_valid', '')
    if method == 'basic':
        methods = measurement.get('method', [])
        locations = measurement.get('location', [])
        versions = measurement.get('version', [])
        threshold = measurement.get('latency', {}).get('threshold')
        slo['service_level_indicator'] = {'basic_sli': {}}
        basic_sli = slo['service_level_indicator']['basic_sli']
        if methods:
            basic_sli['method'] = methods
        if locations:
            basic_sli['location'] = locations
        if versions:
            basic_sli['version'] = versions
        if threshold:
            basic_sli['latency'] = {'threshold': {'seconds': 0, 'nanos':
                int(threshold) * 10 ** 6}}
        else:
            basic_sli['availability'] = {}
    elif method == 'good_bad_ratio':
        filter_good = measurement.get('filter_good', '')
        filter_bad = measurement.get('filter_bad', '')
        slo['service_level_indicator'] = {'request_based': {
            'good_total_ratio': {}}}
        sli = slo['service_level_indicator']
        ratio = sli['request_based']['good_total_ratio']
        if filter_good:
            ratio['good_service_filter'] = filter_good
        if filter_bad:
            ratio['bad_service_filter'] = filter_bad
        if filter_valid:
            ratio['total_service_filter'] = filter_valid
    elif method == 'distribution_cut':
        range_min = measurement.get('range_min', 0)
        range_max = measurement['range_max']
        slo['service_level_indicator'] = {'request_based': {
            'distribution_cut': {'distribution_filter': filter_valid,
            'range': {'max': float(range_max)}}}}
        sli = slo['service_level_indicator']['request_based']
        if range_min != 0:
            sli['distribution_cut']['range']['min'] = float(range_min)
    elif method == 'windows':
        filter = measurement.get('filter')
        slo['service_level_indicator'] = {'windows_based': {'window_period':
            window, 'good_bad_metric_filter': filter}}
    else:
        raise Exception(f'Method "{method}" is not supported.')
    return slo


def delColumn(column, changeSchema=False, connection=None):
    """
        Removes the given column (either the definition from
        ``columnDefinition`` or the SOCol object from ``columns``).

        If ``changeSchema`` is true, then an ``ALTER TABLE`` query is
        made.
        """


def is_rel_one(val, relname):
    """
    # 1. null relation
    rv=val.getRelatedOne('InventoryItemType', False)
    print(is_rel_one(val, 'InventoryItemType'), rv)

    # 2. multiple relations
    rv=val.getRelated('ProductKeyword', None, None, False)
    print(is_rel_one(val, 'ProductKeyword'))
    print(json.dumps(to_json_list(rv), indent=2))

    :param val:
    :param relname:
    :return:
    """
    relation = val.getModelEntity().getRelation(relname)
    reltype = relation.getType()
    return reltype == 'one' or reltype == 'one-nofk'


def comp2dict(composition):
    """Takes composition: Si20 O10, returns dict of atoms {'Si':20,'O':10}"""
    import re
    composition = ''.join(composition)
    pat = re.compile('([A-z]+|[0-9]+)')
    m = re.findall(pat, composition)
    return dict(zip(m[::2], map(int, m[1::2])))


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 disable_cert_logging():
    """
        disable_cert_logging

        Disable SSL/TLS certificate logging

        @return: None
        """


def commit():
    """Commit any action taken during the input phase.
        """


def get_item_properties(item, fields, mixed_case_fields=(), formatters=None):
    """Return a tuple containing the item properties.

    :param item: a single item resource (e.g. Server, Tenant, etc)
    :param fields: tuple of strings with the desired field names
    :param mixed_case_fields: tuple of field names to preserve case
    :param formatters: dictionary mapping field names to callables
       to format the values
    """
    if formatters is None:
        formatters = {}
    row = []
    for field in fields:
        if field in formatters:
            row.append(formatters[field](item))
        else:
            if field in mixed_case_fields:
                field_name = field.replace(' ', '_')
            else:
                field_name = field.lower().replace(' ', '_')
            if not hasattr(item, field_name) and isinstance(item, dict):
                data = item[field_name]
            else:
                data = getattr(item, field_name, '')
            if data is None:
                data = ''
            row.append(data)
    return tuple(row)


def _load_class(cls, d):
    """
    Loads additional properties into class `cls`.
    """
    for k, v in d.items():
        if isinstance(k, tuple):
            typ, k = k
            if typ == 'property':
                v = property(*v)
            elif typ == 'staticmethod':
                v = staticmethod(v)
            elif typ == 'classmethod':
                v = classmethod(v)
        setattr(cls, k, v)
    return cls


def plotConstraints(control, axis=None, show=True):
    """
    Plots constraints used for coil current control

    axis     - Specify the axis on which to plot
    show     - Call matplotlib.pyplot.show() before returning

    """
    import matplotlib.pyplot as plt
    if axis is None:
        fig = plt.figure()
        axis = fig.add_subplot(111)
    for r, z in control.xpoints:
        axis.plot(r, z, 'bx')
    if control.xpoints:
        axis.plot([], [], 'bx', label='X-point constraints')
    for r1, z1, r2, z2 in control.isoflux:
        axis.plot([r1, r2], [z1, z2], ':b^')
    if control.isoflux:
        axis.plot([], [], ':b^', label='Isoflux constraints')
    if show:
        plt.legend()
        plt.show()
    return axis


def dump_string(obj, h5f, **kwargs):
    """ dumps a list object to h5py file"""
    h5f.create_dataset('data', data=[obj], **kwargs)
    h5f.create_dataset('type', data=['string'])


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 __init__(cls, name, bases, attrs):
    """Replace :attr:`_base_store`, :attr:`_base_register_map` and
        :attr:`_base_register_class_map` by copies of themselves

        :argument name: New class name
        :type name: str
        :argument bases: New class bases
        :type bases: tuple
        :argument attrs: New class attributes
        :type attrs: dict

        .. seealso::

           For doctests that use this member, see
           :class:`django_crucrudile.entities.store.EntityStoreMetaclassMixin`

        """
    super().__init__(name, bases, attrs)
    cls._base_store = cls._base_store.copy()


@classmethod
def get_one_electron_energy(cls, calc, **kwargs):
    """Return one electron energy in eV."""
    return cls._get_pw_energy_value(calc, 'energy_one_electron')


def same_sampling_rate(a, b, eps=1e-06):
    """
    Check if two traces have the same sampling rate.

    :param a,b: input traces
    :param eps: relative tolerance
    """
    return abs(a.deltat - b.deltat) < (a.deltat + b.deltat) * eps


def VARIABLE(name):
    """Get string representation containing the reference to a variable with
    given name. This string is intended to be used as a template parameter
    reference within workflow specifications in workflow templates.

    Parameters
    ----------
    name: string
        Template parameter name

    Returns
    -------
    string
    """
    return '$[[{}]]'.format(name)


@staticmethod
def build_colDefs_for_mi_rows(df, keep_multiindex):
    """
        create agGrid columnDefs dict for column grouping
        from multiindex dataframe columns
        """
    mindexrow = df.index
    s = []
    for e in list(mindexrow.names):
        new_e = {'field': e, 'headerName': e.title(), 'rowGroup': True}
        if not keep_multiindex:
            new_e['hide'] = True
        s.append(new_e)
    return s


def solidify(thickness: float=0.01):
    """Create a solid skin by extruding, compensating for sharp angles

    :param thickness: Thickness
    :type thickness: float
    """
    pass


def fede_voltage_update(v_cur, v_rest, v_in, alpha_v, tau_v, dt,
    refrac_counts, pre_trace):
    """Calculate change in cell's voltage based on current voltage and input trace.

    Defined in "Unsupervised Learning of a Hierarchical Spiking Neural Network for Optical Flow Estimation: From Events to Global Motion Perception" - F. Paredes-Valles, et al.

    Voltage updates are performed according to the following formula:

    .. math::

        voltage_{t+1} = voltage_{t} + \\frac{(-(voltage_{t} - rest_{t}) + alpha * (incoming_{t} - pretrace_{t})) * dt}{tau}

    :param v_cur: Current voltages
    :param v_rest: Resting voltages
    :param v_in: Incoming voltages
    :param alpha_v: Incoming voltage scaling factor
    :param tau_v: Voltage decay time constant
    :param dt: Duration of single timestep
    :param refrac_counts: Number of timesteps left in refractory state for each :class:`Neuron`
    :param pre_trace: Incoming trace

    :return: New voltages
    """
    forcing = alpha_v * (v_in - pre_trace).sum(-1)
    v_delta = dt / tau_v * (-(v_cur - v_rest) + forcing)
    non_refrac = refrac_counts == 0
    v_cur += v_delta * non_refrac.to(v_delta.dtype)
    return v_cur


def respond_activity_task_canceled(taskToken=None, details=None):
    """
    Used by workers to tell the service that the  ActivityTask identified by the taskToken was successfully canceled. Additional details can be optionally provided using the details argument.
    These details (if provided) appear in the ActivityTaskCanceled event added to the workflow history.
    A task is considered open from the time that it is scheduled until it is closed. Therefore a task is reported as open while a worker is processing it. A task is closed after it has been specified in a call to  RespondActivityTaskCompleted , RespondActivityTaskCanceled,  RespondActivityTaskFailed , or the task has timed out .
    Access Control
    You can use IAM policies to control this action's access to Amazon SWF resources as follows:
    If the caller does not have sufficient permissions to invoke the action, or the parameter values fall outside the specified constraints, the action fails. The associated event attribute's cause parameter will be set to OPERATION_NOT_PERMITTED. For details and example IAM policies, see Using IAM to Manage Access to Amazon SWF Workflows .
    See also: AWS API Documentation

    :example: response = client.respond_activity_task_canceled(
        taskToken='string',
        details='string'
    )

    :type taskToken: string
    :param taskToken: [REQUIRED]
            The taskToken of the ActivityTask .
            Warning
            taskToken is generated by the service and should be treated as an opaque value. If the task is passed to another process, its taskToken must also be passed. This enables it to provide its progress and respond with results.

    :type details: string
    :param details: Optional. Information about the cancellation.

    :returns:
    taskToken (string) -- [REQUIRED]
    The taskToken of the  ActivityTask .

    Warning
    taskToken is generated by the service and should be treated as an opaque value. If the task is passed to another process, its taskToken must also be passed. This enables it to provide its progress and respond with results.

    details (string) -- Optional. Information about the cancellation.

    """
    pass


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 mergeDataCodingTable(vartable, dctable):
    """Merges information from the data coding table into the variable
    table.

    Called by :func:`loadVariableTable`.

    :arg vartable: The variable table.
    :arg dctable:  The data coding table.
    """
    with_datacoding = vartable['DataCoding'].notna()
    for field in ['NAValues', 'RawLevels', 'NewLevels']:
        mask = vartable[field].isna() & with_datacoding
        newvals = vartable.loc[mask].merge(dctable, left_on='DataCoding',
            right_index=True, suffixes=('_v', '_dc'), copy=False)['{}_dc'.
            format(field)]
        vartable.loc[mask, field] = newvals


def datetimeToString(dt):
    """ Return string representing the year, month, day, and hour of a datetime
        object.

        @param dt Python datetime object

        @return String of the form 'YYYY MM DD HH'
    """
    return '%d %d %d %d' % (dt.year, dt.month, dt.day, dt.hour)


def __call__():
    """Returns information of order."""


@staticmethod
def encode(value):
    """Encode a DER octet string"""
    return value


def sqliteRowsToDicts(sqliteRows):
    """
    Unpacks sqlite rows as returned by fetchall
    into an array of simple dicts.

    :param sqliteRows: array of rows returned from fetchall DB call
    :return:  array of dicts, keyed by the column names.
    """
    return map(lambda r: dict(zip(r.keys(), r)), sqliteRows)


def _reg2int(reg):
    """Converts 32-bit register value to signed integer in Python.

    Parameters
    ----------
    reg: int
        A 32-bit register value read from the mailbox.

    Returns
    -------
    int
        A signed integer translated from the register value.

    """
    result = -(reg >> 31 & 1) * (1 << 31)
    for i in range(31):
        result += (reg >> i & 1) * (1 << i)
    return result


def TIM2LINO_LOCAL(alias, obj):
    """Hook for local special treatment on instances that have been
    imported from TIM.

    """
    return obj


def get_message_id(message):
    """Similar to :meth:`get_input_peer`, but for message IDs."""
    if message is None:
        return None
    if isinstance(message, int):
        return message
    try:
        if message.SUBCLASS_OF_ID == 2030045667:
            return message.id
    except AttributeError:
        pass
    raise TypeError('Invalid message type: {}'.format(type(message)))


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 Na2S(mw_atmos, mh=1):
    """Defines properties for Na2S as condensible"""
    if mh != 1:
        raise Exception(
            'Alert: No M/H Dependence in Na2S Routine. Consult your local theorist to determine next steps.'
            )
    gas_mw = 78.05
    gas_mmr = 1.97e-06 * (gas_mw / mw_atmos)
    rho_p = 1.856
    return gas_mw, gas_mmr, rho_p


def wrapGroup(group):
    """
        decorate a group with property management capabilities if needed
        """


def compute_rotation_frequency(delta_exponent_b, f_rotation_b,
    delta_exponent_c, f_rotation_c):
    """Calculate the rotation frequency between two rotated power spectra.

    Parameters
    ----------
    delta_exponent_b : float
        The applied change in exponent value for power spectrum 'B'.
    f_rotation_b : float
        The rotation frequency applied to power spectrum 'B'.
    delta_exponent_c : float
        The applied change in exponent value for power spectrum 'C'.
    f_rotation_c : float
        The rotation frequency applied to power spectrum 'C'.

    Returns
    -------
    float
        The frequency rotation point between spectra 'B' & 'C'.

    Notes
    -----
    **Code Notes**

    This computes the rotation frequency for two power spectra 'B' & 'C',
    under the assumption that they are both rotated versions of a the
    same original power spectrum 'A'.

    **Derivation**

    Given an original power spectrum A, then:

    - B = A*(f_rotation_b/freqs)^delta_exponent_b
    - C = A*(f_rotation_c/freqs)^delta_exponent_c

    Therefore, what you want is f_rotation_bc, which is the frequency where B==C.

    To find this, we can plug everything back into the equation, to find where
    B[freqs] == C[freqs], which is how we arrive at the solution below.

    Examples
    --------
    Calculate the rotation frequency between two transformed power spectra:

    >>> f_rotation = compute_rotation_frequency(0.5, 25, -0.25, 10)
    """
    return (f_rotation_c ** delta_exponent_c / f_rotation_b ** delta_exponent_b
        ) ** (1 / (delta_exponent_c - delta_exponent_b))


def _format_mongodb_uri(parsed_uri):
    """
    Painstakingly reconstruct a MongoDB URI parsed using pymongo.uri_parser.parse_uri.

    :param parsed_uri: Result of pymongo.uri_parser.parse_uri
    :type parsed_uri: dict

    :return: New URI
    :rtype: str | unicode
    """
    user_pass = ''
    if parsed_uri.get('username') and parsed_uri.get('password'):
        user_pass = '{username!s}:{password!s}@'.format(**parsed_uri)
    _nodes = []
    for host, port in parsed_uri.get('nodelist'):
        if ':' in host and not host.endswith(']'):
            host = '[{!s}]'.format(host)
        if port == 27017:
            _nodes.append(host)
        else:
            _nodes.append('{!s}:{!s}'.format(host, port))
    nodelist = ','.join(_nodes)
    options = ''
    if parsed_uri.get('options'):
        _opt_list = []
        for key, value in parsed_uri.get('options').items():
            if isinstance(value, bool):
                value = str(value).lower()
            _opt_list.append('{!s}={!s}'.format(key, value))
        options = '?' + '&'.join(_opt_list)
    db_name = parsed_uri.get('database') or ''
    res = 'mongodb://{user_pass!s}{nodelist!s}/{db_name!s}{options!s}'.format(
        user_pass=user_pass, nodelist=nodelist, db_name=db_name, options=
        options)
    return res


def has_required_spacing(string, required_spacing):
    """
    Checks if a string has the required amount of spaces
    on each side.

    :param string:           The string which is to be checked.
    :param required_spacing: The number of spaces expected on both
                             sides of the string.
    :return:                 True if the string has the required
                             number of spaces on both sides, False
                             otherwise.

    >>> has_required_spacing("  foo  ", 2)
    True
    >>> has_required_spacing(" foo", 1)
    False
    """
    leading_spaces = len(string) - len(string.lstrip(' '))
    trailing_spaces = len(string) - len(string.rstrip(' '))
    return (leading_spaces == required_spacing and trailing_spaces ==
        required_spacing)


def RemoveSlotGlobal(*args, **kwargs):
    """ Stub Anduin function."""
    print('RemoveSlotGlobal', args, kwargs)