@staticmethod
def description(model):
    """Return string description for given point."""
    return '{}, {}'.format(model.latitude, model.longitude)


@classmethod
def _flatten_param(cls, params):
    """
        Flatten the query params to be compatible with the API.
        :param params: The params object to process.
        :return: Nested dict/list values are flatten into single level dict.
        """
    flatten = params
    if type(params) in [dict, list]:
        flatten = {}
        for k, v in (params.items() if type(params) is dict else enumerate(
            params)):
            f = cls._flatten_param(v)
            if type(f) is dict:
                for kk, vv in f.items():
                    flatten[u'%s.%s' % (k, kk)] = vv
            else:
                flatten[k] = v
    return flatten


@staticmethod
def _is_gcs_s3(user_id):
    """
        Checks S3 key format: alphanumeric chars starting with GOOG.
        """
    return user_id.startswith('GOOG')


def quote_copy(s):
    """Quoting for copy command.  None is converted to \\N.

    Python implementation.
    """
    if s is None:
        return '\\N'
    s = str(s)
    s = s.replace('\\', '\\\\')
    s = s.replace('\t', '\\t')
    s = s.replace('\n', '\\n')
    s = s.replace('\r', '\\r')
    return s


def version_tuple(v):
    """
    Converts a version string into a tuple of ints that can be used for natural comparison.
    """
    return tuple(map(int, v.split('.')))


def sizeof_fmt(num, suffix=''):
    """
    Format the number to a humanized order of magnitude.

    For example, ``11234`` become ``11.23K``.

    :param num:
        The positive integer.
    :param suffix:
        Additional suffix added to the resulting string.

    :returns:
        Formatted number as a string.

    """
    if abs(num) < 1000:
        return '%s%s' % (num, suffix)
    for unit in ['K', 'M', 'G', 'T', 'P', 'E', 'Z']:
        num /= 1000.0
        if abs(num) < 1000.0:
            return '%.2f%s%s' % (num, unit, suffix)
    num /= 1000.0
    return '%.2f%s%s' % (num, 'Y', suffix)


def item_gemeente_adapter(obj, request):
    """
    Adapter for rendering an object of
    :class:`crabpy.gateway.crab.Gemeente` to json.
    """
    return {'id': obj.id, 'niscode': obj.niscode, 'naam': obj.naam,
        'centroid': obj.centroid, 'bounding_box': obj.bounding_box,
        'metadata': {'begin_tijd': obj.metadata.begin_tijd, 'begin_datum':
        obj.metadata.begin_datum, 'begin_bewerking': {'id': obj.metadata.
        begin_bewerking.id, 'naam': obj.metadata.begin_bewerking.naam,
        'definitie': obj.metadata.begin_bewerking.definitie},
        'begin_organisatie': {'id': obj.metadata.begin_organisatie.id,
        'naam': obj.metadata.begin_organisatie.naam, 'definitie': obj.
        metadata.begin_organisatie.definitie}}}


def Property(function):
    """ Property(function)

    A property decorator which allows to define fget, fset and fdel
    inside the function.

    Note that the class to which this is applied must inherit from object!
    Code based on an example posted by Walker Hale:
    http://code.activestate.com/recipes/410698/#c6

    """
    known_keys = 'fget', 'fset', 'fdel', 'doc'
    func_locals = function()
    if not isinstance(func_locals, dict):
        raise RuntimeError('Property function should "return locals()".')
    D = {'doc': function.__doc__}
    for key in func_locals.keys():
        if key in known_keys:
            D[key] = func_locals[key]
        else:
            raise RuntimeError('Invalid Property element: %s' % key)
    return property(**D)


def _sql_params(sql):
    """
    Identify `sql` as either SQL string or 2-tuple of SQL and params.
    Same format as supported by Django's RunSQL operation for sql/reverse_sql.
    """
    params = None
    if isinstance(sql, (list, tuple)):
        elements = len(sql)
        if elements == 2:
            sql, params = sql
        else:
            raise ValueError('Expected a 2-tuple but got %d' % elements)
    return sql, params


def get_hook(cls, unique_id):
    """
        Fetch a registered hook instance by its unique_id
        """
    if not cls.abstract:
        raise TypeError('get_hook method used on a non-abstract hook')
    return cls._registered_hooks.get(unique_id, None)


def _make_list(obj):
    """Returns list corresponding to or containing obj, depending on type."""
    if isinstance(obj, list):
        return obj
    elif isinstance(obj, tuple):
        return list(obj)
    else:
        return [obj]


def http__refreshEtag():
    """        While it may make sense to use the ZODB Object Id or the
        database mtime to generate an Etag, this could
        fail on certain REQUESTS because:

         o The object is not stored in the ZODB, or

         o A Request such as PUT changes the oid or database mtime
           *AFTER* the Response has been written out, but the Etag needs
           to be updated and returned with the Response of the PUT request.

        Thus, Etags need to be refreshed manually when an object changes.
        """


def remove_doubles(threshold: float=0.0001, use_unselected: bool=False):
    """Merge vertices based on their proximity

    :param threshold: Merge Distance, Maximum distance between elements to merge
    :type threshold: float
    :param use_unselected: Unselected, Merge selected to other unselected vertices
    :type use_unselected: bool
    """
    pass


def read_setup_py(path):
    """return contents of setup.py"""
    content = ''
    with open('%s/setup.py' % path, 'r') as setup:
        return ''.join(setup.readlines())


def to_exchange(exchange):
    """转换成正确的交易市场. 如果不存在, 则返回None"""
    exchange_set = {'SH', 'SZ', 'CFFEX', 'SHFE', 'DCE', 'CZCE', 'INE'}
    if not exchange:
        return None
    s = str(exchange).upper().strip()
    return s if s in exchange_set else None


def L(i, d_in, n_us):
    """
    Helper function for calculating fifo load, representing the increase in the
    fifo value during readout period ``i``. Maximum FIFO value can be found
    by summing from ``i=-1`` to ``i=d_in-1``, inclusive.

    :param i: iterator index

    :param d_in: in degree of node in downstream network

    :param n_us: sorted list of number of downstream parents of node (0 == least upstream children) of each connection in downstream network

    :returns: ``int``

    """
    if i == -1:
        return 1
    if i == 0:
        return d_in - 1
    if i == 1:
        return (d_in - i) * (n_us[0] - 1)
    return (d_in - i) * (n_us[i - 1] - n_us[i - 2])


@staticmethod
def p_pgm_optional_list_optional(p):
    """pgm_optional_list_optional : empty
                                      | pgm_optional_list"""
    p[0] = tuple() if p[1] is None else p[1]


def _default_key_normalizer(key_class, request_context):
    """
    Create a pool key out of a request context dictionary.

    According to RFC 3986, both the scheme and host are case-insensitive.
    Therefore, this function normalizes both before constructing the pool
    key for an HTTPS request. If you wish to change this behaviour, provide
    alternate callables to ``key_fn_by_scheme``.

    :param key_class:
        The class to use when constructing the key. This should be a namedtuple
        with the ``scheme`` and ``host`` keys at a minimum.
    :type  key_class: namedtuple
    :param request_context:
        A dictionary-like object that contain the context for a request.
    :type  request_context: dict

    :return: A namedtuple that can be used as a connection pool key.
    :rtype:  PoolKey
    """
    context = request_context.copy()
    context['scheme'] = context['scheme'].lower()
    context['host'] = context['host'].lower()
    for key in ('headers', '_proxy_headers', '_socks_options'):
        if key in context and context[key] is not None:
            context[key] = frozenset(context[key].items())
    socket_opts = context.get('socket_options')
    if socket_opts is not None:
        context['socket_options'] = tuple(socket_opts)
    for key in list(context.keys()):
        context['key_' + key] = context.pop(key)
    for field in key_class._fields:
        if field not in context:
            context[field] = None
    return key_class(**context)


def is_start_chunk(prev_tag, cur_tag):
    """Check if an entity started between the previous and current tags.

    Parameters
    ----------
    prev_tag: str
        Previous chunk tag.

    cur_tag: str
        Current chunk tag.

    Returns
    -------
    chunk_start: boolean.
        True if current tag is the started part of a entity, otherwise False.

    """
    if cur_tag == 'O':
        return False
    if prev_tag == 'O':
        return True
    cur_tag_pos, cur_tag_name = cur_tag.split('-')
    prev_tag_pos, prev_tag_name = prev_tag.split('-')
    if cur_tag_pos in ['B', 'S'
        ] or cur_tag_name != prev_tag_name or prev_tag_pos in ['E', 'S']:
        return True
    return False


def __delitem__(index):
    """Delete an item from the storage, by index"""


@classmethod
def _get_sources(cls, tree):
    """Get sources of a tree

        Parameters
        ----------
            tree : :class:`ParsedTree <ckipnlp.container.util.parsed_tree.ParsedTree>`
                the parser tree.

        Yields
        ------
            int
                the identifier of source nodes.

        Notes
        -----
            A node can be a coreference source if either:

            1. POS-tag is `Nb`
            2. is one of the human words from E-HowNet

        """
    for node in tree.leaves():
        if cls._is_human_word(node):
            yield node.identifier


def pad(s, pad_to_length):
    """Pads the given string to the given length."""
    return ('%-' + '%ds' % pad_to_length) % (s,)


def parse_pathrep(pathrep):
    """ Parse path replacer """
    if pathrep is None:
        return None
    if type(pathrep) is tuple or isinstance(pathrep, list):
        pathrep_old = pathrep[0].replace('\\', '/')
        pathrep_new = pathrep[1]
    else:
        pathrep_old = pathrep.replace('\\', '/')
        pathrep_new = ''
    return pathrep_old, pathrep_new


def get_paginator(operation_name=None):
    """
    Create a paginator for an operation.

    :type operation_name: string
    :param operation_name: The operation name. This is the same name
            as the method name on the client. For example, if the
            method name is create_foo, and you'd normally invoke the
            operation as client.create_foo(**kwargs), if the
            create_foo operation can be paginated, you can use the
            call client.get_paginator('create_foo').

    :rtype: L{botocore.paginate.Paginator}
    """
    pass


@classmethod
def fromApiEntry(cls, entry):
    """
        Class method to instantiate a threat list given a threat list entry
        dictionary.

        @param entry threat list entry dictionary
        @type dict
        @return instantiated object
        @rtype ThreatList
        """
    return cls(entry['threatType'], entry['platformType'], entry[
        'threatEntryType'])


@classmethod
def blue(cls, s):
    """Wrap text in blue."""
    return cls._wrap_colour(s, cls.BLUE)


@classmethod
def get_by_uuid(cls, context, uuid):
    """Find a chassis based on UUID and return a :class:`Chassis` object.

        :param cls: the :class:`Chassis`
        :param context: Security context
        :param uuid: the UUID of a chassis.
        :returns: a :class:`Chassis` object.
        """
    db_chassis = cls.dbapi.get_chassis_by_uuid(uuid)
    chassis = cls._from_db_object(context, cls(), db_chassis)
    return chassis


