def load_setuptools_extension(finder, module):
    """the setuptools.extension module optionally loads
       Pyrex.Distutils.build_ext but its absence is not considered an error."""
    module.IgnoreName('Pyrex.Distutils.build_ext')


def checkBox(nome, variavel, valor='', classe='', Identificador=''):
    """Retorna um checkbox """
    return (
        "%s <input type='checkbox' name='%s' value='%s' class='%s', id='%s' /><br/>"
         % (str(nome), str(variavel), str(valor), str(classe), str(
        Identificador)))


def compress_user(path: str, tilde_expand: bool, tilde_val: str) ->str:
    """Does the opposite of expand_user, with its outputs.
    """
    if tilde_expand:
        return path.replace(tilde_val, '~')
    else:
        return path


def excerptize(text, max_chars):
    """
    Return a brief excerpt from a string of plain text.
    """
    cont_snip = '...'
    words = text[:max_chars].split(' ')[:-1]
    return ' '.join(words + [' ', cont_snip])


@classmethod
def prepare(cls):
    """ Reserved for preparing the application """
    raise NotImplementedError


def build_url(table=''):
    """Return the url for a IBGE table."""
    return f'https://servicodados.ibge.gov.br/api/v3/agregados/{table}'


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


@staticmethod
def rename_attributes(**kwds):
    """Rename node and edge attributes.

        In the style dictionary multiple keywords can be used to address
        attributes. These keywords will be converted to an unique key word,
        used in the remaining code. This allows to keep the keywords used in
        'igrap'.

        ========= ===========================
        keys      other valid keys
        ========= ===========================
        node      vertex, v, n
        edge      link, l, e
        margins   margin
        canvas    bbox, figure_size
        units     unit
        ========= ===========================

        """
    names = {'node_': ['vertex_', 'v_', 'n_'], 'edge_': ['edge_', 'link_',
        'l_', 'e_'], 'margins': ['margin'], 'canvas': ['bbox',
        'figure_size'], 'units': ['units', 'unit']}
    _kwds = {}
    del_keys = []
    for key, value in kwds.items():
        for attr, name_list in names.items():
            for name in name_list:
                if name in key and name[0] == key[0]:
                    _kwds[key.replace(name, attr)] = value
                    del_keys.append(key)
                    break
    for key in del_keys:
        del kwds[key]
    return {**_kwds, **kwds}


@classmethod
def find_lines_with(cls, lines, what):
    """
        returns all lines that contain what
        :param lines:
        :param what:
        :return:
        """
    result = []
    for line in lines:
        if what in line:
            result = result + [line]
    return result


def check_conditions(line, category, method, thresh=0.3):
    """Check conditions of our or m3d txt file"""
    check = False
    assert category in ['pedestrian', 'cyclist', 'all']
    if method == 'gt':
        if category == 'all':
            categories_gt = ['Pedestrian', 'Person_sitting', 'Cyclist']
        else:
            categories_gt = [category.upper()[0] + category[1:]]
        if line.split()[0] in categories_gt:
            check = True
    elif method in ('m3d', '3dop'):
        conf = float(line[15])
        if line[0] == category and conf >= thresh:
            check = True
    elif method == 'monodepth':
        check = True
    else:
        zz = float(line[13])
        conf = float(line[15])
        if conf >= thresh and 0.5 < zz < 70:
            check = True
    return check


def copy_and_sort_node(hdf_temp, hdf_data, table_name='groundparticles',
    progress=False):
    """Sort the data in the tables by the x column

    This speeds up queries to select data based on the x column.

    """
    target_root = hdf_data.get_node('/')
    source_table = hdf_temp.get_node('/', table_name)
    if progress:
        print('Creating the sorted HDF5 file.')
    source_table.copy(newparent=target_root, sortby='x', propindexes=True)
    hdf_temp.copy_node_attrs('/', target_root)


def count(cursor, args):
    """Count the documents"""
    print(cursor.count())


def is_positive_number(input):
    """
    Check if an object can be converted into a positive number.
    Better to ask for forgiveness than for permission.
    """
    try:
        int_val = int(input)
    except:
        return False
    return int_val > 0


def translate_key_values(adict, translations, default=''):
    """Modify the keys in adict to the ones in translations.
    Be careful, this will modify your input dictionary.
    The keys not present in translations will be left intact.

    Parameters
    ----------
    adict: a dictionary

    translations: iterable of 2-tuples
    Each 2-tuple must have the following format:
    (<adict existing key>, <desired key name for the existing key>)

    Returns
    -------
    Translated adict
    """
    for src_key, dst_key in translations:
        adict[dst_key] = adict.pop(src_key, default)
    return adict


@staticmethod
def get_shebang_fix() ->str:
    """FIX: the shebang in python files."""
    return '#!/usr/bin/env python'


@classmethod
def create_empty_file(cls, file_path: str):
    """
        Given a file path, this method will create that file empty. If the file already exists, it will override the
        content with an empty string

        CHANGELOG

        Added 14.06.2019

        :param file_path:
        :return:
        """
    with open(file_path, mode='w+') as file:
        file.write('')


def _windows_shell_quote(s):
    """Return a Windows shell-escaped version of the string *s*

    Windows has potentially bizarre rules depending on where you look. When
    spawning a process via the Windows C runtime the rules are as follows:

    https://docs.microsoft.com/en-us/cpp/cpp/parsing-cpp-command-line-arguments

    To summarize the relevant bits:

    * Only space and tab are valid delimiters
    * Double quotes are the only valid quotes
    * Backslash is interpreted literally unless it is part of a chain that
      leads up to a double quote. Then the backslashes escape the backslashes,
      and if there is an odd number the final backslash escapes the quote.

    :param s: A string to escape
    :return: An escaped string
    """
    if not s:
        return '""'
    buff = []
    num_backspaces = 0
    for character in s:
        if character == '\\':
            num_backspaces += 1
        elif character == '"':
            if num_backspaces > 0:
                buff.append('\\' * (num_backspaces * 2))
                num_backspaces = 0
            buff.append('\\"')
        else:
            if num_backspaces > 0:
                buff.append('\\' * num_backspaces)
                num_backspaces = 0
            buff.append(character)
    if num_backspaces > 0:
        buff.append('\\' * num_backspaces)
    new_s = ''.join(buff)
    if ' ' in new_s or '\t' in new_s:
        return '"%s"' % new_s
    return new_s


def _similarities_group_by_distance(boreholes, disTol=0.1):
    """
    Groups pairs of boreholes by radial distance between borehole.

    Parameters
    ----------
    boreholes : list of Borehole objects
        List of boreholes in the bore field.
    distol : float, defaults to 0.1
        Absolute tolerance (in meters) on radial distance. Two distances
        (d1, d2) between two pairs of boreholes are considered equal if the
        difference between the two distances (abs(d1-d2)) is below tolerance.

    Returns
    -------
    nDis : int
        Number of unique radial distances between pairs of borehole.
    disPairs : list
        List of radial distances.
    nPairs : list
        List of number of pairs for each radial distance.
    pairs : list
        List of tuples of the borehole indices of borehole pairs at each
        radial distance.

    Raises
    ------
    SomeError

    See Also
    --------
    OtherModules

    Examples
    --------

    """
    nPairs = [1]
    pairs = [[(0, 0)]]
    disPairs = [boreholes[0].r_b]
    nDis = 1
    nb = len(boreholes)
    for i in range(nb):
        b1 = boreholes[i]
        if i == 0:
            i2 = i + 1
        else:
            i2 = i
        for j in range(i2, nb):
            b2 = boreholes[j]
            dis = b1.distance(b2)
            if i == j:
                rTol = 1e-06 * b1.r_b
            else:
                rTol = disTol
            for k in range(nDis):
                if abs(disPairs[k] - dis) < rTol:
                    pairs[k].append((i, j))
                    nPairs[k] += 1
                    break
            else:
                nDis += 1
                disPairs.append(dis)
                pairs.append([(i, j)])
                nPairs.append(1)
    return nDis, disPairs, nPairs, pairs


def area(poly):
    """Find the area of a given polygon using the shoelace algorithm.

    Parameters
    ----------
    poly: (2, N) ndarray
        2-dimensional coordinates representing an ordered
        traversal around the edge a polygon.

    Returns
    -------
    area: float

    """
    a = 0.0
    n = len(poly)
    for i in range(n):
        a += poly[i][0] * poly[(i + 1) % n][1] - poly[(i + 1) % n][0] * poly[i
            ][1]
    return abs(a) / 2.0


def recover_last_session():
    """Open the last closed file (“quit.blend”)

    """
    pass


@classmethod
def get_uri(cls, search_string, search_spec='user'):
    """Get the URI for an item

            :param user: The name of the user you need the URI for

            :return: returns servers response to the GET request
        """
    return super().get_uri(uri=cls.uri, search_spec=search_spec,
        search_string=search_string)


def get_related_model(field):
    """Gets the related model from a related field"""
    model = None
    if hasattr(field, 'related_model') and field.related_model:
        model = field.related_model
    elif hasattr(field, 'rel') and field.rel:
        model = field.rel.to
    return model


def __setitem__(key, value):
    """
        Set db or resource value
        """


@staticmethod
def docs_generator(doc_count):
    """
        documents generator
        :param doc_count:
        :return:
        """
    from tlib.es.example_settings import random_doc
    for _ in range(doc_count):
        yield random_doc()


@classmethod
def supports_to_pcm(cls):
    """returns True if all necessary components are available
        to support the .to_pcm() method"""
    try:
        from audiotools.decoders import MP3Decoder
        return True
    except ImportError:
        return False


def extract_lines(data):
    """Extract list of lines from given server data."""
    lines = []
    i = 0
    for _ in range(1000):
        line_length = int(data[i:i + 4], 16)
        line = data[i + 4:i + line_length]
        lines.append(line)
        if line_length == 0:
            i += 4
        else:
            i += line_length
        if i >= len(data):
            break
    return lines


def _sabr_implied_vol_hagan_A11_fprime_by_strike(underlying, strike,
    maturity, alpha, beta, rho, nu):
    """_sabr_implied_vol_hagan_A11_fprime_by_strike
    See :py:func:`_sabr_implied_vol_hagan_A11`.

    :param float underlying:
    :param float strike:
    :param float maturity:
    :param float alpha: must be within :math:`[0, 1]`.
    :param float beta: must be greater than 0.
    :param float rho: must be within :math:`[-1, 1]`.
    :param float nu: volatility of volatility. This must be positive.

    :return: value of factor.
    :rtype: float.
    """
    one_minus_beta_half = (1.0 - beta) / 2.0
    one_plus_beta_half = (1.0 + beta) / 2.0
    factor = one_minus_beta_half * underlying ** one_minus_beta_half
    return factor * strike ** -one_plus_beta_half


def try_convert(value, typing):
    """Try converting input value to specific variable types,
    e.g. int, float..
    """
    converted = True
    try:
        value = typing(value)
    except:
        converted = False
    return converted


def is_among(value, *possibilities):
    """Ensure that the method that has been used for the request is one of the expected ones (e.g., GET or POST)."""
    for possibility in possibilities:
        if value == possibility:
            return True
    raise Exception(
        'A different request value was encountered than expected: %s' % value)


def _check_Y(Y, mlfm):
    """ Backwards compatibility for nonvectorised Y.
    """
    if len(Y.shape) == 1:
        return Y
    elif len(Y.shape) == 2:
        ncol = Y.shape[1]
        nrow = Y.shape[0]
        if ncol == mlfm.dim.K and nrow == mlfm._Ndata:
            return Y.T.ravel()
        elif nrow == mlfm._Ndata * mlfm.dim.K:
            return Y
        else:
            raise ValueError('Bad shape for data Y.')
    else:
        msg = 'Shape of Y is not compatible.'
        raise ValueError(msg)


