def get(isamAppliance, id, check_mode=False, force=False):
    """
    Retrieve a Password Strength
    """
    return isamAppliance.invoke_get('Retrieve a Password Strength',
        '/wga/pwd_strength/{0}'.format(id))


@staticmethod
def simplify_service_access_result(service_access_list: list):
    """
        Simplifies AWS's service_last_accessed object by keeping only the relevant fields of the services that were in use
        :param service_access_list: List of service_last_accessed objects as received from the API
        :return: A list of objects of the format {"ServiceNamespace": ..., "LastAccessed": ...}, and only those that were in use
        """
    return list(map(lambda last_access: {'ServiceNamespace': last_access[
        'ServiceNamespace'], 'LastAccessed': last_access[
        'LastAuthenticated']}, filter(lambda last_access: last_access[
        'TotalAuthenticatedEntities'] > 0, service_access_list)))


def map_index(t, source_idx, target_idx):
    """
    Map a source integer to a target integer across all dims of a LongTensor.
    """
    return t.masked_fill_(t.eq(source_idx), target_idx)


def plot(O, **kwargs):
    """
    Main plotting function.

    This convenience function either calls :func:`plot_graph` or
    :func:`plot_filter` given the type of the passed object. Parameters can be
    passed to those functions.

    Parameters
    ----------
    O : Graph, Filter
        object to plot

    Examples
    --------
    >>> from pygsp import plotting
    >>> G = graphs.Logo()
    >>> plotting.plot(G)

    """
    try:
        O.plot(**kwargs)
    except AttributeError:
        raise TypeError('Unrecognized object, i.e. not a Graph or Filter.')


@classmethod
def get_name(cls):
    """
        Return the name of the resource. This is the model_name for almost all resources.

        :return: (str) lowercase model name
        """
    return cls._meta.model_name


def receive_v1_membership_report(group_state: 'GroupState'):
    """
    Received IGMP Version 1 Membership Report packet regarding group GroupState
    """
    group_state.group_state_logger.debug(
        'Querier Version1MembersPresent: receive_v1_membership_report')
    group_state.set_timer()
    group_state.set_v1_host_timer()


@classmethod
def export_to_hdf5(cls, h5_file, model, eids):
    """exports the elements in a vectorized way"""
    pids = []
    nodes = []
    thetas = []
    for eid in eids:
        element = model.elements[eid]
        pids.append(element.pid)
        nodes.append(element.nodes)
        thetas.append(element.theta)
    h5_file.create_dataset('eid', data=eids)
    h5_file.create_dataset('pid', data=pids)
    h5_file.create_dataset('nodes', data=nodes)
    h5_file.create_dataset('theta', data=thetas)


def delete_blob(bucket, path):
    """ Delete a GCS blob

    Parameters
    ----------
    bucket : str or google.cloud.storage.bucket.Bucket
        Bucket or bucket name
    path : str
        Path to file/folder

    Returns
    -------
    path
        Name of deleted blob
    """
    blob = bucket.blob(path)
    blob.delete()
    return blob.name


def aggregate_options_map(options_map, src_options_map):
    """Aggregate some of the attributes of options map.

    Args:
      options_map: The target map in which we want to aggregate attributes.
        Note: This value is mutated in-place.
      src_options_map: A source map whose values we'd like to see aggregated.
    """
    op_currencies = options_map['operating_currency']
    for currency in src_options_map['operating_currency']:
        if currency not in op_currencies:
            op_currencies.append(currency)
    commodities = options_map['commodities']
    for currency in src_options_map['commodities']:
        commodities.add(currency)


def get_node_path(node):
    """
    节点向上追溯至root的节点路径，包括该节点，包括root，不包括None
    :param oneid_meta.models.Group/Dept node:
    """
    path = []
    while node:
        path.append(node)
        node = node.parent
    return path


def track_settings_to_track():
    """Copy tracking settings from active track to selected tracks

    """
    pass


def parse_timestamp(timestamp):
    """Convert hexagon timestamp to integer (time in milliseconds)."""
    return int(timestamp, 16)


def gamma_logpdf(bx, logx, a_logx, a_logb, gammaln_a):
    """
    Log-density of :math:`\\mathcal{G}(x|a,b)`.

    If you want to get the gradient, just let each parameter be a gradient of
    that term.

    Parameters
    ----------
    bx : ndarray
        :math:`bx`
    logx : ndarray
        :math:`\\log(x)`
    a_logx : ndarray
        :math:`a \\log(x)`
    a_logb : ndarray
        :math:`a \\log(b)`
    gammaln_a : ndarray
        :math:`\\log\\Gamma(a)`
    """
    return a_logb - gammaln_a + a_logx - logx - bx


def _convert_identity(builder, node, graph, err):
    """
    convert to CoreML Linear Activation Layer:
    https://github.com/apple/coremltools/blob/655b3be5cc0d42c3c4fa49f0f0e4a93a26b3e492/mlmodel/format/NeuralNetwork.proto#L417
    """
    builder.add_activation(name=node.name, non_linearity='LINEAR',
        input_name=node.inputs[0], output_name=node.outputs[0], params=[1.0,
        0.0])


def calcp(kA, kV, cosphi=1.0):
    """ Calculates three phase P in MW from kA and kV
    takes an optional input power factor"""
    return 3 ** 0.5 * kV * kA * cosphi


@classmethod
def from_mask(celf, mask):
    """converts a bitmask to a frozenset of EXCEPT.xxx values."""
    result = set()
    for e in celf.__members__.values():
        if e.mask & mask != 0:
            result.add(e)
    return frozenset(result)


@classmethod
def from_markup_bounded(cls, text, box_size, max_font_size, font_fn, *args,
    min_font_size=6, **kwargs):
    """Create image from markup, reducing the font size until it fits. Inefficient."""
    return cls.generate_bounded(box_size, range(max_font_size,
        min_font_size - 1, -1), lambda size: cls.from_markup(text, font_fn(
        size), *args, **kwargs))


def siteScopeFunc():
    """Returns a unique id per site.
        """


def GetInstance(r, instance):
    """
    Gets information about an instance.

    @type instance: str
    @param instance: instance whose info to return

    @rtype: dict
    @return: info about the instance
    """
    return r.request('get', '/2/instances/%s' % instance)


def asymmetry(spectrogram_L, spectrogram_R):
    """
  returns (spectogram_L - spectrogram_R) / (spectogram_L + spectrogram_R)

  The asymmetry measure should be used for both polarizations recorded for a particular observation.

  On can then perform analysis such as integrating the returned spectrogram to determine if the
  asymmetry of the signals are close to zero, indicating equal signal in both polarizations, or
  close to +-1, indicating a strong asymmetry in the L or R polarization.

  spectrogram_L and spectrogram_R should be Numpy arrays.
  """
    return (spectrogram_L - spectrogram_R) / (spectrogram_L + spectrogram_R)


def read_atat_fit_out(filename, filter_names=None, i_energy=1):
    """
    read fit.out of atat
    filter_names - do not read name numbers greater than filter_name
    i_energy - 1 for fit.out, 2 for predstr.out
    return - concentration list, energy list
    """
    X, E, nam = [], [], []
    count = 0
    with open(filename, 'r') as f:
        for line in f:
            vals = line.split()
            try:
                name = int(vals[-1])
            except:
                name = 0
            if filter_names and name > filter_names:
                continue
            e = round(float(vals[i_energy]), 4)
            x = float(vals[0])
            X.append(x)
            E.append(e)
            nam.append(name)
            count += 1
    return X, E


def _iso8601(dt):
    """Turn a datetime object into an ISO8601 formatted date.

    Example::

        fields._iso8601(datetime(2012, 1, 1, 0, 0)) => "2012-01-01T00:00:00"

    :param dt: The datetime to transform
    :type dt: datetime
    :return: A ISO 8601 formatted date string
    """
    return dt.isoformat()


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

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

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


def _rescale(betweenness, n, normalized, directed=False):
    """betweenness_centrality_subset helper."""
    if normalized:
        if n <= 2:
            scale = None
        else:
            scale = 1.0 / ((n - 1) * (n - 2))
    elif not directed:
        scale = 0.5
    else:
        scale = None
    if scale is not None:
        for v in betweenness:
            betweenness[v] *= scale
    return betweenness


def is_timerange(item: str) ->bool:
    """
    Returns True if the item is a TAF to-from time range
    """
    return len(item) == 9 and item[4] == '/' and item[:4].isdigit() and item[5:
        ].isdigit()


def _rehydrate_skeleton_class(skeleton_class, class_dict):
    """Put attributes from `class_dict` back on `skeleton_class`.

    See CloudPickler.save_dynamic_class for more info.
    """
    registry = None
    for attrname, attr in class_dict.items():
        if attrname == '_abc_impl':
            registry = attr
        else:
            setattr(skeleton_class, attrname, attr)
    if registry is not None:
        for subclass in registry:
            skeleton_class.register(subclass)
    return skeleton_class


def claim_vm(cmd, client, lab_name=None, name=None, resource_group_name=None):
    """ Command to claim a VM in the Azure DevTest Lab"""
    if name is not None:
        return client.claim(resource_group_name, lab_name, name)
    from ._client_factory import get_devtestlabs_lab_operation
    return get_devtestlabs_lab_operation(cmd.cli_ctx, None).claim_any_vm(
        resource_group_name, lab_name)


def minimum(root):
    """Return node with smallest key in the tree at given root."""
    if not root:
        return None
    while root.left:
        root = root.left
    return root


def schema_defines_dictionary(schema):
    """
    If properties are not defined for a schema, or unspecified attributes are
    allowed--the schema will translate to an instance of `Dictionary`.
    """
    return schema.type_ == 'object' and (schema.additional_properties or
        not schema.properties)


def is_isolate(G, n):
    """Determines whether a node is an isolate.

    An *isolate* is a node with no neighbors (that is, with degree
    zero). For directed graphs, this means no in-neighbors and no
    out-neighbors.

    Parameters
    ----------
    G : NetworkX graph

    n : node
        A node in `G`.

    Returns
    -------
    is_isolate : bool
       True if and only if `n` has no neighbors.

    Examples
    --------
    >>> G=nx.Graph()
    >>> G.add_edge(1,2)
    >>> G.add_node(3)
    >>> nx.is_isolate(G,2)
    False
    >>> nx.is_isolate(G,3)
    True
    """
    return G.degree(n) == 0


def _parse_content_type_header(header):
    """Returns content type and parameters from given header

    :param header: string
    :return: tuple containing content type and dictionary of
         parameters
    """
    tokens = header.split(';')
    content_type, params = tokens[0].strip(), tokens[1:]
    params_dict = {}
    items_to_strip = '"\' '
    for param in params:
        param = param.strip()
        if param:
            key, value = param, True
            index_of_equals = param.find('=')
            if index_of_equals != -1:
                key = param[:index_of_equals].strip(items_to_strip)
                value = param[index_of_equals + 1:].strip(items_to_strip)
            params_dict[key.lower()] = value
    return content_type, params_dict