def text_multiline(cr, x, y, text, padding=1):
    """
    Draw a string of text with embedded newlines.
    cr - cairo context
    x - leftmost x
    y - topmost y
    text - text to draw
    padding - additional padding between lines.
    """
    if not text:
        return
    for line in text.split('\n'):
        x_bear, y_bear, w, h, x_adv, y_adv = cr.text_extents(text)
        y += h
        cr.move_to(x, y)
        cr.show_text(line)


@classmethod
def get_config_as_dict(cls, **kwargs):
    """
        Registers the `google.appengine.api.lib_config`_ ``ConfigHandle`` and returns its settings as a ``dict``.
        Keyword arguments will override default values defined in the :py:class:`~agar.config.Config` subclass
        (but, of course, will still defer to values in the ``appengine_config.py`` file).

        :param kwargs: Defaults to use for the config instance. Values in ``appengine_config.py`` will still override
            any values you specify.
        :return: A ``dict`` of the configurations.
        """
    c = {}
    config = cls.get_config(**kwargs)
    for key in config._defaults:
        c[key] = config.__getattr__(key)
    return c


def stream(func, page=1, page_size=20):
    """
    Accepts a lambda of a call to a client list method, and streams the results until
    the list has been exhausted

    :Args:
        fun (function): A 1-arity function to apply during the stream

        Example::
            stream(lambda pagination: client.get_collaborators(project_id, **pagination))
    """
    total_pages = page
    while page <= total_pages:
        result_list = func(page=page, page_size=page_size)
        total_pages = result_list.total_pages
        for res in result_list:
            yield res
        page += 1


def tokenizeRelations(rels):
    """Returns an iterable of tokens for the relations given"""


def fpNE(a, b):
    """
    Checks if floating point `a` is not equal to floating point `b`.
    """
    return a != b


def _format_generic(char: int):
    """Format generic char."""
    return f'{char:3d}, 0o{char:03o}, 0x{char:02X}'


def get_context_first_matching_object(context, context_lookups):
    """
    Return the first object found in the context,
    from a list of keys, with the matching key.
    """
    for key in context_lookups:
        context_object = context.get(key)
        if context_object:
            return key, context_object
    return None, None


def find_class_in_dict(cls, d, include=None, exclude=None):
    """Get a list of keys that are an instance of a class in a dict"""
    names = []
    for key, value in d.copy().items():
        if not isinstance(value, type):
            continue
        if issubclass(value, cls):
            if include and include not in key:
                continue
            if exclude and exclude in key:
                continue
            names.append(key)
    return names


def p_try_stmt_plus_2(p):
    """try_stmt_plus : try_stmt_plus except_clause COLON suite"""
    p[2].body = p[4]
    p[0] = p[1] + [p[2]]


def processauthors_ignore_authors(authors_list, ignore):
    """Ignore ignored authors

    See docstring of processauthors() for more information.
    """
    dest = []
    for author in authors_list:
        ignored = False
        for ignoreword in ignore:
            if author.find(ignoreword) != -1:
                ignored = True
                break
        if not ignored:
            dest.append(author)
    return dest


def to_camel_case(snake_case):
    """Makes a snake case string into a camel case one

    Parameters
    -----------
    snake_case : str
        Snake-cased string (e.g., "snake_cased") to be converted to camel-case (e.g., "camelCase")

    Returns
    -------
    str
        Camel-cased (e.g., "camelCased") version of input string
    """
    output_str = ''
    should_upper_case = False
    for c in snake_case:
        if c == '_':
            should_upper_case = True
            continue
        output_str = output_str + c.upper(
            ) if should_upper_case else output_str + c
        should_upper_case = False
    return output_str


def glIsShader(shader: int):
    """Determines if a name corresponds to a shader object.

    :param shader: Specifies a potential shader object.
    :type shader: int
    """
    pass


@classmethod
def read(cls, fp, **options):
    """Read a problem instance from a file-like object.

        Any keyword options are passed to the class constructor. If a keyword
        argument has the same name as a field then they will collide and cause
        an error.

        :param str fp: a file-like object
        :param options: any keyword arguments to pass to the constructor
        :return: problem instance
        :rtype: :class:`Problem`
        """
    return cls.parse(fp.read(), **options)


def human_readable_time(time_ps: int) ->str:
    """Transform **time_ps** to a human readable string.

    Args:
        time_ps (int): Time in pico seconds.

    Returns:
        str: Human readable time.
    """
    time_units = ['femto seconds', 'pico seconds', 'nano seconds',
        'micro seconds', 'mili seconds']
    t = time_ps * 1000
    for tu in time_units:
        if t < 1000:
            return str(t) + ' ' + tu
        t /= 1000
    return str(time_ps)


def parse_ethics_approved_payload(payload):
    """
    A sample payload looks like:

    <CERIF
        xmlns="urn:xmlns:org:eurocris:cerif-1.4-0"
        xsi:schemaLocation="urn:xmlns:org:eurocris:cerif-1.4-0http://www.eurocris.org/Uploads/Web%%20pages/CERIF-1.4/CERIF_1.4_0.xsd"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        release="1.4"
        date="2012-04-12"
        sourceDatabase="OpenEthics">

        <cfProj>
            <cfProjId>%(rmas_id)s</cfProjId> <!-- RMAS identifier -->
            <cfProj_Class>
                <cfClassId>11111-11111-11111-11111</cfClassId><!-- this is the uuid for the status "Ethics Approved" -->
                <cfClassSchemeId>759af93a-34ae-11e1-b86c-0800200c9a66</cfClassSchemeId><!--this is the uuid for the CERIF scheme "Activity Statuses"-->
                <cfStartDate>%(start)s</cfStartDate>
                <cfEndDate>%(end)s</cfEndDate>
            </cfProj_Class>
        </cfProj>
    </CERIF>

    At this stage we are only interested in getting the project id.... we could
    check to make sure that there is a node with the ethics_approved status
    but by virtue of the fact that this is an ethics_approved message we will
    trust that the sender has sent it legitimately.

    Returns:

    The proposal id.
    """
    projid = payload.xpath('p:cfProj/p:cfProjId', namespaces={'p':
        'urn:xmlns:org:eurocris:cerif-1.4-0'}).pop().text
    return projid


def replace_line_block(lines, block, index_start, index_end):
    """Replace a block of lines between two line indices with a new set of lines.

    :param lines: list of lines representing the whole file
    :param block: list of lines representing the new block that should be inserted after old block is removed
    :param index_start: start of the block to be removed
    :param index_end: end of the block to be removed
    :return: list of lines with block of lines replaced
    """
    lines = lines[:index_start] + lines[index_end:]
    lines[index_start:index_start] = block
    return lines


def get_db_size():
    """Returns the approximate size of the database in bytes"""


@classmethod
def _join(cls, text):
    """Convert single newlines (ignored by Markdown) to spaces.

        >>> Markdown._join("abc\\n123")
        'abc 123'

        >>> Markdown._join("abc\\n\\n123")
        'abc\\n\\n123'

        >>> Markdown._join("abc \\n123")
        'abc 123'

        """
    return cls.REGEX_MARKDOWN_SPACES.sub('\\1 \\3', text).strip()


def getArguments(parser):
    """Provides additional validation of the arguments collected by argparse."""
    return parser.parse_args()


@classmethod
def get_instance(cls, *args, **kwargs):
    """
        Factory Method for object creation

        Use this instead of directly initializing the class in order to make
        unit testing much easier.
        """
    return cls(*args, **kwargs)


def to_exchange(exchange):
    """转换成正确的交易市场. 如果不存在, 则返回None"""
    exchange_set = {'SH', 'SZ', 'CFFEX', 'SHFE', 'DCE', 'CZCE', 'INE'}
    if not exchange:
        return None
    s = str(exchange).upper().strip()
    return s if s in exchange_set else None


def tokenize(s):
    """Convert a string into a list of tokens."""
    return s.replace('(', ' ( ').replace(')', ' ) ').split()


def get_directory(DirectoryArn=None):
    """
    Retrieves metadata about a directory.
    See also: AWS API Documentation

    :example: response = client.get_directory(
        DirectoryArn='string'
    )

    :type DirectoryArn: string
    :param DirectoryArn: [REQUIRED]
            The ARN of the directory.

    :rtype: dict
    :return: {
        'Directory': {
            'Name': 'string',
            'DirectoryArn': 'string',
            'State': 'ENABLED'|'DISABLED'|'DELETED',
            'CreationDateTime': datetime(2015, 1, 1)
        }
    }

    """
    pass


def _gen_param_header(name, doc, defaultValueStr, typeConverter):
    """
    Generates the header part for shared variables

    :param name: param name
    :param doc: param doc
    """
    template = """class Has$Name(Params):
    ""\"
    Mixin for param $name: $doc
    ""\"

    $name = Param(Params._dummy(), "$name", "$doc", typeConverter=$typeConverter)

    def __init__(self):
        super(Has$Name, self).__init__()"""
    if defaultValueStr is not None:
        template += """
        self._setDefault($name=$defaultValueStr)"""
    Name = name[0].upper() + name[1:]
    if typeConverter is None:
        typeConverter = str(None)
    return template.replace('$name', name).replace('$Name', Name).replace(
        '$doc', doc).replace('$defaultValueStr', str(defaultValueStr)).replace(
        '$typeConverter', typeConverter)


def Typeof(obj):
    """sort of mapping JSON/python"""
    if obj.__class__.__name__ == 'dict':
        return 'object'
    elif obj.__class__.__name__ == 'str':
        return 'string'
    elif obj.__class__.__name__ == 'function':
        return 'function'
    elif obj.__class__.__name__ == 'list':
        return 'array'
    elif obj.__class__.__name__ == 'bool':
        return 'boolean'
    elif obj.__class__.__name__ == 'int' or obj.__class__.__name__ == 'float' or obj.__class__.__name__ == 'long':
        return 'number'
    return 'null'


def eigenvalues(eigenvalues_at_kpoints, kpoint_index=0, spin_index=0):
    """
    Returns eigenvalues for a given kpoint and spin.

    Args:
        eigenvalues_at_kpoints (list): a list of eigenvalues for all kpoints.
        kpoint_index (int): kpoint index.
        spin_index (int): spin index.

    Returns:
         ndarray
    """
    spin_map = {(0): 0.5, (1): -0.5}
    for eigenvalue in eigenvalues_at_kpoints[kpoint_index]['eigenvalues']:
        if eigenvalue['spin'] == spin_map[spin_index]:
            return eigenvalue['energies']


@classmethod
def get(cls, code):
    """
        Get a service based on a code

        :param str code:
        :return xenops.service.Service:
        """
    return cls._services.get(code)


def make_obstruction(aperture):
    """Create an obstruction of `aperture`.

	Parameters
	----------
	aperture : Field generator
		The aperture to invert.

	Returns
	-------
	Field generator
		The obstruction.
	"""
    return lambda grid: 1 - aperture(grid)