def _unlink(subs, shared):
    """Configure the `doorstop unlink` subparser."""
    info = 'remove a link between two items'
    sub = subs.add_parser('unlink', description=info.capitalize() + '.',
        help=info, **shared)
    sub.add_argument('child', help='child item UID to unlink from parent')
    sub.add_argument('parent', help='parent item UID child is linked to')


def EffectiveDate():
    """Return the effective date

        The value of the first Dublin Core `Date` element qualified by
        'effective' is returned as a unicode string if a qualified
        element is defined, otherwise, an empty unicode string is
        returned. The string is formatted  'YYYY-MM-DD H24:MN:SS TZ'.
        """


def h_24():
    """Return the 24-hour clock representation of the hour"""


def ini_value(key_value):
    """Strips key= from key=value from ini configuration data"""
    equals_idx = key_value.index('=') + 1
    return key_value[equals_idx:]


def check_ped_header(header, cols):
    """
    header (list) - current ped header columns
    cols (list) - typical columns we'll see from indexcov
    """
    header = set(header)
    cols = set(cols)
    is_indexcov = True
    if len(cols - header) > 0:
        is_indexcov = False
    return is_indexcov


@classmethod
def GetProperties(cls, path_spec):
    """Retrieves a dictionary containing the path specification properties.

    Args:
      path_spec (PathSpec): path specification.

    Returns:
      dict[str, str]: path specification properties.

    Raises:
      dict: path specification properties.
    """
    properties = {}
    for property_name in cls.PROPERTY_NAMES:
        if hasattr(path_spec, property_name):
            properties[property_name] = getattr(path_spec, property_name)
    return properties


def today():
    """Return the current local time.

        This is equivalent to date.fromtimestamp(time.time())"""


def scale_clear():
    """Reset scaling of selected bones to their default values

    """
    pass


def by_timestamp(path, depth=1, type='f', name='*', long=False):
    """
    List files sorted by timestamp
    """
    return ('find {path} {mindepth} {maxdepth} {name} {type} | xargs {ls_cmd}'
        .format(path=path, mindepth='-mindepth %d' % depth, maxdepth=
        '-maxdepth %d' % depth, name='-name "%s"' % name, type='-type %s' %
        type, ls_cmd='ls --directory -1t%s' % ('l' if long else '')))


def calc_checksum(data):
    """ Calculate checksum for data """
    check_sum = 0
    for i, value in enumerate(data):
        check_sum = (check_sum + value * 257 + i) % 65536
    return check_sum


def get_model_phi1_phi2(model):
    """
    Ratio of distances between the second minimum and first maximum, and the
    second minimum and second maximum, of the fitted Lomb-Scargle model.
    """
    return model['phi1_phi2']


@staticmethod
def _get_common_info(tuning_alg, epm, eva):
    """
        Returns a dict of information common to both CrossValidator and TrainValidationSplit
        """
    est = tuning_alg.getOrDefault(tuning_alg.estimator)
    params = {'mlModelClass': tuning_alg.__class__.__name__,
        'mlEstimatorUid': tuning_alg.uid, 'estimator': type(est).__name__,
        'evaluator': type(eva).__name__, 'estimatorParamMapsLength': len(epm)}
    return params


def begin_shape(kind=None):
    """
	Begin shape drawing.  This is a helpful way of generating custom shapes quickly.

	:param kind: POINTS, LINES, TRIANGLES, TRIANGLE_FAN TRIANGLE_STRIP, QUADS, or QUAD_STRIP
	:type kind: str
	"""
    global shape_kind, vertices, contour_vertices, vertices_types, contour_vertices_types, is_contour
    if (kind == 'POINTS' or kind == 'LINES' or kind == 'TRIANGLES' or kind ==
        'TRIANGLE_FAN' or kind == 'TRIANGLE_STRIP' or kind == 'QUADS' or
        kind == 'QUAD_STRIP'):
        shape_kind = kind
    else:
        shape_kind = None
    is_contour = False
    vertices = []
    contour_vertices = []
    vertices_types = []
    contour_vertices_types = []


def equivalentConvection(h, eps, theta_inf, theta_s):
    """ Equivalent convection coefficient for radiation effect

	Parameters
	----------
	h : float or (m,n) np.array
		convection coefficient [W/(m2K)]

	eps : float or (m,n) np.array
		emissivity/absorptivity [-]

	theta_inf : float or (m,n) np.array
		exposure temperature [°C]

	theta_s : float or (m,n) np.array
		surface temperature

	Returns
	-------
	h_eq : float or (m,) np.array
		equivalent covection coefficient [W/(m2K)]

	Example use
	-----------
	>>> XXX
	"""
    from scipy.constants import sigma as sig
    Tinf = theta_inf + 273.15
    Ts = theta_s + 273.15
    return h + eps * sig * (Tinf ** 2 + Ts ** 2) * (Tinf + Ts)


@classmethod
def cropImage(cls, binary_object, letters, extension, dir_path='.',
    captcha_name='captcha'):
    """ 切割二值化后的验证码图片，返回切割后的图片对象列表 """
    image_objects = []
    count = 0
    for letter in letters:
        temp_object = binary_object.crop((letter[0], 0, letter[1],
            binary_object.size[1]))
        image_path = '%s/%s.%s' % (dir_path, captcha_name +
            f'___{count + 1}', extension)
        temp_object.convert('RGB').save(image_path)
        image_objects.append(temp_object)
        count += 1
    return image_objects


def __ne__(A, other):
    """Returns true if both objects are not equal"""
    return not A == other


def _is_pure_ngless_function(fname):
    """Whether the given ngless function is pure (i.e., does not need to be
    assigned to a variable)"""
    return fname not in ['write']


def cluster_scale_in(base, cluster_id, count=None, expected_status=
    'SUCCEEDED', wait_timeout=None):
    """Utility function that scale in cluster."""
    params = {'scale_in': {'count': count}}
    res = base.client.trigger_action('clusters', cluster_id, params=params)
    action_id = res['location'].split('/actions/')[1]
    res = base.client.wait_for_status('actions', action_id, expected_status,
        wait_timeout)
    return res['body']['status_reason'], action_id


def _find_quadratic_peak(y):
    """Given an array of 3 numbers in which the first and last numbers are
    less than the central number, determine the array index at which a
    quadratic curve through the 3 points reaches its peak value.

    Parameters
    ----------
    y  : float,float,float
      The values of the curve at x=0,1,2 respectively. Note that y[1]
      must be greater than both y[0] and y[2]. Otherwise +/- infinity
      will be returned.

    Returns
    -------
    xpeak : float
      The floating point array index of the peak of the quadratic. This
      will always be in the range 0.0 to 2.0, provided that y[0]<y[1] and
      y[2]<y[1].

    """
    a = 0.5 * y[0] - y[1] + 0.5 * y[2]
    b = -1.5 * y[0] + 2.0 * y[1] - 0.5 * y[2]
    return -b / (2 * a)


@classmethod
def instr(cls, x=None, y=None, n=None):
    """
        Return a string at cursor or specified position.
        If n is specified, returns at most n characters.

        :param x: optional x value
        :param y: optional y value
        :param n: optional max length of string
        :return: string at position
        """
    x, y = cls._fix_xy(x, y)
    if n is None:
        return cls.WINDOW.instr(y, x)
    else:
        return cls.WINDOW.instr(y, x, n)


def concat_keys_and_values(keys, vals):
    """ Format keys and values in string.
  e.g.
    keys = ['a', 'b', 'c']
    vals = [4, 5, 6]
    str = 'a:4, b:5, c:6'
  """
    fmt = ''
    for tup in zip(keys, vals):
        fmt += ', {0}: {1}'.format(tup[0], tup[1])
    return fmt


def add_columns(header, c):
    """
    add any missing columns to the samples table
    """
    for column in header:
        try:
            c.execute('ALTER TABLE samples ADD COLUMN {0}'.format(column))
        except:
            pass


def _build_index_definition(index):
    """
    Creates request object to Index to be deployed
    :param index:
    :return:
    """
    index_def = {'IndexName': index['name'], 'KeySchema': [{'AttributeName':
        index['index_key_name'], 'KeyType': 'HASH'}], 'Projection': {
        'ProjectionType': 'ALL'}}
    if index.get('index_sort_key_name'):
        index_def['KeySchema'].append({'AttributeName': index[
            'index_sort_key_name'], 'KeyType': 'RANGE'})
    return index_def


def _eafp(ask, default):
    """
    Easier to ask for forgiveness than permission
    `x = _eafp(lambda: int('a'), 0)` is equivalent to `x = int('a') ?? 0`
    """
    try:
        return ask()
    except:
        return default


@classmethod
def _normalize_unit(cls, unit):
    """Resolve a unit to its real name if it's an alias.

        :param unit str: the unit to normalize
        :return: the normalized unit, or None one isn't found
        :rtype: Union[None, str]
        """
    if unit in cls.UNITS_IN_SECONDS:
        return unit
    return cls.UNIT_ALIASES_REVERSE.get(unit, None)


def is_bytes_object(obj):
    """
    Returns True if the argument can be decoded (usually bytes string)
    Based on https://stackoverflow.com/a/34870210
    """
    try:
        obj.decode()
        return True
    except AttributeError:
        return False


def parse_netpath(netpath):
    """Parse ``netpath`` string containing host-name and script-path into a
    tuple of ``(netloc, script-path)``. If script-path is absent, return
    ``(netloc, '')``."""
    parts = netpath.split('/', 1)
    netloc = parts.pop(0)
    script = '/' + (parts.pop(0) if parts else '')
    return netloc, script


def stack_window(new_win, parent_win):
    """Elevate the new window to the topmost level of the stack of windows.

    :param new_win: the new window to be stacked on top.
    :type new_win: `tkinter.Toplevel`
    :param parent_win: the parent window of new_win.
    :type parent_win: `tkinter.Toplevel`
    """
    new_win.lift(parent_win)
    parent_win.attributes('-topmost', False)
    new_win.attributes('-topmost', True)
    new_win.attributes('-topmost', False)


@staticmethod
def analytical(settings):
    """Returns analytical value of estimator given settings."""
    return settings.logz_analytic()


def sieve(dirty):
    """
    Filters out CPF formatting symbols. Symbols that are not used
    in the CPF formatting are left unfiltered on purpose so that
    if fails other tests, because their presence indicate that the
    input was somehow corrupted.
    """
    return ''.join(filter(lambda char: char not in '.-', dirty))


def get_remote_browsers(settings):
    """Return the defined remote browsers in settings."""
    remote_browsers = {}
    if 'remote_browsers' in settings:
        remote_browsers = settings['remote_browsers']
    return remote_browsers


