def humanize_time(secs):
    """
    Takes *secs* and returns a nicely formatted string
    """
    mins, secs = divmod(secs, 60)
    hours, mins = divmod(mins, 60)
    return '%02d:%02d:%02d' % (hours, mins, secs)


def unfold_indices(obj, indices):
    """Unfolds an index chain and returns the corresponding item"""
    original_obj = obj
    for depth, idx in enumerate(indices):
        try:
            obj = obj[idx]
        except IndexError:
            print(
                "IndexError while accessing an item from '{}' at depth {} ({}) using the index chain {}"
                .format(repr(original_obj), depth, idx, indices))
            raise
    return obj


def rgb2html(colour):
    """
    Transforms a RGB triplet into an html hex string.

    :param `colour`: a tuple of red, green, blue integers.
    """
    hexColour = '#%02x%02x%02x' % (colour.r, colour.g, colour.b)
    return hexColour.upper()


def __split_line__(line):
    """
    Cut the line to extract the different fields
    """
    name, ref_url, ioc = line.split(' ')
    name = name.strip()
    ref_url = ref_url.strip()
    ioc = ioc.strip()
    return name, ioc, ref_url


def get_wins(point_margin):
    """Determine a win based on the point margin.

    Parameters
    ----------
    point_margin : int
        The point margin can be positive, zero, or negative.

    Returns
    -------
    won : int
        If the point margin is greater than 0, return 1, else 0.

    """
    won = 1 if point_margin > 0 else 0
    return won


def get_styles():
    """
    Return inline css styles
    """
    style = (
        'background: #3f51b5;display: block;font-size: 13px;font-weight: 100;font-family: Helvetica,Arial,sans-serif;text-transform: uppercase;text-align: center;letter-spacing: 1px;text-decoration: none;margin: 0 auto;line-height: 62px;width: 300px;height: 60px;-webkit-border-radius: 3px;-moz-border-radius: 3px;border-radius: 3px;color: #ffffff;webkit-text-size-adjust: none;mso-hide: all;'
        )
    return style


def _google_docs():
    """
    Returns a query item matching messages that have Google Docs attachments.

    """
    return f'has:document'


def lambd_NH3_CO3_CB89(T, P):
    """n-a: ammonia carbonate [CB89]."""
    lambd = 0.18
    valid = T == 298.15
    return lambd, valid


def pathsplit(path):
    """Split a /-delimited path into a directory part and a basename.

    :param path: The path to split.
    :return: Tuple with directory name and basename
    """
    try:
        dirname, basename = path.rsplit('/', 1)
    except ValueError:
        return '', path
    else:
        return dirname, basename


def shorten(s, N=80):
    """
    Return short representation of string s.

    If len(s) <= N return the whole s. Otherwise return string containing the
    begin and end of s.
    """
    if len(s) <= N:
        return s[:]
    else:
        l = (N - 5) / 2
        return '{} ... {}'.format(s[:l], s[-l:])


def pad_line(line):
    """Helper function to pad line to 80 characters in case it is shorter"""
    size_of_line = len(line)
    if size_of_line < 80:
        padding = 80 - size_of_line + 1
        line = line.strip('\n') + ' ' * padding + '\n'
    return line[:81]


def describe_security_configuration(Name=None):
    """
    Provides the details of a security configuration by returning the configuration JSON.
    See also: AWS API Documentation

    :example: response = client.describe_security_configuration(
        Name='string'
    )

    :type Name: string
    :param Name: [REQUIRED]
            The name of the security configuration.

    :rtype: dict
    :return: {
        'Name': 'string',
        'SecurityConfiguration': 'string',
        'CreationDateTime': datetime(2015, 1, 1)
    }

    """
    pass


def invoke_request(request):
    """
        Invoke the :app:`Pyramid` request pipeline.

        See :ref:`router_chapter` for information on the request pipeline.

        The output should be a :class:`pyramid.interfaces.IResponse` object
        or a raised exception.

        """


def truncate(content, length=100, suffix='...'):
    """
    Truncates a string after a certain number of characters.
    Function always tries to truncate on a word boundary.
    :rtype str
    """
    if len(content) <= length:
        return content
    else:
        return content[:length].rsplit(' ', 1)[0] + suffix


def allow_all(*args, **kwargs):
    """Return dummy permission that always allow an access.

    :returns: A object instance with a ``can()`` method.
    """
    return type('AllowAll', (), {'can': lambda self: True})()


@classmethod
def short2full(cls, code):
    """Convert an ISO 3166-2 country code to the corresponding full name"""
    return cls._country_map.get(code.upper())


def phi(n, p, q):
    """
    Euler's totient function for n which can be written as pq

    This is the number of k in the range 0 <= k <= n where
    gcd(n, k) is = 1 or, in other words, the number of integers
    k <= n that are relatively prime to n.
    """
    return n + 1 - (p + q)


def target_to_difficulty(target):
    """
    Calculate difficulty from target

    :param target: integer.
    :return: float.
    """
    return (
        26959535291011309493156476344723991336010898738574164086137773096960 /
        target)


def exists(file, paths):
    """check if the given file exists in one of the given paths"""
    import os, glob
    for path in paths:
        p = os.path.join(path, file)
        if glob.glob(p):
            return True
        continue
    return False


def find_values(x, k, sep=':', fun=None):
    """Find values in a list of strings containing [k][sep][values]

    Parameters
    ----------
    x : iterable
        Iterable of strings representing lines in a file.
    k : str
        A key or pattern that to search x for.
    sep : str
        A separator that divides the `k` pattern from the target value.
    fun : function-like, optional
        Function used to format target value before returning.

    Returns
    -------
    The target value is returned after removing excess whitespace from left
    and right of the value. If the key or target pattern is not found,
    then None is returned. If an empty string, or whitespace is the found
    value, then None is returned.
    """
    out = None
    for l in x:
        if k in l and sep in l:
            val = l.split(sep, maxsplit=1)[1:][0].lstrip().rstrip()
            if val != '':
                out = val
    if fun is not None and out is not None:
        out = fun(out)
    return out


def _msg(e):
    """Generate a user friendly error message."""
    return e.message


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 getstrippoint(minlink):
    """Find minimum revision that must be stripped to strip a linkrev.

        See the documentation in ``ifilemutation`` for more.
        """


def is_numpy_convertable(v):
    """
    Return whether a value is meaningfully convertable to a numpy array
    via 'numpy.array'
    """
    return hasattr(v, '__array__') or hasattr(v, '__array_interface__')


def prepare_stop_stream_response(stop_stream_response: dict) ->dict:
    """
    Prepares an API response to be returned to the client based on the result of
    stop_stream.
    :param stop_stream_response: the result of stop_stream
    :return: a serialized string suitable for passing to the client
    """
    serialized_stream = {}
    serialized_stream['id'] = stop_stream_response['stream'].id
    serialized_stream['name'] = stop_stream_response['stream'].name
    serialized_stream['start_date'] = stop_stream_response['stream'].start_date
    serialized_stream['stop_date'] = stop_stream_response['stream'].stop_date
    return {'stream': serialized_stream}


def unix_path_join(*args):
    """Join paths using unix slashes.

    Args:
        *args: a list of strings

    Returns:
        string: the joined list
    """
    return '/'.join(args)


def add_deregister_args(parser):
    """Add the deregister command and arguments.

    :param argparse.Subparser parser: parser

    """
    registerp = parser.add_parser('deregister', help=
        'Deregister a service for this node')
    registerp.add_argument('service_id', help='The service registration id')


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

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

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


def inverseQFT(qc, reg, n, pie):
    """
    Performs the inverse quantum Fourier transform on a register reg.
    Apply repeated phase rotations with parameters being pi divided by
    decreasing powers of two, and then apply a Hadamard gate to the nth qubit
    of the register reg.
    """
    for i in range(0, n):
        qc.cu1(-1 * pie / float(2 ** (n - i)), reg[i], reg[n])
    qc.h(reg[n])


def parseSetEnv(l):
    """
    Parses a list of strings of the form "NAME=VALUE" or just "NAME" into a dictionary. Strings
    of the latter from will result in dictionary entries whose value is None.

    :type l: list[str]
    :rtype: dict[str,str]

    >>> parseSetEnv([])
    {}
    >>> parseSetEnv(['a'])
    {'a': None}
    >>> parseSetEnv(['a='])
    {'a': ''}
    >>> parseSetEnv(['a=b'])
    {'a': 'b'}
    >>> parseSetEnv(['a=a', 'a=b'])
    {'a': 'b'}
    >>> parseSetEnv(['a=b', 'c=d'])
    {'a': 'b', 'c': 'd'}
    >>> parseSetEnv(['a=b=c'])
    {'a': 'b=c'}
    >>> parseSetEnv([''])
    Traceback (most recent call last):
    ...
    ValueError: Empty name
    >>> parseSetEnv(['=1'])
    Traceback (most recent call last):
    ...
    ValueError: Empty name
    """
    d = dict()
    for i in l:
        try:
            k, v = i.split('=', 1)
        except ValueError:
            k, v = i, None
        if not k:
            raise ValueError('Empty name')
        d[k] = v
    return d


def _get_cached_func_name_md(func):
    """Get markdown representation of the function name."""
    if hasattr(func, '__name__'):
        return '`%s()`' % func.__name__
    else:
        return 'a cached function'


def _max_steps(i, j, max_length, length_1, length_2):
    """Maximum number of steps required in a L-DTW process to reach a given
    cell.

    Parameters
    ----------
    i : int
        Cell row index

    j : int
        Cell column index

    max_length : int
        Maximum allowed length

    length_1 : int
        Length of the first time series

    length_2 : int
        Length of the second time series

    Returns
    -------
    int
        Number of steps
    """
    candidate_1 = i + j
    candidate_2 = max_length - max(length_1 - i - 1, length_2 - j - 1)
    return min(candidate_1, candidate_2)


def describe_tags(ResourceId=None):
    """
    Describes tags for a WorkSpace.
    See also: AWS API Documentation

    :example: response = client.describe_tags(
        ResourceId='string'
    )

    :type ResourceId: string
    :param ResourceId: [REQUIRED]
            The resource ID of the request.

    :rtype: dict
    :return: {
        'TagList': [
            {
                'Key': 'string',
                'Value': 'string'
            },
        ]
    }

    """
    pass


@classmethod
def _iterable_to_header_element(cls, iterable):
    """
        Convert iterable of tuples into header element ``str``.

        Each tuple is expected to be in one of two forms: (media_range, qvalue,
        extension_params_segment), or (media_range, qvalue).
        """
    try:
        media_range, qvalue, extension_params_segment = iterable
    except ValueError:
        media_range, qvalue = iterable
        extension_params_segment = ''
    if qvalue == 1.0:
        if extension_params_segment:
            element = '{};q=1{}'.format(media_range, extension_params_segment)
        else:
            element = media_range
    elif qvalue == 0.0:
        element = '{};q=0{}'.format(media_range, extension_params_segment)
    else:
        element = '{};q={}{}'.format(media_range, qvalue,
            extension_params_segment)
    return element