@classmethod
def get_filter_set(cls, info: 'ResolveInfo') ->'FilterSet':
    """
        Get field filter set.

        Args:
            info: Graphene resolve info object.

        Returns:
            FilterSet class from field args.

        """
    field_name = info.field_asts[0].name.value
    schema_field = info.parent_type.fields.get(field_name)
    filters_type = schema_field.args[cls.filter_arg].type
    filters: 'FilterSet' = filters_type.graphene_type
    return filters


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

        :param SharedContentRemoveInviteesDetails val:
        :rtype: EventDetails
        """
    return cls('shared_content_remove_invitees_details', val)


@classmethod
def validate_url(cls, url):
    """Strip and trailing slash to validate a url

        :param url: the url address
        :return: the valid url address
        :rtype: string
        """
    if url is None:
        return None
    url = url.strip()
    while url.endswith('/'):
        url = url[:-1]
    return url


def get_language_to_text_map(element):
    """Return a map of languages to text in an InternationalizedText element."""
    language_map = {}
    if element is None:
        return language_map
    intl_strings = element.findall('Text')
    for intl_string in intl_strings:
        text = intl_string.text
        if text is None or not text:
            continue
        language = intl_string.get('language')
        if language is None or not language:
            continue
        language_map[language] = text
    return language_map


@classmethod
def from_string(cls, wf: str, validate: bool=True) ->'Workflow':
    """Create a Workflow from a YAML string."""
    body = {'data': wf}
    return cls.__deserialize(body, validate=validate)


def add_to_most_probable_component(comps, act2, ingoing, outgoing):
    """
    Adds a lost component in parallel cut detection to the most probable component

    Parameters
    -------------
    comps
        Connected components
    act2
        Activity that has been missed
    ingoing
        Map of ingoing attributes
    outgoing
        Map of outgoing attributes

    Returns
    -------------
    comps
        Fixed connected components
    """
    sums = []
    idx_max_sum = 0
    for comp in comps:
        summ = 0
        for act1 in comp:
            if act1 in ingoing and act2 in ingoing[act1]:
                summ = summ + ingoing[act1][act2]
            if act1 in outgoing and act2 in outgoing[act1]:
                summ = summ + outgoing[act1][act2]
        sums.append(summ)
        if sums[-1] > sums[idx_max_sum]:
            idx_max_sum = len(sums) - 1
    comps[idx_max_sum].add(act2)
    return comps


def build_default_config(options):
    """Build a default config from an iterable of options.
    """
    config = {}
    for option in options:
        subconfig = config
        for segment in option.path:
            subconfig = subconfig.setdefault(segment, {})
        subconfig[option.name] = option.default
    return config


def strip_suffix(s, suffix):
    """Strip a suffix from a string, if present."""
    return s[:-len(suffix)] if s.endswith(suffix) and suffix else s


def random_folder_name(k=20):
    """Generate a random name for a folder.

	Args:
		k (int): The length of the out string.
	Returns:
		A folder names.
	"""
    from random import choice
    from string import ascii_letters, digits
    return ''.join(choice(ascii_letters + digits) for n in range(int(k)))


def isprintable(string):
    """Return if all characters in string are printable.

    >>> isprintable('abc')
    True
    >>> isprintable(b'')
    False

    """
    string = string.strip()
    if not string:
        return True
    try:
        return string.isprintable()
    except Exception:
        pass
    try:
        return string.decode().isprintable()
    except Exception:
        pass


@classmethod
def from_TN(cls, tn, inplace=False, **kwargs):
    """Construct a specific tensor network subclass (i.e. one with some
        promise about structure/geometry and tags/inds such as an MPS) from
        a generic tensor network which should have that structure already.

        Parameters
        ----------
        cls : class
            The TensorNetwork subclass to convert ``tn`` to.
        tn : TensorNetwork
            The TensorNetwork to convert.
        inplace : bool, optional
            Whether to perform the conversion inplace or not.
        kwargs
            Extra properties of the TN subclass that should be specified.
        """
    new_tn = tn if inplace else tn.copy()
    for prop in cls._EXTRA_PROPS:
        prop_name = prop.lstrip('_')
        if prop_name in kwargs:
            setattr(new_tn, prop, kwargs.pop(prop_name))
        elif hasattr(tn, prop_name):
            setattr(new_tn, prop, getattr(tn, prop_name))
        else:
            raise ValueError(
                f"You need to specify '{prop_name}' for the tensor network class {cls}, and ensure that it correctly corresponds to the structure of the tensor network supplied, since it cannot be found as an attribute on the TN: {tn}."
                )
    if kwargs:
        raise ValueError(f'Options {kwargs} are invalid for the class {cls}.')
    new_tn.__class__ = cls
    return new_tn


def tags_from_context(context):
    """Helper to extract meta values from a Celery Context"""
    tag_keys = ('compression', 'correlation_id', 'countdown',
        'delivery_info', 'eta', 'exchange', 'expires', 'hostname', 'id',
        'priority', 'queue', 'reply_to', 'retries', 'routing_key',
        'serializer', 'timelimit', 'origin', 'state')
    tags = {}
    for key in tag_keys:
        value = context.get(key)
        if value is None or value == '':
            continue
        if key == 'timelimit' and value in [(None, None), [None, None]]:
            continue
        if key == 'retries' and value == 0:
            continue
        if key == 'origin':
            key = 'hostname'
        tag_name = 'celery.{}'.format(key)
        tags[tag_name] = value
    return tags


def write_output(output_fh, data_iterator, flush_on_each_record=True):
    """
    Write data from data_iterator to output_fh
    """
    for rec in data_iterator:
        output_fh.write(rec)
        if flush_on_each_record:
            output_fh.flush()


def handle_response(response):
    """
    Correct the response datatype if returned incorrectly
    :response Requests.models.Response: a response from the api
    :return: response ready for consumption from wrapper
    """
    print
    data = response.json()
    if data['err_no'] == 0:
        return data['data']
    else:
        print(data['err_msg'])
        return data['err_msg']


def count_companies(client, db_rid=None, company_identifier=None,
    company_name=None, status=None, zip=None, phone_number=None, fax_number
    =None, website=None, verbose=False):
    """
    Counts Companies with a particular set of optional conditions.

    :param client: Pass the authorised connectwise client object
    :type client: Object
    :param db_rid: Company ID
    :type db_rid: Integer
    :param company_identifier: Company Identifier.
    :type company_identifier: String
    :param company_name:
    :type company_name: String
    :param status:
    :type status: String
    :param zip:
    :type zip: String
    :param phone_number:
    :type phone_number: String
    :param fax_number:
    :type fax_number: String
    :param website:
    :type website: String
    :return: Requests object.

    return.json() - json response of the request.
    return.url - requested URL
    return.status_code - status code fo the request
    """
    conditionstring = ''
    if db_rid:
        conditionstring = client._add_condition(conditionstring, 'id', db_rid)
    if company_identifier:
        conditionstring = client._add_condition(conditionstring,
            'identifier', company_identifier)
    if company_name:
        conditionstring = client._add_condition(conditionstring, 'name',
            company_name)
    if status:
        conditionstring = client._add_condition(conditionstring, 'status',
            status)
    if zip:
        conditionstring = client._add_condition(conditionstring, 'zip', zip)
    if phone_number:
        conditionstring = client._add_condition(conditionstring,
            'phoneNumber', phone_number)
    if fax_number:
        conditionstring = client._add_condition(conditionstring,
            'faxNumber', fax_number)
    if website:
        conditionstring = client._add_condition(conditionstring, 'website',
            website)
    if verbose is True:
        print(conditionstring)
    parameters = {'conditions': conditionstring}
    return client._get('/company/companies/count', parameters=parameters)


@classmethod
def get_fully_qualified_class_path(cls):
    """ This returns the fully qualified class name for this class. This can be used for collection_registry lookup
        """
    return cls.__module__ + '.' + cls.__name__


@classmethod
def from_id(cls, value):
    """Create an instance from an ID or return an existing instance.

        New instances are created with :meth:`~openstack.resource.Resource.new`

        :param value: If ``value`` is an instance of this Resource type,
                      it is returned.
                      If ``value`` is an ID which an instance of this
                      Resource type can be created with, one is created
                      and returned.

        :rtype: :class:`~openstack.resource.Resource` or the
                appropriate subclass.
        :raises: :exc:`ValueError` if ``value`` is not an instance of
                 this Resource type or a valid ``id``.
        """
    return cls._from_attr(cls.id_attribute, value)


def nodesetp(v):
    """Return true iff 'v' is a node-set."""
    if isinstance(v, list):
        return True


def _input_fixer(image_columns, image_path):
    """
    This function turns image_columns into a list of a single element if there is only
    one image column. It also fixes the image path to contain a trailing `/` if the path to the
    directory is missing one.

    Parameters
    ----------
    image_columns : list
        A list of the image column headers

    image_path : str
        Path to the image directory
    """
    if isinstance(image_columns, str):
        image_columns = [image_columns]
    if image_path != '' and image_path[-1] != '/':
        image_path = '{}/'.format(image_path)
    return image_columns, image_path


def fourcc_to_int(value, byteorder='little', signed=False):
    """
    Converts a string of 4 characters into a 32-bit integer using
    the supplied byteorder, signage, and latin1 encoding.

    Returns the encoded int.
    """
    assert len(value
        ) == 4, 'The supplied four character code string must be 4 characters long.'
    return int.from_bytes(bytes(value, encoding='latin1'), byteorder,
        signed=signed)


@classmethod
def get_routing_key_for_task(cls, task_name):
    """Маршрутизирует задачи по очередям.

        Примечание: с аргументами в исходниках и документации все напутано,
            поэтому пришлось подстроиться.

        Args:
            task_name(str): path to task
        """
    from shadow_tasks.settings import shadow_settings
    for routing_key, tasks in shadow_settings.QUEUE_TASKS_MAP.items():
        if task_name in tasks:
            return routing_key
    return shadow_settings.DEFAULT_QUEUE


@classmethod
def reset(cls):
    """
        remove all connections.
        Useful for testing scenarios.

        :return: None
        """
    cls.connections = {}


def gen_words(corpus):
    """Yields each word from the given corpus, must be an iterator over lines
    of strings.
    """
    for line in corpus:
        for word in line.strip().split():
            yield word


def remove_multipolygons(gdf):
    """
    Filters out rows of a geodataframe containing MultiPolygons and GeometryCollections.

    This function is optionally used in geojson2coco. For instance segmentation, where
    objects are composed of single polygons, multi part geometries need to be either removed or
    inspected manually to be resolved as a single geometry.
    """
    mask = (gdf.geom_type == 'MultiPolygon') | (gdf.geom_type ==
        'GeometryCollection')
    if mask.any():
        return gdf.drop(gdf[mask].index).reset_index(drop=True)
    else:
        return gdf


def flux_conv(flux_zeropont, counts_zeropoint):
    """
    Calculate the conversion factor from counts to flux.

    This is done by using the zeropoints of the magnitudes in flux and counts.
    The magnitude should be the same no matter how we calculate it, which is
    how we can derive this:

    .. math::
        \\text{mag}_\\text{flux} = \\text{mag}_\\text{counts}

        -2.5 \\log_{10}(F) + Z_F = -2.5 \\log_{10}(C) + Z_C

        \\text{where $F = $ Flux, $C = $ counts, and $Z_F$ and $Z_C$ represent the respective zeropoints when using flux or counts}

        -2.5(\\log_{10}(F) - \\log_{10}(C)) = Z_C - Z_F

        \\log_{10} \\left( \\frac{F}{C} \\right) = \\frac{Z_F - Z_C}{2.5}

        \\frac{F}{C} = 10^{\\frac{Z_F - Z_C}{2.5}}

        F = C * 10^{\\frac{Z_F - Z_C}{2.5}}

        F = C * \\text{Flux Conversion}

        \\text{where Flux Conversion $= 10^{\\frac{Z_F - Z_C}{2.5}}$}

    This flux conversion is what is calculated here.

    NOTE: Make sure the magnitudes really are the same (ie AB/Vega).

    :param flux_zeropoint: zero point for calculating magnitudes when using
                           flux, such that mag = -2.5 log(flux) +
                           `flux_zeropoint`. The actual value will depend
                           on what flux units you want. If you want
                           microJanskys, use 23.9, for example.
    :type flux_zeropoint: float
    :param counts_zeropoint: zero point for calculating magnitues when using
                             counts, such that mag = -2.5 log(counts) +
                             `counts_zeropoint`. This is often found in the
                             header of the image in question.
    :type counts_zeropoing: float
    :returns: float containing the conversion from counts to flux, such that
              flux = counts * flux_conv. See above for derivation.

    """
    return 10 ** ((flux_zeropont - counts_zeropoint) / 2.5)


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


def ret_v(v):
    """
    Returns a function that return the argument v.

    :param v:
        Object to be returned.
    :type v: object

    :return:
        Function that return the argument v.
    :rtype: function
    """
    return lambda : v


def isFolder(segments):
    """
        Return True if segments points to a folder.
        """


@classmethod
def post_get(cls, f):
    """ decorator to accept POST & GET method """
    return cls._accept_method(['POST', 'GET'], f)


def ensuremod(_larch, modname=None):
    """ensure that a group exists"""
    if _larch is not None:
        symtable = _larch.symtable
        if modname is not None and not symtable.has_group(modname):
            symtable.newgroup(modname)
        return symtable


def out_16(library, session, space, offset, data, extended=False):
    """Write in an 16-bit value from the specified memory space and offset.

    Corresponds to viOut16* functions of the VISA library.

    :param library: the visa library wrapped by ctypes.
    :param session: Unique logical identifier to a session.
    :param space: Specifies the address space. (Constants.*SPACE*)
    :param offset: Offset (in bytes) of the address or register from which to read.
    :param data: Data to write to bus.
    :param extended: Use 64 bits offset independent of the platform.
    :return: return value of the library call.
    :rtype: :class:`pyvisa.constants.StatusCode`
    """
    if extended:
        return library.viOut16Ex(session, space, offset, data, extended=False)
    else:
        return library.viOut16(session, space, offset, data, extended=False)


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

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

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

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


def wave_period_tf(frequency):
    """Usage: Calculate wave period (T) using frequency (f)"""
    return 1 / frequency


def getPath(obj):
    """Returns a string representing the physical path to the object.
        """


def _group_flat_tags(tag, tags):
    """Extract tags sharing the same name as the provided tag. Used to collect
    options for radio and checkbox inputs.

    :param Tag tag: BeautifulSoup tag
    :param list tags: List of tags
    :return: List of matching tags

    """
    grouped = [tag]
    name = tag.get('name', '').lower()
    while tags and tags[0].get('name', '').lower() == name:
        grouped.append(tags.pop(0))
    return grouped


def addActions(target, actions):
    """
    Module function to add a list of actions to a widget.

    @param target reference to the target widget (QWidget)
    @param actions list of actions to be added to the target. A
        None indicates a separator (list of QActions)
    """
    if target is None:
        return
    for action in actions:
        if action is None:
            target.addSeparator()
        else:
            target.addAction(action)


def are_instances(lhs, rhs, cls):
    """Return True if both lhs and rhs are instances of cls; False otherwise
    """
    return isinstance(lhs, cls) and isinstance(rhs, cls)


def _density_factor(density_units_in, density_units_out):
    """helper method for convert_density"""
    factor = 1.0
    if density_units_in == 'slug/ft^3':
        pass
    elif density_units_in == 'slinch/in^3':
        factor *= 12 ** 4
    elif density_units_in == 'kg/m^3':
        factor /= 515.378818
    else:
        msg = ('density_units_in=%r is not valid; use [slug/ft^3]' %
            density_units_in)
        raise RuntimeError(msg)
    if density_units_out == 'slug/ft^3':
        pass
    elif density_units_out == 'slinch/in^3':
        factor /= 12 ** 4
    elif density_units_out == 'kg/m^3':
        factor *= 515.378818
    else:
        msg = (
            'density_units_out=%r is not valid; use [slug/ft^3, slinch/in^3]' %
            density_units_out)
        raise RuntimeError(msg)
    return factor


def hide_fields_in_newer_versions(obj):
    """This method hides fields that were added in newer API versions.

    Certain node fields were introduced at certain API versions.
    These fields are only made available when the request's API version
    matches or exceeds the versions when these fields were introduced.
    """
    pass


def _Real(parent, hasProps, propObj, propVal, **kwargs):
    """Creates and returns a widget allowing the user to edit the given
    :class:`.Real` property value. See the :func:`.widgets_number._Number`
    function for more details.

    See the :func:`_String` documentation for details on the parameters.
    """
    from fsleyes_props.widgets_number import _Number
    return _Number(parent, hasProps, propObj, propVal, **kwargs)


def ispartial(x):
    """
    If log line starts with a space it is recognized as a partial line

    >>> ispartial('<time> <event> <some_log_line>')
    False
    >>> ispartial(' <space> <traceback:> <some_line>')
    True
    >>> ispartial('         <tab> <traceback:> <some_line>')
    True
    >>> ispartial('   <white_space> <traceback:> <some_line>')
    True
    >>> ispartial('')
    False
    """
    spaces = ' ', '\t', '\n'
    try:
        if x[0] in spaces:
            return True
    except IndexError:
        return False
    else:
        return False


@classmethod
def paragraph_containing(cls, text):
    """Returns an XPath to find an HTML <p> that contains the text in `text`."""
    return cls('//p[contains(node(), "%s")]' % text)


def is_preprint(r):
    """
    Return whether the link is an arXiv preprint
    """
    ans = False
    journal = r.get('journal', None)
    if journal is not None:
        if 'arxiv' in r['journal'].lower():
            ans = True
    else:
        return True
    adsurl = r.get('adsurl', None)
    if adsurl is not None:
        if 'arxiv' in adsurl.lower() or 'astro.ph' in adsurl:
            ans = True
    return ans


def underline(line, underline='~'):
    """Return an underline string for ``line``.

    Intended for use with level 3 and lower headings.

    Note that the default for ``underline`` assumes that the level
    1 and 2 underlines are the standard ``=`` and ``-``. You can
    pass a different underline character to this function if needed.
    """
    if line.endswith('\n'):
        line = line[:-1]
    return '{}\n'.format(underline * len(line))


def renderNone(v):
    """util function render none"""
    return '' if not v else v


def armature_add(radius: float=1.0, view_align: bool=False, enter_editmode:
    bool=False, location: float=(0.0, 0.0, 0.0), rotation: float=(0.0, 0.0,
    0.0), layers: bool=(False, False, False, False, False, False, False,
    False, False, False, False, False, False, False, False, False, False,
    False, False, False)):
    """Add an armature object to the scene

    :param radius: Radius
    :type radius: float
    :param view_align: Align to View, Align the new object to the view
    :type view_align: bool
    :param enter_editmode: Enter Editmode, Enter editmode when adding this object
    :type enter_editmode: bool
    :param location: Location, Location for the newly added object
    :type location: float
    :param rotation: Rotation, Rotation for the newly added object
    :type rotation: float
    :param layers: Layer
    :type layers: bool
    """
    pass


def _unitary(norm):
    """_unitary() utility copied from numpy"""
    if norm not in (None, 'ortho'):
        raise ValueError(
            'Invalid norm value %s, should be None or "ortho".' % norm)
    return norm is not None


def car(obj):
    """
    Alias of ``obj[0]``.

    >>> car(loads('(a . b)'))
    Symbol('a')
    >>> car(loads('(a b)'))
    Symbol('a')

    """
    return obj[0]


def _check(isamAppliance, certificate, password):
    """
    TODO replace placeholder
    requires additionally pyOpenSSL to load the p12 and extract the issuer, subject, etc
    """
    return False


def pick(seq, func, maxobj=None):
    """Picks the object obj where func(obj) has the highest value."""
    maxscore = None
    for obj in seq:
        score = func(obj)
        if maxscore is None or maxscore < score:
            maxscore, maxobj = score, obj
    return maxobj


def scale_wind_speed(spd, scale_factor: float):
    """
    Scales wind speed by the scale_factor

    :param spd: Series or data frame or a single value of wind speed to scale
    :param scale_factor: Scaling factor in decimal, if scaling factor is 0.8 output would be (1+0.8) times wind speed,
    if it is -0.8 the output would be (1-0.8) times the wind speed
    :return: Series or data frame with scaled wind speeds

    """
    return spd * scale_factor


def email_chk(val):
    """Function to detect the validity email"""
    import re
    regex = '^\\w+([\\.-]?\\w+)*@\\w+([\\.-]?\\w+)*(\\.\\w{2,3})+$'
    c = 0
    if re.search(regex, val):
        return 'Valid'
    else:
        return 'Not Valid'


@classmethod
def tearDownClass(cls):
    """Hook method for deconstructing the class fixture after running all tests in the class."""


def legendre_symbol(a, p):
    """ Compute the Legendre symbol a|p using
    Euler's criterion. p is a prime, a is
    relatively prime to p (if p divides
    a, then a|p = 0)

    Returns 1 if a has a square root modulo
    p, -1 otherwise.
    """
    ls = pow(a, (p - 1) // 2, p)
    return -1 if ls == p - 1 else ls


def getindex(object, index):
    """Returns the value at the specified index. This is provided for
    symmetry with setindex().

    """
    return object[index]


@staticmethod
def isolate(obj):
    """Feed a standard semantic object in and receive a simple list of
        lemmata
        """
    answers = []
    for token in obj:
        lemmata = token[1]
        for pair in lemmata:
            answers.append(pair[0])
    return answers


def rankwithlist(l, lwith, test=False):
    """
    rank l wrt lwith
    """
    if not (isinstance(l, list) and isinstance(lwith, list)):
        l, lwith = list(l), list(lwith)
    from scipy.stats import rankdata
    if test:
        print(l, lwith)
        print(rankdata(l), rankdata(lwith))
        print(rankdata(l + lwith))
    return rankdata(l + lwith)[:len(l)]


def wait(seconds):
    """
    Use this if you want your program wait for a certain time.
    Example:
        wait(3)
        ==> "Nothing happen and there will be no calculation for 3 seconds"
    """
    import time
    time.sleep(seconds)


def text_copy():
    """Copy selected text to clipboard

    """
    pass


def update_ldap_secured(apps, schema_editor):
    """Update ldap_secured settings."""
    LocalConfig = apps.get_model('core', 'LocalConfig')
    lc = LocalConfig.objects.first()
    if lc is None or 'ldap_secured' not in lc._parameters:
        return
    if lc._parameters['ldap_secured']:
        lc._parameters['ldap_secured'] = 'ssl'
    else:
        lc._parameters['ldap_secured'] = 'none'
    lc.save(update_fields=['_parameters'])


def shareable_parameters(cells):
    """Return parameter names if the parameters are shareable among cells.

    Parameters are shareable among multiple cells when all the cells
    have the parameters in the same order if they ever have any.

    For example, if cells are foo(), bar(x), baz(x, y), then
    ('x', 'y') are shareable parameters amounts them, as 'x' and 'y'
    appear in the same order in the parameter list if they ever appear.

    Args:
        cells: An iterator yielding cells.

    Returns:
        None if parameters are not share,
        tuple of shareable parameter names,
        () if cells are all scalars.
    """
    result = []
    for c in cells.values():
        params = c.formula.parameters
        for i in range(min(len(result), len(params))):
            if params[i] != result[i]:
                return None
        for i in range(len(result), len(params)):
            result.append(params[i])
    return result


def outside(s, key, lower=0.0, upper=0.0):
    """Determine if value falls outside upper and lower bounds."""
    v = key(s)
    return v < lower or v > upper


def _time_independent_equals(a, b):
    """
    This compares two values in constant time.

    Taken from tornado:

    https://github.com/tornadoweb/tornado/blob/
    d4eb8eb4eb5cc9a6677e9116ef84ded8efba8859/tornado/web.py#L3060

    """
    if len(a) != len(b):
        return False
    result = 0
    if isinstance(a[0], int):
        for x, y in zip(a, b):
            result |= x ^ y
    else:
        for x, y in zip(a, b):
            result |= ord(x) ^ ord(y)
    return result == 0


@staticmethod
def mm(x, km, vmax):
    """Static method for calculation of Michaelis-Menten function at given x"""
    return vmax * x / (km + x)


def _has_method(arg, method):
    """Returns true if the given object has a method with the given name.

    :param arg: the object

    :param method: the method name
    :type method: string

    :rtype: bool
    """
    return hasattr(arg, method) and callable(getattr(arg, method))


def unlooked_images(request, inst):
    """Generate the page listing all unlooked images in the database

    Parameters
    ----------
    request : HttpRequest object
        Incoming request from the webpage
    inst : str
        Name of JWST instrument

    Returns
    -------
    HttpResponse object
        Outgoing response sent to the webpage
    """
    pass


def renderability_toggle():
    """Toggle the renderability of selected items

    """
    pass


def to_bool(value):
    """Converts 'something' to boolean. Raises exception for invalid formats
    Possible True  values: 1, True, "1", "TRue", "yes", "y", "t"
    Possible False values: 0, False, None, [], {}, "", "0", "faLse", "no", "n", "f", 0.0, ..."""
    if value is None:
        return False
    if str(value).lower() in ('yes', 'y', 'true', 't', '1'):
        return True
    if str(value).lower() in ('no', 'n', 'false', 'f', '0', '0.0', '',
        'none', '[]', '{}'):
        return False
    raise Exception('Invalid value for boolean conversion: ' + str(value))


def print_info(stdscr, message):
    """
    Prints the provided message on the next to last line.
    """
    max_yx = stdscr.getmaxyx()
    stdscr.addstr(max_yx[0] - 2, 1, message)


def filter_duplicate_key(line, message, line_number, marked_line_numbers,
    source, previous_line=''):
    """Return '' if first occurrence of the key otherwise return `line`."""
    if marked_line_numbers and line_number == sorted(marked_line_numbers)[0]:
        return ''
    return line


@staticmethod
def _to_timestamp(datetime):
    """convert datetime to unix timestamp in python2 compatible manner."""
    try:
        return datetime.timestamp()
    except AttributeError:
        return int(datetime.strftime('%s'))


def has_dupes(sequence, target):
    """Given a sequence and search object, return True if there's more
    than one, False if zero or one of them.

    """
    c = 0
    for item in sequence:
        if item is target:
            c += 1
            if c > 1:
                return True
    return False


def demean_image(in_file, in_mask=None, out_file=None):
    """
    Demean image data inside mask
    """
    import numpy as np
    import nibabel as nb
    import os.path as op
    import math
    if out_file is None:
        fname, fext = op.splitext(op.basename(in_file))
        if fext == '.gz':
            fname, _ = op.splitext(fname)
        out_file = op.abspath('./%s_demean.nii.gz' % fname)
    im = nb.load(in_file)
    data = im.get_data().astype(np.float32)
    msk = np.ones_like(data)
    if in_mask is not None:
        msk = nb.load(in_mask).get_data().astype(np.float32)
        msk[msk > 0] = 1.0
        msk[msk < 1] = 0.0
    mean = np.median(data[msk == 1].reshape(-1))
    data[msk == 1] = data[msk == 1] - mean
    nb.Nifti1Image(data, im.affine, im.header).to_filename(out_file)
    return out_file


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 attributes_desc():
    """
    return list of column descriptions
    5_o_Clock_Shadow Arched_Eyebrows Attractive Bags_Under_Eyes Bald Bangs
    Big_Lips Big_Nose Black_Hair Blond_Hair Blurry Brown_Hair Bushy_Eyebrows
    Chubby Double_Chin Eyeglasses Goatee Gray_Hair Heavy_Makeup High_Cheekbones
    Male Mouth_Slightly_Open Mustache Narrow_Eyes No_Beard Oval_Face Pale_Skin
    Pointy_Nose Receding_Hairline Rosy_Cheeks Sideburns Smiling Straight_Hair Wavy_Hair
    Wearing_Earrings Wearing_Hat Wearing_Lipstick Wearing_Necklace Wearing_Necktie Young

    :return: list[str]
    """
    columns = ['5_o_Clock_Shadow', 'Arched_Eyebrows', 'Attractive',
        'Bags_Under_Eyes', 'Bald', 'Bangs', 'Big_Lips', 'Big_Nose',
        'Black_Hair', 'Blond_Hair', 'Blurry', 'Brown_Hair',
        'Bushy_Eyebrows', 'Chubby', 'Double_Chin', 'Eyeglasses', 'Goatee',
        'Gray_Hair', 'Heavy_Makeup', 'High_Cheekbones', 'Male',
        'Mouth_Slightly_Open', 'Mustache', 'Narrow_Eyes', 'No_Beard',
        'Oval_Face', 'Pale_Skin', 'Pointy_Nose', 'Receding_Hairline',
        'Rosy_Cheeks', 'Sideburns', 'Smiling', 'Straight_Hair', 'Wavy_Hair',
        'Wearing_Earrings', 'Wearing_Hat', 'Wearing_Lipstick',
        'Wearing_Necklace', 'Wearing_Necktie', 'Young']
    return map(str.lower, columns)


def describe_record(AcceptLanguage=None, Id=None, PageToken=None, PageSize=None
    ):
    """
    Retrieves a paginated list of the full details of a specific request. Use this operation after calling a request operation ( ProvisionProduct ,  TerminateProvisionedProduct , or  UpdateProvisionedProduct ).
    See also: AWS API Documentation

    :example: response = client.describe_record(
        AcceptLanguage='string',
        Id='string',
        PageToken='string',
        PageSize=123
    )

    :type AcceptLanguage: string
    :param AcceptLanguage: The language code to use for this operation. Supported language codes are as follows:
            'en' (English)
            'jp' (Japanese)
            'zh' (Chinese)
            If no code is specified, 'en' is used as the default.

    :type Id: string
    :param Id: [REQUIRED]
            The record identifier of the ProvisionedProduct object for which to retrieve output information. This is the RecordDetail.RecordId obtained from the request operation's response.

    :type PageToken: string
    :param PageToken: The page token of the first page retrieved. If null, this retrieves the first page of size PageSize .

    :type PageSize: integer
    :param PageSize: The maximum number of items to return in the results. If more results exist than fit in the specified PageSize , the value of NextPageToken in the response is non-null.

    :rtype: dict
    :return: {
        'RecordDetail': {
            'RecordId': 'string',
            'ProvisionedProductName': 'string',
            'Status': 'IN_PROGRESS'|'SUCCEEDED'|'ERROR',
            'CreatedTime': datetime(2015, 1, 1),
            'UpdatedTime': datetime(2015, 1, 1),
            'ProvisionedProductType': 'string',
            'RecordType': 'string',
            'ProvisionedProductId': 'string',
            'ProductId': 'string',
            'ProvisioningArtifactId': 'string',
            'PathId': 'string',
            'RecordErrors': [
                {
                    'Code': 'string',
                    'Description': 'string'
                },
            ],
            'RecordTags': [
                {
                    'Key': 'string',
                    'Value': 'string'
                },
            ]
        },
        'RecordOutputs': [
            {
                'OutputKey': 'string',
                'OutputValue': 'string',
                'Description': 'string'
            },
        ],
        'NextPageToken': 'string'
    }

    """
    pass


def var(array, *args, **kwargs):
    """
    Computes the variance.

    See Also
    --------
    Array.var
    """
    return array.var(*args, **kwargs)


def mutant_to_str(pos, stdvariant, variant, gap_string='-'):
    """Parse mutant to string

    Return HGVS-like format:

    (109, A, G) -> 109A>G
    (200, T, -) -> 200delT
    (360, -, C) -> 360insC
    (450, A, A) -> 450A=A

    Args:
    pos -- position
    stdvariant -- variant of standard sequence
    variant -- variant of align sequence
    gap_string -- a string represent a gap, default '-'

    """
    if stdvariant == variant:
        return '{}{}={}'.format(pos, stdvariant, variant)
    if stdvariant == gap_string:
        mut = '{}ins{}'.format(pos, variant)
    elif variant == gap_string:
        mut = '{}del{}'.format(pos, stdvariant)
    else:
        mut = '{}{}>{}'.format(pos, stdvariant, variant)
    return mut


def correct_bounding_box_list_for_nonzero_origin(bbox_list, full_box_list):
    """The bounding box calculated from an image has coordinates relative to the
    lower-left point in the PDF being at zero.  Similarly, Ghostscript reports a
    bounding box relative to a zero lower-left point.  If the MediaBox (or full
    page box) has been shifted, like when cropping a previously cropped
    document, then we need to correct the bounding box by an additive
    translation on all the points."""
    corrected_box_list = []
    for bbox, full_box in zip(bbox_list, full_box_list):
        left_x = full_box[0]
        lower_y = full_box[1]
        corrected_box_list.append([bbox[0] + left_x, bbox[1] + lower_y,
            bbox[2] + left_x, bbox[3] + lower_y])
    return corrected_box_list


@staticmethod
def _d2s(kvp):
    """Parse dictionary to list of colon-separated address and port.

        :param kvp: dictionary
        :returns: list of colon-separated address and port
        """
    result = []
    for key_val in kvp:
        result.append('%s:%s' % (key_val['address'], key_val['port']))
    return result


def template_name(model, template_name_suffix):
    """
    Given a model and a template name suffix, return the resulting template
    path::

        >>> template_name(Article, "_detail")
        "articles/article_detail.html"
        >>> template_name(User, "_form")
        "auth/user_form.html"
    """
    return '%s/%s%s.html' % (model._meta.app_label, model._meta.model_name,
        template_name_suffix)


def purchase_reserved_node_offering(ReservedNodeOfferingId=None, NodeCount=None
    ):
    """
    Allows you to purchase reserved nodes. Amazon Redshift offers a predefined set of reserved node offerings. You can purchase one or more of the offerings. You can call the  DescribeReservedNodeOfferings API to obtain the available reserved node offerings. You can call this API by providing a specific reserved node offering and the number of nodes you want to reserve.
    For more information about reserved node offerings, go to Purchasing Reserved Nodes in the Amazon Redshift Cluster Management Guide .
    See also: AWS API Documentation

    :example: response = client.purchase_reserved_node_offering(
        ReservedNodeOfferingId='string',
        NodeCount=123
    )

    :type ReservedNodeOfferingId: string
    :param ReservedNodeOfferingId: [REQUIRED]
            The unique identifier of the reserved node offering you want to purchase.

    :type NodeCount: integer
    :param NodeCount: The number of reserved nodes that you want to purchase.
            Default: 1

    :rtype: dict
    :return: {
        'ReservedNode': {
            'ReservedNodeId': 'string',
            'ReservedNodeOfferingId': 'string',
            'NodeType': 'string',
            'StartTime': datetime(2015, 1, 1),
            'Duration': 123,
            'FixedPrice': 123.0,
            'UsagePrice': 123.0,
            'CurrencyCode': 'string',
            'NodeCount': 123,
            'State': 'string',
            'OfferingType': 'string',
            'RecurringCharges': [
                {
                    'RecurringChargeAmount': 123.0,
                    'RecurringChargeFrequency': 'string'
                },
            ]
        }
    }

    :returns:
    pending-payment-This reserved node has recently been purchased, and the sale has been approved, but payment has not yet been confirmed.
    active-This reserved node is owned by the caller and is available for use.
    payment-failed-Payment failed for the purchase attempt.

    """
    pass


def looks_like_issubclass(obj, classname):
    """ Return True if the object has a class or superclass with the given
    class name.

    Ignores old-style classes.
    """
    t = obj
    if t.__name__ == classname:
        return True
    for klass in t.__mro__:
        if klass.__name__ == classname:
            return True
    return False


def keying_set_remove():
    """Remove the active Keying Set

    """
    pass


def provides_facts():
    """
    Returns a dictionary keyed on the facts provided by this module. The value
    of each key is the doc string describing the fact.
    """
    return {'current_re':
        "A list of internal routing instance hostnames for the current RE. These hostnames identify things like the RE's slot ('re0' or 're1'), the RE's mastership state ('master' or 'backup'), and node in a VC ('member0' or 'member1')"
        }


def ndarray(typed_array, shape, dtype):
    """Return a ndarray."""
    _dtype = type(typed_array)
    if dtype and dtype != _dtype:
        raise Exception("dtype doesn't match the type of the array: " +
            _dtype + ' != ' + dtype)
    shape = shape or (len(typed_array),)
    return {'__jailed_type__': 'ndarray', '__value__': typed_array,
        '__shape__': shape, '__dtype__': _dtype}


def tf_core_stop_word_sets(input_dict):
    """
    Returns array of stop words for the selected language
    :param language: Language of returned stop words.

    :returns stop_word_tagger: Array of stop words for the selected language.
    """
    return {'stop_words': ['i', 'me', 'my', 'myself', 'we', 'our', 'ours',
        'ourselves', 'you', 'your', 'yours', 'yourself', 'yourselves', 'he',
        'him', 'his', 'himself', 'she', 'her', 'hers', 'herself', 'it',
        'its', 'itself', 'they', 'them', 'their', 'theirs', 'themselves',
        'what', 'which', 'who', 'whom', 'this', 'that', 'these', 'those',
        'am', 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have',
        'has', 'had', 'having', 'do', 'does', 'did', 'doing', 'would',
        'should', 'could', 'ought', "i'm", "you're", "he's", "she's",
        "it's", "we're", "they're", "i've", "you've", "we've", "they've",
        "i'd", "you'd", "he'd", "she'd", "we'd", "they'd", "i'll", "you'll",
        "he'll", "she'll", "we'll", "they'll", "isn't", "aren't", "wasn't",
        "weren't", "hasn't", "haven't", "hadn't", "doesn't", "don't",
        "didn't", "won't", "wouldn't", "shan't", "shouldn't", "can't",
        'cannot', "couldn't", "mustn't", "let's", "that's", "who's",
        "what's", "here's", "there's", "when's", "where's", "why's",
        "how's", 'a', 'an', 'the', 'and', 'but', 'if', 'or', 'because',
        'as', 'until', 'while', 'of', 'at', 'by', 'for', 'with', 'about',
        'against', 'between', 'into', 'through', 'during', 'before',
        'after', 'above', 'below', 'to', 'from', 'up', 'down', 'in', 'out',
        'on', 'off', 'over', 'under', 'again', 'further', 'then', 'once',
        'here', 'there', 'when', 'where', 'why', 'how', 'all', 'any',
        'both', 'each', 'few', 'more', 'most', 'other', 'some', 'such',
        'no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than', 'too', 'very']
        }


@classmethod
def at(cls, time):
    """
        The probable activity at given time.
        """
    for activity in cls:
        if activity.value.is_current(time):
            return activity.value


@classmethod
def from_extent(cls, extent, origin):
    """Create a rectangle, knowing its upper left origin, and
        spatial extension

        :type extent: Stretch
        :type origin: Point
        :return: a Point instance
        """
    inst = cls()
    inst._extent = extent
    inst._origin = origin
    return inst


def coupon_identify_customer(customer, address, document):
    """ Identify the customer.  This method doesn't have mandatory
        execution (you can identify the customer only if you like), but when
        executed it must be called before calling any method.

        @param customer:
        @type customer:   str

        @param address:
        @type address:    str

        @param document:
        @type document:   str
        """


def more_info():
    """Human-readable string to help the user.

        Should describe the steps taken and any relevant info to help the user
        decide which plugin to use.

        :rtype str:

        """


def pristinemethod(func):
    """
    A decorator for handling pristine settings like callables.

    Use it like this::

        from configurations import Configuration, pristinemethod

        class Develop(Configuration):

            @pristinemethod
            def USER_CHECK(user):
                return user.check_perms()

            GROUP_CHECK = pristinemethod(lambda user: user.has_group_access())

    """
    func.pristine = True
    return staticmethod(func)


def get_name_from_fq_name(name):
    """
    Given a fully-qualified name, get the name part.
    It's the sequence of characters before the last "." in the name.

    Return None if malformed

    >>> get_name_from_fq_name('abc.def')
    'abc'
    >>> get_name_from_fq_name('abc.def.ghi')
    'abc.def'
    >>> get_name_from_fq_name('abc')
    """
    if '.' not in name:
        return None
    return '.'.join(name.split('.')[:-1])


@classmethod
def create_endpoint_group(cls, name, type, endpoints):
    """Wrapper utility that returns a test ipsec policy."""
    body = cls.client.create_endpoint_group(endpoints=endpoints, type=type,
        description='endpoint type:' + type, name=name)
    endpoint_group = body['endpoint_group']
    cls.endpoint_groups.append(endpoint_group)
    return endpoint_group


def whitespace_tokenize(text):
    """Runs basic whitespace cleaning and splitting on a piece of text."""
    text = text.strip()
    if not text:
        return []
    tokens = text.split()
    return tokens


@classmethod
def ebv(cls, coords, dustmap='SFD', hires=False):
    """
        E(B - V) in the line-of-sight of `coords`.

        Parameters
        ----------
        coords : ``SkyCoord``
            Astropy SkyCoord object with the line-of-sight coordinates.
        nhmap : ``str``, optional
            Name of the dust survey. Use ``show_maps`` method
            to see a list of all available maps. Defaults to 'SFD'.
        hires : ``boolean``, optional
            Use high resolution map. If the map is not available locally,
            it is downloaded. Defaults to `False`.

        Returns
        -------
        ebv : ``float`` or ``numpy.ndarray``
            Float, or numpy array with shape like `coords`.
        """
    ebv_hpmap, nside, order = cls._load_map(dustmap, hires=hires)
    ebv = cls._interpolate(coords, ebv_hpmap, nside, order)
    return ebv


def copy_struct(dst, src, repl={}):
    """
    Copy structure from *src* to *dst* with replacement from *repl*.
    """
    repl = repl.copy()
    for k in src._datamodel._fields:
        v = repl.pop(k, getattr(src, k))
        setattr(dst, k, v)
    for k, v in repl.items():
        setattr(dst, k, v)
    return dst


def range_degrees(degrees):
    """
    Put angle into range [0, 360].

    Param: degrees - large angle (float degrees)

    Returns: angle in range (float degrees)
    """
    return degrees % 360.0


def is_data(value):
    """Return whether the value is a wrapped data descriptor."""
    return value is not None and value.is_data


def generate_tclloader_deps(platform):
    """
    Generate platform-specific file names.

    :param platform: Platform type (i.e. subdirectory of target/product).
    :type platform: str
    """
    if platform == 'bbry_qc8953':
        oems = ['oem_att', 'oem_china', 'oem_common', 'oem_sprint',
            'oem_vzw', 'oem_indonesia', 'oem_russia']
        radios = ['china', 'dschina', 'emea', 'global', 'india', 'japan', 'usa'
            ]
    elif platform == 'bbry_qc8953krypton':
        oems = ['oem_att', 'oem_common', 'oem_sprint', 'oem_russia']
        radios = ['americas', 'cdma', 'dscn', 'dsglobal', 'ssglobal']
    elif platform == 'bbry_sdm660':
        oems = ['oem_att', 'oem_china', 'oem_common', 'oem_india',
            'oem_indonesia', 'oem_sprint', 'oem_russia', 'oem_eea', 'oem_b2b']
        radios = ['americas', 'cn', 'dsglobal', 'dsjapan', 'global', 'japan']
    elif platform == 'bbry_sdm636':
        oems = ['oem_china', 'oem_common', 'oem_india', 'oem_russia',
            'oem_eea', 'oem_b2b']
        radios = ['americas', 'dsamericas', 'global', 'dsglobal', 'dscn']
    return oems, radios


def deleteSecContext(context, output_needed=False):
    """
    Releases a security context

    This method releases a security context, potentially providing an
    output buffer as the result

    :param context: the context to be released
    :param bool output_needed: is an output_buffer desired?
    :rtype: bytes or None
    :returns: an output token, if requested (otherwise None)
    """


def generate_batches(num_records, batch_size):
    """Generate batch size list for splitting a number of tasks into batch jobs.

    Given a number of records to split up, and a batch size, generate a
    stream of batchsize, index pairs"""
    num_batches = num_records // batch_size + 1
    for i in range(0, num_batches):
        if i == num_batches - 1:
            batch_size = num_records - batch_size * i
        if batch_size > 0:
            yield batch_size, i


def is_attr_protected(attrname: str) ->bool:
    """return True if attribute name is protected (start with _ and some other
    details), False otherwise.
    """
    return attrname[0] == '_' and attrname != '_' and not (attrname.
        startswith('__') and attrname.endswith('__'))


def add_resource_routes(config, route_name, resource_class, path):
    """
    Add routes to the config for a resource_class and path.
    We also add a route for no method passed.
    """
    config.add_route(name=route_name, pattern='/%s/{method}' % path,
        factory=resource_class)
    config.add_route(name=route_name + '.nomethod', pattern='/%s' % path,
        factory=resource_class)


def getRestPolefigDerv(HKL, Grid, SHCoeff):
    """default doc string

    :param type name: description

    :returns: type name: description

    """
    pass


@staticmethod
def _check_limits(ypos, xpos):
    """Checks if the user has passed some coordinate y / x greater than that existing in the mainframe
        """
    if int(ypos) > 24:
        raise Exception(
            'You have exceeded the y-axis limit of the mainframe screen')
    if int(xpos) > 80:
        raise Exception(
            'You have exceeded the x-axis limit of the mainframe screen')


def register(roomJID, options):
    """
        Send a request to register for a room.

        @param roomJID: The bare JID of the room.
        @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>}

        @param options: A mapping of field names to values, or C{None} to
            cancel.
        @type options: C{dict}
        """


def connect2(s1, s2, p):
    """
	Connects 2 state objects with a given probability.

	Parameters
	----------
	+ s1 `State` state 1
	+ s2 `State` state 2
	+ p  `float` transition probability
	"""
    s1.next[s2.name] = p


@classmethod
def bgred(cls, string, auto=False):
    """Color-code entire string.

        :param str string: String to colorize.
        :param bool auto: Enable auto-color (dark/light terminal).

        :return: Class instance for colorized string.
        :rtype: Color
        """
    return cls.colorize('bgred', string, auto=auto)


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 rm(ren, actor):
    """ Remove a specific actor
    """
    ren.RemoveActor(actor)


@classmethod
def all(klass):
    """
        Get all instances of the given class in the database.  Note that this is the
        equivalent of calling L{find} with no arguments.

        @return: A C{Deferred} which returns the following to a callback:
        A C{list} containing all of the instances in the database.
        """
    return klass.find()


@classmethod
def create(cls, five9, data, refresh=False):
    """Create a record on Five9.

        Args:
            five9 (five9.Five9): The authenticated Five9 remote.
            data (dict): A data dictionary that can be fed to ``deserialize``.
            refresh (bool, optional): Set to ``True`` to get the record data
                from Five9 before returning the record.

        Returns:
            BaseModel: The newly created record. If ``refresh`` is ``True``,
                this will be fetched from Five9. Otherwise, it's the data
                record that was sent to the server.
        """
    raise NotImplementedError()


def fixSlices(slices):
    """A convenience function used by :meth:`selectByValue`,
    :meth:`clearSelection` and :meth:`getIndices`, to sanitise their
    ``restrict`` parameter.
    """
    if slices is None:
        slices = [None, None, None]
    if len(slices) != 3:
        raise ValueError('Three slice objects are required')
    for i, s in enumerate(slices):
        if s is None:
            slices[i] = slice(None)
    return tuple(slices)


def backslashreplace_while_decoding(decoding_error):
    """Replacement for the backslashreplace error handler on Python <3.5."""
    if not isinstance(decoding_error, UnicodeDecodeError):
        raise TypeError(
            'backslashreplace_while_decoding error handler can only be used for decoding'
            )
    repl = '\\' + hex(decoding_error.object[decoding_error.start])[1:]
    return repl, decoding_error.end


def display_fully_qualified(repo_list, list_content, display_callback):
    """Display installed collections in a format more or less like they would be referenced in a playbook"""
    INDENT = ' '
    for repo_item in repo_list:
        repo_msg = '{installed_repository.repository_spec.ns_n_v}'
        display_callback(repo_msg.format(**repo_item))
        if not list_content:
            continue
        for content_item_type_key, content_items_data in repo_item[
            'content_items'].items():
            content_type_msg = '{indent:2}- {content_item_type}'.format(
                content_item_type=content_item_type_key, indent=INDENT)
            display_callback(content_type_msg)
            content_msg = (
                '{indent:4}- {installed_repository.repository_spec.label}.{name}'
                )
            for content_item_data in content_items_data:
                content_item_data['indent'] = INDENT
                display_callback(content_msg.format(**content_item_data))
                if content_item_data['is_plugin']:
                    python_path_msg = (
                        '{indent:6}- (python path) ansible_collections.{installed_repository.repository_spec.label}.plugins.{type}.{name}'
                        )
                    content_item_data['indent'] = INDENT
                    display_callback(python_path_msg.format(**
                        content_item_data))


def generate_epochs(delorean, direction, unit, count):
    """ Generates epochs from a shifted Delorean instance

    Args:
        delorean: Delorean datetime instance to shift from.
        direction: String to shift time forwards or backwards.
            Valid values: 'last', 'next'.
        unit: String of time period unit for count argument.
            What unit in direction should be shifted?
            Valid values: 'hour', 'day', 'week', 'month', 'year'.
        count: Int of units.
            How many units to shift in direction?

    Returns:
        Generator of count int epochs in UTC from a shifted Delorean
    """
    for shift in range(count):
        yield int(delorean._shift_date(direction, unit, shift).epoch)


def nextpower2(i):
    """ Find 2^n that is equal to or greater than. """
    n = 1
    while n < i:
        n *= 2
    return n


def _interpret_output_mode(arg, default='interactive'):
    """
      >>> _interpret_output_mode('Repr_If_Not_None')
      'repr-if-not-none'
    """
    if arg is None:
        arg = default
    rarg = str(arg).strip().lower().replace('-', '').replace('_', '')
    if rarg in ['none', 'no', 'n', 'silent']:
        return 'silent'
    elif rarg in ['interactive', 'i']:
        return 'interactive'
    elif rarg in ['print', 'p', 'string', 'str']:
        return 'str'
    elif rarg in ['repr', 'r']:
        return 'repr'
    elif rarg in ['pprint', 'pp']:
        return 'pprint'
    elif rarg in ['reprifnotnone', 'reprunlessnone', 'rn']:
        return 'repr-if-not-none'
    elif rarg in ['pprintifnotnone', 'pprintunlessnone', 'ppn']:
        return 'pprint-if-not-none'
    elif rarg in ['systemexit', 'exit', 'raise']:
        return 'exit'
    else:
        raise ValueError(
            'Invalid output=%r; expected one of silent/interactive/str/repr/pprint/repr-if-not-none/pprint-if-not-none/exit'
             % (arg,))


def _len_struct(obj):
    """Struct length in bytes.
    """
    try:
        return obj.size
    except AttributeError:
        return 0


def selectGroup(df):
    """ To select a specific group.
	"""
    print('[trim]selecting a group...')
    return df[() & ()]


def capabilities():
    """Obtain capabilities of the peer.

        Returns a set of string capabilities.
        """


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

        :param es_major: major version of Elasticsearch, as string
        :returns:        dictionary with a key, 'items', with the mapping
        """
    mapping = """
        {
            "properties": {
                "description_analyzed": {
                    "type": "text",
                    "index": true
                },
                "comment": {
                    "type": "text",
                    "index": true
                },
                "venue_geolocation": {
                    "type": "geo_point"
                },
                "group_geolocation": {
                    "type": "geo_point"
                }
           }
        } """
    return {'items': mapping}