def time_since1970():
    """
    Returning a decimal number with couting the last seconds since 1970

    @Returns:
    * [float]
    """
    import time
    return time.time()


def p_track_flag(t):
    """track_flag : SILENCE length
                  | ZERO length
                  | DATAFILE STRING
                  | DATAFILE STRING length
                  | FIFO STRING length
                  | PREGAP TIMESTAMP"""
    raise NotImplementedError()


def have_portlets(manager_name, view=None):
    """Determine whether a column should be shown. The left column is
        called plone.leftcolumn; the right column is called plone.rightcolumn.
        """


@staticmethod
def update_synonyms(list_widget, synonyms):
    """ Update the synonyms displayed

        Parameters
        ----------
        list_widget: QListWidget
        synonyms: iterable

        Returns
        -------

        """
    list_widget.clear()
    list_widget.addItems(sorted(synonyms))


@staticmethod
def _get_xdg_subdir():
    """Return the name (not path!) of this application's subdirectory.

        This name may be appended to ``$XDG_CONFIG_DIRS``, ``$XDG_DATA_DIRS``,
        ``$XDG_DATA_HOME``, and so on. For more, search for "subdir" within the
        `XDG base directory specification
        <https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html>`_.
        """
    return 'pulp_smash'


def teardown_databases108(old_config, verbosity, keepdb=False):
    """
    Destroys all the non-mirror databases.
    """
    old_names, mirrors = old_config
    for connection, old_name, destroy in old_names:
        if destroy:
            connection.creation.destroy_test_db(old_name, verbosity, keepdb)


def backoff(attempts):
    """
    Delay increases very rapidly with the number of attemps:
    1, 2, 4, 8, 16, 32, ...

    """
    return 2 ** attempts


def args_loader(source, factory, how_many=1):
    """
    A loader that yields values from a flattened list by grouping values
    together and instantiating a factory.  This loader can be used to
    prepopulate a datasets from command line arguments.

    All ``None`` values returned by the factory are skipped.

    This is a short example where each two consecutive values are grouped
    together and used to create tuple instances from a factory function:

    >>> from importtools import args_loader
    >>> args = ['A1', 'A2', 'B1', 'B2', 'C1', 'C2']
    >>> factory = lambda x, y: tuple([x, y])
    >>> al = args_loader(args, factory, 2)
    >>> sorted(al)
    [('A1', 'A2'), ('B1', 'B2'), ('C1', 'C2')]

    """
    assert len(source) % how_many == 0
    arg_groups = zip(*([iter(source)] * how_many))
    for arg_group in arg_groups:
        value = factory(*arg_group)
        if value is not None:
            yield value


def timezone_choice(tzname, country=None):
    """
    Given a timezone string, convert it to a two-tuple suitable
    for a choice in a FormField.

    >>> timezone_choice('UTC')
    ('UTC', 'UTC')
    >>> timezone_choice('Australia/Sydney')
    ('Australia/Sydney', 'Sydney')
    >>> timezone_choice('America/Indiana/Indianapolis')
    ('America/Indiana/Indianapolis', 'Indianapolis (Indiana)')
    """
    try:
        base, rest = tzname.split('/', 1)
    except ValueError:
        base, rest = None, tzname
    rest = rest.replace('_', ' ')
    try:
        mid, rest = rest.split('/')
        if mid != base and mid != country:
            rest = '{0} ({1})'.format(rest, mid)
    except ValueError:
        pass
    return tzname, rest


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

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


def set_callback(cb):
    """
    Set callback function which is called when FS change is deteced.

    @param cb: Python callable object or function
    """
    global callback
    callback = cb


def treated_routes(config, base_path='/'):
    """A dict containing each of the routes configured in this application.

    In your app configuration, ``config.make_wsgi_app()`` must be
    called *before* routes are extracted::

        app = config.make_wsgi_app()
        config.registry.app_routes = treated_routes(config)
        return app

    The return value is a dict like this::

         {'__static': '/static',  # static routes start with "__"
          'activate': '/activate/{user_id}/{code}'}
    """
    adict = {}
    for route in config.get_routes_mapper().routes.values():
        name = route.name.rstrip('/')
        pattern = route.pattern.strip('/')
        if pattern.endswith('/*subpath'):
            pattern = pattern[:-9]
        adict[name] = base_path + pattern
    return adict


@classmethod
def _is_non_Exif_APP1_segment(cls, stream, offset):
    "\n        Return True if the APP1 segment at *offset* in *stream* is NOT an\n        Exif segment, as determined by the ``'Exif\x00\x00'`` signature at\n        offset 2 in the segment.\n        "
    stream.seek(offset + 2)
    exif_signature = stream.read(6)
    return exif_signature != b'Exif\x00\x00'


def add_fields(iterable, **kw_fields):
    """
    Add fields to each item in ``iterable``. Each key=value pair provided is
    merged into the ``@fields`` object, which will be created if required.

    >>> data_in = [{'@message': 'one message'}, {'@message': 'another message'}]
    >>> data_out = add_fields(data_in, foo='bar', baz='qux')
    >>> [x for x in data_out]
    [{'@fields': {'foo': 'bar', 'baz': 'qux'}, '@message': 'one message'},
     {'@fields': {'foo': 'bar', 'baz': 'qux'}, '@message': 'another message'}]
    """
    k = '@fields'
    for item in iterable:
        if k not in item:
            item[k] = {}
        item[k].update(kw_fields)
        yield item


def is_class_private_name(name):
    """ Determine if a name is a class private name. """
    return name.startswith('__') and not name.endswith('__')


def p_arglist_star3_2(p):
    """arglist_star3 : arglist_star3 COMMA argument"""
    p[0] = p[1] + [p[3]]


@classmethod
def promote_from_model(cls, literal_model):
    """
        Creates an object of this type from the model primitive defining it.
        :param flytekit.models.literals.Literal literal_model:
        :rtype: Timedelta
        """
    return cls(literal_model.scalar.primitive.duration)


def raise_unknown_node(emitter, node):
    """
    unknown_emit callable for Html2CreoleEmitter

    Raise NotImplementedError on unknown tags.
    """
    content = emitter.emit_children(node)
    raise NotImplementedError(
        "Node from type '%s' is not implemented! (child content: %r)" % (
        node.kind, content))


def groupChat(roomJID, body):
    """
        Send a groupchat message.
        """


def terabytes(bits=None, bytes=None, kilobytes=None, megabytes=None,
    gigabytes=None, petabytes=None):
    """Usage: Convert to terabytes. Example: terabytes(gigabytes=512)"""
    if bits is not None:
        return bits / 8000000000000.0
    elif bytes is not None:
        return bytes / 1000000000000.0
    elif kilobytes is not None:
        return kilobytes / 1000000000.0
    elif megabytes is not None:
        return megabytes / 1000000.0
    elif gigabytes is not None:
        return gigabytes / 1000
    elif petabytes is not None:
        return petabytes * 1000
    else:
        raise Exception(
            'You must specify one value. Example: bits, bytes, kilobytes, megabytes, gigabytes, petabytes'
            )


def parse_user_input(string_from_user, selected_scramble):
    """Parses the scramble from the user

    >>> parse_user_input("3X3 5", None)
    ('3x3', 5)
    >>> parse_user_input("5", "3x3")
    ('3x3', 5)
    >>> parse_user_input("RU 3", "MEGAMINX")
    ('RU', 3)
    >>> parse_user_input("SQUARE ONE 10", "4x4")
    ('SQUARE ONE', 10)
    >>> parse_user_input("", "3x3")
    ('3x3', 1)
    >>> parse_user_input("5", "4x4")
    ('4x4', 5)
    """
    parts = string_from_user.split()
    if len(parts) == 0:
        if selected_scramble is None:
            raise RuntimeError("You haven't selected a scramble!")
        else:
            return selected_scramble, 1
    if parts[0] in ['2X2', '3X3', '4X4', '5X5', '6X6', '7X7']:
        parts[0] = parts[0].lower()
    count = 1
    try:
        count = int(parts[-1])
        parts.pop()
    except ValueError:
        pass
    if selected_scramble is not None and len(parts) == 0:
        return selected_scramble, count
    return ' '.join(parts), count


def search_caches(con):
    """
	Try to search cache keys
	"""
    found = False
    for x in con.keys():
        if 'cache' in str(x).lower():
            yield x


def describe_association(Name=None, InstanceId=None, AssociationId=None):
    """
    Describes the associations for the specified Systems Manager document or instance.
    See also: AWS API Documentation

    :example: response = client.describe_association(
        Name='string',
        InstanceId='string',
        AssociationId='string'
    )

    :type Name: string
    :param Name: The name of the SSM document.

    :type InstanceId: string
    :param InstanceId: The instance ID.

    :type AssociationId: string
    :param AssociationId: The association ID for which you want information.

    :rtype: dict
    :return: {
        'AssociationDescription': {
            'Name': 'string',
            'InstanceId': 'string',
            'Date': datetime(2015, 1, 1),
            'LastUpdateAssociationDate': datetime(2015, 1, 1),
            'Status': {
                'Date': datetime(2015, 1, 1),
                'Name': 'Pending'|'Success'|'Failed',
                'Message': 'string',
                'AdditionalInfo': 'string'
            },
            'Overview': {
                'Status': 'string',
                'DetailedStatus': 'string',
                'AssociationStatusAggregatedCount': {
                    'string': 123
                }
            },
            'DocumentVersion': 'string',
            'Parameters': {
                'string': [
                    'string',
                ]
            },
            'AssociationId': 'string',
            'Targets': [
                {
                    'Key': 'string',
                    'Values': [
                        'string',
                    ]
                },
            ],
            'ScheduleExpression': 'string',
            'OutputLocation': {
                'S3Location': {
                    'OutputS3Region': 'string',
                    'OutputS3BucketName': 'string',
                    'OutputS3KeyPrefix': 'string'
                }
            },
            'LastExecutionDate': datetime(2015, 1, 1),
            'LastSuccessfulExecutionDate': datetime(2015, 1, 1)
        }
    }

    :returns:
    (string) --
    (integer) --

    """
    pass


def items(sobject):
    """
    Extract the I{items} from a suds object much like the
    items() method works on I{dict}.
    @param sobject: A suds object
    @type sobject: L{Object}
    @return: A list of items contained in I{sobject}.
    @rtype: [(key, value),...]
    """
    for item in sobject:
        yield item


@classmethod
def enabled(cls) ->bool:
    """Return true if this saver is enabled on the current system."""
    return True


def is_listlike(x):
    """
    >>> is_listlike("foo")
    False
    >>> is_listlike(5)
    False
    >>> is_listlike(b"foo")
    False
    >>> is_listlike([b"foo"])
    True
    >>> is_listlike((b"foo",))
    True
    >>> is_listlike({})
    True
    >>> is_listlike(set())
    True
    >>> is_listlike((x for x in range(3)))
    True
    >>> is_listlike(range(5))
    True
    """
    return hasattr(x, '__iter__') and not isinstance(x, (str, bytes))