def dump_class_simple(target: object, indent: int=0, no_print: bool=False
    ) ->str:
    """Dump class information (simple).

    A function like dump_class but no output of methods.

    Parameters
    ----------
    target : object
        The target object you want to dump.
    indent : int
        Depth to indent
    no_print : bool
        If False(Default), immediately output by print().
        If True, no output. Use return value.

    Returns
    -------
    str
        Dump result text.

    """
    dump_string = ''
    if type(target) is not type:
        return dump_string
    s = 'description of {}.{}:'
    s = '  ' * indent + s.format(target.__module__, target.__name__)
    dump_string = s + '\n'
    s = '  ' * (indent + 1) + '__hash__: {}'.format(target.__hash__(target))
    dump_string += s + '\n'
    s = '  ' * (indent + 1) + '__doc__: {}'.format(target.__doc__)
    dump_string += s + '\n'
    s = '  ' * (indent + 1) + '__qualname__: {}'.format(target.__qualname__)
    dump_string += s + '\n'
    s = '  ' * (indent + 1) + '__module__: {}'.format(target.__module__)
    dump_string += s + '\n'
    s = '  ' * (indent + 1) + '__name__: {}'.format(target.__name__)
    dump_string += s
    if no_print is False:
        print(dump_string)
    return dump_string + '\n'


@staticmethod
def add_slash(url):
    """Adds a final slash to a url if there is not any."""
    return url + '/' if not url.endswith('/') else url


def check_message(expr):
    """checks if an expression is a valid message"""
    if expr.has_form('MessageName', 2):
        symbol, tag = expr.get_leaves()
        if symbol.get_name() and tag.get_string_value():
            return True
    return False


@classmethod
def from_dict(cls, d):
    """
        Deserialize EpitopePrediction from a dictionary of keywords.
        """
    d = d.copy()
    if 'length' in d:
        del d['length']
    return cls(**d)


@classmethod
def ready(cls):
    """
        All modules loaded, and ready to serve.
        Emitted after register routes and before loop start
        :return:
        """
    pass


def quantity_string(name, quantity_dict):
    """Takes in an abbreviation for a quantity and a quantity dictionary,
       and returns a more descriptive string of the quantity as "name (units)."
       Raises ValueError if the name is not in quantity_dict
    """
    if name not in quantity_dict.keys():
        raise ValueError('{0} is not present in quantity_dict'.format(name))
    return '{0} ({1})'.format(quantity_dict[name]['name'], quantity_dict[
        name]['units'])


def cmp(a, b):
    """Compare two numbers A and B, and return 1, 0, and -1 when A > B, A = B,
    and A < B, respectively."""
    if a > b:
        return 1
    elif a < b:
        return -1
    else:
        return 0


def file_to_str(fname):
    """
    Read a file into a string
    PRE: fname is a small file (to avoid hogging memory and its discontents)
    """
    data = None
    with open(fname, 'rU') as fd:
        data = fd.read()
    return data


def debt_to_capital_ratio(debt, equity):
    """Computes debt-to-caital ratio.

    @params
    -------
    debt: total debt
    equity: total shareholders' equity

    returns
    -------
    Debt-to-capital ratio, int or float

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

    """
    return debt / (debt + equity)


@classmethod
def _add_dynamic_field_to_model(cls, field, field_name):
    """
        Add a copy of the DynamicField "field" to the current class and its
        subclasses using the "field_name" name
        """
    new_field = field._create_dynamic_version()
    new_field.name = field_name
    new_field._attach_to_model(cls)
    setattr(cls, '_redis_attr_%s' % field_name, new_field)
    for subclass in cls.__subclasses__():
        subclass._add_dynamic_field_to_model(field, field_name)
    return new_field


def get_preferred_sparse_format():
    """Get the preferred sparse matrix format supported by the backend.

    Different backends have their preferred backend. This info is useful when
    constructing a sparse matrix.
    """
    return 'csr'


def psi_K_MgOH_HCO3_HMW84(T, P):
    """c-c'-a: potassium magnesium-hydroxide bicarbonate [HMW84]."""
    psi = 0.0
    valid = T == 298.15
    return psi, valid


def _get_best_indexes(logits, n_best_size):
    """Get the n-best logits from a list."""
    index_and_score = sorted(enumerate(logits), key=lambda x: x[1], reverse
        =True)
    best_indexes = []
    for i in range(len(index_and_score)):
        if i >= n_best_size:
            break
        best_indexes.append(index_and_score[i][0])
    return best_indexes


def cron_dow_to_calendar(cron_values):
    """ Converts a cron index day of week to a calendar index day of week. """
    if type(cron_values) in [str, int]:
        cron_values = [int(cron_values)]
    calendar_days = []
    for value in cron_values:
        calendar_days.append({(1): 6, (2): 0, (3): 1, (4): 2, (5): 3, (6):
            4, (7): 5}[int(value)])
    return list(calendar_days)


def scan_setup_py():
    """Validate the contents of setup.py against Versioneer's expectations."""
    found = set()
    setters = False
    errors = 0
    with open('setup.py', 'r') as f:
        for line in f.readlines():
            if 'import versioneer' in line:
                found.add('import')
            if 'versioneer.get_cmdclass()' in line:
                found.add('cmdclass')
            if 'versioneer.get_version()' in line:
                found.add('get_version')
            if 'versioneer.VCS' in line:
                setters = True
            if 'versioneer.versionfile_source' in line:
                setters = True
    if len(found) != 3:
        print('')
        print('Your setup.py appears to be missing some important items')
        print('(but I might be wrong). Please make sure it has something')
        print('roughly like the following:')
        print('')
        print(' import versioneer')
        print(' setup( version=versioneer.get_version(),')
        print('        cmdclass=versioneer.get_cmdclass(),  ...)')
        print('')
        errors += 1
    if setters:
        print("You should remove lines like 'versioneer.VCS = ' and")
        print("'versioneer.versionfile_source = ' . This configuration")
        print('now lives in setup.cfg, and should be removed from setup.py')
        print('')
        errors += 1
    return errors


def get_model_counts(tagged_models, tag):
    """ This does a model count so the side bar looks nice.
    """
    model_counts = []
    for model in tagged_models:
        model['count'] = model['query'](tag).count()
        if model['count']:
            model_counts.append(model)
    return model_counts


@staticmethod
def _cmp_open(low, item, high):
    """Compare function for non-repeating intervals."""
    return low <= item < high


def get_file_list_based_on_suffix(file_list, suffix):
    """
    Get filenames endinge with "suffix"
    :param file_list:
    :param suffix:
    :return:
    """
    match_list = []
    for fid in file_list:
        if fid.endswith(suffix):
            match_list.append(fid)
    return match_list


def round_nicely(number):
    """Round a number based on its size (so it looks nice)."""
    if number < 10:
        return round(number, 2)
    if number < 100:
        return round(number, 1)
    return round(number)


def create_monkey(bm: 'bmesh.types.BMesh', matrix: 'mathutils.Matrix',
    calc_uvs: bool) ->dict:
    """Creates a monkey (standard blender primitive).

    :param bm: The bmesh to operate on.
    :type bm: 'bmesh.types.BMesh'
    :param matrix: matrix to multiply the new geometry with
    :type matrix: 'mathutils.Matrix'
    :param calc_uvs: calculate default UVs
    :type calc_uvs: bool
    :return:  verts: output vertstype list of (bmesh.types.BMVert)
    """
    pass


@classmethod
def of(cls, obj):
    """
        Get the usage expectation of a given object.

        :param obj:
            The object for which usage expectation is to be set
        :returns:
            Either a previously made object or a fresh instance of
            :class:`UsageExpectation`.
        """
    try:
        return obj.__usage_expectation
    except AttributeError:
        ua = cls(type(obj))
        obj.__usage_expectation = ua
        return ua


def right_replace(string, old, new):
    """
    replaces last occurrence of old with new in a string
    :param string:
    :param old:
    :param new:
    :return:
    """
    return new.join(string.rsplit(old))


def set_bot(bot):
    """ Set the gbot variable for the struct.py file. """
    globals().update(gbot=bot)


def generic_find_fk_constraint_name(table, columns, referenced, insp):
    """Utility to find a foreign-key constraint name in alembic migrations"""
    for fk in insp.get_foreign_keys(table):
        if fk['referred_table'] == referenced and set(fk['referred_columns']
            ) == columns:
            return fk['name']


def deferred_write(f):
    """A PinBank write mode: write() must be called explicitly."""
    pass


def cmd2args(s):
    """ if s is a list, leave it like that; otherwise split()"""
    if isinstance(s, list):
        return s
    elif isinstance(s, str):
        return s.split()
    else:
        assert False


def _get_subcollections(collection):
    """
    Returns all sub-collections of `collection`.
    """
    for name in collection.database.collection_names():
        cleaned = name[:name.rfind('.')]
        if cleaned != collection.name and cleaned.startswith(collection.name):
            yield cleaned


def _sanitize(name):
    """Replace occurences of ``disallowed_characters`` in name with
    underscores and double quotation marks with single quotation marks.
    """
    disallowed_characters = '\\/:<>?*| '
    for character in disallowed_characters:
        name = name.replace(character, '_')
    return name.replace('"', "'")


def track_color_preset_add(name: str='', remove_active: bool=False):
    """Add or remove a Clip Track Color Preset

    :param name: Name, Name of the preset, used to make the path name
    :type name: str
    :param remove_active: remove_active
    :type remove_active: bool
    """
    pass


def _set_star_value(star_code, number_stars):
    """
    Internal function that is used for update the number of active stars (that define notebook
    difficulty level)

    ----------
    Parameters
    ----------
    star_code : str
        String with the HTML code to be changed.

    number_stars : int
        Number of stars that will be active.

    Returns
    -------
    out : str
        It is returned a string with the HTML code after updating the number of active stars.

    """
    for star in range(1, 6):
        if star <= number_stars:
            star_code = star_code.replace('fa fa-star ' + str(star),
                'fa fa-star checked')
        else:
            star_code = star_code.replace('fa fa-star ' + str(star),
                'fa fa-star')
    return star_code


def sint(S):
    """convert a string to an integer, treating an all-blank string as zero"""
    if S.strip():
        return int(S)
    else:
        return 0


@staticmethod
def _create_emulator(mode):
    """Create emulator for specified mode.

        If no emulator is specified, we will use the Rasa NLU format."""
    if mode is None:
        from chatbot_nlu.emulators import NoEmulator
        return NoEmulator()
    elif mode.lower() == 'wit':
        from chatbot_nlu.emulators.wit import WitEmulator
        return WitEmulator()
    elif mode.lower() == 'luis':
        from chatbot_nlu.emulators.luis import LUISEmulator
        return LUISEmulator()
    elif mode.lower() == 'dialogflow':
        from chatbot_nlu.emulators.dialogflow import DialogflowEmulator
        return DialogflowEmulator()
    else:
        raise ValueError('unknown mode : {0}'.format(mode))


def to_dict(obj):
    """
    Get dict of guts object attributes.

    :param obj: :py:class`Object` object
    """
    return dict(obj.T.inamevals(obj))


def produce_vcftools_log(output, filename, append_mode=False):
    """
        Creates the vcftools log file

        This function will create a log file from the vcftools stderr. Please
        run `check_vcftools_for_errors` prior to check that vcftools finished
        without error.

        Parameters
        ----------
        output : str
            vcftools stderr
        filename : str
            Specifies the filename for the log file
        append_mode : bool
            Used to create a single log file from multiple calls

        Returns
        -------
        output : file
            vcftools log file

    """
    if append_mode:
        vcftools_log_file = open(filename + '.log', 'a')
    else:
        vcftools_log_file = open(filename + '.log', 'w')
    vcftools_log_file.write(str(output))
    vcftools_log_file.close()