def get_session_key(request, key, default=None):
    """
    Gets django sessions request key
    :param request:
    :param key:
    :param default:
    :return:
    """
    return getattr(request, key, default)


def ip2uint_str(ipv4_str):
    """Convert IPv4 string to 32-bit integer value"""
    parts = ipv4_str.split('.')
    if len(parts) != 4:
        raise ValueError('Expected IPv4 address in form A.B.C.D, got {}'.
            format(ipv4_str))
    ip = [0] * 4
    for i, part in enumerate(parts):
        try:
            int_part = int(part)
        except ValueError:
            raise ValueError('Part {} of IPv4 address is not an integer'.
                format(i))
        if int_part < 0 or int_part > 255:
            raise ValueError('Part {} of IPv4 address is not in range 0-255'
                .format(i))
        ip[i] = int_part
    return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3]


@staticmethod
def verify_config_file(config):
    """
        Make sure no values of required parameters are missing from the config file

        Args:
            config (dict): The config dictionary containing the key value pairs pulled from the config file
        Returns:
            Raises ValueError if an empty value is found, None otherwise
        """
    for key in ['galaxy_url', 'galaxy_key', 'history_name',
        'workflow_source', 'workflow']:
        if config[key] is None:
            return key
    return None


def DeleteFile():
    """
    Request to delete a single file or list of my files from remote machine.
    """
    return 'DeleteFile'


