@classmethod
def search_global(cls, text):
    """
        Yield tuples (record, name, icon) for text
        """
    for record in cls.search([('rec_name', 'ilike', '%%%s%%' % text)]):
        yield record, record.rec_name, None


def __init__(context, request):
    """
        Adapts a navigation root and a request.
        """


@classmethod
def get(cls, *args, **kwargs):
    """
        Returns a single object based on the passed filter constraints.

        This is a pass-through to the model objects().:method:`~cqlengine.queries.get`.
        """
    return cls.objects.get(*args, **kwargs)


@staticmethod
def _format_capture(kind, state, details):
    """Tweak what is saved according to your desire(s)."""
    return kind, state, details


def text_sort_key(ex):
    """Sort using the number of tokens in the sequence."""
    if hasattr(ex, 'tgt'):
        return len(ex.src[0]), len(ex.tgt[0])
    return len(ex.src[0])


def proto_select_attribute_in(node, attribute, values):
    """
    Return True if the given attribute of the node is in a list of values.

    To be used as a selector, the function must be wrapped in a way that it can
    be called without the need to explicitly specify the 'attribute' and
    'values' arguments. This can be done using :func:`functools.partial`:

    >>> # select an atom if its name is in a given list
    >>> to_keep = ['BB', 'SC1']
    >>> select_name_in = functools.partial(
    ...     proto_select_attribute_in,
    ...     attribute='atomname',
    ...     values=to_keep
    ... )
    >>> select_name_in(node)

    Parameters
    ----------
    node: dict
        The atom/node to consider.
    attribute: str
        The key to look at in the node.
    values: list
        The values the node attribute can take for the node to be selected.

    Returns
    -------
    bool
    """
    return node.get(attribute) in values


def not_exist_review_in(html):
    """
    html 에 리뷰 컨텐츠가 없는지 체크
    :param html: html 문자열
    :return: 없으면 True 있으면 False
    """
    return html is None or html.text in ('등록된 리뷰가 없습니다', '',
        '이 도서의 첫번째 리뷰어가 되어 주세요.')


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

    :return: rst string
    :rtype: str
    """
    return """
    The ``hostgroup`` model is used to group several hosts.

    """


@classmethod
def _cli_desc(cls):
    """
        Get layer description

        Returns
        -------
        str
            Layer description or 'Apply Layer {}'.format(cls.name) by default
        """
    return cls.desc if cls.desc is not None else "Apply Layer '{}'".format(cls
        .name)


def new():
    """Add New Pose Library to active Object

    """
    pass


@staticmethod
def split_package_version(package_version):
    """Split package==3.2.3 pip freeze output."""
    split_string = package_version.split('==')
    if len(split_string) < 2 and '-e' in package_version:
        split_string = package_version.split('=')
        return {'name': split_string[1]}
    return {'name': split_string[0], 'version': split_string[1]}


def metamorphosis_image_registration_methodv4(*args, **kwargs):
    """Procedural interface for MetamorphosisImageRegistrationMethodv4"""
    import itk
    instance = itk.MetamorphosisImageRegistrationMethodv4.New(*args, **kwargs)
    return instance.__internal_call__()


@staticmethod
def _parse_dn(dn):
    """Parses the pod and link number from a
           distinguished name of the link.

           :param dn: dn string of the link
           :returns: (pod, link)
        """
    name = dn.split('/')
    pod = str(name[1].split('-')[1])
    link = str(name[2].split('-')[1])
    return pod, link


def ttr(num_types, num_tokens):
    """Calculate Type-Token Ratio (TTR).

    Used formula:
        .. math::
            TTR = rac{V}{N}

    Parameters:
        num_types (int): Absolute number of types.
        num_tokens (int): Absolute number of tokens.
    """
    return num_types / num_tokens


def map_transaction(txn):
    """
    Maps a single transaction row to a dictionary.

    Parameters
    ----------
    txn : pd.DataFrame
        A single transaction object to convert to a dictionary.

    Returns
    -------
    dict
        Mapped transaction.
    """
    if isinstance(txn['sid'], dict):
        sid = txn['sid']['sid']
        symbol = txn['sid']['symbol']
    else:
        sid = txn['sid']
        symbol = txn['sid']
    return {'sid': sid, 'symbol': symbol, 'price': txn['price'], 'order_id':
        txn['order_id'], 'amount': txn['amount'], 'commission': txn[
        'commission'], 'dt': txn['dt']}


def split_string(string, length=80, starter=None):
    """Insert `\\n` into long string such that each line has size no more than `length`.

    Parameters
    ----------
    length: int
        Targeted length of the each line.

    starter: string
        String to insert at the beginning of each line.

    """
    if starter is not None:
        target_end = length - len(starter) - 1
    else:
        target_end = length
    sub_string = []
    while string:
        end = target_end
        if len(string) > end:
            while end >= 0 and string[end] != ' ':
                end -= 1
            end += 1
        sub = string[:end].strip()
        if starter is not None:
            sub = starter + ' ' + sub
        sub_string.append(sub)
        string = string[end:]
    return '\n'.join(sub_string) + '\n'


def reverse(s):
    """
    Return reverse of 's'.
    """
    r = ''.join(reversed(s))
    return r


@staticmethod
def _negotiate_integer_value(client_value, server_value):
    """Negotiates two values. If either of them is 0 or None,
        returns the other one. If both are positive integers, returns the
        smallest one.

        :param int client_value: The client value
        :param int server_value: The server value
        :rtype: int

        """
    if client_value == None:
        client_value = 0
    if server_value == None:
        server_value = 0
    if client_value == 0 or server_value == 0:
        val = max(client_value, server_value)
    else:
        val = min(client_value, server_value)
    return val


def float_range(start=0, stop=None, step=1):
    """
    Much like the built-in function range, but accepts floats

    >>> tuple(float_range(0, 9, 1.5))
    (0.0, 1.5, 3.0, 4.5, 6.0, 7.5)
    """
    start = float(start)
    while start < stop:
        yield start
        start += step


@staticmethod
def parse_unix_mode(s):
    """
        Parsing unix mode strings ("rwxr-x--t") into hexacimal notation.

        :param s: mode string
        :type s: :py:class:`str`

        :return mode:
        :rtype: :py:class:`int`
        """
    parse_rw = {'rw': 6, 'r-': 4, '-w': 2, '--': 0}
    mode = 0
    mode |= parse_rw[s[0:2]] << 6
    mode |= parse_rw[s[3:5]] << 3
    mode |= parse_rw[s[6:8]]
    if s[2] == 's':
        mode |= 2112
    elif s[2] == 'x':
        mode |= 64
    elif s[2] != '-':
        raise ValueError
    if s[5] == 's':
        mode |= 1032
    elif s[5] == 'x':
        mode |= 8
    elif s[5] != '-':
        raise ValueError
    if s[8] == 't':
        mode |= 512
    elif s[8] == 'x':
        mode |= 1
    elif s[8] != '-':
        raise ValueError
    return mode


def DoNotPassBorder(grid, point2d):
    """Ensure point is in image
    Arg: grid <- image
         pinrt2d <- x,y
    Returns: new point
    """
    x = point2d[0]
    y = point2d[1]
    if x < 0:
        x = 0
    elif x > grid.shape[0]:
        x = len(grid)
    if y < 0:
        y = 0
    elif y > grid.shape[1]:
        y = len(grid)
    return x, y


def add_keys(apps, schema_editor):
    """
    We can't import the Post model directly as it may be a newer
    version than this migration expects. We use the historical version.
    """
    Setting = apps.get_model('settings', 'Setting')
    key = ''
    try:
        key = 'USER_REGISTER_GIFT_BON_CREDITS'
        Setting.objects.get(key=key)
    except Exception:
        Setting.objects.create(title='شارژ هدیه برای ثبت نام کاربر جدید',
            key=key, value='0', value_type='i', is_show=False,
            is_variable_in_home=False)


def unique_elements_lists(list_in):
    """ return the unique elements in a list"""
    return list(dict.fromkeys(list_in))


def _get_pad_left_right(small, large):
    """ Compute left and right padding values.

    Here we use the convention that if the padding
    size is odd, we pad the odd part to the right
    and the even part to the left.

    Parameters
    ----------
    small : int
        Old size of original 1D array
    large : int
        New size off padded 1D array

    Returns
    -------
    (padleft, padright) : tuple
        The proposed padding sizes.
    """
    assert small < large, 'Can only pad when new size larger than old size'
    padsize = large - small
    if padsize % 2 != 0:
        leftpad = (padsize - 1) / 2
    else:
        leftpad = padsize / 2
    rightpad = padsize - leftpad
    return int(leftpad), int(rightpad)


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


def render_pep440_old(pieces):
    """TAG[.postDISTANCE[.dev0]] .

    The ".dev0" means dirty.

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


def is_progress_notification(value):
    """Check if the given value is valid Rockets progress notification."""
    return isinstance(value, dict) and 'method' in value and value['method'
        ] == 'progress' and 'params' in value and 'id' in value['params']


def is_iterable(obj):
    """
    Test for iterable

    Arguments
    ---------
    obj : any
        Object which is beeing tested
    """
    try:
        iter(obj)
        return True
    except Exception as e:
        pass
    return False


def assert_(condition, message='', exception_type=AssertionError):
    """https://raw.githubusercontent.com/inferno-pytorch/inferno/0561e8a95cde6bfc5e10a3609841b7b0ca5b03ca/inferno/utils/exceptions.py
	Like assert, but with arbitrary exception types."""
    if not condition:
        raise exception_type(message)


def _checkpoint_is_greater(a, b):
    """Ensure elements of checkpoint 'a' are all greater than or equal to those in
    checkpoint 'b'."""
    return (a.checkpoint >= b.checkpoint and a.checkpoint_time >= b.
        checkpoint_time)


def batch_iterator(iterator, batch_size):
    """Returns lists of length batch_size.

    This can be used on any iterator, for example to batch up
    SeqRecord objects from Bio.SeqIO.parse(...), or to batch
    Alignment objects from Bio.AlignIO.parse(...), or simply
    lines from a file handle.

    This is a generator function, and it returns lists of the
    entries from the supplied iterator.  Each list will have
    batch_size entries, although the final list may be shorter.
    """
    entry = True
    while entry:
        batch = []
        while len(batch) < batch_size:
            try:
                entry = next(iterator)
            except StopIteration:
                entry = None
            if entry is None:
                break
            batch.append(entry)
        if batch:
            yield batch


def get_image_label(fieldname):
    """Returns the label of the image field"""


def in_ipython() ->bool:
    """
    Check whether we're in an ipython environment, including jupyter notebooks.
    """
    try:
        eval('__IPYTHON__')
    except NameError:
        return False
    else:
        return True


@staticmethod
def do_not_decorate(f):
    """
        this is for excluding functions from decorating
        :return: the logging decorator if verbose is True, empty decorator otherwise
        """
    setattr(f, 'decorate', False)
    return f