def play(snd):
    """Play Sound snd from beginning to end."""
    snd.play()


def main():
    """lets run this thing"""


def get_constraint_scores(lines):
    """Return a generator with exac constraint scores

        Args:
            lines (Iterator): The lines of the file

        Yields:
            constraint_scores(tuple(hgnc_id, constraint_scores))

    """
    for i, line in enumerate(lines):
        if i > 0:
            line = line.rstrip().split('\t')
            info = line[3].split('|')
            hgnc_id = line[1]
            constraint_score = line[-1]
            yield hgnc_id, constraint_score


@classmethod
def from_file(cls, path, encoding, dialect, fields, converters):
    """Read delimited text from a text file."""
    return cls(open(path, 'r', encoding=encoding), dialect, fields, converters)


def get_atomic_numbers(mol, indices):
    """Get the atomic numbers for the specified atoms.

    Parameters
    ----------
    mol : rdkit.Chem.rdchem.Mol
        RDKit molecule instance.
    indices : list of int
        Specifying atoms.

    Returns
    -------
    list of int
        Atomic numbers computed.
    """
    atomic_numbers = []
    for i in indices:
        atom = mol.GetAtomWithIdx(i)
        atomic_numbers.append(atom.GetAtomicNum())
    return atomic_numbers


def supplements(parms, countrate=None):
    u"""Supplementary parameters:
        [8] n₁ = n*F₁     Particle number of species 1
        [9] n₂ = n*(1-F₁) Particle number of species 2
    """
    n = parms[0]
    F1 = parms[3]
    Info = list()
    Info.append([u'n₁', n * F1])
    Info.append([u'n₂', n * (1.0 - F1)])
    if countrate is not None:
        cpp = countrate / n
        Info.append(['cpp [kHz]', cpp])
    return Info


def config_read_prefixed_options(conf, prefix_name, defaults):
    """
    Read prefixed options from configuration

    :param conf: the configuration
    :param prefix_name: the prefix (including, if needed, an underscore)
    :param defaults: a dict of default values. The dict supplies the
                     option name and type (string or comma separated string)
    :return: a dict containing the options
    """
    params = {}
    for option_name in defaults.keys():
        value = conf.get('%s%s' % (prefix_name, option_name))
        if value:
            if isinstance(defaults.get(option_name), list):
                params[option_name] = []
                for role in value.lower().split(','):
                    params[option_name].append(role.strip())
            else:
                params[option_name] = value.strip()
    return params


def copy_to(input, ctx):
    """Copy the given tensor to the context.

    Parameters
    ----------
    input : Tensor
        The input tensor
    ctx :
        A framework-specific context object.

    Returns
    -------
    Tensor
        The tensor on the given context.
    """
    pass


def base_n_to_int(string, charset):
    """Convert a base-N string into an integer using a given character set.

    :param str string: The string to convert
    :param str charset: The character set to use for the conversion
    :returns str: The converted string
    :raises ValueError: If `charset` contains duplicate characters

    """
    if len(charset) > len(set(charset)):
        raise ValueError('character set contains duplicate characters')
    base = len(charset)
    integer = 0
    for index, char in enumerate(reversed(string)):
        integer += charset.index(char) * base ** index
    return integer


def __call__(context, request):
    """Return a CatalogNavTree instance."""


def safe_communicate(subproc, stdin=''):
    """Executes a Popen.communicate and returns output in a way that is
    compatible with Python 2 & 3 keeping input and output as strings (since
    Python 3 requires bytes objects otherwise)"""
    if not subproc.universal_newlines:
        stdin = stdin.encode('utf-8') if hasattr(stdin, 'encode') else stdin
    stdout, stderr = map(lambda x: x.decode() if hasattr(x, 'decode') else
        x, subproc.communicate(stdin))
    return stdout, stderr


def split_int_colon(modes, nmax=1000):
    """
    Uses numpy-ish syntax to parse a set of integers.  Values are inclusive.
    Blanks are interpreted as 0.

    Parse the following:
       1:10
       1:
       :100
       1:5:2
       :5,11:15:2,10:20
    """
    modes2 = []
    if modes is not None:
        smodes = modes.strip().split(',')
        for mode in smodes:
            mode = mode.strip()
            if ':' in mode:
                smode = mode.split(':')
                if len(smode) == 2:
                    if smode[0] == '':
                        smode[0] = 0
                    istart = int(smode[0])
                    if smode[1] == '':
                        iend = None
                        modes2 = slice(istart, nmax)
                        assert len(smodes) == 1, smodes
                    else:
                        iend = int(smode[1])
                        assert iend > istart, 'smode=%s; istart=%s iend=%s' % (
                            smode, istart, iend)
                        modes2 += list(range(istart, iend + 1))
                elif len(smode) == 3:
                    istart = int(smode[0])
                    iend = int(smode[1])
                    assert iend > istart, 'smode=%s; istart=%s iend=%s' % (
                        smode, istart, iend)
                    istep = int(smode[2])
                    modes2 += list(range(istart, iend + 1, istep))
                else:
                    raise NotImplementedError('smode=%r; len=%s' % (smode,
                        len(smode)))
            else:
                imode = int(mode)
                modes2.append(imode)
        modes = modes2
    try:
        modes.sort()
    except AttributeError:
        pass
    return modes


def get_innermost_rightmost_group(expression, group_start_char='(',
    group_end_char=')'):
    """
    Given an expression and group start/end identifier characters,
    returns the innermost rightmost group. For example:
    '(2-1)+((3-4)-(2*5))', '(', ')' results in '2*5'
    """
    start_index = expression.rfind(group_start_char)
    end_index = start_index + expression[start_index:].find(group_end_char)
    return expression[start_index + 1:end_index]


def line(line, types, null_value=None, columns=None):
    """
    Parses a tsv line
    :param line: The line to parse
    :param types: fields types
    :param null_value: value to interpret as a None
    :param columns: which columns to return
    :return: selected columns
    """
    assert columns is None or len(types) == len(columns)
    fields = line.rstrip('\n').split('\t')
    flen = len(fields)
    res = list()
    for i, vtype in enumerate(types):
        if columns is not None:
            index = columns[i]
        else:
            index = i
        if index < flen:
            field = fields[index]
        else:
            field = null_value
        if i < flen and (null_value is None or field != null_value):
            field = vtype(field)
        else:
            field = None
        res += [field]
    return tuple(res)


def mem(dic, data):
    """
    Maximum Entropy Reconstruction
    """
    raise NotImplementedError


@staticmethod
def get_output_shape(sym, **input_shapes):
    """Get user friendly information of the output shapes."""
    _, s_outputs, _ = sym.infer_shape(**input_shapes)
    return dict(zip(sym.list_outputs(), s_outputs))


def _check_valid(key, val, valid):
    """Helper to check valid options"""
    if val not in valid:
        raise ValueError('%s must be one of %s, not "%s"' % (key, valid, val))


def zcml_strings(dir, domain='zope', site_zcml=None):
    """Retrieve all ZCML messages from `dir` that are in the `domain`."""
    from zope.configuration import xmlconfig, config
    context = config.ConfigurationMachine()
    xmlconfig.registerCommonDirectives(context)
    context.provideFeature('devmode')
    context = xmlconfig.file(site_zcml, context=context, execute=False)
    return context.i18n_strings.get(domain, {})


def set_subnets(LoadBalancerArn=None, Subnets=None):
    """
    Enables the Availability Zone for the specified subnets for the specified load balancer. The specified subnets replace the previously enabled subnets.
    See also: AWS API Documentation

    Examples
    This example enables the Availability Zones for the specified subnets for the specified load balancer.
    Expected Output:

    :example: response = client.set_subnets(
        LoadBalancerArn='string',
        Subnets=[
            'string',
        ]
    )

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

    :type Subnets: list
    :param Subnets: [REQUIRED]
            The IDs of the subnets. You must specify at least two subnets. You can add only one subnet per Availability Zone.
            (string) --

    :rtype: dict
    :return: {
        'AvailabilityZones': [
            {
                'ZoneName': 'string',
                'SubnetId': 'string'
            },
        ]
    }

    """
    pass


def get_volume_id_to_instance_id_map(volume_info):
    """Generate volume id to instance id map.  Unattached volumes will be ignored."""
    instance_id_to_volume_id_map = {}
    for volume_id in volume_info:
        volume = volume_info.get(volume_id)
        if volume.get('Attachments'):
            ec2_instance_id = volume.get('Attachments')[0].get('InstanceId')
            instance_id_to_volume_id_map[volume_id] = ec2_instance_id
    return instance_id_to_volume_id_map


def get_vocabs(datasets):
    """Build vocabulary from an iterable of datasets objects

    Args:
        datasets: a list of dataset objects

    Returns:
        a set of all the words in the dataset

    """
    print('Building vocab...')
    vocab_words = set()
    vocab_tags = set()
    for dataset in datasets:
        for words, tags in dataset:
            vocab_words.update(words)
            vocab_tags.update(tags)
    print('- done. {} tokens'.format(len(vocab_words)))
    return vocab_words, vocab_tags


def pivot_calibration_with_ransac(tracking_matrices, number_iterations,
    error_threshold, concensus_threshold, early_exit=False):
    """
    sksurgerycore.algorithms.pivot_calibration_with_ransac is
    depreciated from v0.6.0, please use
    skscurgerycalibration.algorithms.pivot_calibration_with_ransac from
    from scikit-surgerycalibration instead

    :raises: NotImplementedError
    """
    raise NotImplementedError(
        'sksurgerycore.algorithms.pivot_calibration_with_ransac is ' +
        'depreciated from v0.6.0, please use ' +
        'skscurgerycalibration.algorithms.pivot_calibration_with_ransac ' +
        'from scikit-surgerycalibration instead')


@staticmethod
def create_meta(asset_id, source='Cisco', padding='0'):
    """
        The metadata format is:
        key_id + ',' + Cisco + '00000...'

        till 256  bytes

        :param asset_id: Asset UUID
        :param source: Cisco
        :param padding: 0
        :return: metadata bytearray.
        """
    metadata = bytearray()
    metadata.extend(map(ord, asset_id + ','))
    metadata.extend(map(ord, source))
    while len(metadata) != 256:
        metadata.extend(map(ord, padding))
    return metadata


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


@staticmethod
def _case_of(text):
    """ Return the case-function appropriate for text: upper, lower, title, or just str. """
    if text.isupper():
        return str.upper
    if text[0].isupper():
        return lambda s: s[0].upper() + s[1:]
    return str


def is_using_stdin(paths):
    """Determine if we're going to read from stdin.

    :param list paths:
        The paths that we're going to check.
    :returns:
        True if stdin (-) is in the path, otherwise False
    :rtype:
        bool
    """
    return '-' in paths