def kill_processes_list(list_):
    """
	Terminates a list of processes.
	"""
    for process in list_:
        process.terminate()


@classmethod
def param_spec_names(cls):
    """Lists the names of all param_specs defined in the analysis"""
    return iter(cls._param_specs.keys())


def calculate_ani(dna_fragment_matches):
    """Calculate ANI value for a set of DNA fragment matches.

    :param dna_fragment_matches: A dict comprising matches of DNA fragments.

    :rtype: ANI value.
    """
    ani_matches = 0
    ni_sum = 0.0
    for fm in dna_fragment_matches:
        if float(fm['alignment_length'] - fm['no_non_identities']) / float(fm
            ['length']) > 0.3 and float(fm['alignment_length']) / float(fm[
            'length']) >= 0.7:
            ni_sum += float(fm['alignment_length'] - fm['no_non_identities']
                ) / float(fm['alignment_length'])
            ani_matches += 1
    return ni_sum / float(ani_matches) if ani_matches > 0 else 0


def numbonds(mol) ->int:
    """
    Number of bonds.

    Parameters
    ----------
    mol:
        Molecule

    Returns
    -------
    int
        Number of bonds
    """
    return mol.GetNumBonds()


def set_viewport_background():
    """Set current movie clip as a camera background in 3D view-port (works only when a 3D view-port is visible)

    """
    pass