def maximum_line_length(physical_line, max_line_length, multiline, noqa):
    """Limit all lines to a maximum of 79 characters.

    There are still many devices around that are limited to 80 character
    lines; plus, limiting windows to 80 characters makes it possible to have
    several windows side-by-side.  The default wrapping on such devices looks
    ugly.  Therefore, please limit all lines to a maximum of 79 characters.
    For flowing long blocks of text (docstrings or comments), limiting the
    length to 72 characters is recommended.

    Reports error E501.
    """
    line = physical_line.rstrip()
    length = len(line)
    if length > max_line_length and not noqa:
        chunks = line.split()
        if (len(chunks) == 1 and multiline or len(chunks) == 2 and chunks[0
            ] == '#') and len(line) - len(chunks[-1]) < max_line_length - 7:
            return
        if hasattr(line, 'decode'):
            try:
                length = len(line.decode('utf-8'))
            except UnicodeError:
                pass
        if length > max_line_length:
            return (max_line_length,
                'E501 line too long (%d > %d characters)' % (length,
                max_line_length))


def number():
    """Return the position (starting with "1") within the iteration
        """


def _format_abc(num):
    """Lowercase.  Wraps around at 26."""
    n = (num - 1) % 26
    return chr(n + 97)


def render_pep440_bare(pieces):
    """TAG[.DISTANCE[.dev0]] .

    The ".dev0" means dirty.

    Eexceptions:
    1: no tags. 0.DISTANCE[.dev0]
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        if pieces['distance'] or pieces['dirty']:
            rendered += '.%d' % pieces['distance']
            if pieces['dirty']:
                rendered += '.dev0'
    else:
        rendered = '0.%d' % pieces['distance']
        if pieces['dirty']:
            rendered += '.dev0'
    return rendered


def botFilters():
    """
  customize bot filters to subscribe
  """
    return ['/restapi/v1.0/glip/posts', '/restapi/v1.0/glip/groups',
        '/restapi/v1.0/account/~/extension/~']


def getAncestors():
    """Return the member's line of ancestors in a list (self not included)."""


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

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


def getSignalID(frameOrName, signalName, db):
    """Get the int ID of a signal by giving the message name and signal name.

    frameOrName is the ID str or int for the message. signalName is the name of the signal that you want the ID for.
    """
    myNum = None
    if type(frameOrName) is int:
        try:
            num = db.get_message_by_frame_id(frameOrName).signals
            for i in range(len(num)):
                if num[i].name == signalName:
                    myNum = i
                i += 1
        except:
            print('warning: str addr not in DBC')
            myNum = 'not in DBC'
    elif type(frameOrName) is str:
        try:
            num = db.get_message_by_name(frameOrName).signals
            for i in range(len(num)):
                if num[i].name == signalName:
                    myNum = i
                i += 1
        except:
            print('warning: str addr not in DBC')
            myNum = 'not in DBC'
    return myNum


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