def _point_in_bbox(point, bounds):
    """
    valid whether the point is inside the bounding box
    """
    return not (point['coordinates'][1] < bounds[0] or point['coordinates']
        [1] > bounds[2] or point['coordinates'][0] < bounds[1] or point[
        'coordinates'][0] > bounds[3])


def _check_discrete_args(at, method):
    """
    Checks the arguments for margeff if the exogenous variables are discrete.
    """
    if method in ['dyex', 'eyex']:
        raise ValueError('%s not allowed for discrete variables' % method)
    if at in ['median', 'zero']:
        raise ValueError('%s not allowed for discrete variables' % at)


@staticmethod
def render_preamble(track):
    """Render preamble."""
    return ['#EXT-X-VERSION:3',
        f'#EXT-X-TARGETDURATION:{track.target_duration}']


def transform_vector(vector, matrix):
    """Transform a vector by a matrix. This is similar to transform_point,
    except that translation isn't honored. Think of a vector as displacement in
    space, and a point as, well, a point in space.

    :param list vector: 2-item list
    :param list matrix: 6-item list representing transformation matrix
    :returns list: 2-item transformed point
    """
    x, y = vector
    a, b, c, d, _, _ = matrix
    new_x = x * a + y * c
    new_y = x * b + y * d
    return [new_x, new_y]


def copy(node):
    """
    Copies the node.

    >>> o = BinOp(Add(), NumberConstant(2), NumberConstant(3))
    >>> o2 = copy(o)
    >>> o.__dict__['op'] = Sub()
    >>> print(o, o2)
    (2 - 3) (2 + 3)
    """
    return node.__class__(**dict(node))


def rect(T):
    """create a centered rectangular pulse of width $T"""
    return lambda t: (-T / 2 <= t) & (t < T / 2)


def magtoflux(marr, fzero):
    """Convert from magnitude to flux.
     marr--input array in mags
     fzero--zero point for the conversion
    """
    return fzero * 10 ** (-0.4 * marr)


def stringify(prettify=False):
    """Transformation to JSON string representation"""


@staticmethod
def mimetype():
    """Return most common media type for format."""
    return 'text/plain'


def determine_intersection(token, entity):
    """Calculates how many characters a given token and entity share."""
    pos_token = set(range(token.offset, token.end))
    pos_entity = set(range(entity['start'], entity['end']))
    return len(pos_token.intersection(pos_entity))


def breakout(method):
    """ Decorator for singleton methods that should be available in global scope
        """
    method.break_me_out = None
    return method


@staticmethod
def is_dynamo_stream_event(event):
    """
        Determines if the incoming event is a DynamoDB stream event.
        :param event: The incoming event
        :return: `True` if the event has records. `False` otherwise.
        """
    return 'Records' in event


@classmethod
def namespace(cls):
    """Return namespace corresponding to self.ARGUMENT

        ARGUMENT is a command line argument, thus something in the style of `--code-change-type`.
        When arguments are passed they are saved in namespace in the style of `code_change_type`.
        This property converts command-line style to namespace style.
        """
    if not cls.ARGUMENT:
        return None
    return cls.ARGUMENT.lstrip('-').replace('-', '_')


def create(request):
    """
        Called when a node creation request has been received.

        @param request: The publish-subscribe request.
        @type request: L{wokkel.pubsub.PubSubRequest}
        @return: A deferred that fires with a C{unicode} that represents
                 the identifier of the new node.
        @rtype: L{Deferred<twisted.internet.defer.Deferred>}
        """


def _af_parity(pi):
    """
    Computes the parity of a permutation in array form.

    The parity of a permutation reflects the parity of the
    number of inversions in the permutation, i.e., the
    number of pairs of x and y such that x > y but p[x] < p[y].

    Examples
    ========

    >>> _af_parity([0, 1, 2, 3])
    0
    >>> _af_parity([3, 2, 0, 1])
    1

    See Also
    ========

    Permutation

    """
    n = len(pi)
    a = [0] * n
    c = 0
    for j in range(n):
        if a[j] == 0:
            c += 1
            a[j] = 1
            i = j
            while pi[i] != j:
                i = pi[i]
                a[i] = 1
    return (n - c) % 2


@classmethod
def has(cls, blok):
    """ Return True if the blok was imported

        :param blok: name of the blok to add
        :rtype: boolean
        """
    return blok in cls.modules


def eq_(a, b, msg=None):
    """Shorthand for 'assert a == b, "%r != %r" % (a, b)
    """
    if not a == b:
        raise AssertionError(msg or '%r != %r' % (a, b))


def line_last_word(line):
    """return last word"""
    if len(line.split()) > 0:
        return line.split()[-1]
    else:
        return False


def round_if_near_integer(a, epsilon=0.0001):
    """
    Round a to the nearest integer if that integer is within an epsilon
    of a.
    """
    if abs(a - round(a)) <= epsilon:
        return round(a)
    else:
        return a


def __nonzero__():
    """
        Same as __bool__ for Python 2.
        """


def matches_word(regex, word):
    """
    Return `True` if the whole `word` is matched by `regex`, `False`
    otherwise.
    """
    match = regex.match(word)
    if match:
        return match.start() == 0 and match.end() == len(word)
    return False


@staticmethod
def find_element_last_children(element, timeout=0):
    """ get the last elements in the tree from the root element
        :type element: WebElement
        :type timeout: int
        :rtype: list[WebElement] | []
        """
    return element.find_last_children(timeout)


def getCountries():
    """
        Return a dictionary mapping country tags to country data.

        Country data has at least the 'name' key.
        """


def NormStandardPath(path):
    """
    Normalizes a standard path (posixpath.normpath) maintaining any slashes at the end of the path.

    Normalize:
        Removes any local references in the path "/../"

    StandardPath:
        We are defining that the standard-path is the one with only back-slashes in it, either
        on Windows or any other platform.
    """
    import posixpath
    if path.endswith('/'):
        slash = '/'
    else:
        slash = ''
    return posixpath.normpath(path) + slash