@classmethod
def initialize_class(cls, cls_type, buf, unpacked_args):
    """
        Initialize message class with arguments. Returns cls_type instance.
        """
    return cls_type(buf)


def getImmediatelyAddableTypes():
    """
        Return a subset of the FTI ids from getLocallyAllowedTypes() which
        should be made most easily available.
        """


@staticmethod
def instruction_list():
    """Get the list of mnemonics for all of the instructions to be used
        in features involving specific specific instructions.
        """
    return [b'add', b'al', b'bt', b'call', b'cdq', b'cld', b'cli', b'cmc',
        b'cmp', b'const', b'cwd', b'daa', b'.byte', b'dec', b'endp',
        b'ends', b'faddp', b'fchs', b'fdiv', b'fdivp', b'fdivr', b'fild',
        b'fistp', b'fld', b'fstcw', b'fstcwimul', b'fstp', b'fword',
        b'fxch', b'imul', b'in', b'inc', b'ins', b'int3', b'jb', b'je',
        b'jg', b'jge', b'jl', b'jmp', b'jnb', b'jno', b'jnz', b'jo', b'jz',
        b'lea', b'loope', b'mov', b'movzx', b'mul', b'near', b'neg', b'not',
        b'or', b'out', b'outs', b'pop', b'popf', b'proc', b'push', b'pushf',
        b'rcl', b'rcr', b'rdtsc', b'rep', b'ret', b'retn', b'rol', b'ror',
        b'sal', b'sar', b'sbb', b'scas', b'setb', b'setle', b'setnle',
        b'setnz', b'setz', b'shl', b'shld', b'shr', b'sidt', b'stc', b'std',
        b'sti', b'stos', b'sub', b'test', b'wait', b'xchg', b'xor']


