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 psi_Ba_Na_Cl_PK74(T, P):
    """c-c'-a: barium sodium chloride [PK74]."""
    psi = 0.0
    valid = T == 298.15
    return psi, valid


def ifNone(test, val):
    """return val if test is None else test"""
    return val if test is None else test


def _mergeEntityList(A, B):
    """Return merged entityList os A and B."""
    for i in range(len(B)):
        for key, val in B[i].items():
            if key in A[i]:
                for item in val:
                    A[i][key].append(item)
            else:
                A[i][key] = val
    return A


def import_string(import_name, silent=False):
    """Imports an object based on a string.  This is useful if you want to
    use import paths as endpoints or something similar.  An import path can
    be specified either in dotted notation (``xml.sax.saxutils.escape``)
    or with a colon as object delimiter (``xml.sax.saxutils:escape``).

    If `silent` is True the return value will be `None` if the import fails.

    :param import_name: the dotted name for the object to import.
    :param silent: if set to `True` import errors are ignored and
                   `None` is returned instead.
    :return: imported object
    """
    try:
        if ':' in import_name:
            module, obj_name = import_name.split(':', 1)
        elif '.' in import_name:
            module, obj_name = import_name.rsplit('.', 1)
        else:
            return __import__(import_name)
        return getattr(__import__(module, None, None, [obj_name]), obj_name)
    except (ImportError, AttributeError):
        if not silent:
            raise


def atse_getFieldType(field):
    """ return the type of a field """


def f3(x):
    """A quartic with roots at 0, 1, 2 and 3"""
    return x * (x - 1.0) * (x - 2.0) * (x - 3.0)


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 update_default_flags(df, columns_df, check):
    """
    Update the dataframe with the default flag values for the columns in the columns_df.
    :param df: The raw dataframe which has to be updated with the flags
    :param columns_df: The df containing the list of columns and their respective min/max thresholds.
    :param check: The type of check being performed.
    :return: default flags updated dataframe
    """
    col_to_check = check
    if check == 'range':
        col_to_check = 'min'
    for row in columns_df[columns_df[col_to_check].notnull()].itertuples():
        column_name = row.column_name
        df[column_name + '_' + check + '_flag'] = 0
    return df


def condv(key, dic, default='None'):
    """Helper Funciton to handle missing keys"""
    try:
        val = dic[key]
        if type(val) == list:
            if not val:
                return ''
            if len(val) == 1:
                return val[0]
            else:
                return ';'.join(val)
        else:
            return dic[key]
    except:
        return default


def model_to_dict(model):
    """Turns a Keras model into a Python dictionary

    :param model: Keras model instance
    :return: dictionary with model information
    """
    return dict(model=model.to_json(), weights=model.get_weights())


@staticmethod
def has_battery():
    """Return whether the device has a battery."""
    return False


@classmethod
def quick_visitor(cls, visit_dict, node):
    """Class method to quickly define and run a custom visitor."""
    qv = type('QuickVisitor', cls, visit_dict)
    qv.visit(node)


def the(iterable, context=None):
    """ Returns the first element of an iterable, but requires there to be
      exactly one.
  """
    icontext = 'expected exactly one value'
    if context is not None:
        icontext = icontext + ' for ' + context
    is_first = True
    for elem in iterable:
        if is_first:
            it = elem
            is_first = False
        else:
            raise IndexError('%s: got more than one element (%s, %s, ...)' %
                (icontext, it, elem))
    if is_first:
        raise IndexError('%s: got no elements' % (icontext,))
    return it


def write_jcamp_pair(f, key, value):
    """
    Write out a line of a JCAMP file.

    a line might actually be more than one line of text for arrays.
    """
    line = '##$' + key + '= '
    if type(value) == float or type(value) == int:
        line = line + repr(value)
    elif isinstance(value, str):
        line = line + '<' + value + '>'
    elif type(value) == bool:
        if value:
            line = line + 'yes'
        else:
            line = line + 'no'
    elif isinstance(value, list):
        line = line + '(0..' + repr(len(value) - 1) + ')'
        f.write(line)
        f.write('\n')
        line = ''
        for v in value:
            if len(line) > 70:
                f.write(line)
                f.write('\n')
                line = ''
            if isinstance(v, str):
                to_add = '<' + v + '>'
            else:
                to_add = repr(v)
            if len(line + ' ' + to_add) > 80:
                f.write(line)
                f.write('\n')
                line = ''
            if line != '':
                line = line + to_add + ' '
            else:
                line = to_add + ' '
    f.write(line)
    f.write('\n')
    return


@classmethod
def HeterogeneousLambertian(cls, radius, ro_target, ro_env):
    """Provides parameterisation for heterogeneous Lambertian (ie. uniform BRDF) surfaces.

        These surfaces are modelled in 6S as a circular target surrounded by an environment of a different reflectance.

        Arguments:

        * ``radius`` -- The radius of the target (in km)
        * ``ro_target`` -- The reflectance of the target
        * ``ro_env`` -- The reflectance of the environment

        Both of the reflectances can be set to any of the following:

        - A single float value (for example, 0.634), in which case it is interpreted as a spectrally-constant reflectance value.
        - A constant defined by this class (one of ``GroundReflectance.GreenVegetation``, ``GroundReflectance.ClearWater``, ``GroundReflectance.Sand`` or ``GroundReflectance.LakeWater``) in which case a built-in spectrum of the specified material is used.
        - An array of values (for example, [0.67, 0.85, 0.34, 0.65]) in which case the values are taken to be reflectances across the whole wavelength range at a spacing of 2.5nm. In this case, if the start wavelength is s and the end wavelength is e, the values must be given for the wavelengths: ``s, s+2.5, s+5.0, s+7.5, ..., e-2.5, e``
        - A multidimensional ndarray giving wavelength (column 0) and reflectance (column 1) values
        """
    ro_target_type, ro_target_values = cls._GetTargetTypeAndValues(ro_target)
    ro_env_type, ro_env_values = cls._GetTargetTypeAndValues(ro_env,
        'REFL_REPLACE_2')
    if ro_target_values == '' and ro_env_values == '':
        s = '1 (Non homogeneous surface)\n%s %s %f (ro1 ro2 radius)\n' % (
            ro_target_type, ro_env_type, radius)
    else:
        s = (
            '1 (Non homogeneous surface)\n%s %s %f (ro1 ro2 radius)\n%s\n%s\n'
             % (ro_target_type, ro_env_type, radius, ro_target_values,
            ro_env_values))
    return [s, ro_target, ro_env]


def checkout(repository, target):
    """
    Check out target into the current directory.
    Target can be a branch, review Id, or commit.

    :param repository: Current git repository.
    :param target: Review ID, commit, branch.
    :return: Return the most recent commit ID (top of the git log).
    """
    repository.git.fetch([next(iter(repository.remotes)), target])
    repository.git.checkout('FETCH_HEAD')
    return repository.git.rev_parse(['--short', 'HEAD']).encode('ascii',
        'ignore')


def install(createpdf, options):
    """ This function is called with an object with the createpdf
        module globals as attributes, and with the options from
        the command line parser.  This function does not have
        to exist, but must have the correct call signature if
        it does.
    """


def rename_node_attribute(topology, old_attr, new_attr):
    """Rename all nodes attributes with a specific name to a new name

    Parameters
    ----------
    topology : Topology
        The topology object
    old_attr : any hashable type
        Old attribute name
    new_attr : any hashable type
        New attribute name

    Example
    -------
    >>> import fnss
    >>> topo = fnss.Topology()
    >>> topo.add_node(1, pos=(0, 0))
    >>> topo.add_node(2, pos=(1, 1))
    >>> topo.nodes(data=True)
    [(1, {'pos': (0, 0)}), (2, {'pos': (1, 1)})]
    >>> fnss.rename_edge_attribute(topo, 'pos', 'coordinates')
    >>> topo.edges(data=True)
    [(1, {'coordinates': (0, 0)}), (2, {'coordinates': (1, 1)})]
    """
    for v in topology.nodes():
        if old_attr in topology.adj[v]:
            topology.node[v][new_attr] = topology.node[v][old_attr]
            del topology.node[v][old_attr]


def conform_to_argspec(args, kwargs, argspec):
    """Attempts to take the arguments in arg and kwargs and return only those which can be used
       by the argspec given."""
    regargs, varargs, varkwargs, defaults = argspec
    N = len(regargs)
    newargs = list(args)
    newkwargs = kwargs.copy()
    if varargs is None:
        newargs = newargs[:N]
    else:
        pass
    for varname in regargs[len(newargs):]:
        try:
            newargs.append(newkwargs[varname])
            del newkwargs[varname]
        except KeyError:
            break
    if varkwargs is None:
        newkwargs = {}
    else:
        pass
    return newargs, newkwargs


def call_obj_fn(params: list, obj_fn: callable, obj_fn_args: dict) ->tuple:
    """ call_obj_fn: calls supplied objective function, evaluating using
    supplied parameters; callable in single- and multi-processed configurations

    Args:
        params (list): list of ints or floats corresponding to current bee
            parameter values
        obj_fn (callable): function to accept list of paramters, returns a
            quantitative measurement of fitness
        obj_fn_args (dict): non-tunable kwargs to pass to objective function

    Returns:
        tuple: (params, objective function return value)
    """
    return params, obj_fn(params, **obj_fn_args)


def average_precision(truth, recommend):
    """Average Precision (AP).

    Args:
        truth (numpy 1d array): Set of truth samples.
        recommend (numpy 1d array): Ordered set of recommended samples.

    Returns:
        float: AP.

    """
    if len(truth) == 0:
        if len(recommend) == 0:
            return 1.0
        return 0.0
    tp = accum = 0.0
    for n in range(recommend.size):
        if recommend[n] in truth:
            tp += 1.0
            accum += tp / (n + 1.0)
    return accum / truth.size


def formula_2011_01_01(foyer_fiscal, period, parameters):
    """
        Investissements OUTRE-MER dans le secteur du logement et autres secteurs d’activité
        2011
        TODO: Plafonnement sur la notice
        """
    f7qb = foyer_fiscal('f7qb', period)
    f7qc = foyer_fiscal('f7qc', period)
    f7qd = foyer_fiscal('f7qd', period)
    f7ql = foyer_fiscal('f7ql', period)
    f7qm = foyer_fiscal('f7qm_2012', period)
    f7qt = foyer_fiscal('f7qt_2012', period)
    f7oa = foyer_fiscal('f7oa', period)
    f7ob = foyer_fiscal('f7ob', period)
    f7oc = foyer_fiscal('f7oc', period)
    f7oh = foyer_fiscal('f7oh', period)
    f7oi = foyer_fiscal('f7oi', period)
    f7oj = foyer_fiscal('f7oj', period)
    f7ok = foyer_fiscal('f7ok', period)
    return (f7qb + f7qc + f7qd + f7ql + f7qm + f7qt + f7oa + f7ob + f7oc +
        f7oh + f7oi + f7oj + f7ok)