def create_table(AttributeDefinitions=None, TableName=None, KeySchema=None,
    LocalSecondaryIndexes=None, GlobalSecondaryIndexes=None,
    ProvisionedThroughput=None, StreamSpecification=None):
    """
    The CreateTable operation adds a new table to your account. In an AWS account, table names must be unique within each region. That is, you can have two tables with same name if you create the tables in different regions.
    You can optionally define secondary indexes on the new table, as part of the CreateTable operation. If you want to create multiple tables with secondary indexes on them, you must create the tables sequentially. Only one table with secondary indexes can be in the CREATING state at any given time.
    You can use the DescribeTable action to check the table status.
    See also: AWS API Documentation

    Examples
    This example creates a table named Music.
    Expected Output:

    :example: response = client.create_table(
        AttributeDefinitions=[
            {
                'AttributeName': 'string',
                'AttributeType': 'S'|'N'|'B'
            },
        ],
        TableName='string',
        KeySchema=[
            {
                'AttributeName': 'string',
                'KeyType': 'HASH'|'RANGE'
            },
        ],
        LocalSecondaryIndexes=[
            {
                'IndexName': 'string',
                'KeySchema': [
                    {
                        'AttributeName': 'string',
                        'KeyType': 'HASH'|'RANGE'
                    },
                ],
                'Projection': {
                    'ProjectionType': 'ALL'|'KEYS_ONLY'|'INCLUDE',
                    'NonKeyAttributes': [
                        'string',
                    ]
                }
            },
        ],
        GlobalSecondaryIndexes=[
            {
                'IndexName': 'string',
                'KeySchema': [
                    {
                        'AttributeName': 'string',
                        'KeyType': 'HASH'|'RANGE'
                    },
                ],
                'Projection': {
                    'ProjectionType': 'ALL'|'KEYS_ONLY'|'INCLUDE',
                    'NonKeyAttributes': [
                        'string',
                    ]
                },
                'ProvisionedThroughput': {
                    'ReadCapacityUnits': 123,
                    'WriteCapacityUnits': 123
                }
            },
        ],
        ProvisionedThroughput={
            'ReadCapacityUnits': 123,
            'WriteCapacityUnits': 123
        },
        StreamSpecification={
            'StreamEnabled': True|False,
            'StreamViewType': 'NEW_IMAGE'|'OLD_IMAGE'|'NEW_AND_OLD_IMAGES'|'KEYS_ONLY'
        }
    )

    :type AttributeDefinitions: list
    :param AttributeDefinitions: [REQUIRED]
            An array of attributes that describe the key schema for the table and indexes.
            (dict) --Represents an attribute for describing the key schema for the table and indexes.
            AttributeName (string) -- [REQUIRED]A name for the attribute.
            AttributeType (string) -- [REQUIRED]The data type for the attribute, where:
            S - the attribute is of type String
            N - the attribute is of type Number
            B - the attribute is of type Binary

    :type TableName: string
    :param TableName: [REQUIRED]
            The name of the table to create.

    :type KeySchema: list
    :param KeySchema: [REQUIRED]
            Specifies the attributes that make up the primary key for a table or an index. The attributes in KeySchema must also be defined in the AttributeDefinitions array. For more information, see Data Model in the Amazon DynamoDB Developer Guide .
            Each KeySchemaElement in the array is composed of:
            AttributeName - The name of this key attribute.
            KeyType - The role that the key attribute will assume:
            HASH - partition key
            RANGE - sort key

            Note
            The partition key of an item is also known as its hash attribute . The term 'hash attribute' derives from DynamoDB' usage of an internal hash function to evenly distribute data items across partitions, based on their partition key values.
            The sort key of an item is also known as its range attribute . The term 'range attribute' derives from the way DynamoDB stores items with the same partition key physically close together, in sorted order by the sort key value.
            For a simple primary key (partition key), you must provide exactly one element with a KeyType of HASH .
            For a composite primary key (partition key and sort key), you must provide exactly two elements, in this order: The first element must have a KeyType of HASH , and the second element must have a KeyType of RANGE .
            For more information, see Specifying the Primary Key in the Amazon DynamoDB Developer Guide .
            (dict) --Represents a single element of a key schema. A key schema specifies the attributes that make up the primary key of a table, or the key attributes of an index.
            A KeySchemaElement represents exactly one attribute of the primary key. For example, a simple primary key would be represented by one KeySchemaElement (for the partition key). A composite primary key would require one KeySchemaElement for the partition key, and another KeySchemaElement for the sort key.
            A KeySchemaElement must be a scalar, top-level attribute (not a nested attribute). The data type must be one of String, Number, or Binary. The attribute cannot be nested within a List or a Map.
            AttributeName (string) -- [REQUIRED]The name of a key attribute.
            KeyType (string) -- [REQUIRED]The role that this key attribute will assume:
            HASH - partition key
            RANGE - sort key
            Note
            The partition key of an item is also known as its hash attribute . The term 'hash attribute' derives from DynamoDB' usage of an internal hash function to evenly distribute data items across partitions, based on their partition key values.
            The sort key of an item is also known as its range attribute . The term 'range attribute' derives from the way DynamoDB stores items with the same partition key physically close together, in sorted order by the sort key value.

    :type LocalSecondaryIndexes: list
    :param LocalSecondaryIndexes: One or more local secondary indexes (the maximum is five) to be created on the table. Each index is scoped to a given partition key value. There is a 10 GB size limit per partition key value; otherwise, the size of a local secondary index is unconstrained.
            Each local secondary index in the array includes the following:
            IndexName - The name of the local secondary index. Must be unique only for this table.
            KeySchema - Specifies the key schema for the local secondary index. The key schema must begin with the same partition key as the table.
            Projection - Specifies attributes that are copied (projected) from the table into the index. These are in addition to the primary key attributes and index key attributes, which are automatically projected. Each attribute specification is composed of:
            ProjectionType - One of the following:
            KEYS_ONLY - Only the index and primary keys are projected into the index.
            INCLUDE - Only the specified table attributes are projected into the index. The list of projected attributes are in NonKeyAttributes .
            ALL - All of the table attributes are projected into the index.
            NonKeyAttributes - A list of one or more non-key attribute names that are projected into the secondary index. The total count of attributes provided in NonKeyAttributes , summed across all of the secondary indexes, must not exceed 20. If you project the same attribute into two different indexes, this counts as two distinct attributes when determining the total.

            (dict) --Represents the properties of a local secondary index.
            IndexName (string) -- [REQUIRED]The name of the local secondary index. The name must be unique among all other indexes on this table.
            KeySchema (list) -- [REQUIRED]The complete key schema for the local secondary index, consisting of one or more pairs of attribute names and key types:
            HASH - partition key
            RANGE - sort key
            Note
            The partition key of an item is also known as its hash attribute . The term 'hash attribute' derives from DynamoDB' usage of an internal hash function to evenly distribute data items across partitions, based on their partition key values.
            The sort key of an item is also known as its range attribute . The term 'range attribute' derives from the way DynamoDB stores items with the same partition key physically close together, in sorted order by the sort key value.
            (dict) --Represents a single element of a key schema. A key schema specifies the attributes that make up the primary key of a table, or the key attributes of an index.
            A KeySchemaElement represents exactly one attribute of the primary key. For example, a simple primary key would be represented by one KeySchemaElement (for the partition key). A composite primary key would require one KeySchemaElement for the partition key, and another KeySchemaElement for the sort key.
            A KeySchemaElement must be a scalar, top-level attribute (not a nested attribute). The data type must be one of String, Number, or Binary. The attribute cannot be nested within a List or a Map.
            AttributeName (string) -- [REQUIRED]The name of a key attribute.
            KeyType (string) -- [REQUIRED]The role that this key attribute will assume:
            HASH - partition key
            RANGE - sort key
            Note
            The partition key of an item is also known as its hash attribute . The term 'hash attribute' derives from DynamoDB' usage of an internal hash function to evenly distribute data items across partitions, based on their partition key values.
            The sort key of an item is also known as its range attribute . The term 'range attribute' derives from the way DynamoDB stores items with the same partition key physically close together, in sorted order by the sort key value.

            Projection (dict) -- [REQUIRED]Represents attributes that are copied (projected) from the table into the local secondary index. These are in addition to the primary key attributes and index key attributes, which are automatically projected.
            ProjectionType (string) --The set of attributes that are projected into the index:
            KEYS_ONLY - Only the index and primary keys are projected into the index.
            INCLUDE - Only the specified table attributes are projected into the index. The list of projected attributes are in NonKeyAttributes .
            ALL - All of the table attributes are projected into the index.
            NonKeyAttributes (list) --Represents the non-key attribute names which will be projected into the index.
            For local secondary indexes, the total count of NonKeyAttributes summed across all of the local secondary indexes, must not exceed 20. If you project the same attribute into two different indexes, this counts as two distinct attributes when determining the total.
            (string) --

    :type GlobalSecondaryIndexes: list
    :param GlobalSecondaryIndexes: One or more global secondary indexes (the maximum is five) to be created on the table. Each global secondary index in the array includes the following:
            IndexName - The name of the global secondary index. Must be unique only for this table.
            KeySchema - Specifies the key schema for the global secondary index.
            Projection - Specifies attributes that are copied (projected) from the table into the index. These are in addition to the primary key attributes and index key attributes, which are automatically projected. Each attribute specification is composed of:
            ProjectionType - One of the following:
            KEYS_ONLY - Only the index and primary keys are projected into the index.
            INCLUDE - Only the specified table attributes are projected into the index. The list of projected attributes are in NonKeyAttributes .
            ALL - All of the table attributes are projected into the index.
            NonKeyAttributes - A list of one or more non-key attribute names that are projected into the secondary index. The total count of attributes provided in NonKeyAttributes , summed across all of the secondary indexes, must not exceed 20. If you project the same attribute into two different indexes, this counts as two distinct attributes when determining the total.
            ProvisionedThroughput - The provisioned throughput settings for the global secondary index, consisting of read and write capacity units.
            (dict) --Represents the properties of a global secondary index.
            IndexName (string) -- [REQUIRED]The name of the global secondary index. The name must be unique among all other indexes on this table.
            KeySchema (list) -- [REQUIRED]The complete key schema for a global secondary index, which consists of one or more pairs of attribute names and key types:
            HASH - partition key
            RANGE - sort key
            Note
            The partition key of an item is also known as its hash attribute . The term 'hash attribute' derives from DynamoDB' usage of an internal hash function to evenly distribute data items across partitions, based on their partition key values.
            The sort key of an item is also known as its range attribute . The term 'range attribute' derives from the way DynamoDB stores items with the same partition key physically close together, in sorted order by the sort key value.
            (dict) --Represents a single element of a key schema. A key schema specifies the attributes that make up the primary key of a table, or the key attributes of an index.
            A KeySchemaElement represents exactly one attribute of the primary key. For example, a simple primary key would be represented by one KeySchemaElement (for the partition key). A composite primary key would require one KeySchemaElement for the partition key, and another KeySchemaElement for the sort key.
            A KeySchemaElement must be a scalar, top-level attribute (not a nested attribute). The data type must be one of String, Number, or Binary. The attribute cannot be nested within a List or a Map.
            AttributeName (string) -- [REQUIRED]The name of a key attribute.
            KeyType (string) -- [REQUIRED]The role that this key attribute will assume:
            HASH - partition key
            RANGE - sort key
            Note
            The partition key of an item is also known as its hash attribute . The term 'hash attribute' derives from DynamoDB' usage of an internal hash function to evenly distribute data items across partitions, based on their partition key values.
            The sort key of an item is also known as its range attribute . The term 'range attribute' derives from the way DynamoDB stores items with the same partition key physically close together, in sorted order by the sort key value.

            Projection (dict) -- [REQUIRED]Represents attributes that are copied (projected) from the table into the global secondary index. These are in addition to the primary key attributes and index key attributes, which are automatically projected.
            ProjectionType (string) --The set of attributes that are projected into the index:
            KEYS_ONLY - Only the index and primary keys are projected into the index.
            INCLUDE - Only the specified table attributes are projected into the index. The list of projected attributes are in NonKeyAttributes .
            ALL - All of the table attributes are projected into the index.
            NonKeyAttributes (list) --Represents the non-key attribute names which will be projected into the index.
            For local secondary indexes, the total count of NonKeyAttributes summed across all of the local secondary indexes, must not exceed 20. If you project the same attribute into two different indexes, this counts as two distinct attributes when determining the total.
            (string) --

            ProvisionedThroughput (dict) -- [REQUIRED]Represents the provisioned throughput settings for the specified global secondary index.
            For current minimum and maximum provisioned throughput values, see Limits in the Amazon DynamoDB Developer Guide .
            ReadCapacityUnits (integer) -- [REQUIRED]The maximum number of strongly consistent reads consumed per second before DynamoDB returns a ThrottlingException . For more information, see Specifying Read and Write Requirements in the Amazon DynamoDB Developer Guide .
            WriteCapacityUnits (integer) -- [REQUIRED]The maximum number of writes consumed per second before DynamoDB returns a ThrottlingException . For more information, see Specifying Read and Write Requirements in the Amazon DynamoDB Developer Guide .

    :type ProvisionedThroughput: dict
    :param ProvisionedThroughput: [REQUIRED]
            Represents the provisioned throughput settings for a specified table or index. The settings can be modified using the UpdateTable operation.
            For current minimum and maximum provisioned throughput values, see Limits in the Amazon DynamoDB Developer Guide .
            ReadCapacityUnits (integer) -- [REQUIRED]The maximum number of strongly consistent reads consumed per second before DynamoDB returns a ThrottlingException . For more information, see Specifying Read and Write Requirements in the Amazon DynamoDB Developer Guide .
            WriteCapacityUnits (integer) -- [REQUIRED]The maximum number of writes consumed per second before DynamoDB returns a ThrottlingException . For more information, see Specifying Read and Write Requirements in the Amazon DynamoDB Developer Guide .

    :type StreamSpecification: dict
    :param StreamSpecification: The settings for DynamoDB Streams on the table. These settings consist of:
            StreamEnabled - Indicates whether Streams is to be enabled (true) or disabled (false).
            StreamViewType - When an item in the table is modified, StreamViewType determines what information is written to the table's stream. Valid values for StreamViewType are:
            KEYS_ONLY - Only the key attributes of the modified item are written to the stream.
            NEW_IMAGE - The entire item, as it appears after it was modified, is written to the stream.
            OLD_IMAGE - The entire item, as it appeared before it was modified, is written to the stream.
            NEW_AND_OLD_IMAGES - Both the new and the old item images of the item are written to the stream.

            StreamEnabled (boolean) --Indicates whether DynamoDB Streams is enabled (true) or disabled (false) on the table.
            StreamViewType (string) --When an item in the table is modified, StreamViewType determines what information is written to the stream for this table. Valid values for StreamViewType are:
            KEYS_ONLY - Only the key attributes of the modified item are written to the stream.
            NEW_IMAGE - The entire item, as it appears after it was modified, is written to the stream.
            OLD_IMAGE - The entire item, as it appeared before it was modified, is written to the stream.
            NEW_AND_OLD_IMAGES - Both the new and the old item images of the item are written to the stream.

    :rtype: dict
    :return: {
        'TableDescription': {
            'AttributeDefinitions': [
                {
                    'AttributeName': 'string',
                    'AttributeType': 'S'|'N'|'B'
                },
            ],
            'TableName': 'string',
            'KeySchema': [
                {
                    'AttributeName': 'string',
                    'KeyType': 'HASH'|'RANGE'
                },
            ],
            'TableStatus': 'CREATING'|'UPDATING'|'DELETING'|'ACTIVE',
            'CreationDateTime': datetime(2015, 1, 1),
            'ProvisionedThroughput': {
                'LastIncreaseDateTime': datetime(2015, 1, 1),
                'LastDecreaseDateTime': datetime(2015, 1, 1),
                'NumberOfDecreasesToday': 123,
                'ReadCapacityUnits': 123,
                'WriteCapacityUnits': 123
            },
            'TableSizeBytes': 123,
            'ItemCount': 123,
            'TableArn': 'string',
            'LocalSecondaryIndexes': [
                {
                    'IndexName': 'string',
                    'KeySchema': [
                        {
                            'AttributeName': 'string',
                            'KeyType': 'HASH'|'RANGE'
                        },
                    ],
                    'Projection': {
                        'ProjectionType': 'ALL'|'KEYS_ONLY'|'INCLUDE',
                        'NonKeyAttributes': [
                            'string',
                        ]
                    },
                    'IndexSizeBytes': 123,
                    'ItemCount': 123,
                    'IndexArn': 'string'
                },
            ],
            'GlobalSecondaryIndexes': [
                {
                    'IndexName': 'string',
                    'KeySchema': [
                        {
                            'AttributeName': 'string',
                            'KeyType': 'HASH'|'RANGE'
                        },
                    ],
                    'Projection': {
                        'ProjectionType': 'ALL'|'KEYS_ONLY'|'INCLUDE',
                        'NonKeyAttributes': [
                            'string',
                        ]
                    },
                    'IndexStatus': 'CREATING'|'UPDATING'|'DELETING'|'ACTIVE',
                    'Backfilling': True|False,
                    'ProvisionedThroughput': {
                        'LastIncreaseDateTime': datetime(2015, 1, 1),
                        'LastDecreaseDateTime': datetime(2015, 1, 1),
                        'NumberOfDecreasesToday': 123,
                        'ReadCapacityUnits': 123,
                        'WriteCapacityUnits': 123
                    },
                    'IndexSizeBytes': 123,
                    'ItemCount': 123,
                    'IndexArn': 'string'
                },
            ],
            'StreamSpecification': {
                'StreamEnabled': True|False,
                'StreamViewType': 'NEW_IMAGE'|'OLD_IMAGE'|'NEW_AND_OLD_IMAGES'|'KEYS_ONLY'
            },
            'LatestStreamLabel': 'string',
            'LatestStreamArn': 'string'
        }
    }

    :returns:
    AttributeName - The name of the attribute.
    AttributeType - The data type for the attribute.

    """
    pass


def _assignrepr_bracketed2(assignrepr_bracketed1, values, prefix, width=None):
    """Return a prefixed, wrapped and properly aligned bracketed string
    representation of the given 2-dimensional value matrix using function
    |repr|."""
    brackets = getattr(assignrepr_bracketed1, '_brackets')
    prefix += brackets[0]
    lines = []
    blanks = ' ' * len(prefix)
    for idx, subvalues in enumerate(values):
        if idx == 0:
            lines.append(assignrepr_bracketed1(subvalues, prefix, width))
        else:
            lines.append(assignrepr_bracketed1(subvalues, blanks, width))
        lines[-1] += ','
    if len(values) > 1 or brackets != '()':
        lines[-1] = lines[-1][:-1]
    lines[-1] += brackets[1]
    return '\n'.join(lines)