@staticmethod
def _format_set(values) ->str:
    """
        Formatting list of values in the event of IN operation
        :param values: str
        :return: list
        """
    return list(map('"{}"'.format, values))


def defvalkey(js, key, default=None, take_none=True):
    """
    Returns js[key] if set, otherwise default. Note js[key] can be None.
    :param js:
    :param key:
    :param default:
    :param take_none:
    :return:
    """
    if js is None:
        return default
    if key not in js:
        return default
    if js[key] is None and not take_none:
        return default
    return js[key]


def _py2ri(obj):
    """ Dummy function for py2ri.

    This function will convert Python objects into rpy2.rinterface
    (ri) objects.
    """
    raise NotImplementedError(
        "Conversion 'py2ri' not defined for objects of type '%s'" % str(
        type(obj)))


def get_service_type(f):
    """Retrieves service type from function."""
    return getattr(f, 'service_type', None)


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


def context_set_value(data_path: str='', value: str=''):
    """Set a context value

    :param data_path: Context Attributes, RNA context string
    :type data_path: str
    :param value: Value, Assignment value (as a string)
    :type value: str
    """
    pass


@staticmethod
def p_a2ml(p):
    """a2ml : begin A2ML a2ml_declaration_list end A2ML"""
    p[0] = p[3]