@classmethod
def paginate(cls, page, items):
    """
        Wraps Model.limit to make paginating easier.
        """
    return cls.limit(items, offset=page * items)


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

        :param TeamMergeRequestReminderShownToSecondaryTeamDetails val:
        :rtype: EventDetails
        """
    return cls('team_merge_request_reminder_shown_to_secondary_team_details',
        val)


def pos_byte2str(s):
    """return a list where the element value is the characther index/pos
    in the string from the byte position
    """
    pos_map = []
    for index, c in enumerate(s):
        pos_map.extend([index] * len(c.encode('utf-8')))
    return pos_map


@classmethod
def register_validator(cls, validator, group):
    """
        Registers another order validator in a validation group

        A validator is a callable accepting an order (and only an order).

        There are several types of order validators:

        - Base validators are always called
        - Cart validators: Need to validate for a valid cart
        - Checkout validators: Need to validate in the checkout process
        """
    cls.VALIDATORS.setdefault(group, []).append(validator)


def shift_pos(pos, label_shift):
    """shift a pos by (sx, xy) pixels"""
    shiftx = label_shift[0]
    shifty = label_shift[1]
    pos2 = pos.copy()
    for key, position in pos2.items():
        pos2[key] = position[0] + shiftx, position[1] + shifty
    return pos2


def get_name(url):
    """
    Generate a profile name based on the git url.

    This directly corresponds to the second to last element in the URL.  For
    example: https://github.com/chasinglogic/dotfiles would be 'chasinglogic'

    In the case of an ssh url or other url will correspond to the
    first path element. For example:
    git@github.com:chasinglogic/dotfiles would be 'chasinglogic'
    """
    try:
        if url.find('@') > 1:
            return url.split(':')[-1].split('/')[0]
        else:
            return url.split('/')[-2]
    except Exception:
        return ''


def _anonymize_bv(vmrk_fname):
    """Anonymize BrainVision marker files by stripping out time stamps."""
    pass


@classmethod
def synchronize(cls, options=None):
    """Synchronize a product."""
    cls.command_sub = 'synchronize'
    return cls.execute(cls._construct_command(options), ignore_stderr=True)


def text_to_title(value):
    """when a title is required, generate one from the value"""
    title = None
    if not value:
        return title
    words = value.split(' ')
    keep_words = []
    for word in words:
        if word.endswith('.') or word.endswith(':'):
            keep_words.append(word)
            if len(word) > 1 and '<italic>' not in word and '<i>' not in word:
                break
        else:
            keep_words.append(word)
    if len(keep_words) > 0:
        title = ' '.join(keep_words)
        if title.split(' ')[-1] != 'spp.':
            title = title.rstrip(' .:')
    return title


@classmethod
def tabManager(cls):
    """
        Class method to get a reference to the tab manager widget.

        @return reference to the tab manager widget
        @rtype TabManagerWidget
        """
    if cls._tabManager is None:
        from .TabManager.TabManagerWidget import TabManagerWidget
        cls._tabManager = TabManagerWidget(cls.mainWindow())
        for window in cls.mainWindows():
            cls._tabManager.mainWindowCreated(window, False)
        cls._tabManager.delayedRefreshTree()
    return cls._tabManager


def _get_server_dns_suffx(cli_ctx):
    """
    Gets the DNS suffix for servers in this Azure environment.
    """
    from os import getenv
    return getenv('_AZURE_CLI_SQL_DNS_SUFFIX', default=cli_ctx.cloud.
        suffixes.sql_server_hostname)


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


@classmethod
def from_dict(cls, parsed_dict):
    """Create an Event from a dictionary.

        Args:
            parsed_dict (dict): The dictionary representation of the event.

        """
    raise NotImplementedError()


def prepare(source):
    """Prepare for being received.

        This method is called by the IMessageSource before the message is
        returned before being displayed to the user.

        Two things are generally reasonable to do here:

            - Decide whether the message should be deleted from the source
            - Update the message

        """


def header_flip():
    """Toggle the header over/below the main window area

    """
    pass


def upload_file(filename):
    """ Uploads a single file to a Dropbox account.

    Keyword arguments:
    filename -- Path and name of the file to upload to Dropbox.

    """
    pass


def colormap_select(base_colormap, start=0, end=1.0, reverse=False):
    """
    Given a colormap in the form of a list, such as a Bokeh palette,
    return a version of the colormap reversed if requested, and selecting
    a subset (on a scale 0,1.0) of the elements in the colormap list.

    For instance:

    >>> cmap = ["#000000", "#969696", "#d9d9d9", "#ffffff"]
    >>> colormap_select(cmap,reverse=True)
    ['#ffffff', '#d9d9d9', '#969696', '#000000']
    >>> colormap_select(cmap,0.3,reverse=True)
    ['#d9d9d9', '#969696', '#000000']
    """
    full = list(reversed(base_colormap) if reverse else base_colormap)
    num = len(full)
    return full[int(start * num):int(end * num)]


def stop_deployment(deploymentId=None, autoRollbackEnabled=None):
    """
    Attempts to stop an ongoing deployment.
    See also: AWS API Documentation

    :example: response = client.stop_deployment(
        deploymentId='string',
        autoRollbackEnabled=True|False
    )

    :type deploymentId: string
    :param deploymentId: [REQUIRED]
            The unique ID of a deployment.

    :type autoRollbackEnabled: boolean
    :param autoRollbackEnabled: Indicates, when a deployment is stopped, whether instances that have been updated should be rolled back to the previous version of the application revision.

    :rtype: dict
    :return: {
        'status': 'Pending'|'Succeeded',
        'statusMessage': 'string'
    }

    :returns:
    Pending: The stop operation is pending.
    Succeeded: The stop operation was successful.

    """
    pass


@classmethod
def clearDataset(cls, f0):
    """Return a copy of f0 with no dataset specified, or None if f0 is None."""
    if (f0 is None or f0.owner is None and f0.sizeGeq is None and f0.mtime is
        None and f0.notPaths == [] and f0.regex is None):
        return None
    else:
        return cls(f0.owner, None, f0.sizeGeq, f0.mtime, f0.notPaths, f0.regex)


def process_data(expected_keys, data):
    """
    Check for any expected but missing keyword arguments
    and raise a TypeError else return the keywords arguments
    repackaged in a dictionary i.e the payload.
    :param expected_keys:
    :param data:
    :return payload:
    """
    payload = {}
    for key in expected_keys:
        value = data.pop(key, False)
        if not value:
            raise TypeError('Missing value on key {0}'.format(key))
        else:
            payload[key] = value
    return payload


def checkURL(cls, trust_root, url):
    """quick func for validating a url against a trust root.  See the
        TrustRoot class if you need more control."""
    tr = cls.parse(trust_root)
    return tr is not None and tr.validateURL(url)


@classmethod
def to_binary(cls, val, protocol_version):
    """
        Serialize a value into a bytestring. See the serialize() method for
        more information. This method differs in that if None is passed in,
        the result is the empty string.
        """
    return b'' if val is None else cls.serialize(val, protocol_version)


def calc_vi_mean(base, perturbed, x_delta):
    """Calculate v_i mean.

    Same as calc_vi_stats but only returns the mean.
    """
    dfdx = ((perturbed - base) / x_delta) ** 2
    return dfdx.mean()


def apply_stoplist(corp, nltk_stop=True, add_stop=None, freq=0, in_place=True):
    """
    Returns a Corpus object with stop words eliminated.

    :param corp: Corpus object to apply stoplist to.
    :type corp: Corpus

    :param nltk_stop: If `True` English stopwords from nltk are included
        in the stoplist. Default is `True`.
    :type nltk_stop: boolean, optional

    :param add_stop: list of words to eliminate from `corp` words.
        Default is `None`.
    :type add_stop: List, optional

    :param freq: Eliminates words that appear <= `freq` times. Default is
        0.
    :type freq: int

    :returns: Corpus with words in the stoplist removed.

    :See Also: :class:`vsm.corpus.Corpus`, :meth:`vsm.corpus.Corpus.apply_stoplist`
    """
    stoplist = set()
    if nltk_stop:
        import nltk
        for w in nltk.corpus.stopwords.words('english'):
            stoplist.add(w)
    if add_stop:
        for w in add_stop:
            stoplist.add(w)
    if not in_place:
        return corp.apply_stoplist(stoplist=stoplist, freq=freq)
    else:
        corp.in_place_stoplist(stoplist=stoplist, freq=freq)
        return corp


@classmethod
def generate_mongo_uri(cls):
    """uses config class values to generate mongodb uri and returns connection string"""
    if cls.MONGO_REPLICA_SET:
        cls.MONGO_URI = (
            f'mongodb://{cls.MONGO_HOST}:{cls.MONGO_PORT}/{cls.MONGO_DB}?replicaSet={cls.MONGO_REPLICA_SET}'
            )
    else:
        cls.MONGO_URI = (
            f'mongodb://{cls.MONGO_HOST}:{cls.MONGO_PORT}/{cls.MONGO_DB}')
    return cls.MONGO_URI


@classmethod
def _from_et(cls, root, parent):
    """
        Create a :class:`Package3d` from a :code:`package3d` element.

        :param root: The element tree tree to parse.
        :param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
        :rtype: :class:`Package3d`
        """
    n = cls()
    n._init_from_et(root, parent)
    return n


def _voi_point_cmp(a, b):
    """ TODO: needs documentation """
    if abs(a[1] - b[1]) < 0.2:
        c = a[0] - b[0]
    else:
        c = a[1] - b[1]
    if c < 0:
        return -1
    else:
        return 1


def p_import_as_names_1(p):
    """import_as_names : import_as_name"""
    p[0] = [p[1]]


@classmethod
def insert(cls, c, **kwargs):
    """Inserts an element to the table."""
    verified = {}
    for column in cls.columns:
        try:
            value = kwargs[column.name]
        except KeyError:
            continue
        check = column.column_type.python
        if value is None and not column.nullable:
            raise TypeError(
                f'Cannot pass None to non-nullable column {column.name}.')
        elif (not check or not isinstance(value, check)) and value is not None:
            fmt = (
                'column {0.name} expected {1.__name__}, received {2.__class__.__name__}'
                )
            raise TypeError(fmt.format(column, check, value))
        verified[column.name] = value
    sql = 'INSERT INTO {0} ({1}) VALUES ({2});'.format(cls.__tablename__,
        ', '.join(verified), ', '.join('?' for _ in verified))
    c.execute(sql, tuple(verified.values()))


def region_2d_to_vector_3d(region, rv3d, coord):
    """
    Return a direction vector from the viewport at the specific 2d region
    coordinate.

    :arg region: region of the 3D viewport, typically bpy.context.region.
    :type region: :class:`bpy.types.Region`
    :arg rv3d: 3D region data, typically bpy.context.space_data.region_3d.
    :type rv3d: :class:`bpy.types.RegionView3D`
    :arg coord: 2d coordinates relative to the region:
       (event.mouse_region_x, event.mouse_region_y) for example.
    :type coord: 2d vector
    :return: normalized 3d vector.
    :rtype: :class:`mathutils.Vector`
    """
    from mathutils import Vector
    viewinv = rv3d.view_matrix.inverted()
    if rv3d.is_perspective:
        persinv = rv3d.perspective_matrix.inverted()
        out = Vector((2.0 * coord[0] / region.width - 1.0, 2.0 * coord[1] /
            region.height - 1.0, -0.5))
        w = out.dot(persinv[3].xyz) + persinv[3][3]
        view_vector = persinv * out / w - viewinv.translation
    else:
        view_vector = -viewinv.col[2].xyz
    view_vector.normalize()
    return view_vector


def __new__(mcs, name, bases, attrs):
    """
        Validate state group definition
        """
    if bases != (object,):
        if 'states' in attrs and 'exclude_states' in attrs:
            raise Exception('Use either states or exclude_states but not both')
        elif 'states' not in attrs and 'exclude_states' not in attrs:
            raise Exception(
                'Please specify states or exclude_states to this state group')
        if 'exclude_states' in attrs and not isinstance(attrs[
            'exclude_states'], (list, set)):
            raise Exception(
                'Please give a list (or set) of states to this state group')
        elif 'states' in attrs and not isinstance(attrs['states'], (list, set)
            ):
            raise Exception(
                'Please give a list (or set) of states to this state group')
    return type.__new__(mcs, name, bases, attrs)


def find_organization_or_user_for_default_charges(user):
    """
    Takes a user model and finds either the first non public organization or the user itself
    :param user:
    :return: namespace name to charge by default (organization or user if not part of any organization)
    """
    namespace_to_charge = user.username
    for org in user.organizations:
        if org.organization_name != 'public':
            namespace_to_charge = org.organization_name
            break
    return namespace_to_charge


@classmethod
def delete(cls, sec_group_id, context, region_name):
    """Deletes a Security Group."""
    driver = cls.get_driver(context, region_name)
    driver.delete_security_group(sec_group_id)


def percentile_s(p, sorted_seq):
    """Return percentile `p` of `sorted_seq`.

    >>> l1 = [3, 6, 7, 8, 8,    10, 13, 15, 16, 20]
    >>> l2 = [3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20]
    >>> for l in (l1, l2) :
    ...   for p in (0, 25, 50, 75, 100) :
    ...     print ("%3s percentile of %s elements: %2s" % (p, len (l), percentile (p, l)))
      0 percentile of 10 elements:  3
     25 percentile of 10 elements:  7
     50 percentile of 10 elements:  8
     75 percentile of 10 elements: 15
    100 percentile of 10 elements: 20
      0 percentile of 11 elements:  3
     25 percentile of 11 elements:  7
     50 percentile of 11 elements:  9
     75 percentile of 11 elements: 15
    100 percentile of 11 elements: 20

    """
    l = len(sorted_seq)
    i = int(0.99 + p * l / 100) - 1 if p else 0
    result = sorted_seq[i]
    return result


def convert_body_to_bytes(resp):
    """
    If the request body is a string, encode it to bytes (for python3 support)

    By default yaml serializes to utf-8 encoded bytestrings.
    When this cassette is loaded by python3, it's automatically decoded
    into unicode strings. This makes sure that it stays a bytestring, since
    that's what all the internal httplib machinery is expecting.

    For more info on py3 yaml:
    http://pyyaml.org/wiki/PyYAMLDocumentation#Python3support
    """
    try:
        if resp['body']['string'] is not None and not isinstance(resp[
            'body']['string'], bytes):
            resp['body']['string'] = resp['body']['string'].encode('utf-8')
    except (KeyError, TypeError, UnicodeEncodeError):
        pass
    return resp


def psi_MgOH_Cl_HCO3_HMW84(T, P):
    """c-a-a': magnesium-hydroxide chloride bicarbonate [HMW84]."""
    psi = 0
    valid = T == 298.15
    return psi, valid