def rm_blank(name, replace='', **kwargs):
    """ Replace blank spaces in a name by a given character (default = remove)
    Blanks at extremities are always removed and nor replaced """
    return replace.join(name.split())


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_flavor():
    """Get the flavor of the library (jovian or jovian-pro)"""
    try:
        from jovian._flavor import __flavor__
        return __flavor__
    except ImportError:
        return 'jovian'


def queue_defaults(queue_name, computer=None):
    """
    In this class you specify defaults methods which you can use for workflows
    or normal calculations.
    """
    """
    code = Code.get_from_string(codename)
    code2 = Code.get_from_string(codename2)
    computer = Computer.get(computer_n
    ame)
    """
    queue_resources = None
    print(queue_name)
    computers = {'iff003': {'th1': {'resources': {'num_machines': 1,
        'num_mpiprocs_per_machine': 12}, 'walltime_sec': 30 * 60},
        'th1_small': {'resources': {'num_machines': 1,
        'num_mpiprocs_per_machine': 12}, 'walltime_sec': 20 * 60}}}
    if computer:
        c_name = computer
        queue = computers.get(c_name, {}).get(queue_name, {})
        res = queue.get('resources', None)
        wt = queue.get('walltime_sec', None)
    else:
        c_name = None
        res = None
        wt = None
        for comp in computers.keys():
            queue = computers.get(comp, {}).get(queue_name, {})
            if queue:
                res = queue.get('resources', None)
                wt = queue.get('walltime_sec', None)
    queue_resources = {'resources': res, 'walltime_sec': wt}
    return queue_resources


def pmcfg(cfg):
    """
    prints out the core config file to the prompt with a nice stagger Look for
    readability

    Args:
        cfg: dict of dict in a hierarchy of  {section, {items, values}}
    """
    for sec in cfg.keys():
        print(repr(sec))
        for item in cfg[sec].keys():
            print('\t' + item)
            obj = cfg[sec][item]
            for att in ['type', 'options', 'default', 'description']:
                value = getattr(obj, att)
                print('\t\t' + att)
                if type(value) == list:
                    out = ', '.join(value)
                else:
                    out = value
                print('\t\t\t' + repr(out))


def setcompression(value):
    """Set default compression filter."""
    global NX_COMPRESSION
    if value == 'None':
        value = None
    NX_COMPRESSION = value


def write_config(config, path):
    """
    Write a configuration file.

    Arguments
    config -- a configuration
    path -- the location to serialize config
    """
    with open(path, 'w') as output_file:
        config.write(output_file)


@classmethod
def _getChildText(cls, parent, childname):
    """ provides text of child named by childname

        :param parent: parent node
        :type parent: :class:`lxml.etree.Element`
        :param childname: child name
        :type childname: :opj:`str`
        :returns: text string
        :rtype: :obj:`str`
        """
    children = parent.findall(childname)
    return cls._getText(children[0]) if len(children) else None


def _writemsgwith(write, dest, *args, **opts):
    """Write ui message with the given ui._write*() function

    The specified message type is translated to 'ui.<type>' label if the dest
    isn't a structured channel, so that the message will be colorized.
    """
    if 'type' in opts and not getattr(dest, 'structured', False):
        opts['label'] = opts.get('label', b'') + b' ui.%s' % opts.pop('type')
    write(dest, *args, **opts)


@classmethod
def _get_value_background(cls, config):
    """
        Return the calculated background color based on the "value" key.

        :param config: the config dict
        :return: color string
        """
    try:
        this = config['thresholds'][config['label']]
        order = this.get('order', 'auto')
        if order != 'strict':
            caster = cls._get_caster_func(order, this)
            if caster:
                thresholds = sorted(list(this['colors'].keys()), key=lambda
                    v: caster(v))
                last = thresholds[0]
                for threshold in thresholds:
                    if caster(config['value']) <= caster(threshold):
                        if this.get('shade', None):
                            fraction = cls._get_fraction(last, threshold,
                                caster(config['value']))
                            return cls._shade(fraction, this['colors'][last
                                ], this['colors'][threshold])
                        return this['colors'][threshold]
                    last = threshold
                return this['above']
        return this['colors'][config['value']]
    except KeyError:
        pass
    try:
        return config['value_backgrounds'][config['value']]
    except KeyError:
        pass
    return config['value_background']


def slen(value):
    """超级len命令,能将中文算成两个位置"""
    length = len(value)
    utf8_length = len(value.encode('utf-8'))
    length = (utf8_length - length) / 2 + length
    return int(length)


@classmethod
def get(cls, *args, **kwargs):
    """
        Returns path for the given resource name
        :param args: str, name of the source to retrieve path of
        :return: str
        """
    if 'dirname' in kwargs:
        return cls(kwargs.pop('dirname'))._get(*args)
    else:
        return cls()._get(*args)


def delete_nodes_and_connections_sqla(pks_to_delete):
    """
    Delete all nodes corresponding to pks in the input.
    :param pks_to_delete: A list, tuple or set of pks that should be deleted.
    """
    from aiida.backends.sqlalchemy.models.node import DbNode, DbLink
    from aiida.backends.sqlalchemy.models.group import table_groups_nodes
    from aiida.manage.manager import get_manager
    backend = get_manager().get_backend()
    with backend.transaction() as session:
        stmt = table_groups_nodes.delete().where(table_groups_nodes.c.
            dbnode_id.in_(list(pks_to_delete)))
        session.execute(stmt)
        session.query(DbLink).filter(DbLink.input_id.in_(list(pks_to_delete))
            ).delete(synchronize_session='fetch')
        session.query(DbLink).filter(DbLink.output_id.in_(list(pks_to_delete))
            ).delete(synchronize_session='fetch')
        session.query(DbNode).filter(DbNode.id.in_(list(pks_to_delete))
            ).delete(synchronize_session='fetch')


def get_translation(language):
    """
        get translation (translated object) if exists
        """