def genericGetContent(path):
    """
    Retrieve the data from a given file path.
    """
    fp = path.open()
    try:
        return fp.read()
    finally:
        fp.close()


def find_breakthrough(times, data):
    """return tuple of time,value for the start breakthrough and end breakthrough"""
    selected = data > 0.999 * max(data)
    selected_times = times[selected]
    return (selected_times[0], max(data)), (selected_times[-1], max(data))


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


def generate_resource_id(namespace):
    """Generates the ID of the resource to be added to the plan's master
    template when a new template is added.

    :type namespace: str
    :rtype: str
    """
    return namespace + '-resource'


@classmethod
def fromrelpath(cls, relpath):
    """ return url from canonical relative path. """
    scheme, netlocpath = relpath.split('/', 1)
    return cls(scheme + '://' + netlocpath)


def get_auth(args):
    """
    Return a tuple of (user, password) or None if no authentication
    """
    if args is None or args['--user'] is None:
        return None
    else:
        return args['--user'], args['--password']


def _push(stack, arg):
    """move item from front to index"""
    idx = int(stack.pop())
    stack.insert(idx, stack.pop())


def indexables_from_dsd(dsd):
    """Return indexable items from a DSD."""
    yield dsd.attributes
    yield from dsd.attributes.components
    yield dsd.dimensions
    yield from dsd.dimensions.components
    if dsd.measures:
        yield dsd.measures
        yield from dsd.measures.components
    for gdd in dsd.group_dimensions.values():
        yield gdd
        yield from gdd.components


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 export_ebk(symbols, filename='sloth.ebk'):
    """Export symbols in ebk format."""
    res = [b'']
    for symbol in symbols:
        code, exchange = symbol.split('.')
        if exchange == 'SH':
            res.append(f'1{code}'.encode())
        else:
            res.append(f'0{code}'.encode())
    with open(filename, 'wb') as fout:
        fout.write(b'\r\n'.join(res))


def write_main_entry(model_name):
    """
    Generate Python code defining the __main__ Python entry point

    Parameters
    ----------
    model_name : string
       Name for deep learning model

    Returns
    -------
    string

    """
    return ''


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

        :param TeamDetails val:
        :rtype: FedExtraDetails
        """
    return cls('team', val)


def reveal(select: bool=True):
    """Show all Grease Pencil layers

    :param select: Select
    :type select: bool
    """
    pass


@classmethod
def get_dict_value_as_int(cls, dict_IN, name_IN, default_IN=-1):
    """
        Accepts dictionary, name, and optional default value (if no default
           provided, default is -1).  If dictionary or name missing, returns
           default.  If name not present in dictionary, returns default.  If name
           in dictionary, returns whatever is mapped to name, converted to an
           integer through call to int().

        Parameters:
        - dict_IN - dictionary we are looking in.
        - name_IN - name we are looking for in dictionary.
        - default_IN (defaults to None) - default value to return if problem or not found in dict.

        Returns:
        - value_OUT - value mapped to name_IN in dict_IN, converted to int(), else the default value if problems or if not found in dict.
        """
    value_OUT = None
    value_OUT = cls.get_dict_value(dict_IN, name_IN, default_IN)
    if value_OUT != None:
        value_OUT = int(value_OUT)
    return value_OUT


def _get_branch_head(branch):
    """Get the latest @head specification for a branch."""
    return '%s@head' % branch


def _format_servers_list_power_state(state):
    """Return a formatted string of a server's power state

    :param state: the power state number of a server
    :rtype: a string mapped to the power state number
    """
    power_states = ['NOSTATE', 'Running', '', 'Paused', 'Shutdown', '',
        'Crashed', 'Suspended']
    try:
        return power_states[state]
    except Exception:
        return 'N/A'


def keyframe_delete_by_name(type='Type', confirm_success: bool=True):
    """Alternate access to ‘Delete Keyframe’ for keymaps to use

    :param confirm_success: Confirm Successful Delete, Show a popup when the keyframes get successfully removed
    :type confirm_success: bool
    """
    pass


def getReadErrors(rescueLine):
    """parse ddrescue output line for values of readErrors"""
    lineItems = rescueLine.split(',')
    for item in lineItems:
        if 'errors:' in item:
            reEntry = item.split(':')
            readErrors = int(reEntry[1].strip())
    return readErrors


def p_header_cd_text(t):
    """header_cd_text : CD_TEXT START_BLOCK language_map language_blocks END_BLOCK"""
    from audiotools.toc import CDText
    t[0] = CDText(languages=t[4], language_map=t[3])


def is_between_ordered(val, lowerbound, upperbound):
    """
    Helper function to check projection intervals (SAT)
    """
    return lowerbound <= val and val <= upperbound


def expr2str(expr):
    """Convert a Python expression into a Python code."""
    if isinstance(expr, dict):
        return str(expr)
    if isinstance(expr, list):
        return '%s' % expr
    if isinstance(expr, str):
        return "'%s'" % expr
    return '%s' % str(expr)


def contains_one_element_of_class(obj_cls, iterable_obj):
    """
    Asserts that the specified iterable object contains one and only one element of the specified class.

    :param obj_cls: the class of the object that is expected to be found in the iterable.
    :param iterable_obj: :class:`~collections.abc.Iterable` object.
    :raises: :class:`AssertionError` if the callable does not raise an exception of the specified class.
    """
    if len(iterable_obj) != 1 or type(iterable_obj[0]) is not obj_cls:
        raise AssertionError(
            "Iterable should contain one and only one object of class '{0}'."
            .format(obj_cls.__name__))


def list2cmdline(seq):
    """
	Modified version of the original from subprocess.py
	"""
    result = []
    needquote = False
    for arg in seq:
        bs_buf = []
        if result:
            result.append(' ')
        needquote = ' ' in arg or '\t' in arg or ';' in arg or not arg
        if needquote:
            result.append('"')
        for c in arg:
            if c == '\\':
                bs_buf.append(c)
            elif c == '"':
                result.append('\\' * len(bs_buf) * 2)
                bs_buf = []
                result.append('\\"')
            else:
                if bs_buf:
                    result.extend(bs_buf)
                    bs_buf = []
                result.append(c)
        if bs_buf:
            result.extend(bs_buf)
        if needquote:
            result.extend(bs_buf)
            result.append('"')
    return ''.join(result)


@staticmethod
def range(start, finish, step):
    """Like built-in :func:`~builtins.range`, but with float support"""
    value = start
    while value <= finish:
        yield value
        value += step


def to_float(option, value):
    """
    Converts string values to floats when appropriate
    """
    if type(value) is str:
        try:
            value = float(value)
        except ValueError:
            pass
    return option, value


def sim_lorentz_fwhm(x, x0, fwhm):
    """
    Simulate a Lorentzian lineshape with unit height at the center.

    Simulates discrete points of the continuous Cauchy-Lorentz (Breit-Wigner)
    distribution with unit height at the center.  FWHM (full-width at
    half-maximum) is used as the scale parameter.

    Functional form:

        f(x; x0, fwhm) = (0.5 * fwhm)^2 / ((x-x0)^2 + (0.5 * fwhm)^2)

    Parameters
    ----------
    x : ndarray
        Array of values at which to evaluate distribution.
    x0 : float
        Center of the distribution.
    fwhm : float
        Full-width at half-maximum of distribution.

    Returns
    -------
    f : ndarray
        Distribution evaluated at points in x.

    """
    return (0.5 * fwhm) ** 2 / ((0.5 * fwhm) ** 2 + (x - x0) ** 2)


def mpl_hist_arg(value=True):
    """Find the appropriate `density` kwarg for our given matplotlib version.

    This will determine if we should use `normed` or `density`. Additionally,
    since this is a kwarg, the user can supply a value (True or False) that
    they would like in the output dictionary.

    Parameters
    ----------
    value : bool, optional (default=True)
        The boolean value of density/normed

    Returns
    -------
    density_kwarg : dict
        A dictionary containing the appropriate density kwarg for the
        installed  matplotlib version, mapped to the provided or default
        value
    """
    import matplotlib
    density_kwarg = ('density' if matplotlib.__version__ >= '2.1.0' else
        'normed')
    return {density_kwarg: value}


def wrap_inner(node, tag):
    """Wrap the given tag around the contents of a node."""
    children = list(node.childNodes)
    wrap_node = node.ownerDocument.createElement(tag)
    for c in children:
        wrap_node.appendChild(c)
    node.appendChild(wrap_node)


def update_lease(leases, entry):
    """
    Update a dictionary of DHCP leases with a new entry.

    The dictionary should be indexed by MAC address. The new entry will be
    added to the dictionary unless it would replace an entry for the same MAC
    address from a more recent lease file.
    """
    mac_addr = entry['mac_addr']
    if mac_addr in leases:
        existing = leases[mac_addr]
        if existing['as_of'] >= entry['as_of']:
            return existing
    leases[mac_addr] = entry
    return entry


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


def decode_response(client_message, to_object=None):
    """ Decode response from client message"""
    parameters = dict(response=None)
    parameters['response'] = client_message.read_bool()
    return parameters