def select_linked():
    """Select all points in same strokes as already selected points

    """
    pass


def uniq(iterable, key=lambda x: x):
    """
    Remove duplicates from an iterable. Preserves order.
    :type iterable: Iterable[Ord => A]
    :param iterable: an iterable of objects of any orderable type
    :type key: Callable[A] -> (Ord => B)
    :param key: optional argument; by default an item (A) is discarded
    if another item (B), such that A == B, has already been encountered and taken.
    If you provide a key, this condition changes to key(A) == key(B); the callable
    must return orderable objects.
    """
    keys = set()
    res = []
    for x in iterable:
        k = key(x)
        if k in keys:
            continue
        res.append(x)
        keys.add(k)
    return res


def log2(data=None, name=None, attr=None, out=None, **kwargs):
    """Returns element-wise Base-2 logarithmic value of the input.

    ``2**log2(x) = x``

    The storage type of ``log2`` output is always dense

    Defined in src/operator/tensor/elemwise_unary_op_logexp.cc:L105

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

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

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


def ADMdimList(sType='stacked'):
    """
    Return standard list of dimensions for frame definitions, from :py:func:`epsproc.sphCalc.setADMs()`.

    Parameters
    ----------
    sType : string, optional, default = 'stacked'
        Selected 'stacked' or 'unstacked' dimensions.
        Set 'sDict' to return a dictionary of unstacked <> stacked dims mappings for use with xr.stack({dim mapping}).

    Returns
    -------
    list : set of dimension labels.

    """
    if sType is 'stacked':
        return ['ADM', 't']
    elif sType is 'sDict':
        return {'ADM': ['K', 'Q', 'S'], 't': 't'}
    else:
        return ['K', 'Q', 'S', 't']


def type_match(node_a, node_b):
    """ Checks whether the node types of the inputs match.
        :param node_a: First node.
        :param node_b: Second node.
        :return: True if the object types of the nodes match, False otherwise.
        :raise TypeError: When at least one of the inputs is not a dictionary
                          or does not have a 'node' attribute.
        :raise KeyError: When at least one of the inputs is a dictionary,
                         but does not have a 'node' key.
    """
    return isinstance(node_a['node'], type(node_b['node']))


def lookupAFSDatabase(name, timeout=None):
    """
        Perform an AFSDB record lookup.

        @type name: L{bytes} or L{str}
        @param name: DNS name to resolve.

        @type timeout: Sequence of C{int}
        @param timeout: Number of seconds after which to reissue the query.
            When the last timeout expires, the query is considered failed.

        @rtype: L{Deferred}
        @return: A L{Deferred} which fires with a three-tuple of lists of
            L{twisted.names.dns.RRHeader} instances.  The first element of the
            tuple gives answers.  The second element of the tuple gives
            authorities.  The third element of the tuple gives additional
            information.  The L{Deferred} may instead fail with one of the
            exceptions defined in L{twisted.names.error} or with
            C{NotImplementedError}.
        """


def __new__(_cls, major, minor, micro):
    """Create new instance of VersionInfo(major, minor, micro)."""
    return tuple.__new__(_cls, (major, minor, micro))


@staticmethod
def e_value_normalizer(e_value_raw, celltype_number, number_of_re):
    """
        Normalizes the e-value due to disparity in number of celltypes
        :param e_value_raw: value to normalize
        :param celltype_number: number of cell types in data set
        :param number_of_re: number of RE in sample
        :return: normalized e-value
        """
    coefs = {'a': -164054.1, 'b': 0.9998811, 'c': 6.088948e-06, 'd':
        1.00051, 'm': 0.9527, 'e': -0.1131}
    e_value_expected = (coefs['m'] * number_of_re + coefs['e']
        ) * celltype_number ** (coefs['d'] + (coefs['a'] - coefs['d']) / (1 +
        (number_of_re / coefs['c']) ** coefs['b']))
    e_value_norm = e_value_raw / e_value_expected * 100
    if e_value_norm < 100:
        return e_value_norm
    else:
        return 100


def read_file(filepath):
    """
	for a given file, change it into list of words and numbers, will call this in build_trie

	Parameters
	----------
	filepath: Name of the file we will use

	Return
	------
	a list of words and a list of corresponding weights

	"""
    file = open(filepath, 'r', encoding='utf-8')
    data = file.readlines()
    data_list = []
    for i in range(len(data)):
        if i != 0:
            data_list.append(data[i])
    num_list = []
    word_list = []
    for l in data_list:
        if l != '\n':
            entry = l.split('\t')
            num_list.append(int(entry[0]))
            word_list.append(entry[1][:-1])
    return num_list, word_list


def dl_flush(dl):
    """ Flush double list. (Remove all items).
    """
    curr = dl.head
    while not curr:
        temp = curr
        curr = curr.next
        del temp
    dl.head = None
    dl.tail = None
    dl.itemsInContainer = 0


@classmethod
def register_data_adapter(cls, scheme, adapter):
    """Registers a DataAdapter class for a specific scheme.

        Args:
            scheme: The scheme of the data adapter.
            adapter: The data adapter class.

        Returns:
            None
        """
    if scheme not in cls.SCHEMES:
        cls.SCHEMES[scheme] = {'data_adapter': adapter}


def info_parser(parser):
    """
    Add arguments for info command to parser
    """
    parser.add_argument('group', choices=['run', 'status', 'input',
        'initial-conditions', 'sonic-points', 'crosses-points',
        'sonic-on-scale', 'solutions'])
    return parser


@staticmethod
def _adopt_contact_list(contact_list):
    """
        A contact list is returned from the API with the 'name' key as 'contactlist_name' OR as
        `list_name`. This is different from the other elements, so we patch the object to be
        similar to the other objects returned by the library.

        :param contact_list:
        :return:
        """
    if not contact_list:
        return contact_list
    contact_list = dict(contact_list)
    if 'contactlist_name' in contact_list:
        contact_list['name'] = contact_list['contactlist_name']
        del contact_list['contactlist_name']
    if 'list_name' in contact_list:
        contact_list['name'] = contact_list['list_name']
        del contact_list['list_name']
    return contact_list


def properties():
    """Toggle the properties region visibility

    """
    pass


def truncate_value(limit, value):
    """
    Truncate ``value`` to a maximum of ``limit`` characters.
    """
    values = value.split(u'\n')
    value = values[0]
    if len(value) > limit or len(values) > 1:
        return u'{}…'.format(value[:limit])
    return value


def is_naive(value):
    """
    Determines if a given datetime.datetime is naive.

    The concept is defined in Python's docs:
    http://docs.python.org/library/datetime.html#datetime.tzinfo

    Assuming value.tzinfo is either None or a proper datetime.tzinfo,
    value.utcoffset() implements the appropriate logic.
    """
    return value.utcoffset() is None


def load_image(imagepath, dirname: str='', place_holder: bool=False,
    recursive: bool=False, ncase_cmp: bool=True, convert_callback=None,
    verbose=False, relpath: str=None, check_existing: bool=False,
    force_reload: bool=False) ->'bpy.types.Image':
    """Return an image from the file path with options to search multiple paths and return a placeholder if its not found.

    :param filepath: The image filename If a path precedes it, this will be searched as well.
    :type filepath: str
    :param dirname: is the directory where the image may be located - any file at the end will be ignored.
    :type dirname: str
    :param place_holder: if True a new place holder image will be created. this is useful so later you can relink the image to its original data.
    :type place_holder: bool
    :param recursive: If True, directories will be recursively searched. Be careful with this if you have files in your root directory because it may take a long time.
    :type recursive: bool
    :param ncase_cmp: on non windows systems, find the correct case for the file.
    :type ncase_cmp: bool
    :param convert_callback: a function that takes an existing path and returns a new one. Use this when loading image formats blender may not support, the CONVERT_CALLBACK can take the path for a GIF (for example), convert it to a PNG and return the PNG’s path. For formats blender can read, simply return the path that is given.
    :param relpath: If not None, make the file relative to this path.
    :type relpath: str
    :param check_existing: If true, returns already loaded image datablock if possible (based on file path).
    :type check_existing: bool
    :param force_reload: If true, force reloading of image (only useful when check_existing is also enabled).
    :type force_reload: bool
    :return:  an image or None
    """
    pass


@classmethod
def table_name_col(cls):
    """
        Return the name of the metadata column used to store the feature table
        name.
        """
    return 'table_name'


@task
def get_tasks():
    """Get all paver-defined tasks."""
    from paver.tasks import environment
    for task in environment.get_tasks():
        print(task.shortname)


def p_expression_comment(p):
    """comment : LPAREN comment_text RPAREN
               | LPAREN RPAREN"""
    p[0] = ''


def truncate_to_significant_bits(input_x: int, num_significant_bits: int
    ) ->int:
    """
    Truncates the number such that only the top num_significant_bits contain 1s.
    and the rest of the number is 0s (in binary). Ignores decimals and leading
    zeroes. For example, -0b011110101 and 2, returns -0b11000000.
    """
    x = abs(input_x)
    if num_significant_bits > x.bit_length():
        return x
    lower = x.bit_length() - num_significant_bits
    mask = (1 << x.bit_length()) - 1 - ((1 << lower) - 1)
    if input_x < 0:
        return -(x & mask)
    else:
        return x & mask


def set_initial_position(sgf_game, board):
    """Add setup stones to an Sgf_game reflecting a board position.

    sgf_game -- Sgf_game
    board    -- Board object

    Replaces any existing setup stones in the Sgf_game's root node.

    'board' may be a boards.Board instance, or anything providing the interface
    described by sgf_board_interface.Interface_for_set_initial_position().

    """
    stones = {'b': set(), 'w': set()}
    for colour, point in board.list_occupied_points():
        stones[colour].add(point)
    sgf_game.get_root().set_setup_stones(stones['b'], stones['w'])


@classmethod
def key_prefix(cls):
    """Prefix that we use for Redis storage, used for all keys related
        to this object. Default to class name.
        """
    return cls.__name__


def js_compile(client):
    """
    Compile all instructions in the client into a valid javascript source.
    """
    lines = []
    for action in client._actions:
        source = action._js_source_()
        if source:
            lines.append(source)
    js_source = '\n'.join(lines)
    return js_source


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


def dispatch(data, fns):
    """Apply the functions on the data

    :param data: the data
    :param fns: a list of functions
    :returns: a collection

    >>> x = (1, 42, 5, 79)
    >>> dispatch(x, (min, max))
    [1, 79]

    """
    return map(lambda fn: fn(data), fns)


@classmethod
def get_map(cls) ->dict:
    """
        Returns the map between JSON string and enum values.

        Returns
        -------
        dict
            The map.
        """
    return {None: cls.NONE, 'binary': cls.BINARY, 'multiClass': cls.
        MULTICLASS, 'multiLabel': cls.MULTILABEL, 'univariate': cls.
        UNIVARIATE, 'multivariate': cls.MULTIVARIATE, 'overlapping': cls.
        OVERLAPPING, 'nonOverlapping': cls.NONOVERLAPPING}


def get_close_faces(faces, face_eids, unused_nids_close):
    """this seems like it could be a lot faster"""
    return faces, face_eids


def notifications(request):
    """Make notifications available in all templates."""
    if not request.user.is_authenticated:
        return {}
    return {'notifications': request.user.notifications}


def stop_experiment(api, exp_id):
    """ Stop user experiment submission.

    :param api: API Rest api object
    :param exp_id: scheduler OAR id submission
    """
    return api.stop_experiment(exp_id)


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 canonical_tuple_path(tuple_path):
    """Make a Zope path the smallest possible. Unlike canonical_path
    it takes the path as a tuple.
    """
    canonical_path = []
    for item in tuple_path:
        if item == '..':
            if not canonical_path or not canonical_path[-1]:
                raise ValueError('Invalid path')
            canonical_path.pop()
        elif item != '.':
            if item == '' and canonical_path:
                continue
            canonical_path.append(item)
    return canonical_path


def is_active():
    """Returns True if the reporter is still running. While in this
        state, new Incident triggers will be passed to the existing reporter
        instead of causing a new Incident to be declared. This will tend to
        coalesce back-to-back problems into a single Incident."""


def obj_type(key):
    """If it is a 'dir' it will end with a slash
    otherwise it is a 'file'
    """
    if key[-1:] == '/':
        return 'directory'
    else:
        return 'file'


@classmethod
def from_size(cls, data, width, height):
    """ Instantiate a new class given only screen shot's data and size. """
    monitor = {'left': 0, 'top': 0, 'width': width, 'height': height}
    return cls(data, monitor)