def _iso_inv_map(d):
    """
    Augment *d* with inverse mappings.

    Assumes *d* is not a multigraph.
    """
    _d = {}
    for src, d2 in d.items():
        for tgt, data in d2.items():
            if tgt is not None and src != tgt:
                if tgt not in _d:
                    _d[tgt] = {}
                _d[tgt][src] = '--' + data
    for k, d2 in _d.items():
        d[k].update(d2)


def write_author_ids(cmd, basename, filename):
    """Write the author IDs to an egg-info file.

    Copy the author IDs from a local file into an egg-info file, when the distribution
    attribute ``include_author_ids`` is ``True``. The attribute value is typically
    set by argument ``include_author_ids`` in ``setuptools.setup()``. Intended for use
    by setuptools only.

    Args:
       cmd (setuptools.command.egg_info.egg_info): Object creating a distribution's
           egg-info directory and contents.
       basename (str): Filename to write.
       filename (str): Complete path, with filename, to write.
    """
    import os
    if cmd.distribution.include_author_ids:
        argname = os.path.splitext(basename)[0]
        author_ids = open(basename).read()
        cmd.write_or_delete_file(argname, filename, author_ids)


def table_from_primary_key(pkname):
    """Given the name of a primary key, return the related table.

    :param pkname: the name of a primary key
    :rtype: a SQLAlchemy table
    """
    from . import metadata
    for t in metadata.sorted_tables:
        if len(t.primary_key.columns) == 1 and pkname in t.primary_key.columns:
            return t
    raise RuntimeError('Unknown PK: %s' % pkname)


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 is_conflicting(fsm, eqclass, gamma):
    """
    Return whether the given equivalence class for gamma is conflicting or not.

    fsm -- the model
    eqclass -- a BDD representing a set of states/inputs pairs
    gamma -- a set of agents of fsm

    eqclass must be a distributed knowledge based equivalence class.

    """
    si = fsm.pick_one_state_inputs(eqclass)
    ngamma_cube = fsm.bddEnc.inputsCube - fsm.inputs_cube_for_agents(gamma)
    return (eqclass - (eqclass & si.forsome(fsm.bddEnc.statesCube |
        ngamma_cube))).isnot_false()


@classmethod
def _update_value_set(cls):
    """
        Update the class attribute `attr_list_vect_set` from  `attr_list_vect`
        """
    cls.attr_list_set = set(cls.attr_list_vect)


def element_uml_cardinality(occ, card_entity):
    """Return UML like cardinality for the given pyxst Occurence. Cardinality may be
    overriden by the data model's user_cardinality value.
    """
    cardinality = getattr(card_entity, 'user_cardinality', None)
    if cardinality is None:
        minimum = occ.minimum
        maximum = occ.maximum
        if minimum == maximum == 1:
            return '1'
        elif maximum != 1:
            maximum = 'n'
        return '%s..%s' % (minimum, maximum)
    else:
        return cardinality


def vertex_group_assign_new():
    """Assign the selected vertices to a new vertex group

    """
    pass


def handle_duplicate_notebook(library_db, notebook_data, name):
    """prompts user to resolve duplicate notebook problem"""
    from src.praxxis.display import display_error
    from src.praxxis.library import list_library
    from src.praxxis.library import library
    from src.praxxis.sqlite import sqlite_notebook
    from src.praxxis.sqlite import sqlite_library
    from src.praxxis.notebook import notebook
    from src.praxxis.display import display_notebook
    from src.praxxis.util import error
    library_list = []
    for element in notebook_data:
        library_list.append(element[2])
    display_error.duplicate_notebook_error(name, library_list)
    selection = display_notebook.get_notebook_selection()
    if selection.isdigit():
        if int(selection) <= len(library_list):
            selection = library_list[int(selection) - 1]
        else:
            raise error.LibraryNotFoundError(selection)
    else:
        sqlite_library.check_library_exists(library_db, selection)
    return sqlite_notebook.get_notebook(library_db, name, selection)[0]


def set_origin(use_median: bool=False):
    """Set active marker as origin by moving camera (or its parent if present) in 3D space

    :param use_median: Use Median, Set origin to median point of selected bundles
    :type use_median: bool
    """
    pass


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 elements_for_apsides(apocenter_radius, pericenter_radius):
    """Calculate planar orbital elements for given apside radii."""
    ra = apocenter_radius
    rp = pericenter_radius
    a = (ra + rp) / 2
    e = (ra - rp) / (ra + rp)
    return a, e


def rebuild_proxy():
    """Rebuild all selected proxies and timecode indices using the job system

    """
    pass


@classmethod
def lines(cls, ofstr):
    """ where lines in a string separated by newline comes to (list-of-lines,total-lines) """
    output = []
    i = -1
    l = len(ofstr)
    line, b, i = cls.parse(ofstr, i, len(ofstr), cls.newline)
    while b is not cls.eol:
        output.append(line)
        line, b, i = cls.parse(ofstr, i, len(ofstr), cls.newline)
    output.append(line)
    return output


def linalg_sumlogdiag(A=None, name=None, attr=None, out=None, **kwargs):
    """Computes the sum of the logarithms of the diagonal elements of a square matrix.
    Input is a tensor *A* of dimension *n >= 2*.

    If *n=2*, *A* must be square with positive diagonal entries. We sum the natural
    logarithms of the diagonal elements, the result has shape (1,).

    If *n>2*, *sumlogdiag* is performed separately on the trailing two dimensions for all
    inputs (batch mode).

    .. note:: The operator supports float32 and float64 data types only.

    Examples::

       Single matrix reduction
       A = [[1.0, 1.0], [1.0, 7.0]]
       sumlogdiag(A) = [1.9459]

       Batch matrix reduction
       A = [[[1.0, 1.0], [1.0, 7.0]], [[3.0, 0], [0, 17.0]]]
       sumlogdiag(A) = [1.9459, 3.9318]

    Defined in src/operator/tensor/la_op.cc:L445

    Parameters
    ----------
    A : Symbol
        Tensor of square matrices

    name : string, optional.
        Name of the resulting symbol.

    Returns
    -------
    Symbol
        The result symbol.
    """
    return 0,


def limit_problem_history(problem_hash, limit):
    """Delete problem occurrences leaving only last `limit` of them."""


def cob_page(page):
    """Default controller for pages"""
    pageContent = {'title': page.profile.name + ' Home Page', 'content':
        page.get_lang({'value': 'head.title'})}
    for view in page.views:
        pageContent[view.name] = view.render(None)
    return page.render(pageContent)


def _get_qt_qmake_config(qmake_config, qt_version):
    """ Return a dict of qmake configuration values for a specific Qt version.
    """
    qt_qmake_config = {}
    for name, value in qmake_config.items():
        name_parts = name.split(':')
        if len(name_parts) == 2 and name_parts[0] == qt_version:
            qt_qmake_config[name_parts[1]] = value
    return qt_qmake_config


def quantize_coefficients(qlp_precision, lp_coefficients, order):
    """returns a (qlp_coeffs, qlp_shift_needed) pair
    where qlp_coeffs is a list of ints
    and qlp_shift_needed is a non-negative integer"""
    from math import log
    l = max(map(abs, lp_coefficients[order - 1]))
    if l > 0:
        qlp_shift_needed = min(qlp_precision - 1 - (int(log(l) / log(2)) -
            1) - 1, 2 ** 4 - 1)
    else:
        qlp_shift_needed = 0
    if qlp_shift_needed < -2 ** 4:
        raise ValueError('too much negative shift needed')
    qlp_max = 2 ** (qlp_precision - 1) - 1
    qlp_min = -2 ** (qlp_precision - 1)
    error = 0.0
    qlp_coeffs = []
    if qlp_shift_needed >= 0:
        for lp_coeff in lp_coefficients[order - 1]:
            error += lp_coeff * 2 ** qlp_shift_needed
            qlp_coeffs.append(min(max(int(round(error)), qlp_min), qlp_max))
            error -= qlp_coeffs[-1]
        return qlp_coeffs, qlp_shift_needed
    else:
        for lp_coeff in lp_coefficients[order - 1]:
            error += lp_coeff / 2 ** -qlp_shift_needed
            qlp_coeffs.append(min(max(int(round(error)), qlp_min), qlp_max))
            error -= qlp_coeffs[-1]
        return qlp_coeffs, 0


def traverse_setter(obj, attribute, value):
    """
    Traverses the object and sets the supplied attribute on the
    object. Supports Dimensioned and DimensionedPlot types.
    """
    obj.traverse(lambda x: setattr(x, attribute, value))