def query(query, timeout=None):
    """
        Dispatch C{query} to the method which can handle its type.

        @type query: L{twisted.names.dns.Query}
        @param query: The DNS query being issued, to which a response is to be
            generated.

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

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


def get_optimal_bins(depth, chunk_depth=50, round_up=True):
    """
    Uses depth data to estimate the optimal bin depths for gridding.

    Data is grouped in 50 m chunks (default for chunk_depth) where the
    average sequential depth difference is used to estimate the binning
    resolution for that chunk. The chunk binning resolution is rounded to
    the upper/lower 0.5 metres (specified by user).

    Parameters
    ----------
    depth : array
        A sequential array of depth (concatenated dives)
    chunk_depth : float=50
        chunk depth over which the bin sizes will be calculated
    round_up : True
        if True, rounds up to the nearest 0.5 m, else rounds down.

    Returns
    -------
    bins : array
    bin_avg_sampling_freq : float
        un-rounded depth weighted depth sampling frequency (for verbose use)

    """
    from numpy import abs, arange, array, diff, ceil, floor, isnan, nanmax, nanmedian
    y = array(depth)
    bins = []
    bin_avg_sampling_freq = []
    if round_up:
        round_func = ceil
    else:
        round_func = floor
    d0 = 0
    d1 = chunk_depth
    last_freq = 0.5
    while d0 <= nanmax(depth):
        i = (y > d0) & (y < d1)
        bin_avg_sampling_freq += nanmedian(abs(diff(y[i]))),
        bin_freq = round_func(bin_avg_sampling_freq[-1] * 2) / 2
        if bin_freq == 0:
            bin_freq = 0.5
        elif isnan(bin_freq):
            bin_freq = last_freq
        bin_step = arange(d0, d1, bin_freq).tolist()
        bins += bin_step
        d0 = bin_step[-1] + bin_freq
        d1 = d0 + chunk_depth
        last_freq = bin_freq
    return array(bins), nanmedian(bin_avg_sampling_freq)


def _get_return_value_type_name_from_line(line_str):
    """
    Get the type name of return value from the target line string.

    Parameters
    ----------
    line_str : str
        Target line string.

    Returns
    ----------
    return_value_type_name : str
        Type name of return value.
    """
    colon_exists = ':' in line_str
    if not colon_exists:
        return_value_type_name = line_str.split(':')[0]
    else:
        return_value_type_name = line_str.split(':')[1]
    return_value_type_name = return_value_type_name.strip()
    return return_value_type_name


def _is_switchdev(netdev):
    """Returns True if a netdev has a readable phys_switch_id"""
    try:
        sw_id_file = '/sys/class/net/%s/phys_switch_id' % netdev
        with open(sw_id_file, 'r') as fd:
            phys_switch_id = fd.readline().rstrip()
        if phys_switch_id != '' and phys_switch_id is not None:
            return True
    except (OSError, IOError):
        return False
    return False


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


def __check_colnames_type(cols):
    """Check if it is a list-like object."""
    if cols is None or cols == []:
        return None
    elif not isinstance(cols, list):
        raise TypeError(
            'Third item of the tuple (func, args, cols) must be list-like object not a {} object'
            .format(type(cols)))
    else:
        return cols


@staticmethod
def positional_to_model(value):
    """Converts a positional argument to a model value"""
    return value


def download_file(client, url, dest):
    """Download a file from the remote device

    This method handles the chunking needed to download a file from
    a given URL on the BIG-IP.

    Arguments:
        client (object): The F5RestClient connection object.
        url (string): The URL to download.
        dest (string): The location on (Ansible controller) disk to store the file.

    Returns:
        bool: True on success. False otherwise.
    """
    with open(dest, 'wb') as fileobj:
        chunk_size = 512 * 1024
        start = 0
        end = chunk_size - 1
        size = 0
        current_bytes = 0
        while True:
            content_range = '%s-%s/%s' % (start, end, size)
            headers = {'Content-Range': content_range, 'Content-Type':
                'application/octet-stream'}
            data = {'headers': headers, 'verify': False, 'stream': False}
            response = client.api.get(url, headers=headers, json=data)
            if response.status == 200:
                if size > 0:
                    current_bytes += chunk_size
                    fileobj.write(response.raw_content)
            if end == size:
                break
            crange = response.headers['Content-Range']
            if size == 0:
                size = int(crange.split('/')[-1]) - 1
                if chunk_size > size:
                    end = size
                continue
            start += chunk_size
            if current_bytes + chunk_size > size:
                end = size
            else:
                end = start + chunk_size - 1
    return True


def _product_type(ensemble=False, period='hourly', synoptic=False,
    statistics=False):
    """Construct the product type name from the options."""
    producttype = ''
    if ensemble:
        producttype += 'ensemble_members'
    elif not ensemble:
        producttype += 'reanalysis'
    if period == 'monthly':
        producttype = 'monthly_averaged_' + producttype
        if synoptic:
            producttype += '_by_hour_of_day'
    elif period == 'hourly':
        if ensemble and statistics:
            producttype = ['ensemble_members', 'ensemble_mean',
                'ensemble_spread']
    return producttype


def star_grep(cluster, logdir, cmdline, *args):
    """Scan (not real grep) for string matches in stdout"""
    pattern = cmdline[6:].encode(cluster.defaults['character_encoding'])
    for host in cluster:
        job = cluster.last_result.get(host)
        if job:
            res = job.result
            for line_number, line in enumerate(res.stdout.split(b'\n'), 1):
                if pattern in line:
                    print('%s [%d]: %s' % (host, line_number, line.rstrip()
                        .decode(cluster.defaults['character_encoding'],
                        'replace')))
            for line_number, line in enumerate(res.stderr.split(b'\n'), 1):
                if pattern in line:
                    print('%s [%d/stderr]: %s' % (host, line_number, line.
                        rstrip().decode(cluster.defaults[
                        'character_encoding'], 'replace')))


def auth_is_anon_user(context):
    """ Is this an anonymous user?
        eg Not logged in if a web request and not user defined in context
        if logic functions called directly

        See ckan/lib/base.py:232 for pylons context object logic
    """
    context_user = context.get('user')
    is_anon_user = not bool(context_user)
    return is_anon_user


def wrap360deg(deg: 'np.ndarray') ->'np.ndarray':
    """
    Make sure that degrees (e.g. heading) is within 360 range.

    Ref: https://www.movable-type.co.uk/scripts/latlong-vincenty.html
    """
    mask = (deg < 0) | (deg > 360)
    deg[mask] = (deg[mask] % 360 + 360) % 360
    return deg


def short_information(title, index=0):
    """
    Takes in track information and returns everything as a short formatted String.

    Args:
        title (str): track title string
        index (str): optional track number string

    Returns:
        A short formatted string of all track information.
    """
    if ' - ' in title:
        split_title = str(title).split(' - ', 1)
        if index:
            return '{} {}'.format(index, split_title[1])
        else:
            return '{}'.format(split_title[1])
    elif index:
        return '{} {}'.format(index, title)
    else:
        return title


@staticmethod
def _glued_to(tetrahedron, face):
    """
        Returns (other tet, other face).
        """
    return tetrahedron.Neighbor[face], tetrahedron.Gluing[face].image(face)


def expand_option(option):
    """expand option that is a ',' separated list of assignments.
    """
    kwargs = {}
    option = option.strip()
    if len(option) == 0:
        return kwargs
    parts = option.split(',')
    for part in parts:
        if not part.strip():
            continue
        if '=' not in part:
            raise ValueError("malformed tracker options '{}' in '{}'".
                format(part, option))
        key, val = part.split('=', 1)
        try:
            kwargs[key.strip()] = eval(val.strip())
        except NameError:
            kwargs[key.strip()] = val
    return kwargs


@classmethod
def feature_urls(cls, name):
    """ For implementing component features """
    return []


def add_target():
    """Add a target to the constraint

    """
    pass


@staticmethod
def _increment_last_level(number):
    """
        Increments the last level in number of the item node.

        :param str number: The number of last node.

        :rtype: str
        """
    heading_numbers = number.split('.')
    heading_numbers[-1] = str(int(heading_numbers[-1]) + 1)
    return '.'.join(heading_numbers)


def set_client_id(client_id):
    """
    Set the client ID. This will be stored in the simulations database and is useful for tracking usage.

    :param client_id: The client ID to use.
    """
    global _client_id
    _client_id = client_id


def buffered_read(fh, lock, offsets, bytecounts, buffersize=2 ** 26):
    """Return iterator over segments read from file."""
    length = len(offsets)
    i = 0
    while i < length:
        data = []
        with lock:
            size = 0
            while size < buffersize and i < length:
                fh.seek(offsets[i])
                bytecount = bytecounts[i]
                data.append(fh.read(bytecount))
                size += bytecount
                i += 1
        for segment in data:
            yield segment


def short_author_formatter(copyright_year_string, authors):
    """
    >>> print('\\n'.join(short_author_formatter(
    ...     copyright_year_string='Copyright (C) 1990-2010',
    ...     authors=['Jack', 'Jill', 'John']*5)))
    Copyright (C) 1990-2010 Jack, Jill, John, Jack, Jill, John, Jack, Jill, John, Jack, Jill, John, Jack, Jill, John
    """
    blurb = '{} {}'.format(copyright_year_string, ', '.join(authors))
    return [blurb]


def binarize(W, copy=True):
    """
    Binarizes an input weighted connection matrix.  If copy is not set, this
    function will *modify W in place.*

    Parameters
    ----------
    W : NxN np.ndarray
        weighted connectivity matrix
    copy : bool
        if True, returns a copy of the matrix. Otherwise, modifies the matrix
        in place. Default value=True.

    Returns
    -------
    W : NxN np.ndarray
        binary connectivity matrix
    """
    if copy:
        W = W.copy()
    W[W != 0] = 1
    return W


@classmethod
def vol_type(cls):
    """The type of volume supported by this type."""
    return 'iscsi'


def run_removecomments(nexus_obj, log):
    """
    Removes comments from the trees in a nexus

    :param nexus_obj: A `NexusReader` instance
    :type nexus_obj: NexusReader

    :return: A NexusReader instance with the comments removed.
    """
    new = []
    for tree in nexus_obj.trees:
        new.append(nexus_obj.trees.remove_comments(tree))
    log.info('Removed comments')
    nexus_obj.trees.trees = new
    return nexus_obj


@classmethod
def from_unsigned_bits(cls, n):
    """
        Create a range corresponding to that of an unsigned integer of ``n``
        bits.
        """
    return cls(min=0, max=2 ** n - 1)


def chunk_windows(window, chunksize):
    """Given a user window, split that window into interval tuples (start, end)
       of size chunksize."""
    chunk_start = window['start']
    chunk_end = chunk_start + chunksize
    intervals = []
    while chunk_end <= window['end']:
        interval = chunk_start, chunk_end
        intervals.append(interval)
        chunk_start += chunksize
        chunk_end += chunksize
    if chunk_start < window['end']:
        interval = chunk_start, window['end']
        intervals.append(interval)
    return intervals


def split_escaped(s, glue=',', preserve=False):
    """Handle single-char escapes using backslash."""
    buf = []
    it = iter(s)
    for c in it:
        if c == glue:
            yield ''.join(buf)
            del buf[:]
        elif c == '\\':
            if preserve:
                buf.append(c)
            c = next(it)
            buf.append(c)
        else:
            buf.append(c)
    if buf:
        yield ''.join(buf)


def mac(dic, data, macro=None, noRd=False, noWr=False, all=False, **kwargs):
    """
    Dispatcher similar to the MAC command.

    Parameters
    ----------
    dic : dict
        Dictionary of NMRPipe parameters
    data : ndarray
        Array of NMR data.
    macro : callable
        Python function to apply.
    kwargs : keyword arguments
        Keyword arguments that get passed to the macro

    Returns
    -------
    ndic : dict
        Dictionary of updated NMRPipe parameters.
    ndata : ndarray
        Array of data with macro function applied.

    Notes
    -----
    This is not intended to be a true macro interpreter.  Instead, the purpose
    is to act as a dispatch mechanism to other Python code so that the
    look and feel of nmrPipe is maintained.  The -var and -str parameters
    are not used, as they can be passed directly to the macro as keyword
    arguements.
    """
    if macro is None:
        return dic, data
    if noRd and noWr:
        return macro(dic, data, **kwargs)
    raise NotImplementedError('Only noRd and noWr macros work for now.')


def find_peaks(spikes, peak, window):
    """Locate the peaks in an array of spikes.

    spikes: resampled spike waveforms, dimensions (nspikes, nsamples)
    peak:   the expected peak location
    window: the number of samples to either side of the peak to look for the peak

    Returns array of shift values relative to peak

    """
    r = slice(peak - window, peak + window + 1)
    return spikes[:, (r)].argmax(1) - window


def path_inside_dir(path, directory):
    """
    Returns True if the specified @path is inside @directory,
    performing component-wide comparison. Otherwise returns False.
    """
    return directory == '' and path != '' or path.rstrip('/').startswith(
        directory.rstrip('/') + '/')


def _dirac(a, b):
    """Calculate the dirac function for labels."""
    return int(a == b)


def to_iso639_part1(language_code):
    """
    Convert codes like "en-us" to "en"
    """
    return language_code.split('-', 1)[0]


def nameStep(step, name):
    """Give a step a __name__."""
    step.__name__ = name
    return step


def draw_box(image, box, color):
    """Draw 3-pixel width bounding boxes on the given image array.
    color: list of 3 int values for RGB.
    """
    y1, x1, y2, x2 = box
    image[y1:y1 + 2, x1:x2] = color
    image[y2:y2 + 2, x1:x2] = color
    image[y1:y2, x1:x1 + 2] = color
    image[y1:y2, x2:x2 + 2] = color
    return image


def option_namespace(name):
    """ArgumentParser options namespace (prefix of all options)."""
    return name + '-'


def read(path, repo=None, rev=None, remote=None, mode='r', encoding=None):
    """
    Returns the contents of a tracked file (by DVC or Git). For Git repos, HEAD
    is used unless a rev argument is supplied. The default remote is tried
    unless a remote argument is supplied.
    """
    with open(path, repo=repo, rev=rev, remote=remote, mode=mode, encoding=
        encoding) as fd:
        return fd.read()


def unpack(event, data, n=0):
    """ Fills the event dictionary with selected events.

    Args:

	**event** (dict): Event dictionary to be filled

	**data** (dict): Data dictionary used to fill the event dictionary

    """
    keys = event.keys()
    for key in keys:
        if key in data['list_of_counters'] or key in data['_SINGLETON_']:
            event[key] = data[key][n]
        elif 'INDEX' not in key:
            indexkey = data['datasets_and_indices'][key]
            numkey = data['datasets_and_counters'][key]
            if len(data[indexkey]) > 0:
                index = data[indexkey][n]
            if len(data[numkey]) > 0:
                nobjs = data[numkey][n]
                event[key] = data[key][index:index + nobjs]


def _BuildMessageFromTypeName(type_name, descriptor_pool):
    """Returns a protobuf message instance.

  Args:
    type_name: Fully-qualified protobuf  message type name string.
    descriptor_pool: DescriptorPool instance.

  Returns:
    A Message instance of type matching type_name, or None if the a Descriptor
    wasn't found matching type_name.
  """
    if descriptor_pool is None:
        from google.protobuf import descriptor_pool as pool_mod
        descriptor_pool = pool_mod.Default()
    from google.protobuf import symbol_database
    database = symbol_database.Default()
    try:
        message_descriptor = descriptor_pool.FindMessageTypeByName(type_name)
    except KeyError:
        return None
    message_type = database.GetPrototype(message_descriptor)
    return message_type()


def mirror_y(clip, apply_to='mask'):
    """ flips the clip vertically (and its mask too, by default) """
    return clip.fl_image(lambda f: f[::-1], apply_to=apply_to)


def deserialize_date(string):
    """Deserializes string to date.

    :param string: str.
    :type string: str
    :return: date.
    :rtype: date
    """
    try:
        from dateutil.parser import parse
        return parse(string).date()
    except ImportError:
        return string


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

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


def iter_result_proxy(rp, step=None):
    """Iterate over the ResultProxy."""
    while True:
        if step is None:
            chunk = rp.fetchall()
        else:
            chunk = rp.fetchmany(size=step)
        if not chunk:
            break
        for row in chunk:
            yield row


@classmethod
def from_xspec_model(cls, model_string, params, emin, emax, nbins):
    """
        Create a model spectrum using a model string and parameters
        as input to XSPEC.

        Parameters
        ----------
        model_string : string
            The model to create the spectrum from. Use standard XSPEC
            model syntax. Example: "wabs*mekal"
        params : list
            The list of parameters for the model. Must be in the order
            that XSPEC expects.
        emin : float, (value, unit) tuple, or :class:`~astropy.units.Quantity`
            The minimum energy of the spectrum in keV
        emax : float, (value, unit) tuple, or :class:`~astropy.units.Quantity`
            The maximum energy of the spectrum in keV
        nbins : integer
            The number of bins in the spectrum.
        """
    xspec_in = []
    model_str = '%s &' % model_string
    for param in params:
        model_str += ' %g &' % param
    model_str += ' /*'
    xspec_in.append('model %s\n' % model_str)
    return cls._from_xspec(xspec_in, emin, emax, nbins)


@staticmethod
def _set_content(content):
    """
            the body of the article
            :param content: the content
            :param content: string
            :return: the complet content
            :rtype: string
        """
    return '\n\t<body>{}'.format(content)


def time_left_str(seconds):
    """
    Produces a human-readable string in hh:mm:ss format
    :param seconds:

    :return:
    """
    m, s = divmod(int(seconds), 60)
    h, m = divmod(m, 60)
    d, h = divmod(h, 24)
    if d > 0:
        thetime = 'Projected time remaining  |  {:d}d:{:d}h:{:02d}m'.format(d,
            h, m)
    elif h > 0:
        thetime = 'Projected time remaining:  |  {:d}h:{:02d}m'.format(h, m)
    elif m > 0:
        thetime = 'Projected time remaining:  |  {:02d}m:{:02d}s'.format(m, s)
    else:
        thetime = 'Projected time remaining:  |  {:02d}s'.format(seconds)
    return thetime


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


@classmethod
def get_org_integral_rule_list_by_data(cls, current_org_id, integral_condition
    ):
    """
        根据积分规则所属机构以及满足金额获取本机构启用状态下的积分规则
        :param current_org_id:
        :param integral_condition:
        :return:
        """
    return cls.objects(org_id=current_org_id, status__in=[cls.get_dict_id(
        'integral_status', '启用')], integral_rule_type=cls.get_dict_id(
        'integral_rule_type', '充值'), integral_condition__lte=integral_condition
        ).order_by('-integral_condition').all()


def pdf_escape(value):
    """Escape parentheses and backslashes in ``value``.

    ``value`` must be unicode, or latin1 bytestring.

    """
    if isinstance(value, bytes):
        value = value.decode('latin1')
    return value.translate({(40): '\\(', (41): '\\)', (92): '\\\\'})


def parse_who_reply(text):
    """
    Parse reply of `who` command (listing of players present on the site)
    :param text: text output of the command
    :type text: str
    """
    pass


def to_codes(df):
    """Return a dataframe with all of the categoricals represented as codes"""
    df = df.copy()
    cat_cols = df.select_dtypes(['category']).columns
    df[cat_cols] = df[cat_cols].apply(lambda x: x.cat.codes)
    return df


def get(isamAppliance, uuid, check_mode=False, force=False):
    """
    Get a specific email object
    """
    return isamAppliance.invoke_get('Get a specific email object',
        '/core/rsp_email_objs/{0}'.format(uuid))


def html_escape(string):
    """ Escape HTML special characters ``&<>`` and quotes ``'"``. """
    return string.replace('&', '&').replace('<', '<').replace('>',
        '>').replace('"', '"').replace("'", ''')


def to_list(obj):
    """
    Wraps an object in a list if it's not already one
    """
    if isinstance(obj, list):
        return obj
    return [obj]


def extract_entity_identifier(oLine):
    """
    Returns the entity identifier.

    Parameters:

       oLine: (line object)

    Returns: (one element list of strings)
    """
    return [oLine.line.split()[1]]


def object_kind(object_path):
    """
    Parse the kind of object from an UDisks2 object path.

    Example:
        /org/freedesktop/UDisks2/block_devices/sdb1 => device
        /org/freedesktop/UDisks2/drives/WDC_WD...   => drive
        /org/freedesktop/UDisks2/jobs/5             => job
    """
    try:
        return {'block_devices': 'device', 'drives': 'drive', 'jobs': 'job'
            }.get(object_path.split('/')[4])
    except IndexError:
        return None


def print_greeting(model, observable):
    """
    Prints some user greeting information
    """
    print('*' * 80)
    print('* MODEL')
    print('*' * 80)
    print(model)
    print('*' * 80)
    print('* OBSERVABLE VARIABLES')
    print('*' * 80)
    print('\n'.join(sorted(observable)))


def update_domain_nameservers(DomainName=None, FIAuthKey=None, Nameservers=None
    ):
    """
    This operation replaces the current set of name servers for the domain with the specified set of name servers. If you use Amazon Route 53 as your DNS service, specify the four name servers in the delegation set for the hosted zone for the domain.
    If successful, this operation returns an operation ID that you can use to track the progress and completion of the action. If the request is not completed successfully, the domain registrant will be notified by email.
    See also: AWS API Documentation

    :example: response = client.update_domain_nameservers(
        DomainName='string',
        FIAuthKey='string',
        Nameservers=[
            {
                'Name': 'string',
                'GlueIps': [
                    'string',
                ]
            },
        ]
    )

    :type DomainName: string
    :param DomainName: [REQUIRED]
            The name of the domain that you want to change name servers for.

    :type FIAuthKey: string
    :param FIAuthKey: The authorization key for .fi domains

    :type Nameservers: list
    :param Nameservers: [REQUIRED]
            A list of new name servers for the domain.
            (dict) --Nameserver includes the following elements.
            Name (string) -- [REQUIRED]The fully qualified host name of the name server.
            Constraint: Maximum 255 characters
            GlueIps (list) --Glue IP address of a name server entry. Glue IP addresses are required only when the name of the name server is a subdomain of the domain. For example, if your domain is example.com and the name server for the domain is ns.example.com, you need to specify the IP address for ns.example.com.
            Constraints: The list can contain only one IPv4 and one IPv6 address.
            (string) --

    :rtype: dict
    :return: {
        'OperationId': 'string'
    }

    """
    pass


def age_to_BP(age, age_unit):
    """
    Convert an age value into the equivalent in time Before Present(BP) where Present is 1950

    Returns
    ---------
    ageBP : number
    """
    ageBP = -1000000000.0
    if age_unit == 'Years AD (+/-)' or age_unit == 'Years Cal AD (+/-)':
        if age < 0:
            age = age + 1
        ageBP = 1950 - age
    elif age_unit == 'Years BP' or age_unit == 'Years Cal BP':
        ageBP = age
    elif age_unit == 'ka':
        ageBP = age * 1000
    elif age_unit == 'Ma':
        ageBP = age * 1000000.0
    elif age_unit == 'Ga':
        ageBP = age * 1000000000.0
    else:
        print('Age unit invalid. Age set to -1.0e9')
    return ageBP


def tab_menu(items, selected, side=None):
    """
    Show a menu in form of tabs.

    :param items: The list of :class:`bob.menu.MenuItem` instances to show.
    :param selected: The :data:`name` of the currently selected item.
    :param side: The direction of tabs, may be on of ``"left"``, ``"right"``,
        ``"top"`` or ``"bottom"``. Defaults to ``"top"``.
    """
    return {'items': items, 'selected': selected, 'side': side}


def avg_dicts(dictin1, dictin2, dropmissing=True):
    """Create a new dictionary from two dictionaries by averaging values

    Args:
        dictin1 (DictUpperBound): First input dictionary
        dictin2 (DictUpperBound): Second input dictionary
        dropmissing (bool): Whether to drop keys missing in one dictionary. Defaults to True.

    Returns:
        Dict: Dictionary with values being average of 2 input dictionaries

    """
    dictout = dict()
    for key in dictin1:
        if key in dictin2:
            dictout[key] = (dictin1[key] + dictin2[key]) / 2
        elif not dropmissing:
            dictout[key] = dictin1[key]
    if not dropmissing:
        for key in dictin2:
            if key not in dictin1:
                dictout[key] = dictin2[key]
    return dictout


def gammaln(data=None, name=None, attr=None, out=None, **kwargs):
    """Returns element-wise log of the absolute value of the gamma function \\
    of the input.

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

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

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

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


def transform_projection(G, to_crs='epsg:4326'):
    """
    change the coordinate projection of Shapely "geometry" attributes in edges
    and nodes in the graph
    """
    from functools import partial
    try:
        from shapely.ops import transform
        import pyproj
    except ImportError:
        raise ImportError('pyproj and shapely modules needed. get them here: ',
            'https://pypi.org/project/pyproj/, https://pypi.org/project/Shapely/'
            )
    st_plane = pyproj.Proj(G.graph['crs'], preserve_units=True)
    wgs = pyproj.Proj(init=to_crs)
    project = partial(pyproj.transform, st_plane, wgs)
    for u, v, geometry in G.edges(data='geometry'):
        if geometry:
            G[u][v]['geometry'] = transform(project, geometry)
    for n, geometry in G.nodes(data='geometry'):
        if geometry:
            G.node[n]['geometry'] = transform(project, geometry)
    G.graph['crs'] = to_crs


@staticmethod
def replace_celcius(string):
    """
        Replaces 'celsius' with 'fahrenheit' in the provided string.

        Returns:
            string: The modified string
        """
    return string.replace(u'celsius', u'fahrenheit')


def ADOSC(df):
    """
    Chaikin A/D Oscillator
    """


def _format_servers_list_networks(networks):
    """Return a formatted string of a server's networks

    :param networks: a Server.networks field
    :rtype: a string of formatted network addresses
    """
    output = []
    for network, addresses in networks.items():
        if not addresses:
            continue
        addresses_csv = ', '.join(addresses)
        group = '%s=%s' % (network, addresses_csv)
        output.append(group)
    return '; '.join(output)


def weight_density(values, weights, value=None):
    """ Return weighted density

    :param values:
    :param weights:
    :param value:
    :return:
    """
    return weights[values == value].sum() / weights.sum()


def get_switch_device(switches, switch_info=None, ngs_mac_address=None):
    """Return switch device by specified identifier.

    Returns switch device from switches array that matched with any of
    passed identifiers. ngs_mac_address takes precedence over switch_info,
    if didn't match any address based on mac fallback to switch_info.

    :param switch_info: hostname of the switch or any other switch identifier.
    :param ngs_mac_address: Normalized mac address of the switch.
    :returns: switch device matches by specified identifier or None.
    """
    if ngs_mac_address:
        for sw_info, switch in switches.items():
            mac_address = switch.ngs_config.get('ngs_mac_address')
            if mac_address and mac_address.lower() == ngs_mac_address.lower():
                return switch
    if switch_info:
        return switches.get(switch_info)


def __delitem__(name, obj):
    """Add the named instance to the mapping of instances"""


def add3(vector1, vector2):
    """Return the sum of 3-dimension ``vector1`` and ``vector2``."""
    return vector1[0] + vector2[0], vector1[1] + vector2[1], vector1[2
        ] + vector2[2]


def is_seq(obj):
    """
    Returns true if `obj` is a non-string sequence.
    """
    try:
        len(obj)
    except (TypeError, ValueError):
        return False
    else:
        return not isinstance(obj, str)


@staticmethod
def merge_dicts(x: dict, y: dict) ->dict:
    """Take x dictionary and insert/overwrite y dictionary values

        :type x: dict
        :type y: dict
        :return:
        """
    z = x.copy()
    z.update(y)
    return z


def incrementProcVer(cloneArgs, requestArgs):
    """
    Increment the ProcessingVersion value for any requests cloned via
    clone API, except if it's a Resubmission request.
    TODO: ProcVer can be a dict at top level, until this #6881 gets fixed
    """
    if cloneArgs['RequestType'] == 'Resubmission' or requestArgs.get(
        'RequestType') == 'Resubmission':
        return
    for key in cloneArgs:
        if key == 'ProcessingVersion':
            if isinstance(cloneArgs[key], int):
                cloneArgs[key] += 1
            elif isinstance(cloneArgs[key], dict):
                for taskname in cloneArgs[key]:
                    cloneArgs[key][taskname] += 1
        elif isinstance(cloneArgs[key], dict
            ) and 'ProcessingVersion' in cloneArgs[key]:
            cloneArgs[key]['ProcessingVersion'] += 1
    return


def __len__():
    """Return integer number of increments for the current period setting"""


def _centsshown(centsdev, divsPerSemitone=4) ->str:
    """
    Given a cents deviation from a chromatic pitch, return
    a string to be shown along the notation, to indicate the
    true tuning of the note. If we are very close to a notated
    pitch (depending on divsPerSemitone), then we don't show
    anything. Otherwise, the deviation is always the deviation
    from the chromatic pitch

    Args:
        centsdev: the deviation from the chromatic pitch
        divsPerSemitone: if given, overrides the value in the config

    Returns:
        the string to be shown alongside the notated pitch
    """
    pivot = int(round(100 / divsPerSemitone))
    dist = min(centsdev % pivot, -centsdev % pivot)
    if dist <= 2:
        return ''
    if centsdev < 0:
        return f'–{-centsdev}'
    return str(int(centsdev))


def _validate_use(use: str):
    """Validates the 'use' argument. If invalid, raises an error"""
    use = use.lower()
    valid_use_keywords = {'everything', 'pairwise.complete', 'complete'}
    if use not in valid_use_keywords:
        raise ValueError(f"use must be one of {', '.join(valid_use_keywords)}")
    return use


def to_pascal_case(name):
    """
    Turn a snake_case name into PascalCase.
    """
    return name.title().replace('_', '')


@staticmethod
def serializable() ->bool:
    """ Whether or not this class supports state serialization.

        (This always returns True for TicTacToe)

        Returns
        -------
        is_serializable : bool
            True
        """
    return True


@classmethod
def fromkeys(cls, iterable, *args):
    """Create a ChainMap with a single dict created from the iterable."""
    return cls(dict.fromkeys(iterable, *args))


def editsource():
    """Edit UI source code of the active button

    """
    pass


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


def get_priority(cls):
    """
    Returns the priority of a plugin.
    :param cls: class to get priority from
    :type cls: class
    :return: the priority of cls
    :rtype: int
    """
    if not hasattr(cls, '_plugin_priority'):
        return 0
    return cls._plugin_priority


def interpolate_tuple(startcolor, goalcolor, steps):
    """
    Take two RGB color sets and mix them over a specified number of steps.  Return the list
    """
    R = startcolor[0]
    G = startcolor[1]
    B = startcolor[2]
    targetR = goalcolor[0]
    targetG = goalcolor[1]
    targetB = goalcolor[2]
    DiffR = targetR - R
    DiffG = targetG - G
    DiffB = targetB - B
    buffer = []
    for i in range(0, steps + 1):
        iR = R + DiffR * i // steps
        iG = G + DiffG * i // steps
        iB = B + DiffB * i // steps
        hR = str.replace(hex(iR), '0x', '')
        hG = str.replace(hex(iG), '0x', '')
        hB = str.replace(hex(iB), '0x', '')
        if len(hR) == 1:
            hR = '0' + hR
        if len(hB) == 1:
            hB = '0' + hB
        if len(hG) == 1:
            hG = '0' + hG
        color = str.upper('#' + hR + hG + hB)
        buffer.append(color)
    return buffer


def p_expression_mailbox(p):
    """mailbox : addr_spec
               | angle_addr
               | name_addr"""
    p[0] = p[1]


def get_spgroup_data():
    """
    Return a dictionary that has the spacegroup number as key, and a tuple
    as value, with content::

      (crystal family letter, centering, has_inversion).

    It loads if from a table in the source code for efficiency.
    """
    from .spg_db import spgroup_data
    return spgroup_data


def getChainFor(ob):
    """ Get the chain that applies to the given object.

        o If 'ob' is a string, it is used as portal type name.

        o Permission:  Private (Python only)
        """


def escapeXML(text):
    """Escape special characters in XML."""
    text = text.replace('&', u'\ue001')
    text = text.replace('<', '<')
    text = text.replace('>', '>')
    text = text.replace('"', '"')
    text = text.replace("'", ''')
    text = text.replace(u'\ue001', '&')
    return text