def getMessageIds():
    """Get a list of all the message ids."""


def positive_predictive_value(real, predicted):
    """ PPV = `|True Positives| / (|True Positives| + |False Positives|)`

    Parameters
    ----------
    real : dict
        A dictionary mapping quasispecies to frequencies.

    predicted : dict
        The calculated dictionary mapping quasispecies to frequencies.

    Returns
    -------
    PPV : float
        The positive predicted value
    """
    truepos = set(predicted.keys()) & set(real.keys())
    return len(truepos) / float(len(predicted))


def _verify_root():
    """Verify the command is running with root privileges."""
    import os
    uid = os.getegid()
    if uid != 0:
        return False
    return True


@conf
def gcc_modifier_win32(conf):
    """Configuration flags for executing gcc on Windows"""
    v = conf.env
    v.cprogram_PATTERN = '%s.exe'
    v.cshlib_PATTERN = '%s.dll'
    v.implib_PATTERN = '%s.dll.a'
    v.IMPLIB_ST = '-Wl,--out-implib,%s'
    v.CFLAGS_cshlib = []
    v.append_value('LINKFLAGS', ['-Wl,--enable-auto-import'])


def pdf2cdf(xs):
    """
    Convert the PDF P(X==i) to the CDF P(X<i)
    """
    t = 0
    ys = []
    for x in xs:
        ys.append(t)
        t += x
    return ys


def get_sebastian_aho(player):
    """
    This checks which Sebastian Aho it is based on the position. I have the player id's hardcoded here.

    This function is needed because "get_players_json" doesn't control for when there are two Sebastian Aho's (it just
    writes over the first one).

    :param player: player info

    :return: Player ID for specific Aho
    """
    return 8480222 if player[1] == 'D' else 8478427


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 assign_index(input_df, index_col='idx'):
    """Return input DataFrame with id col.
    """
    out_df = input_df.reset_index(drop=True)
    out_df.loc[:, (index_col)] = out_df.index
    return out_df


@classmethod
def main(cls):
    """Setuptools console-script entrypoint"""
    cmd = cls()
    cmd._parse_args()
    cmd._setup_logging()
    response = cmd._run()
    output = cmd._handle_response(response)
    if output is not None:
        print(output)


def to_native_string(string, encoding='ascii'):
    """Given a string object, regardless of type, returns a representation of
    that string in the native string type, encoding and decoding where
    necessary. This assumes ASCII unless told otherwise.
    """
    if isinstance(string, str):
        return string
    return string.decode(encoding)


def get_conversion(scale, limits):
    """
    Get the conversion equations for each axis.

    limits: dict of min and max values for the axes in the order blr.
    """
    fb = float(scale) / float(limits['b'][1] - limits['b'][0])
    fl = float(scale) / float(limits['l'][1] - limits['l'][0])
    fr = float(scale) / float(limits['r'][1] - limits['r'][0])
    conversion = {'b': lambda x: (x - limits['b'][0]) * fb, 'l': lambda x:
        (x - limits['l'][0]) * fl, 'r': lambda x: (x - limits['r'][0]) * fr}
    return conversion


def gen_select_add(sig_dic):
    """
    Adding for select control.
    :param sig_dic:
        html_media_type = {
        'en': 'tag_media_type',
        'zh': 'Media_type',
        'dic': {1: 'Document', 2: 'Data', 3: 'Program'},
        'type': 'select',
        }
    """
    option_str = ''
    for key, val in sig_dic['dic'].items():
        tmp_str = '<option value="{0}">{1}</option>'.format(key, val)
        option_str += tmp_str
    return (
        """

    {sig_zh}

<select id="{sig_en}" name="{sig_en}" class="form-control">
    {option_str}</select>

    """
        .format(sig_en=sig_dic['en'], sig_zh=sig_dic['zh'], option_str=
        option_str))


def ifloordiv(a, b):
    """Same as a //= b."""
    a //= b
    return a


@staticmethod
def __inRect(x, y, diaPointA, diaPointB):
    """Check if point (x,y) is within an axis-aligned rect
		with the diagonal (diaPointA,diaPointB).
		"""
    diaMinX, diaMaxX = min(diaPointA.x, diaPointB.x), max(diaPointA.x,
        diaPointB.x)
    diaMinY, diaMaxY = min(diaPointA.y, diaPointB.y), max(diaPointA.y,
        diaPointB.y)
    return x >= diaMinX and x <= diaMaxX and y >= diaMinY and y <= diaMaxY


def create_lzh(archive, compression, cmd, verbosity, interactive, filenames):
    """Create a LZH archive."""
    opts = 'a'
    if verbosity > 1:
        opts += 'v'
    cmdlist = [cmd, opts, archive]
    cmdlist.extend(filenames)
    return cmdlist


def _simple_slice(arr, inds, axis):
    """
    This does the same as np.take() except only supports simple slicing,
    not advanced indexing, and thus is much faster.

    References
    ----------
    https://stackoverflow.com/a/37729566
    """
    sl = [slice(None)] * arr.ndim
    sl[axis] = inds
    return arr[tuple(sl)]


def fix_header_colors(lines):
    """Make each but second occurence of multicols {c} argument a {b}.
    """
    lines = lines.replace('{c}', '{b}', 1)
    i = lines.find('{c}')
    return lines[:i + 1] + lines[i + 1:].replace('{c}', '{b}', 1)


@staticmethod
def _normalize_cmd(command):
    """Normalize CLI commands to have a single trailing newline"""
    command = command.rstrip('\n')
    command += '\n'
    return command


def trim_start(transcript, cds_start, max_length=0):
    """
    Method to trim the beginning of a transcript, given both
    the cds_start and the maximal allowed length after trimming.
    :param transcript: the transcript to be trimmed
    :type transcript: Transcript

    :param cds_start: the position at which the CDS starts for this transcript.
    :type cds_start: int

    :param max_length: maximum length of terminal exons.
    :type max_length: int

    :rtype: Transcript

    """
    first = transcript.exons[0]
    if first[1] < cds_start:
        if first[1] - first[0] + 1 > max_length:
            newfirst = tuple([first[1] - max_length, first[1]])
            transcript.remove_exon(first)
            transcript.add_exon(newfirst)
        else:
            newfirst = first
    elif first[0] < cds_start <= first[1]:
        if first[1] - first[0] + 1 > max_length:
            newfirst = tuple([min(cds_start, first[1] - max_length), first[1]])
            transcript.remove_exon(first)
            transcript.add_exon(newfirst)
            transcript.add_exon((cds_start, newfirst[1]), feature='CDS')
        else:
            newfirst = first
    else:
        newfirst = first
    transcript.start = newfirst[0]
    return transcript


def _join_host_port(host, port):
    """Adapted golang's net.JoinHostPort"""
    template = '%s:%s'
    host_requires_bracketing = ':' in host or '%' in host
    if host_requires_bracketing:
        template = '[%s]:%s'
    return template % (host, port)


def datetime_to_epochtime(index):
    """
    Convert DataFrame index from datetime to epoch time

    Parameters
    --------------
    index : pandas Index
        DataFrame index in datetime

    Returns
    ----------
    pandas Index
        DataFrame index in epoch time
    """
    index2 = index.astype('int64') / 10 ** 9
    return index2


@classmethod
def from_df(cls, df, **kwargs):
    """Constructs instance from dataframe containing
           ranged/positioned data."""
    if df.index.nlevels == 3:
        return cls(df, **kwargs)
    elif df.index.nlevels == 2:
        return cls.from_position_df(df, **kwargs)
    else:
        raise ValueError(
            'DataFrame should have either two index levels (for positioned data) or three index levels (for ranged data)'
            )


def getDHMS(seconds):
    """
    Split a given number of seconds into integer
    days, hours, minutes, and seconds.
    This function is used by `fmtDHMS()`, `fmtHMS()`, ...
    which format the time labels for createGantt().
    """
    seconds = int(seconds)
    days = int(seconds / (60 * 60 * 24))
    seconds -= 60 * 60 * 24 * days
    hours = int(seconds / (60 * 60))
    seconds -= 60 * 60 * hours
    minutes = int(seconds / 60)
    seconds -= 60 * minutes
    return [days, hours, minutes, seconds]


@classmethod
def from_box(cls, box):
    """Creates a `BoundingVolume` from a :class:`compas.geometry.Box`.

        Parameters
        ----------
        box: `compas.geometry.Box`

        Examples
        --------
        >>> from compas.geometry import Frame
        >>> from compas.geometry import Box
        >>> from compas_fab.robots import BoundingVolume
        >>> box = Box(Frame.worldXY(), 1., 1., 1.)
        >>> bv = BoundingVolume.from_box(box)
        >>> bv.type
        1
        """
    return cls(cls.BOX, box)