def TrimBytes(byte_string):
    """Trim leading zero bytes."""
    trimmed = byte_string.lstrip(b'\x00')
    if len(trimmed) == 0:
        return b'\x00'
    else:
        return trimmed


def formula_2014_01_01(foyer_fiscal, period, parameters):
    """
        Investissements OUTRE-MER dans le secteur du logement et autres secteurs d’activité
        2014
        """
    fhod = foyer_fiscal('fhod', period)
    fhoe = foyer_fiscal('fhoe', period)
    fhof = foyer_fiscal('fhof', period)
    fhog = foyer_fiscal('fhog', period)
    fhox = foyer_fiscal('fhox', period)
    fhoy = foyer_fiscal('fhoy', period)
    fhoz = foyer_fiscal('fhoz', period)
    fhqb = foyer_fiscal('fhqb', period)
    fhqc = foyer_fiscal('fhqc', period)
    fhqd = foyer_fiscal('fhqd', period)
    fhql = foyer_fiscal('fhql', period)
    fhqm = foyer_fiscal('fhqm', period)
    fhqt = foyer_fiscal('fhqt', period)
    fhoa = foyer_fiscal('fhoa', period)
    fhob = foyer_fiscal('fhob', period)
    fhoc = foyer_fiscal('fhoc', period)
    fhoh = foyer_fiscal('fhoh', period)
    fhoi = foyer_fiscal('fhoi', period)
    fhoj = foyer_fiscal('fhoj', period)
    fhok = foyer_fiscal('fhok', period)
    fhol = foyer_fiscal('fhol', period)
    fhom = foyer_fiscal('fhom', period)
    fhon = foyer_fiscal('fhon', period)
    fhoo = foyer_fiscal('fhoo', period)
    fhop = foyer_fiscal('fhop', period)
    fhoq = foyer_fiscal('fhoq', period)
    fhor = foyer_fiscal('fhor', period)
    fhos = foyer_fiscal('fhos', period)
    fhot = foyer_fiscal('fhot', period)
    fhou = foyer_fiscal('fhou', period)
    fhov = foyer_fiscal('fhov', period)
    fhow = foyer_fiscal('fhow', period)
    fhua = foyer_fiscal('fhua', period)
    fhub = foyer_fiscal('fhub', period)
    fhuc = foyer_fiscal('fhuc', period)
    fhud = foyer_fiscal('fhud', period)
    fhue = foyer_fiscal('fhue', period)
    fhuf = foyer_fiscal('fhuf', period)
    fhug = foyer_fiscal('fhug', period)
    return (fhqb + fhqc + fhqd + fhql + fhqm + fhqt + fhoa + fhob + fhoc +
        fhoh + fhoi + fhoj + fhok + fhol + fhom + fhon + fhoo + fhop + fhoq +
        fhor + fhos + fhot + fhou + fhov + fhow + fhod + fhoe + fhof + fhog +
        fhox + fhoy + fhoz + fhua + fhub + fhuc + fhud + fhue + fhuf + fhug)


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

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


@classmethod
def set_mul_all_edges(cls, key, value):
    """エッジのキーにvalueをかける

        Args:
            key(str):
            value(float):

        Returns:

        """
    query = f'MATCH ()-[r:Link]->() SET r.{key} = r.{key} * {value}'
    with cls.DRIVER.session() as session:
        session.run(query)


def mps2kts(speed_mps):
    """Convert speed value from m/s to knots"""
    return speed_mps * 1.9438445


def assert_equal(a, b, message=None):
    """wrapper for numpy all() method"""
    assert (a.numpy() == b.numpy() if hasattr(b, 'numpy') else b).all(
        ), message


def cpu_units(value):
    """Converts CPU string into numeric in BMIPS"""
    norm = str(value).upper().strip()
    if norm.endswith('%'):
        return int(norm[:-1])
    else:
        return int(norm)


def decode_bytes(data, fallback='iso8859-15'):
    """Decode a bytes-like object that is expected to be a valid string

    First utf8 is tried, then the fallback (defaults to iso8859-15).
    The fallback behavior can be disabled by setting the option to None.
    """
    try:
        return data.decode('utf8')
    except UnicodeDecodeError:
        if fallback:
            return data.decode(fallback)
        raise


def get_first_from_sequence(sequence, default=None):
    """
    Given a sequence, return the first item in the sequence. If the sequence is
    empty, return the passed in default.
    """
    first_result = default
    try:
        first_result = next(sequence)
    except StopIteration:
        pass
    return first_result


def cast(s):
    """ Function which clarifies the implicit type of
    strings, a priori coming from csv-like files.

    Example
    -------
    >>> cast('1')
    1
    >>> cast('1.')
    1.0
    >>> cast('1E+0')
    1.0
    >>> cast('1E+1')
    10.0
    >>> cast('one')
    'one'
    >>> cast('One')
    'one'
    """
    s = str(s)
    try:
        float(s)
        if '.' in s or 'E' in s:
            return float(s)
        else:
            return int(s)
    except:
        return s.lower()


def pytest_enter_pdb(config, pdb):
    """ called upon pdb.set_trace(), can be used by plugins to take special
    action just before the python debugger enters in interactive mode.

    :param _pytest.config.Config config: pytest config object
    :param pdb.Pdb pdb: Pdb instance
    """


def check_dendrogram(dendrogram):
    """Check the shape of a dendrogram."""
    if dendrogram.ndim != 2 or dendrogram.shape[1] != 4:
        raise ValueError('Dendrogram has incorrect shape.')
    else:
        return


def unregister():
    """Remove the registration by unregistering the component"""


def parallax(d):
    """
    Returns parallax in arcsec given distances.
    Args:
        d (float): distance
    Return:
        parallax in arcsecs
    Written by: Logan Pearce, 2017
    """
    from astropy import units as u
    d = d.to(u.pc)
    x = 1 * u.au / d
    return x.to(u.arcsec, equivalencies=u.dimensionless_angles())


def rKerr_LR_Bardeen(j, M=1, branch=0):
    """

    Calculate Kerr Light-Ring Radius

    USAGE:
    rKerr_LR_Bardeen(Dimensionless_BH_Spin,BH_Mass)

    ~ londonl@mit.edu

    """
    from numpy import cos, arccos, sqrt
    from positive import acos
    rKerr_LR = 2 * M * (1 + cos(2.0 / 3 * acos(-j, branch=branch)))
    return rKerr_LR


def el_iter(el):
    """
    Go through all elements
    """
    try:
        for child in el.iter():
            yield child
    except AttributeError:
        for child in el.getiterator():
            yield child


def analyzeProfile(profileFilename, stripDirs=True):
    """Analyze the file produced by cProfile

    obtained by for example:
    - call in script (for main() function in script)
    import cProfile, os
    cProfile.run('main()', os.path.join(os.getcwd(),'main.profile'))

    - or on the command line:
    python -m cProfile [-o profile.bin] [-s sort] scriptfile [arg]"""
    import pstats, os
    p = pstats.Stats(os.path.join(os.pardir, profileFilename))
    if stripDirs:
        p.strip_dirs()
    p.sort_stats('time')
    p.print_stats(0.2)
    return p


def split_command_from_target(bot_username: str, command: (str or None)) ->(str
    , str):
    """
    Determines the command target bot username
    :param bot_username: the username of this bot
    :param command: the command to check
    :return: (the command, the username of the targeted bot)
    """
    target = bot_username
    if command is None or len(command) <= 0:
        return command, target
    if '@' in command:
        command, target = command.split('@', 1)
    return command, target


def strip_some_punct(s):
    """
    Return a string stripped from some leading and trailing punctuations.
    """
    if s:
        s = s.strip(',\'"}{-_:;&@!')
        s = s.lstrip('.>)]\\/')
        s = s.rstrip('<([\\/')
    return s


def _get_line_index(line_or_func, lines):
    """Return the appropriate line index, depending on ``line_or_func`` which
    can be either a function, a positive or negative int, or None.
    """
    if hasattr(line_or_func, '__call__'):
        return line_or_func(lines)
    elif line_or_func:
        if line_or_func >= 0:
            return line_or_func
        else:
            n_lines = sum(1 for line in lines)
            return n_lines + line_or_func
    else:
        return line_or_func


def lru(loads):
    """Always pick the front of the line.

    The content of `loads` is ignored.

    Assumes LRU ordering of loads, with oldest first.
    """
    return 0


@staticmethod
def pop_dset_attrs(var_attrs, dset):
    """
        Pop attributres for given dataset from dataset attributes DataFrame

        Parameters
        ----------
        dset_attrs : pandas.DataFrame
            DataFrame of dataset attributes (dtype, chunks, attrs)
        dset : str
            Dataset of interest

        Returns
        -------
        dset_attrs : pandas.DataFrame
            Updated DataFrame of dataset attributes (dtype, chunks, attrs)
        attrs : pandas.Series
            Series of attributes for given dataset
        """
    attrs = var_attrs.loc[dset]
    var_attrs = var_attrs.drop(dset)
    return var_attrs, attrs


def understands_Unset(cls_or_func):
    """
    Decorator for marking validators as supporting the special Unset value.

    This decorator should be applied to every validator that natively supports
    Unset values. Without it, Unset is never validated.

    This decorator works by setting the ``understands_Unset`` attribute on the
    decorated object and returning it intact.
    """
    cls_or_func.understands_Unset = True
    return cls_or_func


def get_enthalpy_differences(mbar):
    """
        Given an `MBAR <https://pymbar.readthedocs.io/en/latest/mbar.html>`_ class object, this function computes the enthalpy differences for the states defined within.

        :param mbar: An MBAR() class object (from the 'pymbar' package)
        :type mbar: `MBAR <https://pymbar.readthedocs.io/en/latest/mbar.html>`_ class object

        :returns:
          - Delta_u ( np.array( n_mbar_states x n_thermo_states ) - Enthalpy differences for the thermodynamic states in 'mbar'
          - dDelta_u ( np.array( n_mbar_states x n_thermo_states ) - Uncertainty in the enthalpy differences for the thermodynamic states in 'mbar'

        """
    results = mbar.computeEntropyAndEnthalpy()
    results = {'Delta_f': results[0], 'dDelta_f': results[1], 'Delta_u':
        results[2], 'dDelta_u': results[3], 'Delta_s': results[4],
        'dDelta_s': results[5]}
    Delta_u = results['Delta_u']
    dDelta_u = results['dDelta_u']
    return Delta_u, dDelta_u