def get_related_item_element(fk_element):
    """
    Returns related element by its foreign key

    It takes <fk /> element and finds related <item />
    element by attributes
    """
    fk_item_element_selector = '//model[@model="{}"]//item[@key="{}"]'.format(
        fk_element.attrib['model'], fk_element.attrib['key'])
    fk_item_element = fk_element.xpath(fk_item_element_selector)[0]
    return fk_item_element


def _query_builder(parameters):
    """Converts dictionary with queries to http-able query."""
    queries = dict()
    for key in parameters:
        queries.setdefault(key, set())
        if type(parameters[key]) in [list, set]:
            queries[key] = queries[key].union(set(parameters[key]))
        else:
            queries[key].add(parameters[key])
    final_query = ''
    for key, group in queries.items():
        group = sorted(list(group))
        for value in group:
            single_query = f'&{key}={value}'
            if single_query not in final_query:
                final_query += single_query
    final_query = final_query.lstrip('&')
    return f'?{final_query}'


def _resample_function(function, game, _):
    """Function for resampling"""
    return function(game.resample())


@staticmethod
def fix_table_p(tree):
    """
        Force "tabular" tables to not have <p> as top-level within <td>.
        Those <p> mess up table spacing.
        """
    for table in tree.findall('.//table[@class="tabular"]'):
        for td in table.findall('.//td'):
            if not len(td):
                continue
            tdtop = td[0]
            if tdtop.tag == 'p':
                for elem in tdtop:
                    tdtop.addprevious(elem)
            td.text = (td.text or '') + tdtop.text
            td.remove(tdtop)