def _fix_261_mplog():
    """necessary for older python's to disable a broken monkeypatch
    in the logging module.  See multiprocessing/util.py for the
    hasattr() check.  At least in Python 2.6.1 the multiprocessing
    module is not imported by logging and as such the test in
    the util fails.
    """
    import logging
    import multiprocessing
    logging.multiprocessing = multiprocessing


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

        :param FolderLogInfo val:
        :rtype: AssetLogInfo
        """
    return cls('folder', val)


@classmethod
def _defaults(cls, config):
    """
        Provide default configuration for a master view.
        """
    rattail_config = config.registry.settings.get('rattail_config')
    route_prefix = cls.get_route_prefix()
    url_prefix = cls.get_url_prefix()
    instance_url_prefix = cls.get_instance_url_prefix()
    permission_prefix = cls.get_permission_prefix()
    model_key = cls.get_model_key()
    model_title = cls.get_model_title()
    model_title_plural = cls.get_model_title_plural()
    if cls.has_rows:
        row_model_title = cls.get_row_model_title()
    legacy_mobile = cls.legacy_mobile_enabled(rattail_config)
    config.add_tailbone_permission_group(permission_prefix,
        model_title_plural, overwrite=False)
    if cls.listable:
        config.add_tailbone_permission(permission_prefix, '{}.list'.format(
            permission_prefix), 'List / search {}'.format(model_title_plural))
        config.add_route(route_prefix, '{}/'.format(url_prefix))
        config.add_view(cls, attr='index', route_name=route_prefix,
            permission='{}.list'.format(permission_prefix))
        if legacy_mobile and cls.supports_mobile:
            config.add_route('mobile.{}'.format(route_prefix), '/mobile{}/'
                .format(url_prefix))
            config.add_view(cls, attr='mobile_index', route_name=
                'mobile.{}'.format(route_prefix), permission='{}.list'.
                format(permission_prefix))
        if cls.results_downloadable_csv:
            config.add_tailbone_permission(permission_prefix,
                '{}.results_csv'.format(permission_prefix),
                'Download {} as CSV'.format(model_title_plural))
            config.add_route('{}.results_csv'.format(route_prefix),
                '{}/csv'.format(url_prefix))
            config.add_view(cls, attr='results_csv', route_name=
                '{}.results_csv'.format(route_prefix), permission=
                '{}.results_csv'.format(permission_prefix))
        if cls.results_downloadable_xlsx:
            config.add_tailbone_permission(permission_prefix,
                '{}.results_xlsx'.format(permission_prefix),
                'Download {} as XLSX'.format(model_title_plural))
            config.add_route('{}.results_xlsx'.format(route_prefix),
                '{}/xlsx'.format(url_prefix))
            config.add_view(cls, attr='results_xlsx', route_name=
                '{}.results_xlsx'.format(route_prefix), permission=
                '{}.results_xlsx'.format(permission_prefix))
    if cls.supports_quickie_search:
        config.add_tailbone_permission(permission_prefix, '{}.quickie'.
            format(permission_prefix), 'Do a "quickie search" for {}'.
            format(model_title_plural))
        config.add_route('{}.quickie'.format(route_prefix), '{}/quickie'.
            format(route_prefix), request_method='GET')
        config.add_view(cls, attr='quickie', route_name='{}.quickie'.format
            (route_prefix), permission='{}.quickie'.format(permission_prefix))
    if cls.creatable or legacy_mobile and cls.mobile_creatable:
        config.add_tailbone_permission(permission_prefix, '{}.create'.
            format(permission_prefix), 'Create new {}'.format(model_title))
    if cls.creatable:
        config.add_route('{}.create'.format(route_prefix), '{}/new'.format(
            url_prefix))
        config.add_view(cls, attr='create', route_name='{}.create'.format(
            route_prefix), permission='{}.create'.format(permission_prefix))
    if legacy_mobile and cls.mobile_creatable:
        config.add_route('mobile.{}.create'.format(route_prefix),
            '/mobile{}/new'.format(url_prefix))
        config.add_view(cls, attr='mobile_create', route_name=
            'mobile.{}.create'.format(route_prefix), permission='{}.create'
            .format(permission_prefix))
    if cls.populatable:
        config.add_route('{}.populate'.format(route_prefix),
            '{}/{{uuid}}/populate'.format(url_prefix))
        config.add_view(cls, attr='populate', route_name='{}.populate'.
            format(route_prefix), permission='{}.create'.format(
            permission_prefix))
    if cls.supports_set_enabled_toggle:
        config.add_tailbone_permission(permission_prefix,
            '{}.enable_disable_set'.format(permission_prefix),
            'Enable / disable set (selection) of {}'.format(model_title_plural)
            )
        config.add_route('{}.enable_set'.format(route_prefix),
            '{}/enable-set'.format(url_prefix), request_method='POST')
        config.add_view(cls, attr='enable_set', route_name='{}.enable_set'.
            format(route_prefix), permission='{}.enable_disable_set'.format
            (permission_prefix))
        config.add_route('{}.disable_set'.format(route_prefix),
            '{}/disable-set'.format(url_prefix), request_method='POST')
        config.add_view(cls, attr='disable_set', route_name=
            '{}.disable_set'.format(route_prefix), permission=
            '{}.enable_disable_set'.format(permission_prefix))
    if cls.set_deletable:
        config.add_tailbone_permission(permission_prefix, '{}.delete_set'.
            format(permission_prefix), 'Delete set (selection) of {}'.
            format(model_title_plural))
        config.add_route('{}.delete_set'.format(route_prefix),
            '{}/delete-set'.format(url_prefix), request_method='POST')
        config.add_view(cls, attr='delete_set', route_name='{}.delete_set'.
            format(route_prefix), permission='{}.delete_set'.format(
            permission_prefix))
    if cls.bulk_deletable:
        config.add_route('{}.bulk_delete'.format(route_prefix),
            '{}/bulk-delete'.format(url_prefix), request_method='POST')
        config.add_view(cls, attr='bulk_delete', route_name=
            '{}.bulk_delete'.format(route_prefix), permission=
            '{}.bulk_delete'.format(permission_prefix))
        config.add_tailbone_permission(permission_prefix, '{}.bulk_delete'.
            format(permission_prefix), 'Bulk delete {}'.format(
            model_title_plural))
    if cls.mergeable:
        config.add_route('{}.merge'.format(route_prefix), '{}/merge'.format
            (url_prefix))
        config.add_view(cls, attr='merge', route_name='{}.merge'.format(
            route_prefix), permission='{}.merge'.format(permission_prefix))
        config.add_tailbone_permission(permission_prefix, '{}.merge'.format
            (permission_prefix), 'Merge 2 {}'.format(model_title_plural))
    if cls.viewable:
        config.add_tailbone_permission(permission_prefix, '{}.view'.format(
            permission_prefix), 'View details for {}'.format(model_title))
        if cls.has_pk_fields:
            config.add_tailbone_permission(permission_prefix,
                '{}.view_pk_fields'.format(permission_prefix),
                'View all PK-type fields for {}'.format(model_title_plural))
        if cls.secure_global_objects:
            config.add_tailbone_permission(permission_prefix,
                '{}.view_global'.format(permission_prefix),
                'View *global* {}'.format(model_title_plural))
        config.add_route('{}.view_index'.format(route_prefix), '{}/view'.
            format(url_prefix))
        config.add_view(cls, attr='view_index', route_name='{}.view_index'.
            format(route_prefix), permission='{}.view'.format(
            permission_prefix))
        config.add_route('{}.view'.format(route_prefix), instance_url_prefix)
        config.add_view(cls, attr='view', route_name='{}.view'.format(
            route_prefix), permission='{}.view'.format(permission_prefix))
        if legacy_mobile and cls.supports_mobile:
            config.add_route('mobile.{}.view'.format(route_prefix),
                '/mobile{}'.format(instance_url_prefix))
            config.add_view(cls, attr='mobile_view', route_name=
                'mobile.{}.view'.format(route_prefix), permission='{}.view'
                .format(permission_prefix))
        if (cls.has_versions and rattail_config and rattail_config.
            versioning_enabled()):
            config.add_tailbone_permission(permission_prefix, '{}.versions'
                .format(permission_prefix), 'View version history for {}'.
                format(model_title))
            config.add_route('{}.versions'.format(route_prefix),
                '{}/versions/'.format(instance_url_prefix))
            config.add_view(cls, attr='versions', route_name='{}.versions'.
                format(route_prefix), permission='{}.versions'.format(
                permission_prefix))
            config.add_route('{}.version'.format(route_prefix),
                '{}/versions/{{txnid}}'.format(instance_url_prefix))
            config.add_view(cls, attr='view_version', route_name=
                '{}.version'.format(route_prefix), permission='{}.versions'
                .format(permission_prefix))
    if cls.has_image:
        config.add_route('{}.image'.format(route_prefix), '{}/image'.format
            (instance_url_prefix))
        config.add_view(cls, attr='image', route_name='{}.image'.format(
            route_prefix), permission='{}.view'.format(permission_prefix))
    if cls.has_thumbnail:
        config.add_route('{}.thumbnail'.format(route_prefix),
            '{}/thumbnail'.format(instance_url_prefix))
        config.add_view(cls, attr='thumbnail', route_name='{}.thumbnail'.
            format(route_prefix), permission='{}.view'.format(
            permission_prefix))
    if cls.cloneable:
        config.add_tailbone_permission(permission_prefix, '{}.clone'.format
            (permission_prefix), 'Clone an existing {0} as a new {0}'.
            format(model_title))
        config.add_route('{}.clone'.format(route_prefix), '{}/clone'.format
            (instance_url_prefix))
        config.add_view(cls, attr='clone', route_name='{}.clone'.format(
            route_prefix), permission='{}.clone'.format(permission_prefix))
    if cls.touchable:
        config.add_tailbone_permission(permission_prefix, '{}.touch'.format
            (permission_prefix), '"Touch" a {} to trigger datasync for it'.
            format(model_title))
        config.add_route('{}.touch'.format(route_prefix), '{}/touch'.format
            (instance_url_prefix))
        config.add_view(cls, attr='touch', route_name='{}.touch'.format(
            route_prefix), permission='{}.touch'.format(permission_prefix))
    if cls.downloadable:
        config.add_route('{}.download'.format(route_prefix), '{}/download'.
            format(instance_url_prefix))
        config.add_view(cls, attr='download', route_name='{}.download'.
            format(route_prefix), permission='{}.download'.format(
            permission_prefix))
        config.add_tailbone_permission(permission_prefix, '{}.download'.
            format(permission_prefix), 'Download associated data for {}'.
            format(model_title))
    if cls.editable or legacy_mobile and cls.mobile_editable:
        config.add_tailbone_permission(permission_prefix, '{}.edit'.format(
            permission_prefix), 'Edit {}'.format(model_title))
    if cls.editable:
        config.add_route('{}.edit'.format(route_prefix), '{}/edit'.format(
            instance_url_prefix))
        config.add_view(cls, attr='edit', route_name='{}.edit'.format(
            route_prefix), permission='{}.edit'.format(permission_prefix))
    if legacy_mobile and cls.mobile_editable:
        config.add_route('mobile.{}.edit'.format(route_prefix),
            '/mobile{}/edit'.format(instance_url_prefix))
        config.add_view(cls, attr='mobile_edit', route_name=
            'mobile.{}.edit'.format(route_prefix), permission='{}.edit'.
            format(permission_prefix))
    if cls.executable or legacy_mobile and cls.mobile_executable:
        config.add_tailbone_permission(permission_prefix, '{}.execute'.
            format(permission_prefix), 'Execute {}'.format(model_title))
    if cls.executable:
        config.add_route('{}.execute'.format(route_prefix), '{}/execute'.
            format(instance_url_prefix))
        config.add_view(cls, attr='execute', route_name='{}.execute'.format
            (route_prefix), permission='{}.execute'.format(permission_prefix))
    if legacy_mobile and cls.mobile_executable:
        config.add_route('mobile.{}.execute'.format(route_prefix),
            '/mobile{}/execute'.format(instance_url_prefix))
        config.add_view(cls, attr='mobile_execute', route_name=
            'mobile.{}.execute'.format(route_prefix), permission=
            '{}.execute'.format(permission_prefix))
    if cls.deletable:
        config.add_route('{0}.delete'.format(route_prefix), '{}/delete'.
            format(instance_url_prefix))
        config.add_view(cls, attr='delete', route_name='{0}.delete'.format(
            route_prefix), permission='{0}.delete'.format(permission_prefix))
        config.add_tailbone_permission(permission_prefix, '{0}.delete'.
            format(permission_prefix), 'Delete {0}'.format(model_title))
    if cls.supports_import_batch_from_file:
        config.add_tailbone_permission(permission_prefix, '{}.import_file'.
            format(permission_prefix),
            'Create a new import batch from data file')
    if cls.has_rows and cls.rows_downloadable_csv:
        config.add_tailbone_permission(permission_prefix,
            '{}.row_results_csv'.format(permission_prefix),
            'Download {} results as CSV'.format(row_model_title))
        config.add_route('{}.row_results_csv'.format(route_prefix),
            '{}/{{uuid}}/rows-csv'.format(url_prefix))
        config.add_view(cls, attr='row_results_csv', route_name=
            '{}.row_results_csv'.format(route_prefix), permission=
            '{}.row_results_csv'.format(permission_prefix))
    if cls.has_rows and cls.rows_downloadable_xlsx:
        config.add_tailbone_permission(permission_prefix,
            '{}.row_results_xlsx'.format(permission_prefix),
            'Download {} results as XLSX'.format(row_model_title))
        config.add_route('{}.row_results_xlsx'.format(route_prefix),
            '{}/{{uuid}}/rows-xlsx'.format(url_prefix))
        config.add_view(cls, attr='row_results_xlsx', route_name=
            '{}.row_results_xlsx'.format(route_prefix), permission=
            '{}.row_results_xlsx'.format(permission_prefix))
    if cls.has_rows:
        if cls.rows_creatable or legacy_mobile and cls.mobile_rows_creatable:
            config.add_tailbone_permission(permission_prefix,
                '{}.create_row'.format(permission_prefix),
                'Create new {} rows'.format(model_title))
        if cls.rows_creatable:
            config.add_route('{}.create_row'.format(route_prefix),
                '{}/new-row'.format(instance_url_prefix))
            config.add_view(cls, attr='create_row', route_name=
                '{}.create_row'.format(route_prefix), permission=
                '{}.create_row'.format(permission_prefix))
        if legacy_mobile and cls.mobile_rows_creatable:
            config.add_route('mobile.{}.create_row'.format(route_prefix),
                '/mobile{}/new-row'.format(instance_url_prefix))
            config.add_view(cls, attr='mobile_create_row', route_name=
                'mobile.{}.create_row'.format(route_prefix), permission=
                '{}.create_row'.format(permission_prefix))
            if cls.mobile_rows_quickable:
                config.add_route('mobile.{}.quick_row'.format(route_prefix),
                    '/mobile{}/quick-row'.format(instance_url_prefix))
                config.add_view(cls, attr='mobile_quick_row', route_name=
                    'mobile.{}.quick_row'.format(route_prefix), permission=
                    '{}.create_row'.format(permission_prefix))
    if cls.has_rows:
        if cls.rows_viewable:
            config.add_route('{}.view_row'.format(route_prefix),
                '{}/{{uuid}}/rows/{{row_uuid}}'.format(url_prefix))
            config.add_view(cls, attr='view_row', route_name='{}.view_row'.
                format(route_prefix), permission='{}.view'.format(
                permission_prefix))
        if legacy_mobile and cls.mobile_rows_viewable:
            config.add_route('mobile.{}.view_row'.format(route_prefix),
                '/mobile{}/{{uuid}}/rows/{{row_uuid}}'.format(url_prefix))
            config.add_view(cls, attr='mobile_view_row', route_name=
                'mobile.{}.view_row'.format(route_prefix), permission=
                '{}.view'.format(permission_prefix))
    if cls.has_rows:
        if cls.rows_editable or legacy_mobile and cls.mobile_rows_editable:
            config.add_tailbone_permission(permission_prefix, '{}.edit_row'
                .format(permission_prefix), 'Edit individual {} rows'.
                format(model_title))
        if cls.rows_editable:
            config.add_route('{}.edit_row'.format(route_prefix),
                '{}/{{uuid}}/rows/{{row_uuid}}/edit'.format(url_prefix))
            config.add_view(cls, attr='edit_row', route_name='{}.edit_row'.
                format(route_prefix), permission='{}.edit_row'.format(
                permission_prefix))
        if legacy_mobile and cls.mobile_rows_editable:
            config.add_route('mobile.{}.edit_row'.format(route_prefix),
                '/mobile{}/{{uuid}}/rows/{{row_uuid}}/edit'.format(url_prefix))
            config.add_view(cls, attr='mobile_edit_row', route_name=
                'mobile.{}.edit_row'.format(route_prefix), permission=
                '{}.edit_row'.format(permission_prefix))
    if cls.has_rows:
        if cls.rows_deletable or legacy_mobile and cls.mobile_rows_deletable:
            config.add_tailbone_permission(permission_prefix,
                '{}.delete_row'.format(permission_prefix),
                'Delete individual {} rows'.format(model_title))
        if cls.rows_deletable:
            config.add_route('{}.delete_row'.format(route_prefix),
                '{}/{{uuid}}/rows/{{row_uuid}}/delete'.format(url_prefix))
            config.add_view(cls, attr='delete_row', route_name=
                '{}.delete_row'.format(route_prefix), permission=
                '{}.delete_row'.format(permission_prefix))
        if legacy_mobile and cls.mobile_rows_deletable:
            config.add_route('mobile.{}.delete_row'.format(route_prefix),
                '/mobile{}/{{uuid}}/rows/{{row_uuid}}/delete'.format(
                url_prefix))
            config.add_view(cls, attr='mobile_delete_row', route_name=
                'mobile.{}.delete_row'.format(route_prefix), permission=
                '{}.delete_row'.format(permission_prefix))


def get_config_vals(class_, type_):
    """
    Provides a configuration dict that has all the needed fields for the specified type and class
    so that data can be injected into this dic to present to the user.
    """
    return_vals = {'provider_class': class_, 'provider_type': type_,
        'label': ''}
    if class_ == 'compute':
        return_vals['config'] = {'region': '', 'zone': '',
            'queue_threshold': 1, 'max_compute': 1, 'machine_type': 1,
            'disk_size': 100, 'swap_size': '30G', 'preemptible': False}
    if class_ == 'storage' and type_ == 'local':
        return_vals['config'] = {'path': ''}
        return_vals['creds'] = {}
        return return_vals
    if class_ == 'compute' and type_ == 'static':
        return_vals['creds'] = {}
        return return_vals
    if type_ == 'gc':
        return_vals['creds'] = {'client_email': '', 'client_id': '',
            'project_id': '', 'private_key': '', 'private_key_id': '',
            'client_x509_cert_url': '', 'auth_provider_x509_cert_url': '',
            'auth_uri': '', 'token_uri': '', 'type': ''}
    if type_ == 'aws':
        return_vals['creds'] = {'aws_access_key_id': '',
            'aws_secret_access_key': ''}
    if class_ == 'storage':
        return_vals['config'] = {'bucket': '', 'region': '', 'path': ''}
        return return_vals
    return return_vals


@classmethod
def is_loaded(cls):
    """ Return whether the trigrams have been loaded. """
    return cls.trigrams is not None


def get_log(name=None):
    """Return a console logger.

    Output may be sent to the logger using the `debug`, `info`, `warning`,
    `error` and `critical` methods.

    Parameters
    ----------
    name : str
        Name of the log.

    References
    ----------
    .. [1] Logging facility for Python,
           http://docs.python.org/library/logging.html

    """
    import logging
    if name is None:
        name = 'scilab2py'
    else:
        name = 'scilab2py.' + name
    log = logging.getLogger(name)
    log.setLevel(logging.WARN)
    return log


def make_single_user():
    """Ensure that each action is only used once in the set of strips selected

    """
    pass


def gen_bold(text, alternative=False):
    """Creates a bold text.

    Args:
      text (string): The text to set bolt.
      alternative (bool): If true '_' is used instead of '*'

    Returns:
      string: The bold formatted text.

    """
    if alternative:
        return '__' + text + '__'
    else:
        return '**' + text + '**'


@classmethod
def _create_meters_by_month(cls, figure, data_by_year, shifts):
    """Totall drill meters in month by each shift."""
    met_bu_mon = figure.add_subplot(221)
    met_bu_mon.plot(data_by_year[shifts[0]].month, data_by_year[shifts[0]].
        meters, marker='D', markersize=4)
    met_bu_mon.plot(data_by_year[shifts[1]].month, data_by_year[shifts[1]].
        meters, marker='D', markersize=4)
    met_bu_mon.legend(['Смена 1', 'Смена 2'])
    met_bu_mon.set_ylabel('шпурометры, м.')
    met_bu_mon.grid(b=True, linestyle='--', linewidth=0.5)
    met_bu_mon.set_title('Пробурено за смену.')


def file_ext(v):
    """Split of the extension of a filename, without throwing an exception of there is no extension. Does not
    return the leading '.'
    :param v: """
    from os.path import splitext
    if not v:
        return None
    try:
        try:
            v = splitext(v)[1][1:]
        except TypeError:
            v = splitext(v.fspath)[1][1:]
        if v == '*':
            return None
        return v.lower() if v else None
    except IndexError:
        return None


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

        :param SharedFolderUnmountType val:
        :rtype: EventType
        """
    return cls('shared_folder_unmount', val)