def get_filename(connection):
    """Get the name of the file associated with an SQLite connection.

    Parameters
    ----------
    connection : `sqlite3.Connection`
        The database connection

    Returns
    -------
    str
        The name of the file that contains the SQLite database

    Raises
    ------
    RuntimeError
        If more than one database is attached to the connection

    Examples
    --------
    >>> import tempfile
    >>> import os
    >>> with tempfile.TemporaryDirectory() as d:
    ...     with sqlite3.connect(os.path.join(d, 'test.sqlite')) as db:
    ...         print(get_filename(db))
    ...
    /.../test.sqlite

    >>> with tempfile.TemporaryDirectory() as d:
    ...     with sqlite3.connect(os.path.join(d, 'test1.sqlite')) as db1, \\
    ...          sqlite3.connect(os.path.join(d, 'test2.sqlite')) as db2:
    ...         filename = get_filename(db1)
    ...         db2.execute('ATTACH DATABASE "{}" AS db2'.format(filename))
    ...         print(get_filename(db2))
    ...
    Traceback (most recent call last):
      ...
    RuntimeError: Expected exactly one attached database

    """
    result = connection.execute('pragma database_list').fetchall()
    try:
        (_, _, filename), = result
    except ValueError:
        raise RuntimeError('Expected exactly one attached database')
    return filename


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

        Ensure data.message is string, since it can be very large

        :param es_major: major version of Elasticsearch, as string
        :returns:        dictionary with a key, 'items', with the mapping
        """
    mapping = """
        {
            "dynamic":true,
            "properties": {
                "data": {
                    "properties": {
                        "message": {
                            "type": "text",
                            "index": true
                        },
                        "analysis": {
                            "dynamic":false,
                            "properties": {}
                        }
                    }
                }
            }
        }
        """
    return {'items': mapping}


def vv_declare(string, flag, idx2, countstr):
    """Turns Variable declarations into VectorVariable ones"""
    length = string[len(flag):idx2].strip()
    return countstr.replace('Variable(', 'VectorVariable(%s, ' % length)


@classmethod
def load_libsvm(cls, f):
    """Create a dataset by reading a sparse LIBSVM/SVMlight format file
        (with labels only)."""
    nFeat = 0
    for line in f:
        n = int(line.split()[-1].split(':')[0])
        if n > nFeat:
            nFeat = n
    f.seek(0)
    labels = []
    features = []
    for line in f:
        if not line:
            break
        line = line.split()
        label = int(line[0])
        feat = []
        nextidx = 1
        for r in line[1:]:
            idx, val = r.split(':')
            idx = int(idx)
            for _ in range(nextidx, idx):
                feat.append(0.0)
            feat.append(float(val))
            nextidx = idx + 1
        for _ in range(nextidx, nFeat + 1):
            feat.append(0.0)
        features.append(feat[:])
        labels.append([label])
    DS = cls(features, labels)
    return DS


def create_substitutes(logs_location_base, storage_location_base,
    dynamodb_table_name):
    """Return an object which can be used to replace strings in the policy
    files

    The two *_base strings are expected to be bucket/path representations
    Current strings supported are:
    - ${DATALAKE_BUCKET}
    - ${DYNAMODB_TABLE_NAME}
    - ${LOGS_LOCATION_BASE}
    - ${STORAGE_LOCATION_BASE}

"""
    s = {'LOGS_LOCATION_BASE': logs_location_base, 'STORAGE_LOCATION_BASE':
        storage_location_base, 'DYNAMODB_TABLE_NAME': dynamodb_table_name,
        'DATALAKE_BUCKET': storage_location_base.split('/')[0]}
    return s


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 check_for_dev_uniqueness(builders):
    """
    Check that no device appears in more than one of the given list of
    builders.

    :param builders: a list of :class:`swift.common.ring.builder.RingBuilder`
        instances
    :raises ValueError: if the same device is found in more than one builder
    """
    builder2devs = []
    for i, builder in enumerate(builders):
        dev_set = set()
        for dev in builder._iter_devs():
            ip, port, device = dev['ip'], dev['port'], dev['device']
            for j, (other_builder, devs) in enumerate(builder2devs):
                if (ip, port, device) in devs:
                    raise ValueError(
                        'Duplicate ip/port/device combination %s/%s/%s found in builders at indexes %s and %s'
                         % (ip, port, device, j, i))
            dev_set.add((ip, port, device))
        builder2devs.append((builder, dev_set))


def partition(text, sep):
    """
    Splits ``text`` at the first occurrence of ``sep``, returning the result as 3-tuple.

    If the separator is not found, this function returns a 3-tuple containing the
    string itself, followed by two empty strings.

    :return: a 3-tuple containing the part before the separator, the separator itself, and the part after the separator.
    :rtype:  ``tuple`` of ``str``
    """
    assert isinstance(text, str), '%s is not a string' % text
    return text.partition(sep)


def get_state(instance):
    """Return state name like 'terminated' or 'running'"""
    return instance.state['Name']


def get_utility_commands_list(order=None):
    """
    Return a list of utility commands to be executed in parallel with the payload.
    This could e.g. be memory and network monitor commands. A separate function can be used to determine the
    corresponding command setups using the utility command name.
    If the optional order parameter is set, the function should return the list of corresponding commands.
    E.g. if order=UTILITY_BEFORE_PAYLOAD, the function should return all commands that are to be executed before the
    payload. If order=UTILITY_WITH_PAYLOAD, the corresponding commands will be prepended to the payload execution
    string. If order=UTILITY_AFTER_PAYLOAD, the commands that should be executed after the payload has been started
    should be returned.

    :param order: optional sorting order (see pilot.util.constants)
    :return: list of utilities to be executed in parallel with the payload.
    """
    return []


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

    :return: rst string
    :rtype: str
    """
    return """
    The ``command`` model is used to represent a command in the monitored system.

    A command is used:

    - for the hosts and services active checks. The command is a check plugin
    used to determine the host or service state.

    - for the event handlers launched when an host / service state changes.

     - for the notifications sent to inform the users of the detected problems
    """


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


def check_parameter_accepted_values(param, param_name, accepted_values):
    """Raise an error if parameter does not belong to a set of values.

    Parameters
    ----------
    param : unspecified
        Parameter to be tested.
    param_name : string
        Name of the parameter.
    accepted_values : list
        Accepted values that the parameter can take.
    """
    if param not in accepted_values:
        raise ValueError('Parameter {} needs to be in {}, got: {}'.format(
            param_name, accepted_values, param))


@classmethod
def _check_add_constraints(cls, state):
    """
        Obnoxious way to handle this, should ONLY be called from crash monitor.
        """
    state.inspect.address_concretization_add_constraints = (cls.
        _should_add_constraints(state))


def polygon_from_bbox(minx, miny, maxx, maxy):
    """Construct polygon coordinates in numeric list representation from a numeric list representing a bounding box."""
    return [[minx, miny], [maxx, miny], [maxx, maxy], [minx, maxy]]


def sanity_check():
    """
    Perform an initial sanity check before doing anything else in a given workflow.
    This function can be used to verify importing of modules that are otherwise used much later, but it is better to abort
    the pilot if a problem is discovered early.

    :return: exit code (0 if all is ok, otherwise non-zero exit code).
    """
    exit_code = 0
    return exit_code


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

        :param IntegrationPolicyChangedType val:
        :rtype: EventType
        """
    return cls('integration_policy_changed', val)


def smooth_tilt():
    """Interpolate tilt of selected points

    """
    pass


def read_uic2tag(fh, byteorder, dtype, planecount, offsetsize):
    """Read MetaMorph STK UIC2Tag from file and return as dict."""
    assert dtype == '2I' and byteorder == '<'
    values = fh.read_array('<u4', 6 * planecount).reshape(planecount, 6)
    return {'ZDistance': values[:, (0)] / values[:, (1)], 'DateCreated':
        values[:, (2)], 'TimeCreated': values[:, (3)], 'DateModified':
        values[:, (4)], 'TimeModified': values[:, (5)]}


def total_days(time_diff):
    """
    Total time in units of days
    """
    return time_diff.days + (time_diff.seconds + time_diff.microseconds /
        1000000.0) / (24 * 3600.0)


@staticmethod
def hasDefinition(cls):
    """ Check if the protocol has some definition.
        This can help to detect "abstract" protocol that
        only serve as base for other, not to be instantiated.
        """
    return hasattr(cls, '_definition')


def modeladmin_register(modeladmin_class):
    """
    Method for registering ModelAdmin or ModelAdminGroup classes with Wagtail.
    """
    instance = modeladmin_class()
    instance.register_with_wagtail()
    return modeladmin_class


@classmethod
def contribute_api(cls, api):
    """Contribute the API backend to this resource and its managers.

        .. note:: Mainly for internal use
        """
    cls._api = api
    for manager in cls._managers:
        manager.contribute_api(api)


@classmethod
def register(cls, algorithm_name: str, mutation_class):
    """Register a class with a string key."""
    cls.REGISTRY[algorithm_name] = mutation_class
    return mutation_class


def interleave(inter, f, seq):
    """Call f on each item in seq, calling inter() in between.
    """
    seq = iter(seq)
    try:
        f(next(seq))
    except StopIteration:
        pass
    else:
        for x in seq:
            inter()
            f(x)


def getBrokenSymlinkCheckStr(variableName):
    """Will take a file variable name and will print bash code that will
    check if the symlink for that file is broken

    This seems to be helping with files not being staged out properly.
    Likely will not be necessary in bug fixed versions of Swift

    Do not force an exit since other checks may occur afer the symlink
    check"""
    return '# See if the symlink is orphaned... if so exit 1\nif [ ! -e $' + variableName + """ ] ; then
	echo "$""" + variableName + ' symlink good" >> $logFile 2>&1\nelse\n\techo "$' + variableName + """ symlink broken" >> $logFile 2>&1
	exit 1
fi

"""


def str2bool(v):
    """ Convert string to a boolean value.
    References
    ----------
    https://stackoverflow.com/questions/715417/converting-from-a-string-to-boolean-in-python/715468#715468
    """
    return str(v).lower() in ('yes', 'true', 't', '1')


@classmethod
def make_separator(cls, value):
    """Create a separator token"""
    assert value in (',', ';')
    subtype = cls.ARG if value == ',' else cls.ROW
    return cls(value, cls.SEP, subtype)


@classmethod
def from_uirt(cls, data, seed=None):
    """Constructing Dataset from UIRT (User, Item, Rating, Timestamp)
        quadruplet data.

        Parameters
        ----------
        data: array-like, shape: [n_examples, 4]
            Data in the form of triplets (user, item, rating, timestamp)

        seed: int, optional, default: None
            Random seed for reproducing data sampling.

        Returns
        -------
        res: :obj:`<cornac.data.Dataset>`
            Dataset object.

        """
    return cls.build(data, fmt='UIRT', seed=seed)


def parse_escaped_hierarchical_category_name(category_name):
    """Parse a category name."""
    result = []
    current = None
    index = 0
    next_backslash = category_name.find('\\', index)
    next_slash = category_name.find('/', index)
    while index < len(category_name):
        if next_backslash == -1 and next_slash == -1:
            current = (current if current else '') + category_name[index:]
            index = len(category_name)
        elif next_slash >= 0 and (next_backslash == -1 or next_backslash >
            next_slash):
            result.append((current if current else '') + category_name[
                index:next_slash])
            current = ''
            index = next_slash + 1
            next_slash = category_name.find('/', index)
        else:
            if len(category_name) == next_backslash + 1:
                raise Exception("Unexpected '\\' in '{0}' at last position!"
                    .format(category_name))
            esc_ch = category_name[next_backslash + 1]
            if esc_ch not in {'/', '\\'}:
                raise Exception("Unknown escape sequence '\\{0}' in '{1}'!"
                    .format(esc_ch, category_name))
            current = (current if current else '') + category_name[index:
                next_backslash] + esc_ch
            index = next_backslash + 2
            next_backslash = category_name.find('\\', index)
            if esc_ch == '/':
                next_slash = category_name.find('/', index)
    if current is not None:
        result.append(current)
    return result


def find_finished_idxs(pattern_matrix):
    """
    Find indexs that cannot be eliminated further
    """
    rm_idxs = set(range(len(pattern_matrix)))
    for i, row in enumerate(pattern_matrix):
        if (row[2] < 0 or row[2] > 1) and i in rm_idxs:
            rm_idxs.remove(i)
    for i, row in enumerate(pattern_matrix):
        for rowidx in [0, 1]:
            for j in [j for j in rm_idxs if i < j]:
                x = row[rowidx][j - i - 1]
                if x > 1:
                    rm_idxs.remove(j)
    return rm_idxs