def strd(val):
    """Returns date time as ISO format"""
    return val.strftime('%Y-%m-%dT%H:%M:%S')


def add_source_format_arg(parser):
    """
    Adds source format option to parser

    :param parser: the parser to add the source format option to
    :return: None
    """
    parser.add_argument('-s', '--sourceformat', help=
        'encoding format of source file', choices=['ebcdic', 'ascii'],
        default='ebcdic')
    parser.add_argument('--no1014blocking', help=
        'do not use 1014 block format. Just vbs type record', dest=
        'no_1014_blocking', action='store_true')


def convert_txt_as_raw_txt(txt):
    """This function takes a string as input and returns it but the separators as replaced
	by spaces.
	@param: txt (string)
	@return: txt (string)
	"""
    txt = txt.split()
    txt = ' '.join(txt)
    return txt


def getHistory(history_id):
    """Return the history of an object by the given history id.

        Returns a 'IHistory' object.
        """


@classmethod
def from_gs(cls, graphics):
    """Creates a new StrokeState from a ColoredState object."""
    ret = cls()
    ret.color = graphics.stroke_color
    ret.linewidth = graphics.linewidth
    ret.linecap = graphics.linecap
    ret.linejoin = graphics.linejoin
    ret.miterlimit = graphics.miterlimit
    ret.dash = graphics.dash
    return ret


@staticmethod
def gen_colors():
    """
        Maps colors to RGB values

        Creates a dictionary that maps the name of colors to their RBG values

        Parameters
        -------------------
        None

        Returns
        -------
        Dictionary
            A dictionary with color name as the key and
            the RBG values of that color

        """
    colors = {'red': (255, 0, 0), 'green': (0, 255, 0), 'cyan': (0, 255,
        255), 'yellow': (255, 255, 0), 'purple': (255, 0, 255), 'orange': (
        255, 128, 0), 'white': (255, 255, 255), 'black': (0, 0, 0)}
    return colors


def get_f_score(n, beta=1):
    """
    Compute the F-beta score.

    The F(1) score is the harmonic mean of precision and recall. The worst
    value is 0, the best value is 1.

    ``beta < 1`` adds more weight on precision, while ``beta > 1`` adds more
    weight on recall.

    Parameters
    ----------
    n : dict
        Confusion matrix which has integer keys 0, ..., nb_classes - 1;
        an entry n[i][j] is the count how often class i was classified as
        class j.
    beta : float

    Returns
    -------
    float
        F-Score (in [0, 1])

    Examples
    --------
    >>> n = {0: {0: 10, 1: 2}, 1: {0: 5, 1: 83}}
    >>> get_recall(n)
    0.9431818181818182
    """
    assert len(n) == 2, 'F-score is only defined for binary problems'
    assert beta > 0.0
    return (1 + beta ** 2) * float(n[1][1]) / ((1 + beta ** 2) * n[1][1] +
        beta ** 2 * n[1][0] + n[0][1])