def _main_url(entry):
    """Get an entry's URL field (url or ee)."""
    urlfields = 'url', 'ee'
    for f in urlfields:
        if f in entry.fields:
            return entry.fields[f]
    return None


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


@classmethod
def config(cls, seps=None, allow_no_sep=None, figures=None, try_hard=None,
    use_formats=None, use_sformats=None):
    """
        Modify class-configuration.

        :keyword seps:              Allowed separators for formats.
        :keyword allow_no_sep:      Allows formats without any separator.
        :keyword try_hard:          Regardless of any configuration try hard to
                                    build formats for the given string.
        :keyword figures:           List of three booleans that predicts how many
                                    digits formats are allowed to have.

        :type seps:                 list
        :type allow_no_sep:         bool
        :type figures:              list
        """
    if seps:
        cls.SEPS = seps
    if not cls.isnone(allow_no_sep):
        cls.ALLOW_NO_SEP = allow_no_sep
    if not cls.isnone(use_formats):
        cls.USE_FORMATS = use_formats
    if not cls.isnone(use_sformats):
        cls.USE_SFORMATS = use_sformats
    if not cls.isnone(try_hard):
        cls.TRY_HARD = try_hard
    if figures:
        cls.FIGURES = figures
    if not any(cls.FIGURES):
        raise Exception('invalid configuration')


@classmethod
def from_response(cls, node, response):
    """Construct a Transaction from a response dict."""
    fee_amount = None
    fee_note = None
    fee_to_id = None
    if response.get('fees'):
        fee_amount = response['fees'][-1]['fee'],
        fee_note = response['fees'][-1]['note'],
        fee_to_id = response['fees'][-1]['to']['id']
    return cls(node=node, json=response, id=response['_id'], amount=
        response['amount']['amount'], currency=response['amount'][
        'currency'], client_id=response['client']['id'], client_name=
        response['client']['name'], created_on=response['extra'][
        'created_on'], ip=response['extra']['ip'], latlon=response['extra']
        ['latlon'], note=response['extra']['note'], process_on=response[
        'extra']['process_on'], supp_id=response['extra']['supp_id'], fees=
        response['fees'], recent_status=response['recent_status'], timeline
        =response['timeline'], from_info=response['from'], to_info=response
        ['to'], to_type=response['to']['type'], to_id=response['to']['id'],
        fee_amount=fee_amount, fee_note=fee_note, fee_to_id=fee_to_id)


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


def loop_to_region(select_bigger: bool=False):
    """Select region of faces inside of a selected loop of edges

    :param select_bigger: Select Bigger, Select bigger regions instead of smaller ones
    :type select_bigger: bool
    """
    pass


def get_io_engine(session, cloud_name, app_io_id, return_type=None, **kwargs):
    """
    Get Application Engine in Cloud

    :type session: zadarapy.session.Session
    :param session: A valid zadarapy.session.Session object.  Required.

    :type cloud_name: str
    :param cloud_name: The cloud 'name' as returned by get_all_clouds.  For
        example: 'zadaralab01'.  Required.

    :type app_io_id: int
    :param app_io_id: IO engine ID. Required.

    :type return_type: str
    :param return_type: If this is set to the string 'json', this function
        will return a JSON string.  Otherwise, it will return a Python
        dictionary.  Optional (will return a Python dictionary by default).

    :rtype: dict, str
    :returns: A dictionary or JSON data set as a string depending on
        return_type parameter.
    """
    path = '/api/clouds/{0}/engine_types/{1}.json'.format(cloud_name, app_io_id
        )
    return session.get_api(path=path, return_type=return_type, **kwargs)