def disconnect_lifelines(line, send, received):
    """
    Disconnect lifeline and set appropriate kind of message item. If
    there are no lifelines connected on both ends, then remove the message
    from the data model.
    """
    if not line.subject:
        return
    if send:
        event = line.subject.receiveEvent
        if event:
            event.unlink()
    if received:
        event = line.subject.sendEvent
        if event:
            event.unlink()
    if not send or not received:
        message = line.subject
        del line.subject
        if not message.presentation:
            message.unlink()


def abortConnection():
    """
        Close the connection abruptly.

        Discards any buffered data, stops any registered producer,
        and, if possible, notifies the other end of the unclean
        closure.

        @since: 11.1
        """


@staticmethod
def _major_minor(sysroot):
    """ Return the Python major.minor as a tuple. """
    major, minor, _ = sysroot.decode_version_nr(sysroot.target_py_version_nr)
    return major, minor


def insert(text: str=''):
    """Insert text at cursor position

    :param text: Text, Text to insert at the cursor position
    :type text: str
    """
    pass


def getExclusiveReactions(project, orgs=set()):
    """
    Given a bunch of organisms, get two dicts
    mreacts: org_id -->  set(re_id, ...) (common)
    ereacts: org_id -->  set(re_id, ...) (exclusive)
    """
    from ductape.storage.SQLite.database import Kegg
    kegg = Kegg(project)
    ereacts = kegg.getExclusiveReactions(orgs)
    mreacts = {}
    for org_id in orgs:
        mreacts[org_id] = set()
        for oR in kegg.getOrgReact(org_id):
            mreacts[org_id].add(oR.re_id)
    for org_id in orgs:
        mreacts[org_id].difference_update(ereacts[org_id])
    return mreacts, ereacts


def stripnull(string):
    """Return string truncated at first null character.

    Clean NULL terminated C strings.

    >>> stripnull(b'string\\x00')
    b'string'

    """
    i = string.find(b'\x00')
    return string if i < 0 else string[:i]


def convertnontitled(nontitledparagraphs):
    """
    Convert non-titled bullets to strings
    """
    string_list = []
    for paragraphs in nontitledparagraphs:
        lines = []
        for para in paragraphs:
            lines.extend(para)
        string_list.append(b' '.join(lines))
    return string_list


def xheaderify(header_name):
    """Prefix the given name with the freeswitch xheader token
    thus transforming it into an fs xheader variable
    """
    return 'sip_h_X-{}'.format(header_name)


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 snake_split(s):
    """
    Split a string into words list using snake_case rules.
    """
    s = s.strip().replace(' ', '')
    return s.split('_')


def to_networkx(g, node_attrs=None, edge_attrs=None):
    """Convert to networkx graph.

    The edge id will be saved as the 'id' edge attribute.

    Parameters
    ----------
    g : DGLGraph or DGLHeteroGraph
        For DGLHeteroGraphs, we currently only support the
        case of one node type and one edge type.
    node_attrs : iterable of str, optional
        The node attributes to be copied. (Default: None)
    edge_attrs : iterable of str, optional
        The edge attributes to be copied. (Default: None)

    Returns
    -------
    networkx.DiGraph
        The nx graph
    """
    return g.to_networkx(node_attrs, edge_attrs)


def addListing(parser):
    """
    Add option to request the list of versions.
    """
    parser.add_option('-l', '--list', action='store_true', help=
        'list the available versions of the requested project and exit')
    parser.add_option('--list-versions', action='store_true', dest='list',
        help='obsolete spelling of --list', default=False)
    parser.add_option('-L', '--list-platforms', action='store_true', help=
        'list the available platforms for the requested project/version and exit'
        )
    parser.set_defaults(list=False, list_platforms=False)
    return parser


def linear_interpolation_extrapolation(df, target_height):
    """
    Linearly inter- or extrapolates between the values of a data frame.

    This function can be used for the linear inter-/extrapolation of a
    parameter (e.g wind speed) available at two or more different heights, to
    approximate the value at hub height.
    The function is carried out when the parameter `wind_speed_model`,
    `density_model` or `temperature_model` of an instance of the
    :class:`~.modelchain.ModelChain` class is 'interpolation_extrapolation'.

    Parameters
    ----------
    df : :pandas:`pandas.DataFrame<frame>`
        DataFrame with time series for parameter that is to be interpolated or
        extrapolated. The columns of the DataFrame are the different heights
        for which the parameter is available. If more than two heights are
        given, the two closest heights are used. See example below on how the
        DataFrame should look like and how the function can be used.
    target_height : float
        Height for which the parameter is approximated (e.g. hub height).

    Returns
    -------
    :pandas:`pandas.Series<series>`
        Result of the inter-/extrapolation (e.g. wind speed at hub height).

    Notes
    -----

    For the inter- and extrapolation the following equation is used:

    .. math:: f(x) = \\frac{(f(x_2) - f(x_1))}{(x_2 - x_1)} \\cdot
        (x - x_1) + f(x_1)

    Examples
    ---------
    >>> import numpy as np
    >>> import pandas as pd
    >>> wind_speed_10m = np.array([[3], [4]])
    >>> wind_speed_80m = np.array([[6], [6]])
    >>> weather_df = pd.DataFrame(np.hstack((wind_speed_10m,
    ...                                      wind_speed_80m)),
    ...                           index=pd.date_range('1/1/2012',
    ...                                               periods=2,
    ...                                               freq='H'),
    ...                           columns=[np.array(['wind_speed',
    ...                                              'wind_speed']),
    ...                                    np.array([10, 80])])
    >>> value = linear_interpolation_extrapolation(
    ...     weather_df['wind_speed'], 100)[0]

    """
    heights_sorted = df.columns[sorted(range(len(df.columns)), key=lambda i:
        abs(df.columns[i] - target_height))]
    return (df[heights_sorted[1]] - df[heights_sorted[0]]) / (heights_sorted
        [1] - heights_sorted[0]) * (target_height - heights_sorted[0]) + df[
        heights_sorted[0]]


def unicode_format(match):
    """Callback for re.sub for formatting unicode chars."""
    return '\\u{0}'.format(match.group(0)[2:].upper())


@staticmethod
def last_value(counter):
    """
        alphabetical sort data =)
        :param counter: counter JSON
        :return: float or None
        None - когда показания не сданы более 3-х месяцев
        """
    indications = counter['indications']
    indications.sort(key=lambda x: x['period'])
    if indications:
        return float(indications[-1]['indication'])


def delay_denial(func):
    """
    Decorator to declare which methods should have any swift.authorize call
    delayed. This is so the method can load the Request object up with
    additional information that may be needed by the authorization system.

    :param func: function for which authorization will be delayed
    """
    func.delay_denial = True
    return func


def mul_or_none(a, b):
    """Return the element wise multiplicative of the inputs.
    If either input is None, we return None.

    Parameters
    ----------
    a
        A tensor input.
    b
        Another tensor input with the same type as a.

    Returns
    -------
    None if either input is None. Otherwise returns a * b.
    """
    if a is None or b is None:
        return None
    return a * b


def is_suspicious(pe):
    """
    unusual locations of import tables
    non recognized section names
    presence of long ASCII strings
    """
    relocations_overlap_entry_point = False
    sequential_relocs = 0
    if hasattr(pe, 'DIRECTORY_ENTRY_BASERELOC'):
        for base_reloc in pe.DIRECTORY_ENTRY_BASERELOC:
            last_reloc_rva = None
            for reloc in base_reloc.entries:
                if (reloc.rva <= pe.OPTIONAL_HEADER.AddressOfEntryPoint <=
                    reloc.rva + 4):
                    relocations_overlap_entry_point = True
                if (last_reloc_rva is not None and last_reloc_rva <= reloc.
                    rva <= last_reloc_rva + 4):
                    sequential_relocs += 1
                last_reloc_rva = reloc.rva
    warnings_while_parsing = False
    warnings = pe.get_warnings()
    if warnings:
        warnings_while_parsing
    pass


def translate_dna_to_peptide(dna_str):
    """ Translate a DNA sequence encoding a peptide to amino-acid sequence via RNA.

    If 'N' is included in input dna, 'X' will be outputted since 'N' represents
    uncertainty. Also will output a flag indicating if has stop codon.

    Parameters
    ----------
    dna_str: str or List(str). dna string to be translated.

    Returns
    -------
    aa_str: translated peptide
    has_stop_codon: Indicator for showing if the input dna contains stop codon

    """
    codontable = {'ATA': 'I', 'ATC': 'I', 'ATT': 'I', 'ATG': 'M', 'ACA':
        'T', 'ACC': 'T', 'ACG': 'T', 'ACT': 'T', 'AAC': 'N', 'AAT': 'N',
        'AAA': 'K', 'AAG': 'K', 'AGC': 'S', 'AGT': 'S', 'AGA': 'R', 'AGG':
        'R', 'CTA': 'L', 'CTC': 'L', 'CTG': 'L', 'CTT': 'L', 'CCA': 'P',
        'CCC': 'P', 'CCG': 'P', 'CCT': 'P', 'CAC': 'H', 'CAT': 'H', 'CAA':
        'Q', 'CAG': 'Q', 'CGA': 'R', 'CGC': 'R', 'CGG': 'R', 'CGT': 'R',
        'GTA': 'V', 'GTC': 'V', 'GTG': 'V', 'GTT': 'V', 'GCA': 'A', 'GCC':
        'A', 'GCG': 'A', 'GCT': 'A', 'GAC': 'D', 'GAT': 'D', 'GAA': 'E',
        'GAG': 'E', 'GGA': 'G', 'GGC': 'G', 'GGG': 'G', 'GGT': 'G', 'TCA':
        'S', 'TCC': 'S', 'TCG': 'S', 'TCT': 'S', 'TTC': 'F', 'TTT': 'F',
        'TTA': 'L', 'TTG': 'L', 'TAC': 'Y', 'TAT': 'Y', 'TAA': '_', 'TAG':
        '_', 'TGC': 'C', 'TGT': 'C', 'TGA': '_', 'TGG': 'W'}
    dna_str = dna_str.upper()
    has_stop_codon = False
    aa_str = []
    for idx in range(0, len(dna_str), 3):
        codon = dna_str[idx:idx + 3]
        if len(codon) < 3:
            break
        if 'N' in codon:
            aa_str.append('X')
        elif codontable[codon] == '_':
            has_stop_codon = True
            return ''.join(aa_str), has_stop_codon
        else:
            aa_str.append(codontable[codon])
    return ''.join(aa_str), has_stop_codon


def merge_two_dicts(first_dict, second_dict):
    """ Merges two python dicts by making a copy of first then updating with second.
        Returns a copy. """
    return_dict = first_dict.copy()
    return_dict.update(second_dict)
    return return_dict


def _pfbSegLen(p, d):
    """compute a pfb style length from the first 4 bytes of string d"""
    return (ord(d[p + 3]) << 8 | ord(d[p + 2]) << 8 | ord(d[p + 1])
        ) << 8 | ord(d[p])


def gradfft_from_fft(f_fft, KX, KY):
    """Return the gradient of f_fft in spectral space."""
    px_f_fft = 1.0j * KX * f_fft
    py_f_fft = 1.0j * KY * f_fft
    return px_f_fft, py_f_fft


def length():
    """Return the length of the sequence

        Note that this may fail if the TAL iterator was created on a Python
        iterator.
        """