def string_to_numeric(options):
    """
    convert options which own numberic type
    """
    options.seed_value_begin = int(options.seed_value_begin)
    options.cudaid = int(options.cudaid)
    options.gpu_memory_fraction = float(options.gpu_memory_fraction)
    options.grid_coef_time = int(options.grid_coef_time)
    options.cv_coef_time = int(options.cv_coef_time)
    options.coef_ini = float(options.coef_ini)
    options.n_folds = int(options.n_folds)
    options.run_time = int(options.run_time)
    options.whole_run_time = int(options.whole_run_time)
    options.test_size = float(options.test_size)
    options.numfilters = int(options.numfilters)
    options.numlayercnn_per_maxpool = int(options.numlayercnn_per_maxpool)
    options.nummaxpool = int(options.nummaxpool)
    options.dropout_cnn = float(options.dropout_cnn)
    options.dropout_fc = float(options.dropout_fc)
    options.filtersize = int(options.filtersize)
    options.poolsize = int(options.poolsize)
    options.num_classes = int(options.num_classes)
    options.epoch = int(options.epoch)
    options.learning_rate = float(options.learning_rate)
    options.batch_size = int(options.batch_size)
    options.learning_rate_decay = float(options.learning_rate_decay)
    options.momentum = float(options.momentum)
    options.e_stop = int(options.e_stop)
    options.svm_c = float(options.svm_c)
    options.rf_n_estimators = int(options.rf_n_estimators)
    options.rf_max_features = int(options.rf_max_features)
    options.rf_max_depth = int(options.rf_max_depth)
    options.knn_n_neighbors = int(options.knn_n_neighbors)
    options.coeff = float(options.coeff)
    options.new_dim = int(options.new_dim)
    options.lr_visual = float(options.lr_visual)
    options.iter_visual = int(options.iter_visual)
    options.cmap_vmin = float(options.cmap_vmin)
    options.cmap_vmax = float(options.cmap_vmax)
    options.n_quantile = int(options.n_quantile)
    options.min_scale = float(options.min_scale)
    options.max_scale = float(options.max_scale)
    options.min_v = float(options.min_v)
    options.max_v = float(options.max_v)
    options.num_bin = int(options.num_bin)
    options.channel = int(options.channel)
    options.dim_img = int(options.dim_img)
    options.reduc_perle = int(options.reduc_perle)
    options.label_emb = int(options.label_emb)
    options.perlexity_neighbor = int(options.perlexity_neighbor)
    options.n_components_emb = int(options.n_components_emb)
    options.fig_size = int(options.fig_size)
    options.point_size = float(options.point_size)
    options.margin = float(options.margin)
    options.alpha_v = float(options.alpha_v)
    options.recreate_img = int(options.recreate_img)
    return options


def _is_in_group(opt, group):
    """Check if opt is in group."""
    for value in group._opts.values():
        if not value['opt'] != opt:
            return True
    return False


def set_warn(reg, warn):
    """ Groups warning messages for printout. """
    if warn:
        try:
            reg.warning += 'Warning: ' + warn + '\n'
        except:
            reg.warning = 'Warning: ' + warn + '\n'
    else:
        pass


def new():
    """Add a new material

    """
    pass


def renorm_flux(flux, companion_fluxratio: float, compaion: bool):
    """
	Renormalizes light curve flux to account for the existence of an unresolved companion.
	Args:
		flux (numpy array): Normalized flux of each data point.
		companion_fluxratio (float): Proportion of flux that comes from the unresolved companion.
		companion (bool): True if the transit is around the unresolved companion and False if it is not.
	Returns:
		renormed_flux (nump array): Remormalized flux of each data point.
	"""
    if compaion == True:
        renormed_flux = (flux - (1 - companion_fluxratio)
            ) / companion_fluxratio
    elif compaion == False:
        renormed_flux = (flux - companion_fluxratio) / (1 - companion_fluxratio
            )
    return renormed_flux


def input(message, default=None, cli_args=None, force_interactive=False):
    """Accept input from the user.

        When not setting force_interactive=True, you must provide a
        default value.

        :param str message: message to display to the user
        :param str default: default (non-interactive) response to prompt
        :param bool force_interactive: True if it's safe to prompt the user
            because it won't cause any workflow regressions

        :returns: tuple of (`code`, `input`) where
            `code` - str display exit code
            `input` - str of the user's input
        :rtype: tuple

        :raises errors.MissingCommandlineFlag: if called in non-interactive
            mode without a default set

        """


def tokenizeValues(values, name):
    """Returns an iterable of tokens for the values of the given index
        name"""


def get_legacy_py_generator_body_template():
    """
    In Python 2 we cannot use `yield from` in the generated function body.
    This is a replacement, from PEP380 - see https://www.python.org/dev/peps/pep-0380/#formal-semantics

    note: we removed a few lines so that `StopIteration` exceptions are re-raised
    :return:
    """
    return """def %s
    _i = iter(_func_impl_(%s))    # initialize the generator
    _y = next(_i)                    # first iteration
    while 1:
        try:
            _s = yield _y            # yield the first output and retrieve the new input
        except GeneratorExit as _e:  # ---generator exit error---
            try:
                _m = _i.close        # if there is a close method
            except AttributeError:
                pass
            else:
                _m()                 # use it first
            raise _e                 # then re-raise exception
        except BaseException as _e:  # ---other exception
            _x = sys.exc_info()      # if captured exception, grab info
            try:
                _m = _i.throw        # if there is a throw method
            except AttributeError:
                raise _e             # otherwise re-raise
            else:
                _y = _m(*_x)         # use it
        else:                        # --- nominal case: the new input was received
            # if _s is None:
            #     _y = next(_i)
            # else:
            _y = _i.send(_s)     # let the implementation decide if None means "no new input" or "new input = None\"
"""


def tagQuery(tag, tag_name, attrs):
    """Custom tag matcher. Takes into account that tags can
    have several classes."""
    if tag_name and tag_name != tag.name:
        return False
    for key, value in attrs.items():
        tag_attribute_value = tag.attrs.get(key)
        if not tag_attribute_value:
            return False
        if not isinstance(tag_attribute_value, list):
            tag_attribute_value = tag_attribute_value.split()
        if value in tag_attribute_value:
            continue
        return False
    return True


def validate_varchar_length(column_defs, column_name):
    """ validation for varchar_length parameter """
    return


def _setup_plot(limits, axis=None):
    """Sets up the figure axes and handles options common to all plots."""
    import matplotlib.pyplot as plt
    dim = len(limits)
    if dim == 3:
        is_3d = True
        from mpl_toolkits.mplot3d import Axes3D
    else:
        is_3d = False
        assert dim == 2
    if axis is None:
        fig = plt.figure()
        axis = fig.add_subplot(111, projection='3d' if is_3d else None)
    else:
        fig = None
    axis.set_xlim(*limits[0])
    axis.set_ylim(*limits[1])
    if is_3d:
        axis.set_zlim(*limits[2])
    return fig, axis, is_3d


def _unquote(string):
    """remove optional quotes (simple or double) from the string

    :type string: str or unicode
    :param string: an optionally quoted string

    :rtype: str or unicode
    :return: the unquoted string (or the input string if it wasn't quoted)
    """
    if not string:
        return string
    if string[0] in '"\'':
        string = string[1:]
    if string[-1] in '"\'':
        string = string[:-1]
    return string


def getMapiPath(field):
    """
    Remove the paramaters from a log records path field.

    :param field:   the mentioned log record's namespace field
    :return:        the path w/o parameters
    """
    return field.split('?')[0]


def without_color(line, color, mode=0):
    """This function does nothing to the input line.
    Just a ancillary function when there is not output color"""
    return line


def update_window(p, args):
    """Adds new args to a window if they exist"""
    content = p['content']
    layout = content['layout']
    layout.update(args.get('layout', {}))
    opts = args.get('opts', {})
    for opt_name, opt_val in opts.items():
        if opt_name in p:
            p[opt_name] = opt_val
    if 'legend' in opts:
        pdata = p['content']['data']
        for i, d in enumerate(pdata):
            d['name'] = opts['legend'][i]
    return p


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

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


def area_move(x: int=0, y: int=0, delta: int=0):
    """Move selected area edges

    :param x: X
    :type x: int
    :param y: Y
    :type y: int
    :param delta: Delta
    :type delta: int
    """
    pass


@classmethod
def build_pxe_default(cls, options=None):
    """Build PXE default template"""
    cls.command_sub = 'build-pxe-default'
    return cls.execute(cls._construct_command(options), output_format='csv')


def unquote_header_value(value, is_filename=False):
    """Unquotes a header value.  (Reversal of :func:`quote_header_value`).
    This does not use the real unquoting but what browsers are actually
    using for quoting.

    :param value: the header value to unquote.
    :rtype: str
    """
    if value and value[0] == value[-1] == '"':
        value = value[1:-1]
        if not is_filename or value[:2] != '\\\\':
            return value.replace('\\\\', '\\').replace('\\"', '"')
    return value


def pauseProducing():
    """
        Pause producing data.

        Tells a producer that it has produced too much data to process for
        the time being, and to stop until C{resumeProducing()} is called.
        """


def handle_extensions(extensions):
    """
    Organize multiple extensions that are separated with commas or passed by
    using --extension/-e multiple times.

    For example: running 'djmodels-admin makemessages -e js,txt -e xhtml -a'
    would result in an extension list: ['.js', '.txt', '.xhtml']

    >>> handle_extensions(['.html', 'html,js,py,py,py,.py', 'py,.py'])
    {'.html', '.js', '.py'}
    >>> handle_extensions(['.html, txt,.tpl'])
    {'.html', '.tpl', '.txt'}
    """
    ext_list = []
    for ext in extensions:
        ext_list.extend(ext.replace(' ', '').split(','))
    for i, ext in enumerate(ext_list):
        if not ext.startswith('.'):
            ext_list[i] = '.%s' % ext_list[i]
    return set(ext_list)


@classmethod
def _un_set_signal_handler(cls):
    """
        Set the default signal handler
        """
    import signal
    signal.signal(signal.SIGINT, signal.SIG_DFL)


@classmethod
def fix_non_manifold(cls, context, sides):
    """naive iterate-until-no-more approach for fixing manifolds"""
    total_non_manifold = cls.count_non_manifold_verts(context)
    if not total_non_manifold:
        return
    bm_states = set()
    bm_key = cls.elem_count(context)
    bm_states.add(bm_key)
    while True:
        cls.fill_non_manifold(sides)
        cls.delete_newly_generated_non_manifold_verts()
        bm_key = cls.elem_count(context)
        if bm_key in bm_states:
            break
        else:
            bm_states.add(bm_key)


def set_worst(old_worst, new_worst):
    """
    Pad new_worst with zeroes to prevent it being shorter than old_worst.

    >>> set_worst(311920, '48-49')
    '48-490'
    >>> set_worst(98, -2)
    -20
    """
    if isinstance(new_worst, bool):
        return new_worst
    negative = hasattr(old_worst, '__neg__') and old_worst < 0 or hasattr(
        new_worst, '__neg__') and new_worst < 0
    try:
        old_worst = abs(old_worst)
        new_worst = abs(new_worst)
    except TypeError:
        pass
    new_len = len(str(new_worst))
    old_len = len(str(old_worst))
    if new_len < old_len:
        new_type = type(new_worst)
        new_worst = str(new_worst).ljust(old_len, '0')
        new_worst = new_type(new_worst)
    if negative:
        try:
            new_worst = -1 * abs(new_worst)
        except:
            pass
    return new_worst