def get_eng_file_rel_path(file_prefix, num_bits):
    """
    Returns path to English file

    Returns
    -------
    str

    """
    return file_prefix + '_' + str(num_bits) + '_eng.txt'


def _msg_head_str(msg):
    """A utility to print the head of the str representation of an object."""
    msg_limit = 32
    msg_str = f"'{msg}'"
    if len(msg_str) > msg_limit:
        msg_str = msg_str[:msg_limit] + "'..."
    return msg_str


def p_include_file_empty(p):
    """ include_file : include NEWLINE _ENDFILE_
    """
    p[0] = [p[2]]


def get_content_type(filename: str) ->str:
    """
    Retrieves a sensible content type for a file
    :param filename: The name of the file
    :return: The content type of the file
    """
    try:
        extension = filename.rsplit('.', 1)[1].lower()
        if extension == 'jar':
            return 'application/java-archive'
        elif extension == 'txt':
            return 'text/plain'
        else:
            return 'application/octet-stream'
    except IndexError:
        return 'application/octet-stream'


def get_host_port(address):
    """Split a network address of the form ``host:port``.

    Parameters
    ----------
    network : str
        The network address.

    Returns
    -------
    host : str
        The hostname, or an empty string if missing.
    port : int, None
        The port number, or None if missing.

    """
    host, _, port = address.partition(':')
    return host, int(port) if port else None


def PolsRenewal(t):
    """Number of policies: Renewal policies"""
    return 0


def throttle_backoff_handler(details):
    """Callback to be used when a throttle backoff is invoked.

    For more details see: https://github.com/litl/backoff/#event-handlers

    Args:
        dictionary (dict): Details of the backoff invocation. Valid keys
            include:
                target: reference to the function or method being invoked.
                args: positional arguments to func.
                kwargs: keyword arguments to func.
                tries: number of invocation tries so far.
                wait: seconds to wait (on_backoff handler only).
                value: value triggering backoff (on_predicate decorator only).
    """
    activity = details['args'][0]
    activity.logger.info(
        'Throttle Exception occurred on try {}. Sleeping for {} seconds'.
        format(details['tries'], details['wait']))


def is_tuple(obj):
    """
    Checks if a given sequence is a tuple.

    Parameters
    ----------
    obj : object
        The input array.

    Returns
    -------
    test result : bool
        The test result of whether seq is a tuple or not.

    >>> is_tuple(('a', 'b'))
    True

    >>> is_tuple(['a', 'b'])
    False

    >>> is_tuple(4)
    False
    """
    return True if isinstance(obj, tuple) else False


def __new__(cls, *args, **kwargs):
    """Create instances of this class with proxied special names."""
    klass = cls.get_class_def()
    instance = object.__new__(klass)
    klass.__init__(instance, *args, **kwargs)
    return instance


def is_response_to_head(response):
    """
    Checks whether the request of a response has been a HEAD-request.
    Handles the quirks of AppEngine.

    :param conn:
    :type conn: :class:`httplib.HTTPResponse`
    """
    method = response._method
    if isinstance(method, int):
        return method == 3
    return method.upper() == 'HEAD'


def config_from_json(path):
    """Load simple JSON mapping to Python dict
    """
    import json
    with open(path, 'rb') as config_file:
        loaded = json.load(config_file)
    return loaded


def _create_model(model, values):
    """Create a new model."""
    model.update(values)
    model.save()
    return model


def lerp(a, b, x):
    """linear interpolation"""
    return a + x * (b - a)


def add_in_prompt(text, prompt_no):
    """Add the In [1]: prompts to a block of code."""
    if prompt_no is None:
        prompt = 'In [ ]: '
    else:
        prompt = 'In [%d]: ' % prompt_no
    margin = ' ' * len(prompt)
    colour_prompt = '%s' % prompt
    lines = text.splitlines(keepends=True)
    return colour_prompt + margin.join(lines)


def import_global(path):
    """ Import a class from a string module class path """
    components = path.split('.')
    module = components[:-1]
    module = '.'.join(module)
    mod = __import__(module, fromlist=[str(components[-1])])
    return getattr(mod, str(components[-1]))


def update_bn_forward(apps, schema_editor):
    """
    Updates the Clustering Example Bayesian Network Object.
    """
    BayesianNetwork = apps.get_model('bayesian_networks', 'BayesianNetwork')
    bn = BayesianNetwork.objects.get(name='Clustering (Example)')
    bn.results_storage = 'dmf:examples.UserInfo.cluster_1'
    bn.engine_meta_iterations = 15
    bn.counter_threshold = 10
    bn.threshold_actions = ':recalculate'
    bn.save()


@classmethod
def add_format(cls, string_):
    """Adds formatting of this type to a string"""
    return string_