def perimeter_of_part(partition, part):
    """
    Totals up the perimeter of the part in the partition.
    Requires that 'boundary_perim' be a node attribute, 'shared_perim' be an edge
    attribute, 'cut_edges' be an updater, and 'exterior_boundaries' be an updater.
    """
    exterior_perimeter = partition['exterior_boundaries'][part]
    interior_perimeter = partition['interior_boundaries'][part]
    return exterior_perimeter + interior_perimeter


def remove_oversea_areas(df, lat=[36, 72], lon=[-10.6, 31]):
    """
    Remove plants outside continental Europe such as the Canarian Islands etc.
    """
    df = df.loc[df.lat.isnull() | df.lon.isnull() | (df.lat >= lat[0]) & (
        df.lat <= lat[1]) & (df.lon >= lon[0]) & (df.lon <= lon[1])]
    return df


def params_from_locals(vlist, locvars):
    """Returns a dictionary where values in `vlist` are returned in a `dict`
    only if their values are not `None`.

    Args:
        vlist (list): of `str` variable names in `locvars`.
        locvars (dict): `locals()` dictionary from the requesting context.
    """
    result = {}
    for v in vlist:
        if v in locvars and locvars[v] is not None:
            result[v] = locvars[v]
    return result


@classmethod
def from_ip(cls, ip):
    """Find the smallest network containing that IP."""
    return cls.all_from_ip(ip)[0]


@classmethod
def on_pre_start(cls, name, *args):
    """Apply patch to run before nginx actually starts."""
    if name in ['nginx']:
        if '-or' not in args:
            cls._ocean.start(name, *(args + ('-or',)))
            cls._rewrite_conf()
            cls._update_manifest_nginx()
            cls._ocean._alt_fullyconnect()


@classmethod
def _get_version(cls):
    """Return VCS program version."""
    return cls._popen(['review', '--version'], merge_err=True).split()[-1]


def get_axis_aligned_bbox(region):
    """
    convert region to (center_x, center_y, bbox_w, bbox_h)
    that represent by axis aligned box

    Parameters
    ----------
        region: np.array (4*N)
        bbox region location

    Return:
        Center location weight and height
    """
    region_x = region[0]
    region_y = region[1]
    bbox_w = region[2]
    bbox_h = region[3]
    center_x = region_x + bbox_w / 2
    center_y = region_y + bbox_h / 2
    return center_x, center_y, bbox_w, bbox_h


def is_authenticated(request, view, obj=None):
    """
    Checks if the current user is authenticated.
    """
    return request.user.is_authenticated()


def topological_sort(graph, key=None):
    """
    Topological sort of graph's vertices.

    Parameters
    ==========

    ``graph`` : ``tuple[list, list[tuple[T, T]]``
        A tuple consisting of a list of vertices and a list of edges of
        a graph to be sorted topologically.

    ``key`` : ``callable[T]`` (optional)
        Ordering key for vertices on the same level. By default the natural
        (e.g. lexicographic) ordering is used (in this case the base type
        must implement ordering relations).

    Examples
    ========

    Consider a graph::

        +---+     +---+     +---+
        | 7 |\\    | 5 |     | 3 |
        +---+ \\   +---+     +---+
          |   _\\___/ ____   _/ |
          |  /  \\___/    \\ /   |
          V  V           V V   |
         +----+         +---+  |
         | 11 |         | 8 |  |
         +----+         +---+  |
          | | \\____   ___/ _   |
          | \\      \\ /    / \\  |
          V  \\     V V   /  V  V
        +---+ \\   +---+ |  +----+
        | 2 |  |  | 9 | |  | 10 |
        +---+  |  +---+ |  +----+
               \\________/

    where vertices are integers. This graph can be encoded using
    elementary Python's data structures as follows::

        >>> V = [2, 3, 5, 7, 8, 9, 10, 11]
        >>> E = [(7, 11), (7, 8), (5, 11), (3, 8), (3, 10),
        ...      (11, 2), (11, 9), (11, 10), (8, 9)]

    To compute a topological sort for graph ``(V, E)`` issue::

        >>> topological_sort((V, E))
        [3, 5, 7, 8, 11, 2, 9, 10]

    If specific tie breaking approach is needed, use ``key`` parameter::

        >>> topological_sort((V, E), key=lambda v: -v)
        [7, 5, 11, 3, 10, 8, 9, 2]

    Only acyclic graphs can be sorted. If the input graph has a cycle,
    then ValueError will be raised::

        >>> topological_sort((V, E + [(10, 7)]))
        Traceback (most recent call last):
        ...
        ValueError: cycle detected

    References
    ==========

    * https://en.wikipedia.org/wiki/Topological_sorting

    """
    V, E = graph
    L = []
    S = set(V)
    E = list(E)
    for v, u in E:
        S.discard(u)
    if key is None:

        def key(value):
            return value
    S = sorted(S, key=key, reverse=True)
    while S:
        node = S.pop()
        L.append(node)
        for u, v in list(E):
            if u == node:
                E.remove((u, v))
                for _u, _v in E:
                    if v == _v:
                        break
                else:
                    kv = key(v)
                    for i, s in enumerate(S):
                        ks = key(s)
                        if kv > ks:
                            S.insert(i, v)
                            break
                    else:
                        S.append(v)
    if E:
        raise ValueError('cycle detected')
    else:
        return L


@classmethod
def get_testing_options(cls, **kwargs):
    """Method to return a dictionary of testing options for this class.

        Returns:
            dict: Dictionary of variables to use for testing.

        """
    iobj = {'a': ['b', int(1), float(1.0)], 'c': {'z': 'hello'}}
    out = {'kwargs': {}, 'empty': {}, 'dtype': None, 'extra_kwargs': {},
        'objects': [iobj], 'typedef': {'type': 'object'}}
    out['contents'] = b'a:\n- b\n- 1\n- 1.0\nc:\n    z: hello\n'
    return out


@staticmethod
def _slug_is_available(slug, parent_page, page=None):
    """
        Determine whether the given slug is available for use on a child page of
        parent_page. If 'page' is passed, the slug is intended for use on that page
        (and so it will be excluded from the duplicate check).
        """
    if parent_page is None:
        return True
    siblings = parent_page.get_children()
    if page:
        siblings = siblings.not_page(page)
    return not siblings.filter(slug=slug).exists()


def updateFromExternalObject(externalObject, context, **kwargs):
    """
        Update the object this is adapting from the external object.

        Alternately, the signature can be ``updateFromExternalObject(externalObject)``
        or simply ``updateFromExternalObject(externalObject, **kwargs)``. In this
        last case, ``context`` will be passed as a value in ``**kwargs``.

        :return: If not ``None``, a value that can be interpreted as a boolean,
                indicating whether or not the internal object actually
                underwent updates. If ``None``, the caller should assume that the object
                was updated (to allow older
                code that doesn't return at all.)
        """


def getitem_in(obj, name):
    """ Finds a key in @obj via a period-delimited string @name.
        @obj: (#dict)
        @name: (#str) |.|-separated keys to search @obj in
        ..
            obj = {'foo': {'bar': {'baz': True}}}
            getitem_in(obj, 'foo.bar.baz')
        ..
        |True|
    """
    for part in name.split('.'):
        obj = obj[part]
    return obj


def ids_to_str(ids):
    """Convert a list of article IDs to a comma separated string of IDs.

    Parameters
    ----------
    ids : bs4.element.ResultSet
        List of article IDs.

    Returns
    -------
    ids_str : str
        A string of all concatenated IDs.
    """
    n_ids = len(ids)
    ids_str = str(ids[0].text)
    for ind in range(1, n_ids):
        ids_str = ids_str + ',' + str(ids[ind].text)
    return ids_str


def terms():
    """Return a list of all terms in this node, excluding NOT subtrees."""


def lookupWellKnownServices(name, timeout=None):
    """
        Perform a WKS record lookup.

        @type name: C{str}
        @param name: DNS name to resolve.

        @type timeout: Sequence of C{int}
        @param timeout: Number of seconds after which to reissue the query.
            When the last timeout expires, the query is considered failed.

        @rtype: L{Deferred}
        @return: A L{Deferred} which fires with a three-tuple of lists of
            L{twisted.names.dns.RRHeader} instances.  The first element of the
            tuple gives answers.  The second element of the tuple gives
            authorities.  The third element of the tuple gives additional
            information.  The L{Deferred} may instead fail with one of the
            exceptions defined in L{twisted.names.error} or with
            C{NotImplementedError}.
        """


@classmethod
def create(cls, codebase, vault_dir, name, keys=None):
    """Create a new vault in the specified directory."""
    vault = cls.get()
    buf = vault.encrypt('---\n{}')
    codebase.write(f'{vault_dir}/{name}.aes', buf, mode='wb', newline=False)
    return vault


@classmethod
def with_setup(cls, *setup_phases):
    """Create PhaseGroup creator function with predefined setup phases."""
    return cls.with_context(setup_phases, [])


def obj(context, nodes, **attrs):
    """
    Creates Python object with the attributes created from named matches.
    This action is used as default action for rules with named matches.
    """
    grammar = context.parser.grammar
    rule_name = context.production.symbol.fqn
    cls = grammar.classes[rule_name]
    instance = cls(**attrs)
    instance._pg_start_position = context.start_position
    instance._pg_end_position = context.end_position
    return instance


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

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


def setup(mail_verification=False, require_user_to_be_verified=False,
    use_sessions_when_client_calls_endpoint=False, *fixed_user_attributes):
    """Use `mail_verification` to control whether the register function should automatically try to verify the users' email. You can also manually do that by calling `serverly.user.mail.send_verification_email()`.

    If `require_user_to_be_verified`, users will only authenticate if their email is verified.

    If `use_sessions_when_client_calls_endpoint`, a new user activity will automatically be registered if the client uses an endpoint.

    `fixed_user_attributes` is a list which contains the attribute names of User attributes which may not be changed by the API. Useful for roles.
    """
    global verify_mail, only_user_verified, use_sessions, persistant_user_attributes
    verify_mail = mail_verification
    only_user_verified = require_user_to_be_verified
    use_sessions = use_sessions_when_client_calls_endpoint
    persistant_user_attributes = fixed_user_attributes


def compute_value(v, f):
    """
    Return the value of ``f`` at ``v``.

    INPUT:

    - ``v`` -- a function field valuation on `F`
    - ``f`` -- an element of `F`

    OUTPUT: The value of ``f`` at the point corresponding to ``v``.

    This is either an element of the residue field of the valuation ``v``
    (which is a finite extension of the base field of `F`), or `\\infty`.

    """
    from sage.rings.infinity import Infinity
    if v(f) < 0:
        return Infinity
    else:
        return v.reduce(f)