def is_number(c):
    """
    Return True if the character /c/ can form part of a number in esc.
    Raise AssertionError if the string is not exactly one character.

    >>> is_number('0')
    True

    >>> is_number('5')
    True

    >>> is_number('.')
    True

    >>> is_number('a')
    False

    >>> is_number('168.3')
    Traceback (most recent call last):
      ...
    AssertionError: c must be a single character

    >>> is_number('')
    Traceback (most recent call last):
      ...
    AssertionError: c must be a single character
    """
    assert len(c) == 1, 'c must be a single character'
    return '0' <= c <= '9' or c in ('.', '_', 'e')


def default_filter(src, dst):
    """The default progress/filter callback; returns True for all files"""
    return dst


def get_object_content(cmis_id):
    """Return an ICMISFileResult representing the data associated
        with the specified id. This is not applicable on non-fillable
        objects.
        """


@staticmethod
def _get_name(model) ->str:
    """Extract the name from an instance of namespace_model.

        :param model: The model to convert
        """
    return model.name


def fixup_columns(cols):
    """Replace index location column to name with `col` prefix

    Args:
        cols (list): List of original columns

    Returns:
        list: List of column names

    """
    out_cols = []
    for col in cols:
        if type(col) == int:
            out_cols.append('col{:d}'.format(col))
        else:
            out_cols.append(col)
    return out_cols


def provider_parser(subparser):
    """Configure provider parser for Easyname DNS"""
    subparser.description = 'A provider for Easyname DNS.'
    subparser.add_argument('--auth-username', help=
        'Specify username used to authenticate')
    subparser.add_argument('--auth-password', help=
        'Specify password used to authenticate')


def p_pool_content(p):
    """ pool_content : failover_stmt pool_content
                     | range_stmt pool_content
                     | pool_allow_deny_decls pool_content
                     | empty
    """
    p[0] = p[1]
    if len(p) > 2:
        p[0].update(p[2])


def set_dict_arg(key, arg, line_dim_obj, artists, legend_handles=None):
    """Helper for artist-sepcific matplotlib kwargs"""
    set_attr_name = 'set_' + key
    for dim_index, value in arg.items():
        index = line_dim_obj._array_index(dim_index)
        if isinstance(index, int):
            key_artists = [artists[index]]
        else:
            key_artists = artists[index]
        if not key_artists:
            continue
        for artist in key_artists:
            getattr(artist, set_attr_name)(value)
        if legend_handles is not None:
            for artist in key_artists:
                artist.set_label(dim_index)
            legend_handles[dim_index] = artist


def get_collaborations(s):
    """Get collaborations from the signature.

    Parameters
    ----------
    :param s: dict
        Signature

    Returns
    -------
    :returns: string
        Collaboations separated by a space
    """
    v = s['publication']['collaborations']
    v = ' '.join(v)
    return v


@classmethod
def from_string(cls, string):
    """
        Creates a new instance and loads the passed string

        :param unicode string: connection string to be parsed
        :rtype: ConnectionString

        """
    self = cls()
    self._store_items(self._parse_string(string.lstrip()),
        allow_prio_overriding=False)
    return self


@staticmethod
def parseDisabledLine(configLine):
    """Parser the config line and returns a tuple"""
    parts = configLine.split(':::', 2)
    if len(parts) != 3:
        raise ValueError('Incorrect disabled plugin description: ' + configLine
            )
    return int(parts[0]), parts[1], parts[2]


@classmethod
def decode(cls, msgs):
    """
        Placeholder for message decoding

        :returns: ``msgs``
        """
    return msgs


@staticmethod
def pretty_to_seconds(pretty_duration):
    """Converts pretty printed timestamp to seconds
        """
    millis_split = pretty_duration.split('.')
    millis = 0
    if len(millis_split) == 2:
        millis = int(millis_split[1])
        left = millis_split[0]
    else:
        left = pretty_duration
    left_split = left.split(':')
    if len(left_split) < 3:
        hours = 0
        minutes = int(left_split[0])
        seconds = int(left_split[1])
    else:
        hours = int(left_split[0])
        minutes = int(left_split[1])
        seconds = int(left_split[2])
    result = millis / 1000.0 + seconds + minutes * 60 + hours * 3600
    return result


def deregister_task_from_maintenance_window(WindowId=None, WindowTaskId=None):
    """
    Removes a task from a Maintenance Window.
    See also: AWS API Documentation

    :example: response = client.deregister_task_from_maintenance_window(
        WindowId='string',
        WindowTaskId='string'
    )

    :type WindowId: string
    :param WindowId: [REQUIRED]
            The ID of the Maintenance Window the task should be removed from.

    :type WindowTaskId: string
    :param WindowTaskId: [REQUIRED]
            The ID of the task to remove from the Maintenance Window.

    :rtype: dict
    :return: {
        'WindowId': 'string',
        'WindowTaskId': 'string'
    }

    """
    pass


def is_aa_seq(file):
    """check input gene files to make sure they are amino acid sequences and not nucletotide sequences"""
    with open(file, 'r') as infile:
        all_count, atcg_count = 0, 0
        for line in infile:
            if line.startswith('>'):
                pass
            else:
                all_count += len(line)
                atcg_count += line.upper().count('A') + line.upper().count('T'
                    ) + line.upper().count('C') + line.upper().count('G')
        atcg_per = atcg_count / all_count
        if atcg_per > 0.7:
            return False
        else:
            return True


def resumeProducing():
    """
        Resume producing data.

        This tells a producer to re-add itself to the main loop and produce
        more data for its consumer.
        """


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

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

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


@staticmethod
def p_value_descriptions_list(p):
    """value_descriptions_list : value_descriptions_for
                                   | value_descriptions_for value_descriptions_list"""
    try:
        p[0] = [p[1]] + p[2]
    except IndexError:
        p[0] = [p[1]]


def __get_attributes(elements, params):
    """Get elements using element's attributes.

    Parameters:
    - elements [list] : List of elements to filter for its attributes
    - params [dict] : A dict that contains elements to search the element for
    Returns:
    - output [WebElement list] : A subset list of found WebElements inside elements argument
    """
    params_tmp = params.copy()
    elements_tmp = elements.copy()
    found = False
    ret_items = []
    while len(params_tmp) > 0:
        for item in elements_tmp:
            key = next(iter(params_tmp))
            if key == 'text':
                if item.text == params_tmp.get('text'):
                    found = True
            elif key == 'tag_name_attribute':
                if item.tag_name == params_tmp.get('tag_name_attribute'):
                    found = True
            elif item.get_attribute(key) == params_tmp.get(key):
                found = True
            if found:
                ret_items.append(item)
            found = False
        del params_tmp[key]
        if len(ret_items) > 0 and len(params_tmp) > 0:
            elements_tmp = ret_items
            ret_items = []
    return ret_items


def insert_stock_transfer_record(data: dict, bank_account: object):
    """Inserts a transfer record between a bank account and a stock account.
    """
    from finance.models import Asset, deposit
    asset_krw = Asset.query.filter(Asset.name == 'KRW').first()
    subtotal = data['subtotal']
    date = data['date']
    if data['name'] == '증거금이체':
        return deposit(bank_account, asset_krw, -subtotal, date)
    elif data['name'] == '매매대금정산':
        return deposit(bank_account, asset_krw, subtotal, date)
    else:
        raise ValueError("Unrecognized transfer type '{}'".format(data['name'])
            )


def add_delta_dst(dt, delta):
    """Add a timedelta to a datetime, adjusting DST when appropriate"""
    naive_dt = dt.replace(tzinfo=None)
    return dt.tzinfo.localize(naive_dt + delta)


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


@staticmethod
def _sink_BigQuery():
    """Method to add BigQuery as sink."""
    pass


def index_of_dict_in_list(l, value, key=None):
    """Get index of item (a dict) in list

    # Example:
    ```python
    l = [
        {'a': 1},
        {'a': 2},
        {'a': 3}
    ]
    index_of_dict_in_list(l, 2) # returns 1
    ```
    """
    if key is None:
        for i, d in enumerate(l):
            v, = d.values()
            if v == value:
                return i
    else:
        for i, d in enumerate(l):
            if d[key] == value:
                return i
    raise ValueError('No value matched')


def play_conditions_met(magnet):
    """
        Returns true if file has been found and
        torrent download ratio excees play ratio specified.
    """
    if not magnet['file']:
        return False
    if magnet['play_ratio'] == -1:
        return False
    return magnet['play_ratio'] <= magnet['handle'].status().progress * 100


def matrix_factor(mfp_a, mfp_b, mfp_matrix_a, mfp_matrix_b, rho_a, rho_b):
    """Determines the matrix multiplicity factor. Mean free path values can be
found using an external program QUASES-IMFP-TPP2M.

    mfp_a        : Mean free path (mfp) of a in bulk, eg. mfp_a(KE_{Mn 2p3/2})
    mfp_b        : Mean free path (mfp) of b in bulk, eg. mfp_b(KE_{Co 2p3/2})
    mfp_matrix_a : Mean free path of matrix with kinetic energy of a
                   mfp_matirx(KE_{Mn 2p3/2})
    mfp_matrix_b : Mean free path of matrix with kinetic energy of b
                   mfp_matirx(KE_{Co 2p3/2})
    rho_a        : Density of species a
    rho_b        : Density of species b
    """
    a = mfp_matrix_a / mfp_a / rho_a
    b = mfp_matrix_b / mfp_b / rho_b
    return a / b


@classmethod
def get_related_models(cls, *models):
    """
        Return list of related model for this one
        """
    related_models = []
    for model in models:
        try:
            for fk in model.foreign_keys:
                if cls.primary_key[0] == fk:
                    related_models.append(model)
        except AttributeError:
            pass
    return related_models


def from_url(url, db=None, **kwargs):
    """
    Returns an active Redis client generated from the given database URL.

    Will attempt to extract the database id from the path url fragment, if
    none is provided.
    """
    from redis.client import Redis
    return Redis.from_url(url, db, **kwargs)


def _parse_redis_connection(connection):
    """
    Parse redis connection to host, db
    :param connection: redis connection
    :return: host, db
    """
    connection_kwargs = connection.connection_pool.connection_kwargs
    return connection_kwargs.get('host', 'local'), connection_kwargs.get('port'
        ), connection_kwargs.get('db', '0')


@classmethod
def GetPluginObjectByName(cls, plugin_name):
    """Retrieves a specific plugin object by its name.

    Args:
      plugin_name (str): name of the plugin.

    Returns:
      BasePlugin: a plugin object or None if not available.
    """
    plugin_class = cls._plugin_classes.get(plugin_name, None)
    if plugin_class:
        return plugin_class()
    return None


def encoding_from_lang(lang):
    """
    Parse encoding from LANG environment value.

    Example::

        >>> encoding_from_lang('en_US.UTF-8@misc')
        'UTF-8'
    """
    encoding = lang
    if '.' in lang:
        _, encoding = lang.split('.', 1)
    if '@' in encoding:
        encoding, _ = encoding.split('@', 1)
    return encoding