def dissolve_edges(use_verts: bool=True, use_face_split: bool=False):
    """Dissolve edges, merging faces

    :param use_verts: Dissolve Verts, Dissolve remaining vertices
    :type use_verts: bool
    :param use_face_split: Face Split, Split off face corners to maintain surrounding geometry
    :type use_face_split: bool
    """
    pass


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

        :param SsoAddCertDetails val:
        :rtype: EventDetails
        """
    return cls('sso_add_cert_details', val)


def p_gcl_start_projection(t):
    """gcl_expr : OP_START_PROJECTION gcl_expr RCPAREN"""
    t[0] = 'Start', t[2]


def gluLookAt(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz):
    """Define a viewing transformation.

    :param eyez: Specifies the position of the eye point.
    :param centerz: Specifies the position of the reference point.
    :param upz: Specifies the direction of the up vector.
    """
    pass


def inspect_object(obj, refresh=True):
    """
    inspect provided object (container, image) and return raw dict with the metadata

    :param obj: instance of Container or an Image
    :param refresh: bool, refresh the metadata or return cached?
    :return: dict
    """
    if hasattr(obj, 'inspect'):
        return obj.inspect(refresh=refresh)
    return obj.get_metadata(refresh=refresh)


def py2_replace_version(argv):
    """

    Workaround for Python 2.7 argparse, which does not accept empty COMMAND

    If `-V` or `--version` present and every argument before it begins with `-`,
    then convert it to `version.
    """
    try:
        ind = argv.index('--version')
    except ValueError:
        try:
            ind = argv.index('-V')
        except ValueError:
            ind = None
    if ind is not None:
        for k in range(ind):
            if argv[k][0] != '-':
                ind = None
                break
        if ind is not None:
            argv[ind] = 'version'
    return argv


def segment_diff(s1, s2):
    """
    Returns the sum of absolute difference between
    two segments' end points.
    Only perfectly aligned segments return 0
    """
    return abs(s1[0] - s2[0]) + abs(s1[1] - s2[1])


def keying_set_path_add():
    """Add empty path to active Keying Set

    """
    pass


def stroke_split():
    """Split selected points as new stroke on same frame

    """
    pass


@staticmethod
def _connection_status_flag(flags, flag_to_find):
    """
        Is the given flag in the connection status flags?

        flags -- the 'flags' parameter returned by ble_evt_connection_status.
        flag_to_find -- the flag to look for in flags.

        Returns true if flag_to_find is in flags. Returns false otherwise.
        """
    return flags & flag_to_find == flag_to_find


def zero_mul_simp(l, index):
    """Used to combine two reduced words."""
    while index >= 0 and index < len(l) - 1 and l[index][0] == l[index + 1][0]:
        exp = l[index][1] + l[index + 1][1]
        base = l[index][0]
        l[index] = base, exp
        del l[index + 1]
        if l[index][1] == 0:
            del l[index]
            index -= 1


@classmethod
def processor_names(cls):
    """
        Returns a list of all available processor names/
        """
    values = []
    for processor in cls.processors:
        values.append(processor.name)
    return values


def output(text: str, quiet=False):
    """Outputs the text to STDOUT in non-quiet mode

    :param text: Message to output
    """
    if not quiet:
        print(text)


@classmethod
def fix_tree(cls):
    """
        Solves problems that can appear when transactions are not used and
        a piece of code breaks, leaving the tree in an inconsistent state.
        """
    raise NotImplementedError


def lambd_H3PO4_Na_HFM89(T, P):
    """n-c: phosphoric-acid sodium [HFM89]."""
    lambd = 0.075
    valid = T == 298.15
    return lambd, valid


def frobenius(point, q):
    """
    The Frobenius endomorphism @f$ \\phi @f$.

    @return    The point @f$ (x^q, y^q) @f$ if @p point is @f$ (x, y) @f$.
    """
    return point.__class__(point.x() ** q, point.y() ** q)


def get_list_union(*args: list) ->set:
    """ Returns union of x lists as a set"""
    return set().union(*args)


def getConfiguration():
    """
        Get node's configuration.

        The configuration must at least have two options:
        C{pubsub#persist_items}, and C{pubsub#deliver_payloads}.

        @return: C{dict} of configuration options.
        """


@staticmethod
def _adapt_num(v):
    """Adapt a numeric parameter."""
    if not v and v != 0:
        return None
    return v


def invert(invert_r: bool=False, invert_g: bool=False, invert_b: bool=False,
    invert_a: bool=False):
    """Invert image’s channels

    :param invert_r: Red, Invert Red Channel
    :type invert_r: bool
    :param invert_g: Green, Invert Green Channel
    :type invert_g: bool
    :param invert_b: Blue, Invert Blue Channel
    :type invert_b: bool
    :param invert_a: Alpha, Invert Alpha Channel
    :type invert_a: bool
    """
    pass


def load_xml(finder, module):
    """the builtin xml package attempts to load the _xmlplus module to see if
       that module should take its role instead; ignore the failure to find
       this module, though."""
    module.IgnoreName('_xmlplus')


def _make_group_with_markder(app_list, _config):
    """internal method , use group_marker . would be deprecated in next version 0.2.0 """
    for app in app_list:
        model_list = app['models']
        destlist = []
        groups = {}
        for m in model_list:
            marker = _config['group_marker'
                ] if 'group_marker' in _config else '-'
            if marker in m['name']:
                grp, name = m['name'].split(marker)
                m['name'] = name
                if grp in groups:
                    groups[grp]['models'].append(m)
                else:
                    grpobj = {'group_name': grp, 'models': [m]}
                    groups[grp] = grpobj
                    destlist.append(grpobj)
                m['name'] = name
            else:
                destlist.append(m)
        app['models'] = destlist


@classmethod
def is_yaml_tag_supported(cls, yaml_tag):
    """
        Implementing classes should return True if they are able to decode yaml objects with this yaml tag.
        Default implementation relies on class attribute `__yaml_tag_suffix__` if provided, either manually or through
        the `@yaml_info` decorator.

        :param yaml_tag:
        :return:
        """
    if hasattr(cls, '__yaml_tag_suffix__'
        ) and cls.__yaml_tag_suffix__ is not None:
        if '__yaml_tag_suffix__' in cls.__dict__:
            return cls.__yaml_tag_suffix__ == yaml_tag
        else:
            raise TypeError(
                '`__yaml_tag_suffix__` field is not redefined by class {}, cannot inherit from YamlAbleproperly.'
                .format(cls))
    else:
        raise NotImplementedError(
            "class {} does not seem to have a non-None '__yaml_tag_suffix__' field. You can either create one manually or by decorating your class with @yaml_info. Alternately you should override the 'is_yaml_tag_supported' method from YamlAble."
            .format(cls))


def _toolkit_get_topk_bottomk(values, k=5):
    """
    Returns a tuple of the top k values from the positive and
    negative values in a SArray

    Parameters
    ----------
    values : SFrame of model coefficients

    k: Maximum number of largest positive and k lowest negative numbers to return

    Returns
    -------
    (topk_positive, bottomk_positive) : tuple
            topk_positive : list
                floats that represent the top 'k' ( or less ) positive
                values
            bottomk_positive : list
                floats that represent the top 'k' ( or less ) negative
                values
    """
    top_values = values.topk('value', k=k)
    top_values = top_values[top_values['value'] > 0]
    bottom_values = values.topk('value', k=k, reverse=True)
    bottom_values = bottom_values[bottom_values['value'] < 0]
    return top_values, bottom_values


def crop(clip, x1=None, y1=None, x2=None, y2=None, width=None, height=None,
    x_center=None, y_center=None):
    """
    Returns a new clip in which just a rectangular subregion of the
    original clip is conserved. x1,y1 indicates the top left corner and
    x2,y2 is the lower right corner of the croped region.
    All coordinates are in pixels. Float numbers are accepted.

    To crop an arbitrary rectangle:

    >>> crop(clip, x1=50, y1=60, x2=460, y2=275)

    Only remove the part above y=30:

    >>> crop(clip, y1=30)

    Crop a rectangle that starts 10 pixels left and is 200px wide

    >>> crop(clip, x1=10, width=200)

    Crop a rectangle centered in x,y=(300,400), width=50, height=150 :

    >>> crop(clip,  x_center=300 , y_center=400,
                        width=50, height=150)

    Any combination of the above should work, like for this rectangle
    centered in x=300, with explicit y-boundaries:

    >>> crop(x_center=300, width=400, y1=100, y2=600)

    """
    if width and x1 is not None:
        x2 = x1 + width
    elif width and x2 is not None:
        x1 = x2 - width
    if height and y1 is not None:
        y2 = y1 + height
    elif height and y2 is not None:
        y1 = y2 - height
    if x_center:
        x1, x2 = x_center - width / 2, x_center + width / 2
    if y_center:
        y1, y2 = y_center - height / 2, y_center + height / 2
    x1 = x1 or 0
    y1 = y1 or 0
    x2 = x2 or clip.size[0]
    y2 = y2 or clip.size[1]
    return clip.fl_image(lambda pic: pic[int(y1):int(y2), int(x1):int(x2)],
        apply_to=['mask'])


def refetch(obj):
    """Queries the database for the same object that is passed in, refetching
    its contents in case they are stale.

    :param obj:
        Object to refetch

    :returns:
        Refreshed version of the object
    """
    return obj.__class__.objects.get(id=obj.id)


def render_pep440_old(pieces):
    """TAG[.postDISTANCE[.dev0]] .

    The ".dev0" means dirty.

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


def generate_docstring(operation_spec):
    """Generate a docstring for an operation defined in operation_spec (swagger)"""
    docs = operation_spec.get('description', 'No Description')
    docs += '\n\n'
    parameters = operation_spec.get('parameters', [])
    if len(parameters) != 0:
        docs += '\tArguments:\n\n'
    for parameter in parameters:
        docs += '{0} ({1}:{2}): {3}\n'.format(parameter.get('name'),
            parameter.get('type', 'No Type'), 'Required' if parameter.get(
            'required', False) else 'Not Required', parameter.get(
            'description'))
    return docs


def requires_to_requires_dist(requirement):
    """Return the version specifier for a requirement in PEP 345/566 fashion."""
    if getattr(requirement, 'url', None):
        return ' @ ' + requirement.url
    requires_dist = []
    for op, ver in requirement.specs:
        requires_dist.append(op + ver)
    if not requires_dist:
        return ''
    return ' (%s)' % ','.join(sorted(requires_dist))


def patchAsyncio():
    """Patch asyncio to allow nested event loops."""
    import nest_asyncio
    nest_asyncio.apply()


@classmethod
def get_queue(cls, name, priority=0, **fields_if_new):
    """
        Get, or create, and return the wanted queue.
        If the queue is created, fields in fields_if_new will be set for the new
        queue.
        """
    queue_kwargs = {'name': name, 'priority': priority}
    retries = 0
    while retries < 10:
        retries += 1
        try:
            queue, created = cls.get_or_connect(**queue_kwargs)
        except IndexError:
            continue
        except ValueError:
            try:
                queue = cls.collection(**queue_kwargs).instances()[0]
            except IndexError:
                continue
            else:
                created = False
        break
    if created and fields_if_new:
        queue.set_fields(**fields_if_new)
    return queue


def merge(new_items, into_list):
    """
    Appends items from `new_items` into `into_list`, only if they are not already there.
    :param new_items:
    :param into_list:
    :return:
    """
    at_least_one_added = False
    for l in new_items:
        if l not in into_list:
            into_list.append(l)
            at_least_one_added = True
    return at_least_one_added


@classmethod
def RenderUndoRedoChanged(cls, obj):
    """render undo/redo"""
    raise 'not implemented'


@staticmethod
def order(links, n):
    """
    Give a list of Links that each contain node n, flips any links so
    that n is always the first element of the link.
    """
    r = []
    for l in links:
        assert n in l
        if l._n[0] == n:
            r.append(l)
        else:
            r.append(l.flip())
    return r


@classmethod
def help(cls):
    """ Prints the Pattern class docstring to the console """
    return print(cls.__doc__)


def _convert_write_result(operation, command, result):
    """Convert a legacy write result to write commmand format."""
    affected = result.get('n', 0)
    res = {'ok': 1, 'n': affected}
    errmsg = result.get('errmsg', result.get('err', ''))
    if errmsg:
        if result.get('wtimeout'):
            res['writeConcernError'] = {'errmsg': errmsg, 'code': 64,
                'errInfo': {'wtimeout': True}}
        else:
            error = {'index': 0, 'code': result.get('code', 8), 'errmsg':
                errmsg}
            if 'errInfo' in result:
                error['errInfo'] = result['errInfo']
            res['writeErrors'] = [error]
            return res
    if operation == 'insert':
        res['n'] = len(command['documents'])
    elif operation == 'update':
        if 'upserted' in result:
            res['upserted'] = [{'index': 0, '_id': result['upserted']}]
        elif result.get('updatedExisting') is False and affected == 1:
            update = command['updates'][0]
            _id = update['u'].get('_id', update['q'].get('_id'))
            res['upserted'] = [{'index': 0, '_id': _id}]
    return res


def calc_M20(peaks, HKL, ifX20=True):
    """needs a doc string"""
    diff = 0
    X20 = 0
    for Nobs20, peak in enumerate(peaks):
        if peak[3]:
            Qobs = 1.0 / peak[7] ** 2
            Qcalc = 1.0 / peak[8] ** 2
            diff += abs(Qobs - Qcalc)
        elif peak[2]:
            X20 += 1
        if Nobs20 == 19:
            d20 = peak[7]
            break
    else:
        d20 = peak[7]
        Nobs20 = len(peaks)
    for N20, hkl in enumerate(HKL):
        if hkl[3] < d20:
            break
    Q20 = 1.0 / d20 ** 2
    if diff:
        M20 = Q20 / (2.0 * diff)
    else:
        M20 = 0
    if ifX20:
        M20 /= 1.0 + X20
    return M20, X20


def first(x):
    """First element of `x`, or None if missing"""
    try:
        return next(iter(x))
    except StopIteration:
        return None


def extract_canonical(bs4):
    """Extracting canonical url

    :param bs4:
    :return:
    """
    link_rel = bs4.select('link[rel="canonical"]')
    if link_rel.__len__() > 0:
        if link_rel[0].has_attr('href'):
            return link_rel[0]['href']
    return None


def collapse_json(text, indent=12):
    """Compacts a string of json data by collapsing whitespace after the
    specified indent level

    NOTE: will not produce correct results when indent level is not a multiple
    of the json indent level
    """
    initial = ' ' * indent
    out = []
    sublevel = []
    pending = None
    for line in text.splitlines():
        if line.startswith(initial):
            if line[indent] == ' ':
                if pending:
                    sublevel.append(pending)
                    pending = None
                item = line.strip()
                sublevel.append(item)
                if item.endswith(','):
                    sublevel.append(' ')
            elif sublevel:
                sublevel.append(line.strip())
                out.append(''.join(sublevel))
                sublevel = []
            else:
                if pending:
                    out.append(pending)
                pending = line.rstrip()
        else:
            if pending:
                out.append(pending)
                pending = None
            if sublevel:
                out.append(''.join(sublevel))
            out.append(line)
    return '\n'.join(out)


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


def 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 check_sol(sol, m_objs, H, verbose=False):
    """
    Determine whether a solution (sol) is valid.

    Input
    sol         list, solution with m_objs integers
    m_objs      int, number of objectives
    H           int, granularity >= 2
    verbose     bool, flag to show messages

    Output
    ok          bool, if ok is False, sol is invalid
    error_pos   int, position of the first invalid value found in sol (if any)
    """
    ok = True
    error_pos = None
    for pos in range(m_objs - 2, -1, -1):
        lb = 0
        ub = H - sum(sol[:pos])
        if sol[pos] >= lb and sol[pos] <= ub:
            continue
        else:
            ok = False
            error_pos = pos
            if verbose:
                print(' * %s, pos %d' % (sol, pos))
    return ok, error_pos


def get_symbolic_weight_names(layer, weights=None):
    """Attribute names for weights

    Looks up the attribute names of weight tensors.

    :param layer: Targeted layer.
    :param weights: A list of weight tensors.
    :return: The attribute names of the weights.
    """
    if weights is None:
        weights = layer.weights
    good_guesses = ['kernel', 'bias', 'gamma', 'beta', 'moving_mean',
        'moving_variance', 'depthwise_kernel', 'pointwise_kernel']
    ret = []
    for weight in weights:
        for attr_name in (good_guesses + dir(layer)):
            if hasattr(layer, attr_name) and id(weight) == id(getattr(layer,
                attr_name)):
                ret.append(attr_name)
                break
    if len(weights) != len(ret):
        raise Exception('Could not find symoblic weight name(s).')
    return ret


@classmethod
def get_conditional_uni(cls, left_parent, right_parent):
    """Identify pair univariate value from parents.

        Args:
            left_parent (Edge):
                left parent
            right_parent (Edge):
                right parent

        Returns:
            tuple[np.ndarray, np.ndarray]:
                left and right parents univariate.
        """
    left, right, _ = cls._identify_eds_ing(left_parent, right_parent)
    left_u = left_parent.U[0] if left_parent.L == left else left_parent.U[1]
    right_u = right_parent.U[0] if right_parent.L == right else right_parent.U[
        1]
    return left_u, right_u


def __build_word_numeral(*args):
    """
    Build word numeral regexp from list.

    :param args:
    :type args:
    :param kwargs:
    :type kwargs:
    :return:
    :rtype:
    """
    re_ = None
    for word_list in args:
        for word in word_list:
            if not re_:
                re_ = '(?:(?=\\w+)'
            else:
                re_ += '|'
            re_ += word
    re_ += ')'
    return re_


def split():
    """Split selected strips at their midpoints

    """
    pass


def callable_bool(value):
    """ A compatibility wrapper for pre Django 1.10 User model API that used
    is_authenticated() and is_anonymous() methods instead of attributes
    """
    if callable(value):
        return value()
    else:
        return value


def save(checkin_message):
    """ save a new version of the object
        """


def upper_bound(l, k):
    """
    >>> upper_bound([1, 2, 2, 3, 4], 2)
    3
    >>> upper_bound([1, 2, 2, 3, 4], 5)
    -1

    :param l:
    :param k:
    :return:
    """
    if l[-1] <= k:
        return -1
    i = len(l) // 2
    start, end = 0, len(l) - 1
    while start < end:
        if l[i] > k:
            end = i
        else:
            start = i + 1
        i = start + (end - start) // 2
    return i


@classmethod
def default_cal_visible(cls, iduser=None, calendar=None, pattern=None):
    """ new calendars are visible
        """
    return True


def _mask_border_keypoints(image_shape, keypoints, distance):
    """Mask coordinates that are within certain distance from the image border.

    Parameters
    ----------
    image_shape : (2, ) array_like
        Shape of the image as ``(rows, cols)``.
    keypoints : (N, 2) array
        Keypoint coordinates as ``(rows, cols)``.
    distance : int
        Image border distance.

    Returns
    -------
    mask : (N, ) bool array
        Mask indicating if pixels are within the image (``True``) or in the
        border region of the image (``False``).

    """
    rows = image_shape[0]
    cols = image_shape[1]
    mask = (distance - 1 < keypoints[:, (0)]) & (keypoints[:, (0)] < rows -
        distance + 1) & (distance - 1 < keypoints[:, (1)]) & (keypoints[:,
        (1)] < cols - distance + 1)
    return mask


def make_subdicts(base, keychain):
    """Generate sub-dictionaries based on a keychain.

    Starting from the base dictionary for each key in the keychain
    another sub-dictionary will be added and then used as the new base
    dictionary. The result will be a chain of child dictionaries.
    At the end the innermost sub-dictionary will be returned for
    convenience.

    Args:
        base (dict): The root dictionary which will contain all
            sub-directories after this function is done.

        keychain (list): Each key of the list results in an additional
            sub-dictionary in `base`.
    Returns:
        The innermost dictionary that was created.

    Examples:
        >>> from configstacker import utils
        >>> base_dict = {}
        >>> inner_dict = utils.make_subdicts(base_dict, ['a', 'b', 'c'])
        >>> inner_dict
        {}
        >>> base_dict
        {'a': {'b': {'c': {}}}}

        >>> base_dict = {'a': {}}  # some preexisting dictionary
        >>> inner_dict = utils.make_subdicts(base_dict, ['m', 'n'])
        >>> inner_dict['x'] = 1    # some changes in the innermost dictionary
        >>> base_dict
        {'a': {}, 'm': {'n': {'x': 1}}}
    """
    for key in keychain:
        base = base.setdefault(key, {})
    return base


def _initializer(lats, lons, data):
    """Declare global variables needed for SensorMapGeometryTransformer3D.to_map_geometry and to_sensor_geometry.

    :param lats:
    :param lons:
    :param data:
    """
    global _global_shared_lats, _global_shared_lons, _global_shared_data
    _global_shared_lats = lats
    _global_shared_lons = lons
    _global_shared_data = data


def _alexander_numpy(crossings, variable=-1.0, quadrant='lr'):
    """
    Numpy implementation of the Alexander polynomial (evaluated
    at a float), assuming the input has been sanitised by
    :func:`alexander`.
    """
    import numpy as n
    num_crossings = int(len(crossings) / 2)
    dtype = n.complex if isinstance(variable, n.complex) else n.float
    matrix = n.zeros((num_crossings, num_crossings), dtype=dtype)
    line_num = 0
    crossing_num_counter = 0
    crossing_dict = {}
    crossing_exists = False
    over_clock = 1.0 - 1.0 / variable
    under_clock_after = 1.0 / variable
    over_aclock = 1 - variable
    under_aclock_after = variable
    for i in range(len(crossings)):
        identifier, over, clockwise = crossings[i]
        if identifier in crossing_dict:
            crossing_num = crossing_dict.pop(identifier)
            crossing_exists = True
        if not crossing_exists:
            crossing_num = crossing_num_counter
            crossing_num_counter += 1
            crossing_dict[identifier] = crossing_num
        crossing_exists = False
        if over > 0.99999:
            mat_elt = over_clock if clockwise > 0.999 else over_aclock
            matrix[crossing_num, line_num % num_crossings] = mat_elt
        else:
            new_mat_elt = (under_clock_after if clockwise > 0.999 else
                under_aclock_after)
            matrix[crossing_num, line_num % num_crossings] = -1
            line_num += 1
            matrix[crossing_num, line_num % num_crossings] = new_mat_elt
    if quadrant == 'lr':
        poly_val = n.linalg.det(matrix[1:, 1:])
    elif quadrant == 'ur':
        poly_val = n.linalg.det(matrix[:-1, 1:])
    elif quadrant == 'ul':
        poly_val = n.linalg.det(matrix[:-1, :-1])
    elif quadrant == 'll':
        poly_val = n.linalg.det(matrix[1:, :-1])
    if not isinstance(poly_val, n.complex):
        poly_val = n.abs(poly_val)
    return poly_val


def get_related_association_proxy_model(attr):
    """Returns the model class specified by the given SQLAlchemy relation
    attribute, or ``None`` if no such class can be inferred.

    `attr` must be a relation attribute corresponding to an association proxy.

    """
    prop = attr.remote_attr.property
    for attribute in ('mapper', 'parent'):
        if hasattr(prop, attribute):
            return getattr(prop, attribute).class_
    return None


def select_linked_pick(extend: bool=False, deselect: bool=False, location:
    float=(0.0, 0.0)):
    """Select all UV vertices linked under the mouse

    :param extend: Extend, Extend selection rather than clearing the existing selection
    :type extend: bool
    :param deselect: Deselect, Deselect linked UV vertices rather than selecting them
    :type deselect: bool
    :param location: Location, Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds
    :type location: float
    """
    pass


def double_justification(wedges=(15, 15)):
    """0075 then 0005+0075 (will be cast in reverse order)
    with or without justifying wedge positions.
    Used for putting a line to the galley, setting the wedges as well.
    """
    w_0075, w_0005 = wedges
    return ['NKJS 0075 0005 {}'.format(w_0005)] if w_0075 == w_0005 else [
        'NKS 0075 {}'.format(w_0075), 'NKJS 0075 0005 {}'.format(w_0005)]


def queryObject(uid, default=None):
    """Return an object by its unique id

        Return the default if the uid isn't registered
        """


def get_variable_value(values, c, idx, default):
    """Determine value for variables.

    :param values: list of values for variables
    :param list c: list of variables, or string variable
    :param int idx: index of the variable in c for which to return value
    :param default: default return value
    :return: value
    """
    if isinstance(c, str):
        c = [c]
    n = ':'.join(c)
    if n in values and 1 < len(c) == len(values[n]):
        result = values[n][idx]
    else:
        result = values.get(c[idx], default)
    return result


@staticmethod
def generate_queue_endpoint(region, accountid, queue_name):
    """
            @type region: string
            @param region: the region of queue, such as: cn-hangzhou

            @type accountid: string
            @param accountid: the accountid of queue's owner

            @type queue_name: string
            @param queue_name
        """
    return 'acs:mns:%s:%s:queues/%s' % (region, accountid, queue_name)


def getHostByName(name, timeout=(1, 3, 11, 45)):
    """
        Resolve the domain name C{name} into an IP address.

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

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

        @rtype: L{twisted.internet.defer.Deferred}
        @return: The callback of the Deferred that is returned will be
            passed a string that represents the IP address of the
            specified name, or the errback will be called if the
            lookup times out.  If multiple types of address records
            are associated with the name, A6 records will be returned
            in preference to AAAA records, which will be returned in
            preference to A records.  If there are multiple records of
            the type to be returned, one will be selected at random.

        @raise twisted.internet.defer.TimeoutError: Raised
            (asynchronously) if the name cannot be resolved within the
            specified timeout period.
        """


def compress_edges(graph):
    """
    compress edges of networks by finding common paths

    Parameters
    ----------
    graph: networkx.DiGraph

    Returns
    -------

    """
    g = graph.copy()
    nodes = set(g.nodes())
    neighbor_dict = {}
    for n in nodes:
        neigh = tuple(g.neighbors(n))
        if tuple(neigh) in neighbor_dict:
            neighbor_dict[tuple(neigh)].append(n)
        else:
            neighbor_dict[tuple(neigh)] = []
            neighbor_dict[tuple(neigh)].append(n)
    for i in neighbor_dict:
        neigh = neighbor_dict[i]
        if len(i) != 1 or len(neigh) == 1:
            continue
        interaction_types = {}
        for j in neighbor_dict[i]:
            if g.has_edge(i[0], j):
                direction = 'type1'
                edge = g.get_edge(i[0], j)
            elif g.has_edge(j, i[0]):
                direction = 'type2'
                edge = g.get_edge(j, i[0])
            edge_type = edge.attr['arrowhead']
            if edge_type + direction in interaction_types:
                interaction_types[edge_type + direction].append(j)
            else:
                interaction_types[edge_type + direction] = []
                interaction_types[edge_type + direction].append(j)
        for k in interaction_types:
            if len(interaction_types[k]) > 1:
                to_join = []
                for each in interaction_types[k]:
                    if len(g.neighbors(each)) == 1:
                        to_join.append(each)
                if len(to_join) > 1:
                    label = '{'
                    for node in to_join:
                        g.remove_node(node)
                        label += ' %s |' % str(node)
                    label = label[:-1]
                    label += '}'
                    g.add_node(label, shape='record', label=label)
                    if k.endswith('type2'):
                        g.add_edge(label, i[0], dir='both', arrowhead=k[:-5
                            ], arrowtail='none')
                    elif k.endswith('type1'):
                        g.add_edge(i[0], label, dir='both', arrowhead=k[:-5
                            ], arrowtail='none')
    return g


def get_rxns(db, id_list):
    """Returns reactions with associated IDs from a Mongo database.

    :param db: DB to search
    :type db: A Mongo Database
    :param id_list: IDs to get compounds for.
    :type id_list: list
    :return: Reaction JSON documents
    :rtype: list
    """
    reactions = []
    for rxn_id in id_list:
        reactions.append(db.reactions.find_one({'_id': rxn_id}))
    return reactions


def resolve_name(name):
    """Resolve a name like ``module.object`` to an object and return it.

    Raise ImportError if the module or name is not found.
    """
    parts = name.split('.')
    cursor = len(parts) - 1
    module_name = parts[:cursor]
    attr_name = parts[-1]
    while cursor > 0:
        try:
            ret = __import__('.'.join(module_name), fromlist=[attr_name])
            break
        except ImportError:
            if cursor == 0:
                raise
            cursor -= 1
            module_name = parts[:cursor]
            attr_name = parts[cursor]
            ret = ''
    for part in parts[cursor:]:
        try:
            ret = getattr(ret, part)
        except AttributeError:
            raise ImportError(name)
    return ret


def v_tnorm(X, tnorm=None):
    """Calculates the given tnorm alongside the vector X"""
    tam = len(X)
    for ix, elem in enumerate(X):
        if ix == 0:
            acum_norm = tnorm(elem, X[ix + 1])
        elif ix < tam - 1:
            acum_norm = tnorm(acum_norm, X[ix + 1])
    return acum_norm


def simplify_provenance(proxy):
    """If there are multiple dates given for some of the provenance
    fields, we can logically conclude which one is the most meaningful."""
    for prop_name in ['modifiedAt', 'retrievedAt']:
        if proxy.has(prop_name, quiet=True):
            values = proxy.get(prop_name)
            proxy.set(prop_name, max(values))
    for prop_name in ['authoredAt', 'publishedAt']:
        if proxy.has(prop_name, quiet=True):
            values = proxy.get(prop_name)
            proxy.set(prop_name, min(values))
    return proxy


def liabilities(assets, equity):
    """
    Computes total liabilities.

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

    returns
    -------
    Returns total liabilities, int or float
    """
    return assets - equity


def _rescale_layout(pos, scale=1):
    """Return scaled position array to (-scale, scale) in all axes.

    The function acts on NumPy arrays which hold position information.
    Each position is one row of the array. The dimension of the space
    equals the number of columns. Each coordinate in one column.

    To rescale, the mean (center) is subtracted from each axis separately.
    Then all values are scaled so that the largest magnitude value
    from all axes equals `scale` (thus, the aspect ratio is preserved).
    The resulting NumPy Array is returned (order of rows unchanged).

    Parameters
    ----------
    pos : numpy array
        positions to be scaled. Each row is a position.

    scale : number (default: 1)
        The size of the resulting extent in all directions.

    Returns
    -------
    pos : numpy array
        scaled positions. Each row is a position.

    """
    lim = 0
    for i in range(pos.shape[1]):
        pos[:, (i)] -= pos[:, (i)].mean()
        lim = max(abs(pos[:, (i)]).max(), lim)
    if lim > 0:
        for i in range(pos.shape[1]):
            pos[:, (i)] *= scale / lim
    return pos


def get_monitor_table_constraints(data_dict, table_name):
    """Add any necessary table constrains to the given table via the
    ``data_dict``.

    Parameters
    ----------
    data_dict : dict
        A dictionary whose keys are column names and whose values
        are column definitions.
    table_name : str
        The name of the database table

    Returns
    -------
    data_dict : dict
        An updated ``data_dict`` with the approriate table constraints
        for the monitor added.
    """
    return data_dict


def plural(count):
    """
    Return plural word ending for english.
    I.e. 's' if count != 1 else ''.
    """
    return 's' if count != 1 else ''


def VARIANCE(src_column):
    """
    Builtin variance aggregator for groupby. Synonym for tc.aggregate.VAR

    Example: Get the rating variance of each user.

    >>> sf.groupby("user",
    ...            {'rating_var':tc.aggregate.VARIANCE('rating')})
    """
    return '__builtin__var__', [src_column]


def time_reversal(path, order_function, interfaces, start_condition):
    """Perform a time-reversal move.

    Parameters
    ----------
    path : object like :py:class:`.PathBase`
        This is the input path which will be used for generating a
        new path.
    order_function : object like :py:class:`.OrderParameter`
        The class used for obtaining the order parameter(s).
    interfaces : list/tuple of floats
        These are the interface positions of the form
        ``[left, middle, right]``.
    start_condition : string
        The starting condition, 'L'eft or 'R'ight.

    Returns
    -------
    out[0] : boolean
        True if the path can be accepted.
    out[1] : object like :py:class:`.PathBase`
        The time reversed path.
    out[2] : string
        Status of the path, this is one of the strings defined in
        `.path._STATUS`.

    """
    new_path = path.reverse(order_function)
    start, _, _, _ = new_path.check_interfaces(interfaces)
    if path.get_move() == 'ld':
        new_path.set_move('ld')
    else:
        new_path.generated = 'tr', 0, 0, 0
    if start == start_condition:
        accept = True
        status = 'ACC'
    else:
        accept = False
        status = 'BWI'
    new_path.status = status
    return accept, new_path, status


def get_destination(trip):
    """
    Return the Destination name for the trip
    :param trip: trip Object
    :return: string containing Destination name
    """
    destination = ''
    if 'destname' in trip.keys():
        destination = trip['destname']
    if destination == '':
        try:
            destination = trip['dest']
        except KeyError as e:
            destination = ''
    return destination


def list_jobs(accountId=None, vaultName=None, limit=None, marker=None,
    statuscode=None, completed=None):
    """
    This operation lists jobs for a vault, including jobs that are in-progress and jobs that have recently finished.
    To retrieve an archive or retrieve a vault inventory from Amazon Glacier, you first initiate a job, and after the job completes, you download the data. For an archive retrieval, the output is the archive data. For an inventory retrieval, it is the inventory list. The List Job operation returns a list of these jobs sorted by job initiation time.
    The List Jobs operation supports pagination. You should always check the response Marker field. If there are no more jobs to list, the Marker field is set to null . If there are more jobs to list, the Marker field is set to a non-null value, which you can use to continue the pagination of the list. To return a list of jobs that begins at a specific job, set the marker request parameter to the Marker value for that job that you obtained from a previous List Jobs request.
    You can set a maximum limit for the number of jobs returned in the response by specifying the limit parameter in the request. The default limit is 1000. The number of jobs returned might be fewer than the limit, but the number of returned jobs never exceeds the limit.
    Additionally, you can filter the jobs list returned by specifying the optional statuscode parameter or completed parameter, or both. Using the statuscode parameter, you can specify to return only jobs that match either the InProgress , Succeeded , or Failed status. Using the completed parameter, you can specify to return only jobs that were completed (true ) or jobs that were not completed (false ).
    For the underlying REST API, see List Jobs .
    See also: AWS API Documentation

    Examples
    The example lists jobs for the vault named my-vault.
    Expected Output:

    :example: response = client.list_jobs(
        vaultName='string',
        limit='string',
        marker='string',
        statuscode='string',
        completed='string'
    )

    :type accountId: string
    :param accountId: The AccountId value is the AWS account ID of the account that owns the vault. You can either specify an AWS account ID or optionally a single '- ' (hyphen), in which case Amazon Glacier uses the AWS account ID associated with the credentials used to sign the request. If you use an account ID, do not include any hyphens ('-') in the ID.
            Note: this parameter is set to '-' bydefault if no value is not specified.

    :type vaultName: string
    :param vaultName: [REQUIRED]
            The name of the vault.

    :type limit: string
    :param limit: The maximum number of jobs to be returned. The default limit is 1000. The number of jobs returned might be fewer than the specified limit, but the number of returned jobs never exceeds the limit.

    :type marker: string
    :param marker: An opaque string used for pagination. This value specifies the job at which the listing of jobs should begin. Get the marker value from a previous List Jobs response. You only need to include the marker if you are continuing the pagination of results started in a previous List Jobs request.

    :type statuscode: string
    :param statuscode: The type of job status to return. You can specify the following values: InProgress , Succeeded , or Failed .

    :type completed: string
    :param completed: The state of the jobs to return. You can specify true or false .

    :rtype: dict
    :return: {
        'JobList': [
            {
                'JobId': 'string',
                'JobDescription': 'string',
                'Action': 'ArchiveRetrieval'|'InventoryRetrieval',
                'ArchiveId': 'string',
                'VaultARN': 'string',
                'CreationDate': 'string',
                'Completed': True|False,
                'StatusCode': 'InProgress'|'Succeeded'|'Failed',
                'StatusMessage': 'string',
                'ArchiveSizeInBytes': 123,
                'InventorySizeInBytes': 123,
                'SNSTopic': 'string',
                'CompletionDate': 'string',
                'SHA256TreeHash': 'string',
                'ArchiveSHA256TreeHash': 'string',
                'RetrievalByteRange': 'string',
                'Tier': 'string',
                'InventoryRetrievalParameters': {
                    'Format': 'string',
                    'StartDate': 'string',
                    'EndDate': 'string',
                    'Limit': 'string',
                    'Marker': 'string'
                }
            },
        ],
        'Marker': 'string'
    }

    :returns:
    Archive retrieval jobs that specify a range that is not tree-hash aligned.
    Archival jobs that specify a range that is equal to the whole archive and the job status is InProgress.
    Inventory jobs.

    """
    pass


def defaultgroupsfinder(username, request):
    """ The c2cgeoportal default group finder. To be used as the callback of
    the ``AuthTktAuthenticationPolicy`` or any callback-based authentication
    policy. """
    if not hasattr(request, 'user') or request.user is None:
        return []
    role = request.user.role
    return [role.name] if role else []


def mostly_numerals(user_agent):
    """
    UserAgent string is mostly numeric, discard
    15B93
    """
    alphabetic_chars = 0
    for char in user_agent:
        if not char.isnumeric():
            alphabetic_chars += 1
    return alphabetic_chars < 2


def authtoken_method(token):
    """ an authentication method using rest_framework Token
    """
    from rest_framework.authtoken.models import Token
    user = Token.objects.filter(key=token).first()
    if user is not None:
        user = user.user
    return user


def t_heredoc_END_HEREDOC(t):
    """(?<=\\n)[A-Za-z_][\\w_]*"""
    if t.value == t.lexer.heredoc_label:
        del t.lexer.heredoc_label
        t.lexer.pop_state()
    else:
        t.type = 'ENCAPSED_AND_WHITESPACE'
    return t


def _validateArgs(wordArgs):
    """
    Insure the word args that were provided are valid.
    """
    if wordArgs['id'] == 'all':
        raise Exception("Cannot show changes from 'all' backups.")


def add_message_to_digest(msg):
    """
        Adds a message to the digest, to be delivered next time digest
        delivery occurs.
        """


def ifnone(o: any, default: any) ->any:
    """
    Returns `o` if it is not `None`; returns `default` otherwise.

    Parameters
    ----------
    o : any
        The value to be checked.
    default : any
        The default return value when `o` is `None`.

    Examples
    --------
    >>> ifnone(5, 'default-value')
    5

    >>> ifnone(None, 42)
    42
    """
    return o if o is not None else default


def remove_bottom_margin(ax):
    """Set bottom of plot to 0 y value."""
    ylim = 0, ax.get_ylim()[1]
    ax.set_ylim(*ylim)


def _numeric_selector(features, useful_cols):
    """
    Function skips numeric encoding and just selects the numeric features as specified in useful_cols

    Returns
    -------
    numeric_features_transformed : pandas.DataFrame
        Dataframe of transformed features

    """
    numeric_cols = useful_cols.loc[useful_cols.dtype == 'numeric', 'feature'
        ].values
    numeric_features = features[numeric_cols]
    return numeric_features


def radon_maintainability_parser(stdout, stderr, previous_reports=None):
    """
    Example line: apps/api/urls.py - A
    """
    lines = stdout.split('\n')[:-1]
    summary = {'A': 0, 'B': 0, 'C': 0}
    for line in lines:
        maintainability = line.split(' ')[2]
        assert maintainability in ['A', 'B', 'C']
        summary[maintainability] += 1
    summary['total'] = sum(summary.values())
    return {'stdout': stdout, 'stderr': stderr, 'summary': summary}


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


def coerce_put_post(request):
    """
    Django doesn't particularly understand REST.
    In case we send data over PUT, Django won't
    actually look at the data and load it. We need
    to twist its arm here.

    The try/except abominiation here is due to a bug
    in mod_python. This should fix it.
    """
    if request.method == 'PUT':
        if hasattr(request, '_post'):
            del request._post
            del request._files
        try:
            request.method = 'POST'
            request._load_post_and_files()
            request.method = 'PUT'
        except AttributeError:
            request.META['REQUEST_METHOD'] = 'POST'
            request._load_post_and_files()
            request.META['REQUEST_METHOD'] = 'PUT'
        request.PUT = request.POST


def sam_send(sock, line_and_data):
    """Send a line to the SAM controller, but don't read it"""
    if isinstance(line_and_data, tuple):
        line, data = line_and_data
    else:
        line, data = line_and_data, b''
    line = bytes(line, encoding='ascii') + b' \n'
    sock.sendall(line + data)


def freeze_model(model):
    """Freeze all model weights to prevent training."""
    for param in model.parameters():
        param.requires_grad = False
    return model


def create(name: str='Collection'):
    """Create an object collection from selected objects

    :param name: Name, Name of the new collection
    :type name: str
    """
    pass


def split_to_batches(start_incl, end_incl, batch_size):
    """start_incl and end_incl are inclusive, the returned batch ranges are also inclusive"""
    for batch_start in range(start_incl, end_incl + 1, batch_size):
        batch_end = min(batch_start + batch_size - 1, end_incl)
        yield batch_start, batch_end


@classmethod
def from_stream(cls, stream, marker_code, offset):
    """
        Extract the horizontal and vertical dots-per-inch value from the APP1
        header at *offset* in *stream*.
        """
    segment_length = stream.read_short(offset)
    if cls._is_non_Exif_APP1_segment(stream, offset):
        return cls(marker_code, offset, segment_length, 72, 72)
    tiff = cls._tiff_from_exif_segment(stream, offset, segment_length)
    return cls(marker_code, offset, segment_length, tiff.horz_dpi, tiff.
        vert_dpi)


def check(condition, message, *args, **kwargs):
    """Check state and raise exception if not valid"""
    if not condition:
        raise ValueError(message.format(*args, **kwargs))


def applications():
    """Return list of applications

    Applications are typically provided by the profile,
    this function is called when "Show all apps" is enabled.

    """
    return []


def iter_chunks(sizes, max_size):
    """Split sizes into chunks of total max_size each

    Parameters
    ----------
    sizes : iterable of numbers
        The sizes to be chunked
    max_size : number
        Maximum total size per chunk.
        It must be greater or equal than each size in sizes
    """
    chunk, chunk_sum = [], 0
    iter_sizes = iter(sizes)
    size = next(iter_sizes, None)
    while size is not None:
        assert size <= max_size
        if chunk_sum + size <= max_size:
            chunk.append(size)
            chunk_sum += size
            size = next(iter_sizes, None)
        else:
            assert chunk
            yield chunk
            chunk, chunk_sum = [], 0
    if chunk:
        yield chunk


def cli_billing_list_invoices(client, generate_url=False):
    """List all available invoices of the subscription"""
    return client.list(expand='downloadUrl' if generate_url else None)


@staticmethod
def init_target_configuration(target_configuration):
    """ Perform any module specific initialisation of the target
        target configuration.  Typically this is the initialisation of module
        specific attributes.  To avoid name clashes attributes should be given
        a module specific prefix.  target_configuration is the target
        configuration.
        """
    target_configuration.qtp_version = None
    target_configuration.qtp_sip_dir = None


def validate(form, actions, form_prefix, data, default_validate=None):
    """Process a submitted action, if any

        Check each of the given actions to see if any were submitted.

        If an action was submitted, then validate the input.  The input
        is called by calling the action's validator, ir it has one, or
        by calling the default_validate passed in.

        If the input is validated successfully, and the action has one
        success handler, then the success handler is called.

        If the input was validated and there were errors, then the
        action's failure handler will be called, if it has one.

        If an action was submitted, then the function returns the
        result of validation and the action.  The result of validation
        is normally a boolean, but may be None if no validator was
        provided.

        If no action was submitted, then None is returned for both the
        result of validation and the action.

        """


def session_draw_bis_melty(sessions_id, weblog, weblog_columns_dict):
    """
    Draw the graph of sessions with sessions_id given in entry
    """
    from graph_tool.all import Graph
    from graph_tool.all import graph_draw
    session = weblog[weblog.session_id == sessions_id]
    session = session.rename(index=str, columns={weblog_columns_dict[
        'requested_page_column']: 'requested_page', weblog_columns_dict[
        'referrer_page_column']: 'referrer_page'})
    s_pages = session[['requested_page', 'requested_external']]
    s_pages_ref = session[['referrer_page', 'referrer_external']]
    s_pages_ref = s_pages_ref.rename(index=str, columns={'referrer_page':
        'requested_page', 'referrer_external': 'requested_external'})
    s_pages = s_pages.append(s_pages_ref)
    s_pages.drop_duplicates(subset='requested_page', inplace=True)
    g = Graph()
    v = {}
    halo = g.new_vertex_property('bool')
    for row in s_pages.itertuples():
        v[row.requested_page] = g.add_vertex()
        if row.requested_external:
            halo[v[row.requested_page]] = True
        else:
            halo[v[row.requested_page]] = False
    session.apply(lambda x: g.add_edge(v[x.referrer_page], v[x.
        requested_page]), axis=1)
    graph_draw(g, vertex_halo=halo, output='./_session' + str(sessions_id) +
        '.png')
    return


def fix_order(correct_order, new_order, sorting):
    """
    Fixes the order of a list in `sorting` with `new_order` to
    match the index order layed out in `correct_order`.

    Parameters
    ----------
    correct_order : list.
        contains keys in the correct order, guides sorting of the list `sorting`
    new_order : list.
        contains same set of keys in correct_order, but in a different order.
    sorting : list.
        list to be sorted based on the order in `correct_order`.
    """
    if correct_order == new_order:
        return sorting, new_order
    new_idx_order = []
    for i in correct_order:
        new_idx_order += [new_order.index(i)]
    reordered_vals = []
    reordered_keys = []
    for i in range(len(new_idx_order)):
        reordered_vals += [sorting[new_idx_order[i]]]
        reordered_keys += [new_order[new_idx_order[i]]]
    assert correct_order == reordered_keys, 'keys not correctly ordered in `fix_order()`'
    return reordered_vals, reordered_keys


def _fit_text(text, length, filling=True):
    """裁剪或者填补字符串，控制其显示的长度

    >>> _fit_text('12345', 6)
    '12345 '
    >>> _fit_text('哈哈哈哈哈s', 6)  # doctest: -ELLIPSIS
    '哈哈 …'
    >>> _fit_text('哈s哈哈哈哈s', 6)  # doctest: -ELLIPSIS
    '哈s哈…'
    >>> _fit_text('sssss', 5)
    'sssss'

    FIXME: 这样可能会截断一些英文词汇
    """
    assert 80 >= length >= 5
    text_len = 0
    len_index_map = {}
    for i, c in enumerate(text):
        if ord(c) < 19968:
            text_len += 1
            len_index_map[text_len] = i
        else:
            text_len += 2
            len_index_map[text_len] = i
    if text_len <= length:
        if filling:
            return text + (length - text_len) * ' '
        return text
    remain = length - 1
    if remain in len_index_map:
        return text[:len_index_map[remain] + 1] + '…'
    else:
        return text[:len_index_map[remain - 1] + 1] + ' …'


def _m3_a8_profile(opts, node_class):
    """ Create a node_class profile from namespace object """
    profile = node_class(profilename=opts.name, power=opts.power_mode)
    profile.set_consumption(period=opts.period, average=opts.average, power
        =opts.power, voltage=opts.voltage, current=opts.current)
    profile.set_radio(mode=opts.mode, channels=opts.channels, period=opts.
        rperiod, num_per_channel=opts.num_per_channel)
    return profile


def shorten(x):
    """
    convert 3-letter amino acid name to 1-letter form
    Parameters
    ----------
    x : str , thrre letter aa sequence

    Returns
    y : str, one-letter aa sequence
    -------

    """
    d = {'CYS': 'C', 'ASP': 'D', 'SER': 'S', 'GLN': 'Q', 'LYS': 'K', 'ILE':
        'I', 'PRO': 'P', 'THR': 'T', 'PHE': 'F', 'ASN': 'N', 'GLY': 'G',
        'HIS': 'H', 'LEU': 'L', 'ARG': 'R', 'TRP': 'W', 'ALA': 'A', 'VAL':
        'V', 'GLU': 'E', 'TYR': 'Y', 'MET': 'M', 'UNK': 'U'}
    if len(x) % 3 != 0:
        raise ValueError('Input length should be a multiple of three')
    y = ''
    for i in range(int(len(x) / 3)):
        y += d[x[3 * i:3 * i + 3]]
    return y


def removeService(service):
    """
        Remove a service from this collection.
        """


def get_key_val_of_max_key(dict_obj):
    """Returns the key-value pair with the largest key in the given dict.

    Example:
    --------
    >>> dict_obj = {5: 'g', 3: 'z'}
    >>> print(get_key_val_of_max_key(dict_obj))
    (5, 'g')
    """
    return max(dict_obj.items(), key=lambda item: item[0])


def lookup_table_image_filter(*args, **kwargs):
    """Procedural interface for LookupTableImageFilter"""
    import itk
    instance = itk.LookupTableImageFilter.New(*args, **kwargs)
    return instance.__internal_call__()


def _check_is_max_context(doc_spans, cur_span_index, position):
    """Check if this is the 'max context' doc span for the token."""
    best_score = None
    best_span_index = None
    for span_index, doc_span in enumerate(doc_spans):
        end = doc_span.start + doc_span.length - 1
        if position < doc_span.start:
            continue
        if position > end:
            continue
        num_left_context = position - doc_span.start
        num_right_context = end - position
        score = min(num_left_context, num_right_context
            ) + 0.01 * doc_span.length
        if best_score is None or score > best_score:
            best_score = score
            best_span_index = span_index
    return cur_span_index == best_span_index


def p_top_statement_list(p):
    """top_statement_list : top_statement_list top_statement
                          | empty"""
    if len(p) == 3:
        p[0] = p[1] + [p[2]]
    else:
        p[0] = []


@classmethod
def execute(cls, session_id, data, state_name):
    """
        Execute the wizard state.

        session_id is a Session id
        data is a dictionary with the session data to update
        state_name is the name of state to execute

        Returns a dictionary with:
            - ``actions``: a list of Action to execute
            - ``view``: a dictionary with:
                - ``fields_view``: a fields/view definition
                - ``defaults``: a dictionary with default values
                - ``buttons``: a list of buttons
        """
    cls.check_access()
    wizard = cls(session_id)
    for key, values in data.items():
        record = getattr(wizard, key)
        for field, value in values.items():
            if field == 'id':
                continue
            setattr(record, field, value)
    return wizard._execute(state_name)


def argsort(seq):
    """ Returns a list of indices that would sort a list.

    Parameters
    ----------
    seq: List
        The list.

    Returns
    -------
    List[int]
        The list of indices that would sort the given list ``seq``.

    Notes
    -----
    If the returned list of indices can be a NumPy array, use `numpy.lexsort`
    instead. If the given list ``seq`` is a NumPy array, use `numpy.argsort`
    instead.

    """
    return sorted(range(len(seq)), key=seq.__getitem__)


def ensure_unicode(s):
    """Not all of PyObjC understands unicode paths very well yet"""
    if isinstance(s, bytes):
        return s.decode('utf-8')
    return s


def booleanValue(value):
    """Return True or False is value is something sensible.
        Else return None."""
    ix = value.find('#')
    if ix != -1:
        value = value[:ix].rstrip()
    lcvalue = value.lower()
    if lcvalue in ['true', 'yes', 'on']:
        return True
    if lcvalue in ['false', 'no', 'off']:
        return False


def get_keywords():
    """Get the keywords needed to look up the version information."""
    git_refnames = '$Format:%d$'
    git_full = '$Format:%H$'
    git_date = '$Format:%ci$'
    keywords = {'refnames': git_refnames, 'full': git_full, 'date': git_date}
    return keywords


def sequence_mass(sequence):
    """Return a mass for this sequence - initially will be 128.0 * len"""
    if isinstance(sequence, type(42)):
        return 128.0 * sequence
    return 128.0 * len(sequence)


def list_xz(archive, compression, cmd, verbosity, interactive):
    """List a XZ archive."""
    cmdlist = [cmd]
    cmdlist.append('-l')
    if verbosity > 1:
        cmdlist.append('-v')
    cmdlist.append(archive)
    return cmdlist


def bandgap_to_rgb(gap):
    """This converts a given wavelength of light to an
    approximate RGB color value. The wavelength must be given
    in nanometers in the range from 380 nm through 750 nm
    (789 THz through 400 THz).

    Based on code by Dan Bruton
    http://www.physics.sfasu.edu/astro/color/spectra.html

    INPUTS:
    bandgap --> bandgap of a molecule
    """
    wavelength = 1239.84187 / gap
    w = int(wavelength)
    if w >= 380 and w < 440:
        R = -(w - 440.0) / (440.0 - 350.0)
        G = 0.0
        B = 1.0
    elif w >= 440 and w < 490:
        R = 0.0
        G = (w - 440.0) / (490.0 - 440.0)
        B = 1.0
    elif w >= 490 and w < 510:
        R = 0.0
        G = 1.0
        B = -(w - 510.0) / (510.0 - 490.0)
    elif w >= 510 and w < 580:
        R = (w - 510.0) / (580.0 - 510.0)
        G = 1.0
        B = 0.0
    elif w >= 580 and w < 645:
        R = 1.0
        G = -(w - 645.0) / (645.0 - 580.0)
        B = 0.0
    elif w >= 645 and w <= 780:
        R = 1.0
        G = 0.0
        B = 0.0
    else:
        R = 0.0
        G = 0.0
        B = 0.0
    if w >= 380 and w < 420:
        SSS = 0.3 + 0.7 * (w - 350) / (420 - 350)
    elif w >= 420 and w <= 700:
        SSS = 1.0
    elif w > 700 and w <= 780:
        SSS = 0.3 + 0.7 * (780 - w) / (780 - 700)
    else:
        SSS = 0.0
    SSS *= 255
    return [int(SSS * R), int(SSS * G), int(SSS * B)]


def split_region(contents, region_name):
    """Split `contents` by region with `region_name`.

    Returns:
        Tuple[str, str, str]:
            A tuple containing the start block, region block, and end block.
            Start block contains the start region line. End block contains
            the end region line.

    Raises:
        ValueError:
            If could not find region with `region_name` or found duplicate
            region definitions of `region_name`.
    """
    start_line = f'<!--START {region_name}-->'
    end_line = f'<!--END {region_name}-->'
    start_lines = []
    region_lines = []
    end_lines = []
    found_start = False
    found_end = False
    for line_no, line in enumerate(contents.split('\n')):
        line_stripped = line.strip()
        if line_stripped == end_line:
            if found_end:
                raise ValueError(
                    f'Found duplicate end line "{end_line}" at line {line_no + 1}.'
                    )
            found_end = True
        if not found_start:
            start_lines.append(line)
        elif not found_end:
            region_lines.append(line)
        else:
            end_lines.append(line)
        if line_stripped == start_line:
            if found_start:
                raise ValueError(
                    f'Found duplicate start line "{start_line}" at line {line_no + 1}.'
                    )
            found_start = True
    if not found_start:
        raise ValueError(f'Could not find start line "{start_line}".')
    if not found_end:
        raise ValueError(f'Could not find end line "{end_line}".')
    start_block = '\n'.join(start_lines) + '\n'
    region_block = '\n'.join(region_lines) + '\n' if region_lines else ''
    end_block = '\n'.join(end_lines)
    return start_block, region_block, end_block


def _new_versions(quay, conda):
    """Calculate the versions that are in conda but not on quay.io."""
    sconda = set(conda)
    squay = set(quay) if quay else set()
    return sconda - squay


def reservation_scope(namespace, binding):
    """
    Get the namespaces that are in the bindings reservation scope

    Returns the namespace nodes the binding name must be resolvable in

    :param namespace: The local namespace of a binding
    :type namespace: :class:`ast.AST`
    :param binding: The binding to get the reservation scope for
    :type binding: Binding
    :rtype: set[ast.AST]

    """
    namespaces = set([namespace])
    for node in binding.references:
        while node is not namespace:
            namespaces.add(node.namespace)
            node = node.namespace
    return namespaces


def is_gesture(name: str) ->bool:
    """Return True or False to indicate if the named gesture is currently
    active."""


def get_metadata_lines(name):
    """Yield named metadata resource as list of non-blank non-comment lines

       Leading and trailing whitespace is stripped from each line, and lines
       with ``#`` as the first non-blank character are omitted."""


@classmethod
def autoScroller(cls):
    """
        Class method to get a reference to the auto scroller.

        @return reference to the auto scroller object
        @rtype AutoScroller
        """
    if cls._autoScroller is None:
        from .AutoScroll.AutoScroller import AutoScroller
        cls._autoScroller = AutoScroller()
    return cls._autoScroller


def get_form_url(request, protocol='http', preview=False):
    """
    Return a form list url endpoint to be used to make a request to Enketo.

    For example, it will return https://example.com and Enketo will know to
    look for the form list at https://example.com/formList. If a username is
    provided then Enketo will request the form list from
    https://example.com/[username]/formList. Same applies for preview if
    preview is True and also to a single form when xform_pk is provided.
    """
    http_host = request.META.get('HTTP_HOST',
        'dev.monitora.sisicmbio.icmbio.gov.br')
    url = '%s://%s' % (protocol, http_host)
    if preview:
        url = '%s/preview' % url
    return '{}/xform'.format(url)


def _result_iter(cursor, arraysize):
    """An iterator that uses fetchmany to keep memory usage down"""
    while True:
        results = cursor.fetchmany(arraysize)
        if not results:
            break
        for result in results:
            yield result


def chunks(iterable, chunk_size):
    """ Splits iterable objects into chunk of fixed size.
    The last chunk may be truncated.
    """
    chunk = []
    for item in iterable:
        chunk.append(item)
        if len(chunk) == chunk_size:
            yield chunk
            chunk = []
    if chunk:
        yield chunk


def noparser(xmlthing):
    """Keep the raw response from the service."""
    return xmlthing


@classmethod
def _from_dict(cls, _dict):
    """Initialize a ToneInput object from a json dictionary."""
    args = {}
    if 'text' in _dict:
        args['text'] = _dict.get('text')
    else:
        raise ValueError(
            "Required property 'text' not present in ToneInput JSON")
    return cls(**args)


def _get_csv_fieldnames(csv_reader):
    """Find fieldnames in Polarion exported csv file."""
    fieldnames = []
    for row in csv_reader:
        for col in row:
            field = col.strip().replace('"', '').replace(' ', '').replace('(',
                '').replace(')', '').lower()
            fieldnames.append(field)
        if 'id' in fieldnames:
            break
        del fieldnames[:]
    if not fieldnames:
        return None
    while True:
        field = fieldnames.pop()
        if field:
            fieldnames.append(field)
            break
    suffix = 1
    for index, field in enumerate(fieldnames):
        if not field:
            fieldnames[index] = 'field{}'.format(suffix)
            suffix += 1
    return fieldnames


@classmethod
def new(cls, cipher_name, key, iv, mac_alg=b'', mac_key=b'', etm=False):
    """Construct a new SSH packet encryption object"""
    raise NotImplementedError


def maybe_evaluate(obj):
    """Try to evaluate and return the passed object."""
    try:
        return obj.__maybe_evaluate__()
    except AttributeError:
        return obj


def gap_insert(frames: int=10):
    """Insert gap at current frame to first strips at the right, independent of selection or locked state of strips

    :param frames: Frames, Frames to insert after current strip
    :type frames: int
    """
    pass


@classmethod
def fixed_length(cls, l, allow_empty=False):
    """Create a sedes for binary data with exactly `l` bytes."""
    return cls(l, l, allow_empty=allow_empty)


def strip_magics(source):
    """
    Given the source of a cell, filter out all cell and line magics.
    """
    filtered = []
    for line in source.splitlines():
        if not line.startswith('%') or line.startswith('%%'):
            filtered.append(line)
    return '\n'.join(filtered)


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

        :param CreateFolderEntryResult val:
        :rtype: CreateFolderBatchResultEntry
        """
    return cls('success', val)


def lookupAll(required, provided):
    """Find all adapters from the required to the provided interfaces

        An iterable object is returned that provides name-value two-tuples.
        """


def check_dataset_shape(dataset):
    """Confirm the dataset has shape 3 x nrows x ncols."""
    if len(dataset.shape) != 3:
        raise ValueError('Each image needs 3 dimensions: rgb, nrows, ncols')
    if dataset.shape[0] != 3:
        raise ValueError(
            """The dataset's first dimension must have all 3
colors: red, green, and blue...in that order."""
            )


@classmethod
def from_tuskar_model(cls, role):
    """Translates from the Tuskar domain model.

        :type role: tuskar.manager.models.Role
        """
    r = cls(**{'uuid': role.uuid, 'name': role.name, 'version': role.
        version, 'description': role.description})
    return r


def build_option_parser(parser):
    """Hook to add global options"""
    return parser


def take(data, indices, dim):
    """Takes elements from an input array along the given dim.

    Parameters
    ----------
    data : Tensor
        The data tensor.
    indices : Tensor
        The indices tensor.
    dim : Tensor
        The dimension to gather along.
    """
    pass


def check_context(container):
    """ same as isAllowed, but raises HTTPForbidden """


@classmethod
def next_session_id(cls):
    """Return the next unique session ID."""
    session_id = cls._next_session_id
    cls._next_session_id += 1
    return session_id


def get_url(locale, workspace, webservice):
    """Form an absolute Azure ML url and return it as a string.

    :param locale: Azure region.
    :param workspace: Azure ML workspace id.
    :param webservice: Azure ML webservice id.
    :return: str
    """
    return (
        'https://{}.management.azureml.net/workspaces/{}/webservices/{}/endpoints'
        .format(locale, workspace, webservice))


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 echo_worker(data):
    """
    Example of worker that simply echoes back the received data.

    :param data: Request data dict.
    :returns: True, data
    """
    print('echo worker running')
    return data


def validate_scopes(scope_guess, scope_matcher):
    """Check the scope guess against a set of possible scopes and return correct scope_id."""
    scope_matches = []
    for scope_match in scope_matcher:
        if scope_guess == str(scope_match['number']):
            scope_matches.append(scope_match)
        elif len(scope_guess) >= 2 and scope_guess.lower() in scope_match[
            'scope_id'].lower():
            scope_matches.append(scope_match)
        elif scope_guess.lower() in scope_match['scope'].lower():
            scope_matches.append(scope_match)
    if len(scope_matches) == 1:
        return scope_matches[0]
    print('Could not match; be more specific')
    return None


def parse_float(value, default=0.0):
    """Convert 'value' to float"""
    if not value:
        return default
    try:
        return float(value)
    except (ValueError, TypeError):
        return default


def _set_optimizer_param(optimizer, param_group, param_name, value):
    """Set a parameter on an all or a specific parameter group of an
    optimizer instance. To select all param groups, use ``param_group='all'``.
    """
    if param_group == 'all':
        groups = optimizer.param_groups
    else:
        groups = [optimizer.param_groups[int(param_group)]]
    for group in groups:
        group[param_name] = value


@classmethod
def from_dict(cls, data: dict) ->'Field':
    """
        Creates a :class:`~github.query.Field` object from a dict.

        Parameters
        ----------
        data: :class:`dict`
            The dict to convert into a :class:`~github.query.Field`.

        Returns
        -------
        :class:`~github.query.Field`
            The field object.
        """
    name = data['name']
    alias = data.get('alias', None)
    field = cls(name=name, alias=alias)
    return field


@staticmethod
def raw_value():
    """
        Whether the instruction needs the raw data, or if the value can be
        shell expanded.

        * **return:** True, if the instruction needs non-shell-expanded value.
        """
    return False


def FormatClassToPython(i):
    """
    Transform a typed class name into a form which can be used as a python
    attribute

    example::

        >>> FormatClassToPython('Lfoo/bar/foo/Barfoo$InnerClass;')
        'Lfoo_bar_foo_Barfoo_InnerClass'

    :param i: classname to transform
    :rtype: str
    """
    i = i[:-1]
    i = i.replace('/', '_')
    i = i.replace('$', '_')
    return i


def partitioned(items, n=3):
    """Partition items into n buckets."""
    max_items_per_bucket, rem = divmod(len(items), n)
    if rem:
        max_items_per_bucket += 1
    bucket = []
    for item in items:
        if len(bucket) >= max_items_per_bucket:
            yield bucket
            bucket = []
        bucket.append(item)
    yield bucket


@classmethod
def decode_ssh_public(cls, packet):
    """Decode an SSH format RSA public key"""
    e = packet.get_mpint()
    n = packet.get_mpint()
    return n, e


def _format_list_items(list_items):
    """Generate an indented string out of a list of items."""
    list_string = ''
    if list_items:
        for item in list_items:
            list_string = list_string + "    '" + item + "',\n"
        list_string = '[\n    {}\n]'.format(list_string.strip()[:-1])
    else:
        list_string = '[]'
    return list_string


def generate_semantic_data_key(used_semantic_keys):
    """ Create a new and unique semantic data key

    :param list used_semantic_keys: Handed list of keys already in use
    :rtype: str
    :return: semantic_data_id
    """
    semantic_data_id_counter = -1
    while True:
        semantic_data_id_counter += 1
        if 'semantic data key ' + str(semantic_data_id_counter
            ) not in used_semantic_keys:
            break
    return 'semantic data key ' + str(semantic_data_id_counter)


@classmethod
def from_string(cls, string):
    """
        Instantiates a pred from a string, normalising as necessary
        """
    normalised = cls.normalise_string(string)
    return cls.from_normalised_string(normalised)


def question(text: str) ->str:
    """Get text prefixed with a question emoji.

    Returns
    -------
    str
        The new message.

    """
    return '❓ {}'.format(text)


def parse_categories(dataframe, **parse_args):
    """
    A function to parse out categories from sequence IDs

    parse_arguments can be:
    - delimiter: character vector to split ID
    - field: field number in 0-index designating which field to keep
    OR
    - regex: a regex expression with a single capture group
    OR
    - callback: a function that takes the seqid and returns the
        category
    """
    if 'delimiter' in parse_args.keys():
        delimiter = parse_args['delimiter']
        field = int(parse_args['field'])
        dataframe['category'] = dataframe.seqid.str.split(delimiter).str.get(
            field)
    elif 'regex' in parse_args.keys():
        regex = parse_args['regex']
        dataframe['category'] = dataframe.seqid.str.extract(regex, expand=False
            )
    elif 'callback' in parse_args.keys():
        callback = parse_args['callback']
        dataframe['category'] = dataframe.seqid.apply(lambda s: callback(s))
    else:
        raise Exception('Not sure how to parse categories.')
    return dataframe


@classmethod
def execute(cls, cmd, env=None, cwd=None, stdin_payload=None, **kwargs):
    """Execute a command via subprocess.Popen and returns the stdio.

    :param string|list cmd: A list or string representing the command to run.
    :param dict env: An environment dict for the execution.
    :param string cwd: The target cwd for command execution.
    :param string stdin_payload: A string representing the stdin payload, if any, to send.
    :return: A tuple of strings representing (stdout, stderr), pre-decoded for utf-8.
    :raises: `Executor.ExecutableNotFound` when the executable requested to run does not exist.
             `Executor.NonZeroExit` when the execution fails with a non-zero exit code.
    """
    process = cls.open_process(cmd=cmd, env=env, cwd=cwd, **kwargs)
    stdout_raw, stderr_raw = process.communicate(input=stdin_payload)
    stdout = stdout_raw.decode('utf-8'
        ) if stdout_raw is not None else stdout_raw
    stderr = stderr_raw.decode('utf-8'
        ) if stderr_raw is not None else stderr_raw
    if process.returncode != 0:
        raise cls.NonZeroExit(cmd, process.returncode, stdout, stderr)
    return stdout, stderr


def config_view():
    """ Plugin configuration """


def cut_microsoft_quote(html_message):
    """ Cuts splitter block and all following blocks. """
    splitter = html_message.xpath(
        "//div[@style='border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0cm 0cm 0cm']|//div[@style='border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in']|//div[@style='border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0cm 0cm 0cm']|//div[@style='border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in']|//div[@style='padding-top: 5px; border-top-color: rgb(229, 229, 229); border-top-width: 1px; border-top-style: solid;']"
        )
    if splitter:
        splitter = splitter[0]
        if splitter == splitter.getparent().getchildren()[0]:
            splitter = splitter.getparent()
    else:
        splitter = html_message.xpath(
            "//div/div[@class='MsoNormal' and @align='center' and @style='text-align:center']/font/span/hr[@size='3' and @width='100%' and @align='center' and @tabindex='-1']"
            )
        if len(splitter):
            splitter = splitter[0]
            splitter = splitter.getparent().getparent()
            splitter = splitter.getparent().getparent()
    if len(splitter):
        parent = splitter.getparent()
        after_splitter = splitter.getnext()
        while after_splitter is not None:
            parent.remove(after_splitter)
            after_splitter = splitter.getnext()
        parent.remove(splitter)
        return True
    return False


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 _hgvs_to_zbc(i):
    """Convert hgvs (1 based, missing zero) """
    if i >= 1:
        i -= 1
    return i


def p_indexes(t):
    """trackitems : trackitem
                  | trackitems trackitem"""
    if len(t) == 2:
        t[0] = [t[1]]
    else:
        t[0] = t[1] + [t[2]]


def size(fontid: int, size: int, dpi: int):
    """Set the size and dpi for drawing text.

    :param fontid: The id of the typeface as returned by blf.load(), for default font use 0.
    :type fontid: int
    :param size: Point size of the font.
    :type size: int
    :param dpi: dots per inch value to use for drawing.
    :type dpi: int
    """
    pass


def not_contains(x, y):
    """
    Python's operator module does not have a function for the ``not in`` operator. That's a shame.
    """
    return y not in x


@classmethod
def header_prevhash(cls, header):
    """Given a header return previous hash"""
    return header[4:36]


def docstr2rst(docstr):
    """Return reStructuredText from docstring"""
    idx_whitespace = len(docstr.rstrip()) - len(docstr)
    whitespace = docstr[idx_whitespace:]
    return eval(docstr) + whitespace


def remove(filename, space):
    """Remove file from given space.

        """


@staticmethod
def _parse(spec):
    """Parse an alias name, arguments and definition"""
    raise NotImplementedError


def original_msg(e):
    """Undo oslo-messaging added traceback to return original exception msg"""
    msg = e.args[0].split('\nTraceback (most recent call last):')[0]
    if len(msg) != len(e.args[0]):
        if len(msg) > 0 and msg[-1] in ("'", '"'):
            msg = msg[:-1]
        if len(msg) > 1 and msg[0:2] in ('u"', "u'"):
            msg = msg[2:]
        elif len(msg) > 0 and msg[0] in ("'", '"'):
            msg = msg[1:]
        return msg
    else:
        return e.args[0]


def set_sqlite_autocommit(cn, autocommit):
    """SQLite autocommit setter for core."""
    if isinstance(autocommit, bool):
        cn.isolation_level = None if autocommit else ''
    else:
        cn.isolation_level = autocommit