def read(filename, binary=True):
    """
    Open and read a file
    :param filename: filename to open and read
    :param binary: True if the file should be read as binary
    :return: bytes if binary is True, str otherwise
    """
    with open(filename, 'rb' if binary else 'r') as f:
        return f.read()


def format2sec(value):
    """Convert format [value,unit] in seconds"""
    if value is None:
        return 0
    elif isinstance(value, (int, float)):
        return value
    else:
        i = ['sec', 'min', 'hour', 'day'].index(value[1])
        t = int(value[0]) * [1, 60, 3600, 86400][i]
        return t


def bookmark_toggle():
    """Toggle bookmarks display

    """
    pass


def get_index(lis, argument):
    """Find the index of an item, given either the item or index as an argument.

    Particularly useful as a wrapper for arguments like channel or axis.

    Parameters
    ----------
    lis : list
        List to parse.
    argument : int or object
        Argument.

    Returns
    -------
    int
        Index of chosen object.
    """
    if isinstance(argument, int):
        if -len(lis) <= argument < len(lis):
            return argument
        else:
            raise IndexError('index {0} incompatible with length {1}'.
                format(argument, len(lis)))
    else:
        return lis.index(argument)


def _intersects_with_annotaton(second_start, segmentation, chrom, strand):
    """
    Test if second_start corresopnds to any entry in segmentation.

    Returns
    -------
        bool
    Does the read's second_start corresopnd to any known segment in segmentation

    """
    for gene_content in segmentation.values():
        for transcript_id, transcript_content in gene_content.items():
            if transcript_id == 'gene_segment':
                continue
            for segment in transcript_content:
                if strand == '+':
                    if second_start == segment.start:
                        return True
                elif second_start == segment.stop:
                    return True
    return False


def _default_ns_prefix(nsmap):
    """
    XML doc may have several prefix:namespace_url pairs, can also specify
    a namespace_url as default, tags in that namespace don't need a prefix
    NOTE:
    we rely on default namespace also present in prefixed form, I'm not sure if
    this is an XML certainty or a quirk of the eBay WSDLs

    in our case the WSDL contains:
        <wsdl:documentation>
            <Version>1.0.0</Version>
        </wsdl:documentation>
    ...but our query needs to give a prefix to the path of `Version` so we need
    to determine the default namespace of the doc, find the matching prefix and
    return it
    """
    if None in nsmap:
        default_url = nsmap[None]
        prefix = None
        for key, val in nsmap.iteritems():
            if val == default_url and key is not None:
                prefix = key
                break
        else:
            raise ValueError('Default namespace {url} not found as a prefix'
                .format(url=default_url))
        return prefix
    raise ValueError('No default namespace found in map')


def _column_to_property(column):
    """ assumes the column name has _id postfix """
    return column[:-3]


def kelvin_to_celsius(kelvin):
    """
    Convert Kelvin to Celsius
    """
    return kelvin - 273.15


def unindex(id):
    """Unindex an object in container identified by id"""


def extrude_repeat(offset: float=2.0, steps: int=10):
    """Extrude selected vertices, edges or faces repeatedly

    :param offset: Offset
    :type offset: float
    :param steps: Steps
    :type steps: int
    """
    pass


def trivial(perm):
    """The trivial permutation statistic, for convenience

    >>> Permutation.random(10).trivial()
    0
    """
    return 0


def matches(character):
    """ Returns true if the given character matches the token. """
    return lambda tokens: tokens and tokens[0] == character


@staticmethod
def is_guid(guid: str) ->bool:
    """Check whether text is minds 18digit long GUID"""
    if guid.isdigit() and len(guid) == 18:
        return True
    return False


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 uint32(x):
    """python does not have 32 bit integer so we need this hack to produce uint32 after bit operations"""
    return x & 4294967295


@classmethod
def delete_all(cls):
    """Удалить все записи из заблицы."""
    cls.delete_qs(cls.all())


def get_route_name(request):
    """Get a route name from URL Dispatch or Traversal."""
    if request.matched_route:
        return request.matched_route.name
    return 'no-matched-route'


def get_fprimer_percent_aln(fprimer, percent_alignment):
    """
    Gets the len of the fprimer and calculates minimum percent alignment
    based on user input of maximum alignment between 2 primers allowed.
    See percent alignment help for info.
    Args:
        fprimer (str): the forward primer
    Returns:
        fp_len (int): user defined total number of bases to allowed to match.
    """
    fp_len = []
    for fseq in fprimer:
        f_len = len(fseq)
        min_dimer_alignment = int(f_len * (percent_alignment / 100))
        fp_len.append(min_dimer_alignment)
    return fp_len


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

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


@classmethod
def new(cls, unit):
    """Returns new instance.

    :rtype: `entrezpy.elink.linkset.unit.linksetunit.linkin.LinkIn`
    """
    return cls(unit)


def delete_obsolete_perms(apps, schema_editor):
    """Delete obsolete permissions from the database."""
    Permission = apps.get_model('auth', 'Permission')
    Permission.objects.filter(codename__in=['add_collection', 'add_entity',
        'download_collection', 'download_entity', 'download_data']).delete()


def _convert_opts(opts):
    """
    Convert list with command options to single string value
    with 'space' delimeter
    :param opts: list with space-delimeted values
    :return: string with space-delimeted values
    """
    return ' '.join(opts)


def __getitem__(index):
    """return item at index, or slice"""


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

        :param PaperPublishedLinkChangePermissionDetails val:
        :rtype: EventDetails
        """
    return cls('paper_published_link_change_permission_details', val)


@classmethod
def fromWeb3(cls, web3, addr=None):
    """
        Generate an ENS instance with web3

        :param `web3.Web3` web3: to infer connection information
        :param hex-string addr: the address of the ENS registry on-chain. If not provided,
            ENS.py will default to the mainnet ENS registry address.
        """
    return cls(web3.manager.providers, addr=addr)


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


@classmethod
def append_warning(cls, message, **kwds):
    """Unknown error is fatal and should break any further progress"""
    cls.append_message(message, message_type='warning', **kwds)


@staticmethod
def _scale_ordered_unit_names(unit_names):
    """
            Swap the day_of_week and month order so that 'overflow' happens in the right order.
            :returns: unit names in ascending order of scale
        """
    unit_names[4], unit_names[5] = unit_names[5], unit_names[4]
    return unit_names


def get_ftype_params(field):
    """
    Convenient getter
    :param field:
    :return:
    """
    return field[1], field[2:]


def _rel_create_dict(relationships):
    """ Convert a set of :class:`.Relationship` objects into a dictionary
    of :class:`.Relationship` lists, keyed by type.

    :param relationships:
    :return:
    """
    d = {}
    for relationship in relationships:
        key = type(relationship).__name__
        d.setdefault(key, []).append(relationship)
    return d


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


@staticmethod
def p_loc_measurement_optional_list(p):
    """loc_measurement_optional_list : loc_measurement_optional
                                         | loc_measurement_optional loc_measurement_optional_list"""
    try:
        p[0] = [p[1]] + p[2]
    except IndexError:
        p[0] = [p[1]]


def green(s):
    """
    Return the given string (``s``) surrounded by the ANSI escape codes to
    print it in green.
    :param s: string to console-color green
    :type s: str
    :returns: s surrounded by ANSI color escapes for green text
    :rtype: str
    """
    return '\x1b[0;32m' + s + '\x1b[0m'


def parallel(sys1, *sysn):
    """
    Return the parallel connection sys1 + sys2 (+ ... + sysn)

    Parameters
    ----------
    sys1 : scalar, StateSpace, TransferFunction, or FRD
    *sysn : other scalars, StateSpaces, TransferFunctions, or FRDs

    Returns
    -------
    out : scalar, StateSpace, or TransferFunction

    Raises
    ------
    ValueError
        if `sys1` and `sys2` do not have the same numbers of inputs and outputs

    See Also
    --------
    series
    feedback

    Notes
    -----
    This function is a wrapper for the __add__ function in the
    StateSpace and TransferFunction classes.  The output type is usually
    the type of `sys1`.  If `sys1` is a scalar, then the output type is
    the type of `sys2`.

    If both systems have a defined timebase (dt = 0 for continuous time,
    dt > 0 for discrete time), then the timebase for both systems must
    match.  If only one of the system has a timebase, the return
    timebase will be set to match it.

    Examples
    --------
    >>> sys3 = parallel(sys1, sys2) # Same as sys3 = sys1 + sys2

    >>> sys5 = parallel(sys1, sys2, sys3, sys4) # More systems

    """
    from functools import reduce
    return reduce(lambda x, y: x + y, sysn, sys1)


def group_results(experiments, outcomes, group_by, grouping_specifiers,
    grouping_labels):
    """
    Helper function that takes the experiments and results and returns a list
    based on groupings. Each element in the dictionary contains the experiments
    and results for a particular group, the key is the grouping specifier.

    Parameters
    ----------
    experiments : DataFrame
    outcomes : dict
    group_by : str
               The column in the experiments array to which the grouping
               specifiers apply. If the name is'index' it is assumed that the
               grouping specifiers are valid indices for numpy.ndarray.
    grouping_specifiers : iterable
                    An iterable of grouping specifiers. A grouping
                    specifier is a unique identifier in case of grouping by
                    categorical uncertainties. It is a tuple in case of
                    grouping by a parameter uncertainty. In this cose, the code
                    treats the tuples as half open intervals, apart from the
                    last entry, which is treated as closed on both sides.
                    In case of 'index', the iterable should be a dictionary
                    with the name for each group as key and the value being a
                    valid index for numpy.ndarray.

    Returns
    -------
    dict
        A dictionary with the experiments and results for each group, the
        grouping specifier is used as key

    ..note:: In case of grouping by parameter uncertainty, the list of
             grouping specifiers is sorted. The traversal assumes half open
             intervals, where the upper limit of each interval is open, except
             for the last interval which is closed.

    """
    groups = {}
    if group_by != 'index':
        column_to_group_by = experiments.loc[:, (group_by)]
    for label, specifier in zip(grouping_labels, grouping_specifiers):
        if isinstance(specifier, tuple):
            lower_limit, upper_limit = specifier
            if grouping_specifiers.index(specifier) == len(grouping_specifiers
                ) - 1:
                logical = (column_to_group_by >= lower_limit) & (
                    column_to_group_by <= upper_limit)
            else:
                logical = (column_to_group_by >= lower_limit) & (
                    column_to_group_by < upper_limit)
        elif group_by == 'index':
            logical = specifier
        else:
            logical = column_to_group_by == specifier
        group_outcomes = {}
        for key, value in outcomes.items():
            value = value[logical]
            group_outcomes[key] = value
        groups[label] = experiments.loc[(logical), :], group_outcomes
    return groups


def trimboth(l, proportiontocut):
    """