def load_glib(finder, module):
    """Ignore globals that are imported."""
    module.AddGlobalName('GError')
    module.AddGlobalName('IOChannel')
    module.AddGlobalName('IO_ERR')
    module.AddGlobalName('IO_FLAG_APPEND')
    module.AddGlobalName('IO_FLAG_GET_MASK')
    module.AddGlobalName('IO_FLAG_IS_READABLE')
    module.AddGlobalName('IO_FLAG_IS_SEEKABLE')
    module.AddGlobalName('IO_FLAG_IS_WRITEABLE')
    module.AddGlobalName('IO_FLAG_MASK')
    module.AddGlobalName('IO_FLAG_NONBLOCK')
    module.AddGlobalName('IO_FLAG_SET_MASK')
    module.AddGlobalName('IO_HUP')
    module.AddGlobalName('IO_IN')
    module.AddGlobalName('IO_NVAL')
    module.AddGlobalName('IO_OUT')
    module.AddGlobalName('IO_PRI')
    module.AddGlobalName('IO_STATUS_AGAIN')
    module.AddGlobalName('IO_STATUS_EOF')
    module.AddGlobalName('IO_STATUS_ERROR')
    module.AddGlobalName('IO_STATUS_NORMAL')
    module.AddGlobalName('Idle')
    module.AddGlobalName('MainContext')
    module.AddGlobalName('MainLoop')
    module.AddGlobalName('OPTION_ERROR')
    module.AddGlobalName('OPTION_ERROR_BAD_VALUE')
    module.AddGlobalName('OPTION_ERROR_FAILED')
    module.AddGlobalName('OPTION_ERROR_UNKNOWN_OPTION')
    module.AddGlobalName('OPTION_FLAG_FILENAME')
    module.AddGlobalName('OPTION_FLAG_HIDDEN')
    module.AddGlobalName('OPTION_FLAG_IN_MAIN')
    module.AddGlobalName('OPTION_FLAG_NOALIAS')
    module.AddGlobalName('OPTION_FLAG_NO_ARG')
    module.AddGlobalName('OPTION_FLAG_OPTIONAL_ARG')
    module.AddGlobalName('OPTION_FLAG_REVERSE')
    module.AddGlobalName('OPTION_REMAINING')
    module.AddGlobalName('OptionContext')
    module.AddGlobalName('OptionGroup')
    module.AddGlobalName('PRIORITY_DEFAULT')
    module.AddGlobalName('PRIORITY_DEFAULT_IDLE')
    module.AddGlobalName('PRIORITY_HIGH')
    module.AddGlobalName('PRIORITY_HIGH_IDLE')
    module.AddGlobalName('PRIORITY_LOW')
    module.AddGlobalName('Pid')
    module.AddGlobalName('PollFD')
    module.AddGlobalName('SPAWN_CHILD_INHERITS_STDIN')
    module.AddGlobalName('SPAWN_DO_NOT_REAP_CHILD')
    module.AddGlobalName('SPAWN_FILE_AND_ARGV_ZERO')
    module.AddGlobalName('SPAWN_LEAVE_DESCRIPTORS_OPEN')
    module.AddGlobalName('SPAWN_SEARCH_PATH')
    module.AddGlobalName('SPAWN_STDERR_TO_DEV_NULL')
    module.AddGlobalName('SPAWN_STDOUT_TO_DEV_NULL')
    module.AddGlobalName('Source')
    module.AddGlobalName('Timeout')
    module.AddGlobalName('child_watch_add')
    module.AddGlobalName('filename_display_basename')
    module.AddGlobalName('filename_display_name')
    module.AddGlobalName('filename_from_utf8')
    module.AddGlobalName('get_application_name')
    module.AddGlobalName('get_current_time')
    module.AddGlobalName('get_prgname')
    module.AddGlobalName('glib_version')
    module.AddGlobalName('idle_add')
    module.AddGlobalName('io_add_watch')
    module.AddGlobalName('main_context_default')
    module.AddGlobalName('main_depth')
    module.AddGlobalName('markup_escape_text')
    module.AddGlobalName('set_application_name')
    module.AddGlobalName('set_prgname')
    module.AddGlobalName('source_remove')
    module.AddGlobalName('spawn_async')
    module.AddGlobalName('timeout_add')
    module.AddGlobalName('timeout_add_seconds')


def migRing(populations, k, selection, replacement=None, migarray=None):
    """Perform a ring migration between the *populations*. The migration first
    select *k* emigrants from each population using the specified *selection*
    operator and then replace *k* individuals from the associated population
    in the *migarray* by the emigrants. If no *replacement* operator is
    specified, the immigrants will replace the emigrants of the population,
    otherwise, the immigrants will replace the individuals selected by the
    *replacement* operator. The migration array, if provided, shall contain
    each population's index once and only once. If no migration array is
    provided, it defaults to a serial ring migration (1 -- 2 -- ... -- n --
    1). Selection and replacement function are called using the signature
    ``selection(populations[i], k)`` and ``replacement(populations[i], k)``.
    It is important to note that the replacement strategy must select *k*
    **different** individuals. For example, using a traditional tournament for
    replacement strategy will thus give undesirable effects, two individuals
    will most likely try to enter the same slot.

    :param populations: A list of (sub-)populations on which to operate
                        migration.
    :param k: The number of individuals to migrate.
    :param selection: The function to use for selection.
    :param replacement: The function to use to select which individuals will
                        be replaced. If :obj:`None` (default) the individuals
                        that leave the population are directly replaced.
    :param migarray: A list of indices indicating where the individuals from
                     a particular position in the list goes. This defaults
                     to a ring migration.
    """
    nbr_demes = len(populations)
    if migarray is None:
        migarray = list(range(1, nbr_demes)) + [0]
    immigrants = [[] for i in range(nbr_demes)]
    emigrants = [[] for i in range(nbr_demes)]
    for from_deme in range(nbr_demes):
        emigrants[from_deme].extend(selection(populations[from_deme], k))
        if replacement is None:
            immigrants[from_deme] = emigrants[from_deme]
        else:
            immigrants[from_deme].extend(replacement(populations[from_deme], k)
                )
    for from_deme, to_deme in enumerate(migarray):
        for i, immigrant in enumerate(immigrants[to_deme]):
            indx = populations[to_deme].index(immigrant)
            populations[to_deme][indx] = emigrants[from_deme][i]


def simple(child, shared, parent):
    """Return sub-set of children who are "simple" in the sense of group_children"""
    return not child.get('refs', ()) and (not shared.get(child['address']) or
        shared.get(child['address']) == [parent['address']])


def _update_axes(ax, xincrease, yincrease, xscale=None, yscale=None, xticks
    =None, yticks=None, xlim=None, ylim=None):
    """
    Update axes with provided parameters
    """
    if xincrease is None:
        pass
    elif xincrease and ax.xaxis_inverted():
        ax.invert_xaxis()
    elif not xincrease and not ax.xaxis_inverted():
        ax.invert_xaxis()
    if yincrease is None:
        pass
    elif yincrease and ax.yaxis_inverted():
        ax.invert_yaxis()
    elif not yincrease and not ax.yaxis_inverted():
        ax.invert_yaxis()
    if xscale is not None:
        ax.set_xscale(xscale)
    if yscale is not None:
        ax.set_yscale(yscale)
    if xticks is not None:
        ax.set_xticks(xticks)
    if yticks is not None:
        ax.set_yticks(yticks)
    if xlim is not None:
        ax.set_xlim(xlim)
    if ylim is not None:
        ax.set_ylim(ylim)


def is_model(data):
    """ True if time sery data was created by a model """
    return 'T' in data and 'start' in data


def accept_alerts(driver):
    """Accept any alerts which prevent page HTML from loading"""
    try:
        while True:
            driver.switch_to.alert.accept()
    except:
        pass


@classmethod
def _find_note_text_pieces(cls, text):
    """Splits notes text and return notes"""
    notes = []
    _text = text
    while _text:
        start_pos = _text.find(cls.NOTE_START)
        end_pos = _text.find(cls.NOTE_END)
        if start_pos != -1 and end_pos != -1:
            note_len = len(cls.NOTE_END)
            note_text = _text[start_pos:end_pos + note_len]
            notes.append(note_text)
        else:
            break
        _text = _text[end_pos + len(cls.NOTE_END):]
    return notes


def indexed_count():
    """Return the number of document ids currently indexed.  Logically
        equivalent to len(self.indexed())."""


def split_value(v, n=2):
    """
    If ``v`` is a list of ``n`` elements, return it; if it is
    'undefined', return a list of ``n`` 'undefined' values; else
    generate an error
    """
    if v == 'undefined':
        return ['undefined'] * n
    else:
        assert len(v) == n, 'Value wrong length'
        return v


def uri_is_internal(uri):
    """
    >>> uri_is_internal('/word/media/image1.png')
    True
    >>> uri_is_internal('http://google/images/image.png')
    False
    """
    return uri.startswith('/')


def getUserInfo(appkey, username, password):
    """Returns returns a struct containing userinfo

        userid, firstname, lastname, nickname, email, and url.
        """


@staticmethod
def staticclassattribute(function):
    """Return given function as a staticmethod, handle None as None.

        This allows storing the function as a class attribute.
        """
    return staticmethod(function) if function is not None else None


def _seq_refs(obj, unused):
    """Return specific referents of a frozen/set, list, tuple and xrange object.
    """
    return obj


def timezone(zone):
    """Try to get timezone using pytz or python-dateutil

    :param zone: timezone str
    :return: timezone tzinfo or None
    """
    try:
        import pytz
        return pytz.timezone(zone)
    except ImportError:
        pass
    try:
        from dateutil.tz import gettz
        return gettz(zone)
    except ImportError:
        return None


def is_undefined(obj):
    """Check if the object passed is undefined.  This does nothing more than
    performing an instance check against :class:`Undefined` but looks nicer.
    This can be used for custom filters or tests that want to react to
    undefined variables.  For example a custom default filter can look like
    this::

        def default(var, default=''):
            if is_undefined(var):
                return default
            return var
    """
    from .runtime import Undefined
    return isinstance(obj, Undefined)


@classmethod
def apply_query_lte(cls, queryset, options, value):
    """Apply `lte` functional query.

        Syntax:

            /endpoint/?field_name__lte={value}__{boost}
            /endpoint/?field_name__lte={value}

        Example:

            http://localhost:8000/api/articles/?id__lte=1__2.0
            http://localhost:8000/api/articles/?id__lte=1

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


@staticmethod
def _is_search_path(item):
    """check if item is a search_path"""
    if not isinstance(item, dict):
        return False
    if sorted(item.keys()) != ['path', 'value']:
        return False
    if not isinstance(item['path'], list):
        return False
    if isinstance(item['value'], (dict, list)):
        return False
    return True


def dict_from_cookiejar(cj):
    """Returns a key/value dictionary from a CookieJar.

    :param cj: CookieJar object to extract cookies from.
    :rtype: dict
    """
    cookie_dict = {}
    for cookie in cj:
        cookie_dict[cookie.name] = cookie.value
    return cookie_dict


@staticmethod
def _get_name_dn_delimiters():
    """
        Return a list of strings that surround the name within the dn
        :return: list of strings that surround the name within the dn
        """
    raise NotImplementedError