Slices off the passed proportion of items from BOTH ends of the passed
list (i.e., with proportiontocut=0.1, slices 'leftmost' 10% AND 'rightmost'
10% of scores.  Assumes list is sorted by magnitude.  Slices off LESS if
proportion results in a non-integer slice index (i.e., conservatively
slices off proportiontocut).

Usage:   ltrimboth (l,proportiontocut)
Returns: trimmed version of list l
"""
    lowercut = int(proportiontocut * len(l))
    uppercut = len(l) - lowercut
    return l[lowercut:uppercut]


def extract_dtype(descriptor, key):
    """
    Work around the fact that we currently report jsonschema data types.
    """
    reported = descriptor['data_keys'][key]['dtype']
    if reported == 'array':
        return float
    else:
        return reported


@classmethod
def join(cls, *addrs):
    """Concatenate the values of the given MultiAddr strings or objects,
        encapsulating each successive MultiAddr value with the previous ones."""
    return cls(b''.join(map(lambda a: cls(a).to_bytes(), addrs)))


def escape_formatting(text):
    """
    Escape things that would otherwise confuse `.format`.
    """
    return text.replace('{', '{{').replace('}', '}}')


def check_clearbit_rate_limit(response=None):
    """Determines whether we've exceeded the rate limit."""
    print('check_clearbit_rate_limit()')
    print('headers: {}'.format(response.headers))
    rate_limit = response.headers['x-ratelimit-limit']
    remaining = response.headers['x-ratelimit-remaining']
    reset_time = response.headers['x-ratelimit-reset']
    print('rate_limit: {}'.format(rate_limit))
    print('requests_remaining: {}'.format(remaining))
    print('reset_time: {}'.format(reset_time))
    rate_limit_exceeded = False
    if remaining == '0':
        rate_limit_exceeded = True
        print('rate limit exceeded: {}'.format(rate_limit_exceeded))
    results = {'rate_limit_exceeded': rate_limit_exceeded, 'reset_time':
        reset_time}
    print('results: {}'.format(results))
    return results


def generate_documentation_subparser(subparsers):
    """Generates the subparser for the auto-documentation option."""
    documentation_parser = subparsers.add_parser('docs')
    documentation_parser.set_defaults(action='docs')
    documentation_parser.add_argument('module', metavar='module', help=
        'Name of the module that uses the symmetric object.')
    documentation_parser.add_argument('-f', '--filename', dest='filename',
        default='', help=
        'Name of the file in where to write the documentation.')
    documentation_parser.add_argument('-m', '--markdown', dest='markdown',
        action='store_const', default=False, const=True, help=
        'Generate simpler, human-readable Markdown documentation.')


@classmethod
def get_template(cls, template_id):
    """
        Used to interact with Studio's create_xblock method to instantiate pre-defined templates.
        """
    return {'data': {'type': template_id, 'content': cls.MESSAGE_TYPES[
        template_id]['default']}}


def delete_marker():
    """Delete marker for current frame from selected tracks

    """
    pass


def quotename(name):
    """
    Escapes a schema, table, or column name for use in SQL. hana_ml functions and methods that take schema, table, or column names
    already escape their input by default, but those that take SQL don't (and can't) perform escaping automatically.

    Parameters
    ----------
    name : str
        The schema, table, or column name.

    Returns
    -------
    str
        The escaped name. The string is surrounded in quotation marks,
        and existing quotation marks are escaped by doubling them.
    """
    return '"{}"'.format(name.replace('"', '""'))


def namespace(settings):
    """
    Return the namespace associated with these settings
    """
    if getattr(settings, 'SETTINGSD_NAMESPACE', False):
        return settings
    key = getattr(settings, 'SETTINGSD_NS')
    ns = getattr(settings, key)
    return ns


def update_state(td_state, job_results):
    """
    Updates the torsiondrive state with the compute jobs. The state is updated inplace

    Parameters
    ----------
    td_state : dict
        The current torsiondrive state
    job_results : dict
        A dictionary of completed jobs and job ID's

    Returns
    -------
    None
    """
    for grid_id_str, job_result_tuple_list in job_results.items():
        if grid_id_str not in td_state['grid_status']:
            td_state['grid_status'][grid_id_str] = []
        td_state['grid_status'][grid_id_str] += job_result_tuple_list
    return td_state


def map_db_collection_with_class(db, db_classes):
    """
    maps database-collection with classes
    """
    for db_class in db_classes:
        name = db_class._collection
        if name:
            setattr(db, name, db_class(getattr(db, name)))


def format_description(string):
    """
    Adds the header and a final new line to the issue description string.
    """
    return str('**Issue description:**\n---\n\n' + string + '\n' * 2)


def str_to_bool(b_str):
    """ returns True  if b_str is '1', 't', 'true', 'y' or 'yes' (case insensitive)
                False if b_str is '0', 'f', 'false', 'n' or 'no' (case insensitive)
        raise ValueError exception in other cases
    """
    b_str = b_str.lower()
    if b_str in ('t', 'true', '1', 'y', 'yes'):
        return True
    if b_str in ('f', 'false', '0', 'n', 'no'):
        return False
    raise ValueError("invalid boolean litteral '%s'" % (b_str,))


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_file_valid(name):
    """Decide if a file is valid."""
    return not name.startswith(u'.')


def _modify(entry, data):
    """
    Modify an :class:`.Entry` with the data.
    """
    entry.__data__.update(data)


@classmethod
def drop_privileges(cls, *privileges):
    """
        Drops privileges.

        @type  privileges: int...
        @param privileges: Privileges to drop.

        @raise WindowsError: Raises an exception on error.
        """
    cls.adjust_privileges(False, privileges)


def print_barcode(code):
    """ Print a barcode representing the given code. """


def get_labels(ticks, data):
    """Reads the phase diagram data and returns the labels that correspond
    to the phases displayed on the phase diagram.

    Parameters
    ----------
    ticks : list
        Phases that are displayed.
    data  : list
        list of dictionaries.

    Returns
    -------
    labels : list
        list of labels.
    """
    labels = []
    for i in range(0, ticks.size):
        val = ticks[i] - 1
        val = int(val)
        label = data[val]['Label']
        labels.append(label)
    return labels


def vertex_group_deselect():
    """Deselect all selected vertices assigned to the active vertex group

    """
    pass


def mass_emc(energy, speedoflight):
    """Usage: mass_emc(energy of an object, speed of light) - You can use the constant light_speed."""
    return energy / speedoflight ** 2


@classmethod
def _merge(cls, d1, d2):
    """ d1 overwrites values in d2 """
    for k in d1.keys():
        if isinstance(d1[k], cls.container) and k in d2 and isinstance(d2[k
            ], cls.container):
            d2[k] = cls._merge(d1[k], d2[k])
        else:
            d2[k] = d1[k]
    return d2


def configure(conf):
    """
	Finds the following programs:

	* *glib-genmarshal* and set *GLIB_GENMARSHAL*
	* *glib-mkenums* and set *GLIB_MKENUMS*
	* *glib-compile-schemas* and set *GLIB_COMPILE_SCHEMAS* (not mandatory)
	* *glib-compile-resources* and set *GLIB_COMPILE_RESOURCES* (not mandatory)
	"""
    conf.find_glib_genmarshal()
    conf.find_glib_mkenums()
    conf.find_glib_compile_schemas(mandatory=False)
    conf.find_glib_compile_resources(mandatory=False)


def singlyfy_parameters(parameters):
    """
    Makes a cgi-parsed parameter dictionary into a dict where the values that
    are just a list of a single value, are converted to just that single value.
    """
    for key, value in parameters.items():
        if isinstance(value, (list, tuple)) and len(value) == 1:
            parameters[key] = value[0]
    return parameters


@classmethod
def from_catmaid(cls, catmaid_client, stack_group_id=None, stack_id=None,
    scale=0, x=None, y=None, z=None, tool=None, active_skeleton_id=None,
    active_node_id=None):
    """
        Instantiate CatmaidUrl based on a CATMAID interface instance.

        Parameters
        ----------
        catmaid_client : CatmaidClient or catpy.applications.base.CatmaidClientApplication
        stack_group_id : int
        stack_id : int
        scale : float
        x : float
            x coordinate in project (real) space
        y : float
            y coordinate in project (real) space
        z : float
            z coordinate in project (real) space
        tool : str
        active_skeleton_id : int
        active_node_id : int

        Returns
        -------
        CatmaidUrl
        """
    return cls(catmaid_client.base_url, catmaid_client.project_id,
        stack_group_id, stack_id, scale, x, y, z, tool, active_skeleton_id,
        active_node_id)


@classmethod
def createFromMatch(cls, curBodyStr, matchObj):
    """
            createFromMatch - Create this BodyElement from a given match object, and return the element and remainder for parsing

                @param curBodyStr <str> - The current body string (matchObj should have matched at the head of this)

                @param matchObj <re.match> - The match object

                @return tuple( createdElement<BodyElement>, remainingBodyStr<str> ) - A tuple of the created element and the remaining portion to parse
        """
    groupDict = matchObj.groupdict()
    thisElement = cls(**groupDict)
    curBodyStr = curBodyStr[matchObj.span()[1]:]
    return thisElement, curBodyStr


@classmethod
def resolve_attr_spec(cls, spec, cb_obj, model=None):
    """
        Resolves a Callback attribute specification looking the
        corresponding attribute up on the cb_obj, which should be a
        bokeh model. If not model is supplied cb_obj is assumed to
        be the same as the model.
        """
    if not cb_obj:
        raise Exception('Bokeh plot attribute %s could not be found' % spec)
    if model is None:
        model = cb_obj
    spec = spec.split('.')
    resolved = cb_obj
    for p in spec[1:]:
        if p == 'attributes':
            continue
        if isinstance(resolved, dict):
            resolved = resolved.get(p)
        else:
            resolved = getattr(resolved, p, None)
    return {'id': model.ref['id'], 'value': resolved}


def isfuncdesc(desc):
    """Tests if a description is a function-type description."""
    return desc is not None and 'signatures' in desc


@staticmethod
def is_empty_address(address_data):
    """An address will have at minimum a tax_number field it will still be considered empty"""
    return list(address_data.keys()) == ['tax_number']


def vertex_group_copy():
    """Make a copy of the active vertex group

    """
    pass


def size_str(size):
    """
    size: number of bytes
    Return a human-readable string.
    """
    if size is None:
        return None
    for unit in ('', 'k', 'm', 'g', 't'):
        if size < 100 and size != int(size):
            return '%.1f%s' % (size, unit)
        if size < 1024:
            return '%d%s' % (size, unit)
        size /= 1024.0


def normalize_column_name(name):
    """Check if a string is a reasonable thing to use as a column name."""
    if not isinstance(name, str):
        raise ValueError('%r is not a valid column name.' % name)
    name = name.strip()[:63]
    if isinstance(name, str):
        while len(name.encode('utf-8')) >= 64:
            name = name[:len(name) - 1]
    if not len(name) or '.' in name or '-' in name:
        raise ValueError('%r is not a valid column name.' % name)
    return name


def widget_children(widget):
    """Return the list of all children of the widget"""
    return widget.children.values()


def edge_detect(pin, event_callback, bounce):
    """Add detection for RISING and FALLING events."""
    import Adafruit_BBIO.GPIO as GPIO
    GPIO.add_event_detect(pin, GPIO.BOTH, callback=event_callback,
        bouncetime=bounce)


def msg_delayed_filter(message, now):
    """Return True IFF the message is currently delayed."""
    return now < message.delay_expires


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


def setnarrowpats(newincludes, newexcludes):
    """Define the narrowspec for this repository."""


@staticmethod
def domain_log(logs):
    """
        list logs:  The list of nameserversets to be pretty printed.
        """
    if 'resData' in logs:
        logs = logs['resData']
    count, total = 0, len(logs['domain'])
    output = '\n%i log entries:\n' % total
    for log in logs['domain']:
        count += 1
        output += (
            """%i of %i - %s status: '%s' price: %.2f invoice: %s date: %s remote address: %s
"""
             % (count, total, log['domain'], log['status'], log['price'],
            log['invoice'], log['date'], log['remoteAddr']))
        output += "           user text: '%s'\n" % log['userText'].replace('\n'
            , '\n           ')
    return output


def bresenham(start, end):
    """
    Rasterize a line from start to end onto a grid with grid-width 1.

    :param start: A sequence of length 2, containing the x,y coordinates of the start of the line
    :param start: A sequence of length 2, containing the x,y coordinates of the end of the line
    :returns: A list of tuples (x,y), where x and y are integers.
    """
    if start == end:
        return [start]
    points = []
    dx = end[0] - start[0]
    dy = end[1] - start[1]
    x, y = start
    if dx == 0:
        sx = 0
    else:
        sx = dx // abs(dx)
    if dy == 0:
        sy = 0
    else:
        sy = dy // abs(dy)
    dx = abs(dx)
    dy = abs(dy)
    if dx > dy:
        err = dx / 2.0
        while x != end[0]:
            points.append((x, y))
            err -= dy
            if err < 0:
                y += sy
                err += dx
            x += sx
    else:
        err = dy / 2.0
        while y != end[1]:
            points.append((x, y))
            err -= dx
            if err < 0:
                x += sx
                err += dy
            y += sy
    points.append((x, y))
    return points


@staticmethod
def of_type(of_type):
    """Confuse pylint so it doesn't complain about fluent-endpoints."""


def isElectron(pid):
    """Determine if the PID is that of an electron or positron"""
    return abs(pid) == 11


def line_starts_with(line: str, string: str, case_insensitive: bool=True
    ) ->bool:
    """
    Checks if the line starts with the given string.

    :param line:                The line to check.
    :param string:              The string to look for.
    :param case_insensitive:    Whether the check should disregard case.
    :return:                    True if the line starts with the given string, False otherwise.
    """
    if case_insensitive:
        line = line.lower()
        string = string.lower()
    return line.startswith(string)


@classmethod
def _from_dict(cls, _dict):
    """Initialize a DocInfo object from a json dictionary."""
    args = {}
    if 'html' in _dict:
        args['html'] = _dict.get('html')
    if 'title' in _dict:
        args['title'] = _dict.get('title')
    if 'hash' in _dict:
        args['hash'] = _dict.get('hash')
    return cls(**args)


def common_parent(node1, node2):
    """return the first common parent between node1 and node2

    algorithm :
     1) index node1's parents
     2) climb among node2's parents until we find a common parent
    """
    node1_parents = set()
    while node1:
        node1_parents.add(node1)
        node1 = node1.parent
    while node2:
        if node2 in node1_parents:
            return node2
        node2 = node2.parent
    raise Exception('DUH!')


def is_valid_boolstr(val):
    """Check if the provided string is a valid bool string or not."""
    boolstrs = 'true', 'false', 'yes', 'no', 'y', 'n', '1', '0'
    return str(val).lower() in boolstrs


def inconsistentFilesPerSample(json_dict):
    """
    For each sample, count the number of files found. If any sample has an inconsistent number compared to the others, returns True
    Useful for identifying sample IDs missing an expected file, or sample IDs that erroneously picked up extra files
    """
    numset = set()
    for sample in json_dict['samples']:
        numset.add(len(sample['files']))
    if len(numset) > 1:
        return True


def particle_system_add():
    """Add a particle system

    """
    pass


def add_new_property(agent, property_name, getter_function):
    """Add a new property to an agent.

    Actually, the property is added to the class of the agent, as
    Python properties are descriptors. Yet, the dynamic attribution of
    properties must me done through instances rather than classes,
    since agents must add the name of the property to their
    ``_mbr_cache`` attribute.

    Parameters
    ----------
    agent: AbstractAgent
        the agent to which the property must be added
    property_name: str
        the name of the property
    getter_function: lambda
        the function upon which the property is built

    """
    setattr(agent.__class__, property_name, property(getter_function))
    agent._mbr_cache.add(property_name)


@classmethod
def topic(cls, **kwargs) ->str:
    """Get topic for message."""
    site_id = kwargs.get('site_id', '+')
    request_id = kwargs.get('request_id', '#')
    return f'hermes/audioServer/{site_id}/playBytes/{request_id}'


def term2str(term):
    """Convert a term argument to string.

    :param term: the term to convert
    :type term: Term | None | int
    :return: string representation of the given term where None is converted to '_'.
    :rtype: str
    """
    if term is None:
        return '_'
    elif type(term) is int:
        if term >= 0:
            return 'A%s' % (term + 1)
        else:
            return 'X%s' % -term
    else:
        return str(term)


def convert_performance_map_to_bpmn(aggregated_statistics,
    inv_elements_correspondence):
    """
    Convert performance map to BPMN

    Parameters
    ------------
    aggregated_statistics
        Aggregated statistics calculated on elements of the Petri net
    inv_elements_correspondence:
        Correspondence between elements of the BPMN graph and elements of the Petri net

    Returns
    ------------
    bpmn_aggreg_statistics
        Aggregated statistics on elements of the BPMN graph
    """
    bpmn_aggreg_statistics = {}
    for el in inv_elements_correspondence:
        for petri_el in inv_elements_correspondence[el]:
            if petri_el in aggregated_statistics:
                bpmn_aggreg_statistics[el] = aggregated_statistics[petri_el]
                break
    return bpmn_aggreg_statistics


def _is_visible(idx_row, idx_col, lengths):
    """
    Index -> {(idx_row, idx_col): bool}).
    """
    return (idx_col, idx_row) in lengths


def get_module_path(module):
    """Gets the absolute path of a `module`.

    :param module: Either module object or a (dotted) string for the module.

    :returns: The path of the module.

    If the module is a package, returns the directory path (not the path to the
    ``__init__``).

    If `module` is a string and it's not absolute, raises a TypeError.

    """
    from importlib import import_module
    from xotl.tools.fs.path import normalize_path
    mod = import_module(module) if isinstance(module, str) else module
    path = mod.__path__[0] if hasattr(mod, '__path__') else mod.__file__
    return normalize_path(path)


def dict_merge(*dict_list):
    """
  Given zero or more dicts, shallow copy and merge them into a new dict, with
  precedence to dictionary values later in the dict list.
  Helpful mainly before Python 3.5.
  https://stackoverflow.com/questions/38987/how-to-merge-two-dictionaries-in-a-single-expression
  https://docs.python.org/dev/whatsnew/3.5.html#pep-448-additional-unpacking-generalizations
  """
    result = {}
    for d in dict_list:
        result.update(d)
    return result


def intersectBed(lst1, lst2):
    """
	Return intersection of two bed regions.

	Parameters
	----------
	lst1 : list
		The 1st genomic region. List of chrom, start, end.
		Example: ['chr1',10, 100]

	lst2 : list
		 The 2nd genomic region. List of chrom, start, end.
		 Example: ['chr1',50, 120]

	Examples
	--------
	>>> intersectBed(['chr1',10, 100],['chr1',50, 120])
	('chr1', 50, 100)
	>>> intersectBed(['chr1',10, 100],['chr1',20, 30])
	('chr1', 20, 30)

	"""
    chr1, st1, end1 = lst1
    chr2, st2, end2 = lst2
    if int(st1) > int(end1) or int(st2) > int(end2):
        raise Exception('Start cannot be larger than end')
    if chr1 != chr2:
        return None
    if int(st1) > int(end2) or int(end1) < int(st2):
        return None
    return chr1, max(st1, st2), min(end1, end2)


@classmethod
def isSupportedContent(cls, fileContent):
    """Returns if the files are valid for this filetype"""
    return bytearray(fileContent)[:4] == b'\x7fELF'


def set_security_groups(LoadBalancerArn=None, SecurityGroups=None):
    """
    Associates the specified security groups with the specified load balancer. The specified security groups override the previously associated security groups.
    See also: AWS API Documentation

    Examples
    This example associates the specified security group with the specified load balancer.
    Expected Output:

    :example: response = client.set_security_groups(
        LoadBalancerArn='string',
        SecurityGroups=[
            'string',
        ]
    )

    :type LoadBalancerArn: string
    :param LoadBalancerArn: [REQUIRED]
            The Amazon Resource Name (ARN) of the load balancer.

    :type SecurityGroups: list
    :param SecurityGroups: [REQUIRED]
            The IDs of the security groups.
            (string) --

    :rtype: dict
    :return: {
        'SecurityGroupIds': [
            'string',
        ]
    }

    :returns:
    (string) --

    """
    pass


def cache_page(page_cache, page_hash, cache_size):
    """Add a page to the page cache."""
    page_cache.append(page_hash)
    if len(page_cache) > cache_size:
        page_cache.pop(0)


def _pad_window(wnd, pad):
    """Add padding to windows
    """
    return (wnd[0][0] - pad, wnd[0][1] + pad), (wnd[1][0] - pad, wnd[1][1] +
        pad)


def quote_sheetname(sheetname):
    """
    Convert a worksheet name to a quoted  name if it contains spaces or
    special characters.

    Args:
       sheetname: The worksheet name. String.

    Returns:
        A quoted worksheet string.

    """
    if not sheetname.isalnum() and not sheetname.startswith("'"):
        sheetname = sheetname.replace("'", "''")
        sheetname = "'%s'" % sheetname
    return sheetname


def print_xml(data, keys=['url']):
    """Given xml data, get value within 'xml' key and print it
    """
    data = data.copy()
    for key in keys:
        print(key, data[key])
    yield data


def merge_images(input_filepath1: str='', input_filepath2: str='',
    output_filepath: str=''):
    """Combine OpenEXR multilayer images rendered with different sampleranges into one image with reduced noise

    :param input_filepath1: Input Filepath, File path for image to merge
    :type input_filepath1: str
    :param input_filepath2: Input Filepath, File path for image to merge
    :type input_filepath2: str
    :param output_filepath: Output Filepath, File path for merged image
    :type output_filepath: str
    """
    pass


def ignore_and_continue(exn):
    """Called in an exception handler to ignore any exception and continue."""
    return True


def get_empty_str_if_none(value):
    """
    Returns an empty string if the value is None, otherwise returns the value
    """
    return value if value != None else ''


def validators_from_config(validators):
    """Consolidate (potentially hex-encoded) list of validators
    into list of binary address representations.
    """
    result = []
    for validator in validators:
        if len(validator) == 40:
            validator = validator.decode('hex')
        result.append(validator)
    return result


def is_key_exchange(message):
    """
    Checks that message has key_exchange data.
    Return key or None.
    """
    try:
        if message['action'] == 'key_exchange':
            return message['key']
    except Exception:
        pass
    return None


def user_is_authenticated(user):
    """
        Added to the rule set automatically as an alternative to the
        login_required decorator
    """
    return user.is_authenticated()


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

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

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


def label_residue(residue):
    """ Return a string of the label of the biopython [1] residue object.

    The label of the residue is the following:
        Chain + Position

    Parameters
    ----------
    residue: Bio.PDB.Residue.Residue
        The residue to be labeled.

    Notes
    -----
    1. http://biopython.org/wiki/Biopython

    """
    position = str(residue.id[1])
    chain = residue.parent.id
    return chain + position


def num_neg(df, class_feat, pos_class):
    """ Returns number of instances that are NOT labeled positive. """
    return len(df[df[class_feat] != pos_class])


def show_service_info(service, version):
    """Show current service and its version.

    :param service: Name of the current service.
    :param versions: The version of the current service.
    :return: None
    """
    print(f'{service} ({version})', end=' ')


def set_detach():
    """Sets up a following call to daemonize() to detach from the foreground
    session, running this process in the background."""
    global _detach
    _detach = True


def discobrackets_begin(stream, **params):
    """Discobrackets output preamble is empty.
    """
    pass


def __new__(cls):
    """ This class cannot be instantiated. """
    return cls


def parse_metaconfig_line(line):
    """ Parses line and return key=value tuple """
    delimiter_pos = line.find('=')
    if delimiter_pos == -1:
        raise ValueError("'=' not found in metaconfig line " + line)
    var_name = line[:delimiter_pos].strip()
    if len(var_name) == 0:
        raise ValueError('variable name not found in metaconfig line ' + line)
    var_expr = line[delimiter_pos + 1:].strip()
    return var_name, var_expr


def format_time(time):
    """Formats a datetime as an ISO 8601 compliant string."""
    return time.strftime('%Y-%m-%dT%H:%M:%SZ')


def read_rpc_xml_worldview(tree):
    """
    Read RPC fields from a parsed XML tree assuming the worldview XML format

    Args:
        tree: parsed XML tree

    Returns:
        dictionary read from the RPC file, or empty dict in case of failure

    """
    m = {}
    im = tree.find('RPB/IMAGE')
    l = im.find('LINENUMCOEFList/LINENUMCOEF')
    m['LINE_NUM_COEFF'] = l.text
    l = im.find('LINEDENCOEFList/LINEDENCOEF')
    m['LINE_DEN_COEFF'] = l.text
    l = im.find('SAMPNUMCOEFList/SAMPNUMCOEF')
    m['SAMP_NUM_COEFF'] = l.text
    l = im.find('SAMPDENCOEFList/SAMPDENCOEF')
    m['SAMP_DEN_COEFF'] = l.text
    m['ERR_BIAS'] = float(im.find('ERRBIAS').text)
    m['LINE_OFF'] = float(im.find('LINEOFFSET').text)
    m['SAMP_OFF'] = float(im.find('SAMPOFFSET').text)
    m['LAT_OFF'] = float(im.find('LATOFFSET').text)
    m['LONG_OFF'] = float(im.find('LONGOFFSET').text)
    m['HEIGHT_OFF'] = float(im.find('HEIGHTOFFSET').text)
    m['LINE_SCALE'] = float(im.find('LINESCALE').text)
    m['SAMP_SCALE'] = float(im.find('SAMPSCALE').text)
    m['LAT_SCALE'] = float(im.find('LATSCALE').text)
    m['LONG_SCALE'] = float(im.find('LONGSCALE').text)
    m['HEIGHT_SCALE'] = float(im.find('HEIGHTSCALE').text)
    return m


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

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


def vertex_weight_set_active(weight_group: int=-1):
    """Set as active vertex group

    :param weight_group: Weight Index, Index of source weight in active vertex group
    :type weight_group: int
    """
    pass


def _collapse0(a):
    """Collapse all dimensions of `a` except the first.
    """
    return a.reshape(a.shape[0], -1)


def truncate_arg_value(value, max_len=1024):
    """Truncate values which are bytes and greater than `max_len`.
    Useful for parameters like 'Body' in `put_object` operations.
    """
    if isinstance(value, bytes) and len(value) > max_len:
        return b'...'
    return value


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


@staticmethod
def extension():
    """Return most common file extension for format."""
    return 'xlsx'


@classmethod
def _getlinealias(cls, i):
    """
        Return the alias for a line given the index
        """
    lines = cls._getlines()
    if i >= len(lines):
        return ''
    linealias = lines[i]
    return linealias


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


def _sdq(input_text=''):
    """function to escape ' in xpath for tagui live mode"""
    return input_text.replace("'", '"')


def init_twilio():
    """Initialize twilio credentials."""
    from attbillsplitter.utils import initialize_twiolio
    initialize_twiolio()


def is_sequence(arg):
    """
    Checks if arg is a sequence
    """
    if isinstance(arg, str):
        return False
    return not hasattr(arg, 'strip') and hasattr(arg, '__getitem__'
        ) or hasattr(arg, '__iter__')


def valid_choices(choices):
    """
    Return list of choices's keys
    """
    for key, value in choices:
        if isinstance(value, (list, tuple)):
            for key, _ in value:
                yield key
        else:
            yield key


def make_service_domain_name(service, region=''):
    """ Helper function for creating proper service domain names. """
    tld = '.com.cn' if region == 'cn-north-1' else '.com'
    return '{}.amazonaws{}'.format(service, tld)


def get_col_lb(me, xid):
    """get_col_lb with transparent index mapping."""
    xid = me._colmap.map(xid) if xid else xid
    if xid > 0:
        return me._get_col_lb(xid)


def write(fieldNode, schema, field):
    """Write the metadata for the field in the given schema to the
        fieldNode. The node will already exist and be populated with
        standard data.
        """


@classmethod
def new(cls):
    """
        Return newly created empty numbering part, containing only the root
        ``<w:numbering>`` element.
        """
    raise NotImplementedError


def labelize_flip(couple):
    """
    Returns a string from a 2-uple couple of the form (name, flip).

    TESTS::

        sage: from surface_dynamics.interval_exchanges.template import labelize_flip
        sage: labelize_flip((0,1))
        ' 0'
        sage: labelize_flip((0,-1))
        '-0'
    """
    if couple[1] == -1:
        return '-' + str(couple[0])
    return ' ' + str(couple[0])


def as_pandas(data):
    """
    Takes a sqlDataFrame and returns a pandas data frame

    :param data: sql.DataFrame
    :return: pandas.DataFrame
    """
    return data.toPandas()


def get_top_long_short_abs(positions, top=10):
    """
    Finds the top long, short, and absolute positions.

    Parameters
    ----------
    positions : pd.DataFrame
        The positions that the strategy takes over time.
    top : int, optional
        How many of each to find (default 10).

    Returns
    -------
    df_top_long : pd.DataFrame
        Top long positions.
    df_top_short : pd.DataFrame
        Top short positions.
    df_top_abs : pd.DataFrame
        Top absolute positions.
    """
    positions = positions.drop('cash', axis='columns')
    df_max = positions.max()
    df_min = positions.min()
    df_abs_max = positions.abs().max()
    df_top_long = df_max[df_max > 0].nlargest(top)
    df_top_short = df_min[df_min < 0].nsmallest(top)
    df_top_abs = df_abs_max.nlargest(top)
    return df_top_long, df_top_short, df_top_abs


@staticmethod
def _make_device_info_dictionary(index, device_info):
    """
        Internal method to create Device Info dictionary that mirrors
        PortAudio's ``PaDeviceInfo`` structure.

        :rtype: dict
        """
    device_name = device_info.name
    for codec in ['utf-8', 'cp1252']:
        try:
            device_name = device_name.decode(codec)
            break
        except:
            pass
    return {'index': index, 'structVersion': device_info.structVersion,
        'name': device_name, 'hostApi': device_info.hostApi,
        'maxInputChannels': device_info.maxInputChannels,
        'maxOutputChannels': device_info.maxOutputChannels,
        'defaultLowInputLatency': device_info.defaultLowInputLatency,
        'defaultLowOutputLatency': device_info.defaultLowOutputLatency,
        'defaultHighInputLatency': device_info.defaultHighInputLatency,
        'defaultHighOutputLatency': device_info.defaultHighOutputLatency,
        'defaultSampleRate': device_info.defaultSampleRate}


def filter_match(result):
    """
    Builtin Callback, remove all output if the string is not found in the
    output
    similar to grep
    :param result:
    """
    if result.out_string().find(result.setting('match')
        ) == -1 and result.err_string().find(result.setting('match')) == -1:
        result.out = ''
        result.err = ''
    return result


def ship_shoot(ship, x: float, y: float):
    """Make a ship fire at the designated coordinates

    ship: The ship which to move

    x: X coordinate

    y: Y coordinate
    """
    return '{0} shoots at {1},{2}'.format(ship, x, y)