def _verify_argument_is_older_than_owner(owner_identifier, arg_identifier):
    """
    A helper function to catch an Exception early, so it doesn't get caught by the server where the error message is less clear.
    """
    if (arg_identifier.preliminary is not None and owner_identifier.
        preliminary is not None):
        if arg_identifier.preliminary == owner_identifier.preliminary:
            if arg_identifier.id >= owner_identifier.id:
                raise ValueError(
                    'An object used as an argument must be created before the object it belongs to.'
                    )


def get_pipeline_url(environment: str, enterprise_id: str, pipeline_id: str
    =None) ->str:
    """
    Build and return pipeline url for scapi endpoint
    :param environment:
    :param enterprise_id:
    :param pipeline_id:
    :param stage_id:
    :param operation_id:
    :return: Url
    """
    url = (
        f'https://{environment}-api.esper.cloud/api/v1/enterprise/{enterprise_id}/pipeline/'
        )
    if pipeline_id:
        url += f'{pipeline_id}/'
    return url


@staticmethod
def _get_object_prop(vm, attributes):
    """Safely get a property or return None"""
    result = vm
    for attribute in attributes:
        try:
            result = getattr(result, attribute)
        except (AttributeError, IndexError):
            return None
    return result


def samplets(features, confounds, x_var=None, y_var=None, group_by=None,
    color_by=None, sort_x_by=None):
    """
    Plot of the feature distribution for each samplet
    along a axis of a given variable,
    grouped and coloured by chosen variables.
    """
    raise NotImplementedError()


@staticmethod
def __format_rowname(stru):
    """
        Private method to format the name of the rows in the stats table
        :param stru:
        :return:
        """
    total_length = 35
    return ' ' * (total_length - len(stru) - 1) + '{}:'.format(stru.rstrip(':')
        )


def ceiling_root(num, pwr):
    """
    Returns the integer ``num ** (1. / pwr)`` if num is a perfect square/cube/etc,
    or the integer ceiling of this value, if it's not.
    """
    res = num ** (1.0 / pwr)
    int_res = int(round(res))
    if int_res ** pwr == num:
        return int_res
    else:
        return int(res + 1)


def prettify(paradigms):
    """utility function. pretty print.
    """
    for num, paradigm in enumerate(paradigms, start=1):
        pos, li_ending_and_form = paradigm
        print('=' * 20, num, '=' * 20)
        print('POS =', pos)
        for ending, form in li_ending_and_form:
            print('• ending = {} form = {}'.format(ending, form))
        print()


def p_list_apostrophe(p):
    """list_apostrophe : APOSTROPHE list_apostrophe
                       | APOSTROPHE"""
    if len(p) == 2:
        p[0] = 1
    else:
        p[0] = p[2] + 1


def create_metaRd_db(dbcon):
    """ Create an database to store R help pages.

    dbcon: database connection (assumed to be SQLite - may or may not work
           with other databases)
    """
    dbcon.execute(
        """
CREATE TABLE package (
name TEXT UNIQUE,
title TEXT,
version TEXT,
description TEXT
);
"""
        )
    dbcon.execute(
        """
CREATE TABLE rd_meta (
id INTEGER, file TEXT UNIQUE, name TEXT, type TEXT, title TEXT, encoding TEXT,
package_rowid INTEGER
);
"""
        )
    dbcon.execute('\nCREATE INDEX type_idx ON rd_meta (type);\n')
    dbcon.execute(
        '\nCREATE TABLE rd_alias_meta (\nrd_meta_rowid INTEGER, alias TEXT\n);\n'
        )
    dbcon.execute('\nCREATE INDEX alias_idx ON rd_alias_meta (alias);\n')
    dbcon.commit()


def sample():
    """Add keyframes on every frame between the selected keyframes

    """
    pass


def select_last(only_selected_strokes: bool=False, extend: bool=False):
    """Select last point in Grease Pencil strokes

    :param only_selected_strokes: Selected Strokes Only, Only select the last point of strokes that already have points selected
    :type only_selected_strokes: bool
    :param extend: Extend, Extend selection instead of deselecting all other selected points
    :type extend: bool
    """
    pass


@classmethod
def global_config(cls, key, *args):
    """ This reads or sets the global settings stored in class.settings. """
    if args:
        cls.settings = cls.settings.copy()
        cls.settings[key] = args[0]
    else:
        return cls.settings[key]


def check_max_rotatable_bonds(group, tors, tors_ring_num):
    """

        Check if some sidechain has more

        than 2 rotatable bonds to lower

        its resolution

    """
    LIMIT_ROTATABLE_BONDS = 2
    max_rotatable_bonds = []
    for grp in range(max(group) + 1):
        count = 0
        for i in range(len(tors)):
            if group[tors[i][0]] == grp or group[tors[i][1]] == grp:
                if tors_ring_num[i] == 0:
                    count += 1
        if count > LIMIT_ROTATABLE_BONDS:
            max_rotatable_bonds.append(True)
        else:
            max_rotatable_bonds.append(False)
    return max_rotatable_bonds


@classmethod
def follower_list(cls, object_id):
    """Return a list of followers of the object."""
    query = cls._get_followers(object_id).all()
    followers = cls._filter_following_objects(query)
    return followers


@staticmethod
def to_rankine(kelvin):
    """ Convert kelvin to rankine """
    return kelvin * 9 / 5


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


def get_max_memory_allocated(device: str='cuda'):
    """
    Finds out the maximum memory allocated, then clears the max memory allocated.

    This currently only works for PyTorch models.

    TODO: Support TensorFlow and MXNet.

    :param device: (str) - name of device (Torch style) -> e.g. 'cuda'
    :return: float or None - if torch is in the environment, max memory allocated, else None
    """
    try:
        import torch
        max_mem = torch.cuda.max_memory_allocated(device=device)
        torch.cuda.reset_max_memory_allocated(device=device)
        return max_mem
    except ImportError:
        return None


def number_strings(*strings):
    """Print a list of strings with a number preceding each."""
    for number, string in enumerate(strings):
        number += 1
        print(number, string)
    return


def AR_10(dul):
    """Association release AR-10.

    On receiving A-RELEASE-RP, issue release confirmation

    State-event triggers: Sta10 + Evt13

    References
    ----------
    1. DICOM Standard 2015b, PS3.8, Table 9-7, "Associate Establishment
       Related Actions"

    Parameters
    ----------
    dul : pynetdicom.dul.DULServiceProvider
        The DICOM Upper Layer Service instance for the local AE

    Returns
    -------
    str
        Sta12, the next state of the state machine
    """
    dul.to_user_queue.put(dul.primitive)
    return 'Sta12'


def stats_history_csv_header():
    """Headers for the stats history CSV"""
    return ','.join(('"Type"', '"Name"', '"Timestamp"', '"# requests"',
        '"# failures"', '"Requests/s"', '"Requests Failed/s"',
        '"Median response time"', '"Average response time"',
        '"Min response time"', '"Max response time"',
        '"Average Content Size"', '"50%"', '"66%"', '"75%"', '"80%"',
        '"90%"', '"95%"', '"98%"', '"99%"', '"99.9%"', '"99.99%"',
        '"99.999"', '"100%"')) + '\n'


def hello(name, which=1):
    """
    Hello-es a name.
    You can choose from 4 different helloes.
    """
    if which == 1:
        return 'Hello %s' % name
    if which == 2:
        return 'Hi %s' % name
    if which == 3:
        return 'Greetings %s' % name
    if which == 4:
        return "'sup %s" % name
    if which > 4 or which < 1:
        raise ValueError(
            "Hello number %s doesn't exist. There are only 4 helloes." % which)
    if name is None:
        raise Exception('You need someone to say hello to.')


def wsgi_to_bytes(data):
    """coerce wsgi unicode represented bytes to real ones"""
    if isinstance(data, bytes):
        return data
    return data.encode('latin1')


def write_disagg_fuel_sector(path_to_txt, data):
    """Write out disaggregated fuel

    Arguments
    ----------
    path_to_txt : str
        Path to txt file
    data : dict
        Data to write out
    """
    file = open(path_to_txt, 'w')
    file.write('{}, {}, {}, {}, {}'.format('region', 'enduse', 'sector',
        'fueltypes', 'fuel') + '\n')
    for region, sectors in data.items():
        for sector, enduses in sectors.items():
            for enduse, fuels in enduses.items():
                for fueltype, fuel in enumerate(fuels):
                    file.write('{}, {}, {}, {}, {}'.format(str.strip(region
                        ), str.strip(enduse), str.strip(sector), str(int(
                        fueltype)), str(float(fuel)) + '\n'))
    file.close()
    return


@classmethod
def from_json(cls, connection, json_pool, is_summary=False):
    """Create a Pool object from a json pool.

        :param qarnot.connection.Connection connection: the cluster connection
        :param dict json_pool: Dictionary representing the pool
        :returns: The created :class:`~qarnot.pool.Pool`.
        """
    new_pool = cls(connection, json_pool['name'], json_pool['profile'],
        json_pool['instanceCount'])
    new_pool._update(json_pool)
    new_pool._is_summary = is_summary
    return new_pool


def build_plane_map_from_ranges(z_range, t_range):
    """ Determines the plane to load. """
    plane_map = []
    for t in t_range:
        for z in z_range:
            plane_map.append([t, z])
    return plane_map


def wf_id():
    """
    It returns the workflow job ID for the current workflow job.

    In airflow it can be found using Jinja templating for `run_id`
    This has the effect that some parameters cannot be templated, and thus
    this will fail.
    """
    return '{{ run_id }}'


def yaw(ax, ay, az):
    """Angle of z-axis relative to ground (psi)

    Args
    ----
    ax: ndarray
        x-axis acceleration values
    ay: ndarray
        y-axis acceleration values
    az: ndarray
        z-axis acceleration values

    Returns
    -------
    yaw: ndarray
        Yaw angle in radians
    """
    import numpy
    return numpy.arctan2(ax, ay)


def set_data_retrieval_policy(accountId=None, Policy=None):
    """
    This operation sets and then enacts a data retrieval policy in the region specified in the PUT request. You can set one policy per region for an AWS account. The policy is enacted within a few minutes of a successful PUT operation.
    The set policy operation does not affect retrieval jobs that were in progress before the policy was enacted. For more information about data retrieval policies, see Amazon Glacier Data Retrieval Policies .
    See also: AWS API Documentation

    Examples
    The example sets and then enacts a data retrieval policy.
    Expected Output:

    :example: response = client.set_data_retrieval_policy(
        Policy={
            'Rules': [
                {
                    'Strategy': 'string',
                    'BytesPerHour': 123
                },
            ]
        }
    )

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

    :type Policy: dict
    :param Policy: The data retrieval policy in JSON format.
            Rules (list) --The policy rule. Although this is a list type, currently there must be only one rule, which contains a Strategy field and optionally a BytesPerHour field.
            (dict) --Data retrieval policy rule.
            Strategy (string) --The type of data retrieval policy to set.
            Valid values: BytesPerHour|FreeTier|None
            BytesPerHour (integer) --The maximum number of bytes that can be retrieved in an hour.
            This field is required only if the value of the Strategy field is BytesPerHour . Your PUT operation will be rejected if the Strategy field is not set to BytesPerHour and you set this field.

    :return: response = client.set_data_retrieval_policy(
        Policy={
            'Rules': [
                {
                    'BytesPerHour': 10737418240,
                    'Strategy': 'BytesPerHour',
                },
            ],
        },
        accountId='-',
    )

    print(response)

    """
    pass


def expand_request_pixels(request, radius=1):
    """ Expand request by `radius` pixels. Returns None for non-vals requests
    or point requests. """
    if request['mode'] != 'vals':
        return None
    width, height = request['width'], request['height']
    x1, y1, x2, y2 = request['bbox']
    pwidth, pheight = x2 - x1, y2 - y1
    if pwidth == 0 or pheight == 0:
        return None
    amount_x = pwidth / width * radius
    amount_y = pheight / height * radius
    new_request = request.copy()
    new_request['bbox'
        ] = x1 - amount_x, y1 - amount_x, x2 + amount_y, y2 + amount_y
    new_request['width'] += 2 * radius
    new_request['height'] += 2 * radius
    return new_request


def no_translate_debug_logs(logical_line, filename):
    """Check for 'LOG.debug(_('
    As per our translation policy,
    https://wiki.openstack.org/wiki/LoggingStandards#Log_Translation
    we shouldn't translate debug level logs.
    * This check assumes that 'LOG' is a logger.
    * Use filename so we can start enforcing this in specific folders instead
      of needing to do so all at once.
    N319
    """
    if logical_line.startswith('LOG.debug(_('):
        yield 0, "D706: Don't translate debug level logs"


@classmethod
def parseKwargs(cls, config_psf, logger):
    """Parse the psf field of a configuration dict and return the kwargs to use for
        initializing an instance of the class.

        The base class implementation just returns the kwargs as they are, but derived classes
        might want to override this if they need to do something more sophisticated with them.

        :param config_psf:      The psf field of the configuration dict, config['psf']
        :param logger:          A logger object for logging debug info. [default: None]

        :returns: a kwargs dict to pass to the initializer
        """
    kwargs = {}
    kwargs.update(config_psf)
    kwargs.pop('type', None)
    return kwargs


def volTetra(xyz, A, B, C, D):
    """
    Returns the volume for tetrahedras volume specified by the indexes A to D.

    :param numpy.ndarray xyz: X,Y,Z vertex vector
    :param numpy.ndarray A,B,C,D: vert index of the tetrahedra
    :rtype: numpy.ndarray
    :return: V, volume of the tetrahedra

    Algorithm https://en.wikipedia.org/wiki/Tetrahedron#Volume

    .. math::

       V = {1 \\over 3} A  h

       V = {1 \\over 6} | ( a - d ) \\cdot ( ( b - d )  ( c - d ) ) |

    """
    AD = xyz[(A), :] - xyz[(D), :]
    BD = xyz[(B), :] - xyz[(D), :]
    CD = xyz[(C), :] - xyz[(D), :]
    V = (BD[:, (0)] * CD[:, (1)] - BD[:, (1)] * CD[:, (0)]) * AD[:, (2)] - (
        BD[:, (0)] * CD[:, (2)] - BD[:, (2)] * CD[:, (0)]) * AD[:, (1)] + (
        BD[:, (1)] * CD[:, (2)] - BD[:, (2)] * CD[:, (1)]) * AD[:, (0)]
    return V / 6


def _ecdf_y(data, complementary=False):
    """Give y-values of an ECDF for an unsorted column in a data frame.

    Parameters
    ----------
    data : Pandas Series
        Series (or column of a DataFrame) from which to generate ECDF
        values
    complementary : bool, default False
        If True, give the ECCDF values.

    Returns
    -------
    output : Pandas Series
        Corresponding y-values for an ECDF when plotted with dots.

    Notes
    -----
    .. This only works for plotting an ECDF with points, not for staircase
       ECDFs
    """
    if complementary:
        return 1 - data.rank(method='first') / len(data) + 1 / len(data)
    else:
        return data.rank(method='first') / len(data)


def delete_dhcp_options(DryRun=None, DhcpOptionsId=None):
    """
    Deletes the specified set of DHCP options. You must disassociate the set of DHCP options before you can delete it. You can disassociate the set of DHCP options by associating either a new set of options or the default set of options with the VPC.
    See also: AWS API Documentation

    Examples
    This example deletes the specified DHCP options set.
    Expected Output:

    :example: response = client.delete_dhcp_options(
        DryRun=True|False,
        DhcpOptionsId='string'
    )

    :type DryRun: boolean
    :param DryRun: Checks whether you have the required permissions for the action, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation . Otherwise, it is UnauthorizedOperation .

    :type DhcpOptionsId: string
    :param DhcpOptionsId: [REQUIRED]
            The ID of the DHCP options set.

    :return: response = client.delete_dhcp_options(
        DhcpOptionsId='dopt-d9070ebb',
    )

    print(response)

    """
    pass


def get_user_name(user_email):
    """
        returns the full name associated with the user_email
        """


def de_select_last():
    """(De)select last of visible part of each NURBS

    """
    pass


def truncate_seq_pair(tokens_a, max_num_tokens, rng):
    """Truncates a pair of sequences to a maximum sequence length."""
    while True:
        total_length = len(tokens_a)
        if total_length <= max_num_tokens:
            return tokens_a
        trunc_tokens = tokens_a
        assert len(trunc_tokens) >= 1
        if rng.random() < 0.5:
            tokens_a = trunc_tokens[1:]
        else:
            tokens_a = trunc_tokens[:-1]


def strip_consecutive_repeated_char(s, ch):
    """Strip characters in a string which are consecutively repeated.

    Useful when in notes or some other free text fields on Mambu, users
    capture anything and a lot of capture errors not always detected by
    Mambu get through. You want some cleaning? this may be useful.

    This is a string processing function.
    """
    sdest = ''
    for i, c in enumerate(s):
        if i != 0 and s[i] == ch and s[i] == s[i - 1]:
            continue
        sdest += s[i]
    return sdest


def _raise_exception(exception_object):
    """ Raise exception with short traceback """
    raise exception_object


def list_handshakes_for_organization(Filter=None, NextToken=None,
    MaxResults=None):
    """
    Lists the handshakes that are associated with the organization that the requesting user is part of. The ListHandshakesForOrganization operation returns a list of handshake structures. Each structure contains details and status about a handshake.
    This operation can be called only from the organization's master account.
    See also: AWS API Documentation

    :example: response = client.list_handshakes_for_organization(
        Filter={
            'ActionType': 'INVITE'|'ENABLE_ALL_FEATURES'|'APPROVE_ALL_FEATURES',
            'ParentHandshakeId': 'string'
        },
        NextToken='string',
        MaxResults=123
    )

    :type Filter: dict
    :param Filter: A filter of the handshakes that you want included in the response. The default is all types. Use the ActionType element to limit the output to only a specified type, such as INVITE , ENABLE-ALL-FEATURES , or APPROVE-ALL-FEATURES . Alternatively, for the ENABLE-ALL-FEATURES handshake that generates a separate child handshake for each member account, you can specify the ParentHandshakeId to see only the handshakes that were generated by that parent request.
            ActionType (string) --Specifies the type of handshake action.
            If you specify ActionType , you cannot also specify ParentHandshakeId .
            ParentHandshakeId (string) --Specifies the parent handshake. Only used for handshake types that are a child of another type.
            If you specify ParentHandshakeId , you cannot also specify ActionType .
            The regex pattern for handshake ID string requires 'h-' followed by from 8 to 32 lower-case letters or digits.

    :type NextToken: string
    :param NextToken: Use this parameter if you receive a NextToken response in a previous request that indicates that there is more output available. Set it to the value of the previous call's NextToken response to indicate where the output should continue from.

    :type MaxResults: integer
    :param MaxResults: (Optional) Use this to limit the number of results you want included in the response. If you do not include this parameter, it defaults to a value that is specific to the operation. If additional items exist beyond the maximum you specify, the NextToken response element is present and has a value (is not null). Include that value as the NextToken request parameter in the next call to the operation to get the next part of the results. Note that Organizations might return fewer results than the maximum even when there are more results available. You should check NextToken after every operation to ensure that you receive all of the results.

    :rtype: dict
    :return: {
        'Handshakes': [
            {
                'Id': 'string',
                'Arn': 'string',
                'Parties': [
                    {
                        'Id': 'string',
                        'Type': 'ACCOUNT'|'ORGANIZATION'|'EMAIL'
                    },
                ],
                'State': 'REQUESTED'|'OPEN'|'CANCELED'|'ACCEPTED'|'DECLINED'|'EXPIRED',
                'RequestedTimestamp': datetime(2015, 1, 1),
                'ExpirationTimestamp': datetime(2015, 1, 1),
                'Action': 'INVITE'|'ENABLE_ALL_FEATURES'|'APPROVE_ALL_FEATURES',
                'Resources': [
                    {
                        'Value': 'string',
                        'Type': 'ACCOUNT'|'ORGANIZATION'|'ORGANIZATION_FEATURE_SET'|'EMAIL'|'MASTER_EMAIL'|'MASTER_NAME'|'NOTES'|'PARENT_HANDSHAKE',
                        'Resources': {'... recursive ...'}
                    },
                ]
            },
        ],
        'NextToken': 'string'
    }

    :returns:
    REQUESTED : This handshake was sent to multiple recipients (applicable to only some handshake types) and not all recipients have responded yet. The request stays in this state until all recipients respond.
    OPEN : This handshake was sent to multiple recipients (applicable to only some policy types) and all recipients have responded, allowing the originator to complete the handshake action.
    CANCELED : This handshake is no longer active because it was canceled by the originating account.
    ACCEPTED : This handshake is complete because it has been accepted by the recipient.
    DECLINED : This handshake is no longer active because it was declined by the recipient account.
    EXPIRED : This handshake is no longer active because the originator did not receive a response of any kind from the recipient before the expiration time (15 days).

    """
    pass


@classmethod
def set_counter(cls, name, value):
    """
        Special function to update vm prefix count.

        :param name:
        :param value:
        :param user:
        :return:
        """
    cls.set(name, str(value), type='int')
    cls.set(name, str(value), type='int')


def is_iterable(something):
    """
    Test if it is an iterable other than
    a string.

    Returns
    -------
    bool
        True if an iterable other than str,
        False otherwise.
    """
    try:
        iter(something)
    except TypeError:
        return False
    return True and not isinstance(something, str)


def combine(*styles):
    """Combine multiple style specifications into one.

    Parameters
    ----------
    styles: sequence of :class:`dict` instances
        A collection of dicts containing CSS-compatible name-value pairs.

    Returns
    -------
    styles: :class:`dict` containing CSS-compatible name-value pairs.
    """
    computed_style = {}
    for style in styles:
        if style is not None:
            computed_style.update(style)
    return computed_style


def bedcolumns_parser(subparsers):
    """
    Parser for the bedcolumns tool.
    """
    parser = subparsers.add_parser('bedcolumns', help=
        'determine the numbers of BED and extra columns', description=
        'Determine the number of BED columns and the number of extra columns in a BED file'
        )
    parser.add_argument('bed_file', help='a BED file')


def isdouble(dtype):
    """Check if ``dtype`` is double precision.
    """
    return dtype in ('float64', 'complex128')


def _get_column_letter(col_idx):
    """Convert a column number into a column letter (3 -> 'C')

    Right shift the column col_idx by 26 to find column letters in reverse
    order.  These numbers are 1-based, and can be converted to ASCII
    ordinals by adding 64.

    """
    if not 1 <= col_idx <= 18278:
        raise ValueError('Invalid column index {0}'.format(col_idx))
    letters = []
    while col_idx > 0:
        col_idx, remainder = divmod(col_idx, 26)
        if remainder == 0:
            remainder = 26
            col_idx -= 1
        letters.append(chr(remainder + 64))
    return ''.join(reversed(letters))


@classmethod
def get_sentinel(cls, name):
    """Return the sentinel with the given name, creating it if necessary."""
    return cls.__sentinels.setdefault(name, cls(name))


def __str__(cls):
    """Renders as empty tag."""
    if cls.self_closing:
        return '<%s/>' % cls.__name__
    else:
        return '<%s></%s>' % (cls.__name__, cls.__name__)


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


@classmethod
def edit(cls, record, parent=None, autoCommit=True, title=''):
    """
        Prompts the user to edit the inputed record.

        :param      record | <orb.Table>
                    parent | <QWidget>

        :return     <bool> | accepted
        """
    dlg = cls.getDialog('edit', parent)
    try:
        name = record.schema().displayName()
    except AttributeError:
        name = record.__class__.__name__
    if not title:
        title = 'Edit {0}'.format(name)
    dlg.setWindowTitle(title)
    widget = dlg._mainwidget
    widget.setRecord(record)
    widget.setAutoCommitOnSave(autoCommit)
    result = dlg.exec_()
    return result == 1


def disable_color():
    """Disable colours by setting colour code constants to empty strings."""
    global LIGHT_GREEN
    LIGHT_GREEN = ''
    global LIGHT_RED
    LIGHT_RED = ''
    global LIGHT_BLUE
    LIGHT_BLUE = ''
    global DARK_RED
    DARK_RED = ''
    global END_COLOR
    END_COLOR = ''


def generate_news_url(query, first, recent, country_code):
    """(str, str) -> str
    A url in the required format is generated.
    """
    query = '+'.join(query.split())
    url = 'http://www.bing.com/news/search?q=' + query + '&first' + first
    if recent in ['h', 'd', 'w', 'm', 'y']:
        url = url + '&qft=sortbydate%3d%221%22'
    if country_code is not None:
        url += '&cc=' + country_code
    return url


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


def fullname(o):
    """ Get the fully-qualified class name of an object

    :param o: object of any kind
    :type o: object
    :return: fully-qualified class name
    :rtype: string

    """
    return o.__module__ + '.' + o.__class__.__name__


def _get_bounds(z, b, wl, x0, xRes):
    """
    Gets the indices of range of wavelength that the wavelength wl is in
    with the size of some initial wavelength range.

    Used for checking if species with multiple lines (as in the OVI doublet)
    fit all lines appropriately.

    Parameters
    ----------
    z : float
        redshift
    b : (3) ndarray/list
        initial bounds in form [i0,i1,i2] where i0 is the index of the
        minimum flux for the complex, i1 is index of the lower wavelength
        edge of the complex, and i2 is the index of the higher wavelength
        edge of the complex.
    wl : float
        unredshifted wavelength of the peak of the new region
    x0 : float
        wavelength of the index 0
    xRes : float
        difference in wavelength for two consecutive indices

    Returns
    -------
    indices : (2) tuple
        Tuple (i1,i2) where i1 is the index of the lower wavelength bound of
        the new region and i2 is the index of the higher wavelength bound of
        the new region
    """
    r = [-b[1] + 100 + b[0], b[2] + 100 - b[0]]
    redWl = (z + 1) * wl
    iRedWl = int((redWl - x0) / xRes)
    indices = iRedWl - r[0], iRedWl + r[1]
    return indices


def plot(im1, im2=None, cmap1='gray', cmap2='jet', slice=0, alpha=1,
    show_plot=True, save_plot=False):
    """
    Convenience function to handle plotting of neurodata arrays.
    Mostly tested with 8-bit image and 32-bit annos, but lots of
    things should work.  Mimics (and uses) matplotlib, but transparently
    deals with RAMON objects, transposes, and overlays.  Slices 3D arrays
    and allows for different blending when using overlays.  We require
    (but verify) that dimensions are the same when overlaying.

    Arguments:
        im1 (array): RAMONObject or numpy array
        im2 (array) [None]:  RAMONObject or numpy array
        cmap1 (string ['gray']): Colormap for base image
        cmap2 (string ['jet']): Colormap for overlay image
        slice (int) [0]: Used to choose slice from 3D array
        alpha (float) [1]: Used to set blending option between 0-1

    Returns:
        None.

    """
    import numpy as np
    import matplotlib.pyplot as plt
    fig = plt.figure()
    ax = plt.Axes(fig, [0.0, 0.0, 1.0, 1.0])
    ax.set_axis_off()
    fig.add_axes(ax)
    base_image = False
    im1_proc = None
    if hasattr(im1, 'cutout') and im1.cutout is not None:
        im1_proc = im1.cutout
    elif im1 is not None:
        im1_proc = im1
    if im1_proc is not None and len(np.shape(im1_proc)) == 3:
        im1_proc = im1_proc[:, :, (slice)]
    if im1_proc is not None:
        base_image = True
    overlay_image = False
    im2_proc = None
    if im2 is not None:
        if hasattr(im2, 'cutout') and im2.cutout is not None:
            im2_proc = im2.cutout
        elif im2 is not None:
            im2_proc = im2
        if im2_proc is not None and len(np.shape(im2_proc)) == 3:
            im2_proc = im2_proc[:, :, (slice)]
    if im2_proc is not None and np.shape(im1_proc) == np.shape(im2_proc):
        overlay_image = True
    if base_image:
        plt.imshow(im1_proc.T, cmap=cmap1, interpolation='bilinear')
    if base_image and overlay_image and alpha == 1:
        im2_proc = np.ma.masked_where(im2_proc == 0, im2_proc)
        plt.imshow(im2_proc.T, cmap=cmap2, interpolation='nearest')
    elif base_image and overlay_image and alpha < 1:
        plt.hold(True)
        im2_proc = np.asarray(im2_proc, dtype='float')
        im2_proc[im2_proc == 0] = np.nan
        plt.imshow(im2_proc.T, cmap=cmap2, alpha=alpha, interpolation='nearest'
            )
    if save_plot is not False:
        plt.savefig(save_plot, dpi=300, pad_inches=0)
    if show_plot is True:
        plt.show()
    pass


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

        :param NoteAclInviteOnlyDetails val:
        :rtype: EventDetails
        """
    return cls('note_acl_invite_only_details', val)


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


def _validate_documentation_existence(moler_module, test_data, observer_type):
    """Check if module has at least one variant of output documented"""
    if len(test_data.keys()) == 0:
        expected_info = '{}_OUTPUT/{}_KWARGS/{}_RESULT'.format(observer_type,
            observer_type, observer_type)
        error_msg = '{} is missing documentation: {}'.format(moler_module,
            expected_info)
        return error_msg
    return ''


def clamp(x, l, u):
    """
    clamp x to be l <= x <= u

    >>> clamp(5, 1, 10)
    5
    >>> clamp(-1, 1, 10)
    1
    >>> clamp(12, 1, 10)
    10
    """
    assert l <= u
    return l if x < l else u if x > u else x


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


@classmethod
def convert_to_review_url(cls, base_url, review_num):
    """Create a web url from review number."""
    return base_url + '/pull/' + review_num.strip('#')


def new_lcc_index_db(basedir):
    """
    This generates an lcc-index DB in the basedir.

    """
    from .backend import abcat
    return abcat.sqlite_make_lcc_index_db(basedir)


def wrap_commands_in_shell(commands):
    """
    Wrap commands in a shell
    :param list commands: list of commands to wrap
    :param str ostype: OS type, linux or windows
    :rtype: str
    :return: a shell wrapping commands
    """
    return "/bin/bash -c 'set -e -o pipefail; {};'".format(';'.join(commands))


def getid(obj):
    """Extracts object ID.

    Abstracts the common pattern of allowing both an object or an
    object's ID (UUID) as a parameter when dealing with relationships.
    """
    try:
        return obj.id
    except AttributeError:
        return obj


@classmethod
def to_seconds(cls, timing, unit, model):
    """converts the schedule values to seconds, depending on to the
        schedule_model the value will differ. So if the schedule_model is
        'effort' or 'length' then the schedule_time and schedule_unit values
        are interpreted as work time, if the schedule_model is 'duration' then
        the schedule_time and schedule_unit values are considered as calendar
        time.
        """
    if not unit:
        return None
    lut = {'min': 60, 'h': 3600, 'd': 86400, 'w': 604800, 'm': 2419200, 'y':
        31536000}
    if model in ['effort', 'length']:
        from stalker import defaults
        day_wt = defaults.daily_working_hours * 3600
        week_wt = defaults.weekly_working_days * day_wt
        month_wt = 4 * week_wt
        year_wt = int(defaults.yearly_working_days) * day_wt
        lut = {'min': 60, 'h': 3600, 'd': day_wt, 'w': week_wt, 'm':
            month_wt, 'y': year_wt}
    return timing * lut[unit]


def add_debug_toolbar(app):
    """ Add debug toolbar """
    from bucket.feature.debug_toolbar import debug_toolbar_feature
    debug_toolbar_feature(app)


def callInThread(callable, *args, **kwargs):
    """
        Run the callable object in a separate thread.
        """


def print_alignment(mapping, instance1, instance2):
    """
    print the alignment based on a node mapping
    Args:
        mapping: current node mapping list
        instance1: nodes of AMR 1
        instance2: nodes of AMR 2

    """
    result = []
    for instance1_item, m in zip(instance1, mapping):
        r = instance1_item[1] + '(' + instance1_item[2] + ')'
        if m == -1:
            r += '-Null'
        else:
            instance2_item = instance2[m]
            r += '-' + instance2_item[1] + '(' + instance2_item[2] + ')'
        result.append(r)
    return ' '.join(result)


def _np__random_shuffle(x):
    """
    Modify a sequence in-place by shuffling its contents.

    This function only shuffles the array along the first axis of a
    multi-dimensional array. The order of sub-arrays is changed but
    their contents remain the same.

    Parameters
    ----------
    x: ndarray
        The array or list to be shuffled.

    Returns
    -------
    None

    Examples
    --------
    >>> arr = np.arange(10)
    >>> np.random.shuffle(arr)
    >>> arr
    array([5., 1., 0., 6., 7., 3., 9., 8., 4., 2.])  # random

    Multi-dimensional arrays are only shuffled along the first axis:

    >>> arr = np.arange(9).reshape((3, 3))
    >>> np.random.shuffle(arr)
    >>> arr
    array([[6., 7., 8.], # random
           [3., 4., 5.],
           [0., 1., 2.]])
    """
    pass


@classmethod
def as_dict(cls):
    """
        Returns the key-label pairs of the enumeration as a dict.
        """
    return dict(cls.all())


def add_edit_time(apps, schema_editor):
    """ Add edit_time to all existing Article instances """
    Article = apps.get_model('helpcenter', 'Article')
    for article in Article.objects.all():
        if not article.time_edited:
            article.time_edited = article.time_published
        article.save()


def reorder_to_back():
    """Reorder workspace to be first in the list

    """
    pass


def jmespath(value, query):
    """
    Queries the data using the JMESPath query language.
    Examples:
    >>> import six
    >>> locations = [{'name': 'Seattle', 'state': 'WA'},
    ... {"name": "New York", "state": "NY"},
    ... {"name": "Bellevue", "state": "WA"},
    ... {"name": "Olympia", "state": "WA"}]
    >>> query = "[?state == 'WA'].name | sort(@) | {WashingtonCities: join(', ', @)}"  # noqa: E501
    >>> WACities = jmespath(locations, query)
    >>> if six.PY2:
    ...  WACities == {u'WashingtonCities': u'Bellevue, Olympia, Seattle'}
    ... elif six.PY3:
    ...  WACities == {'WashingtonCities': 'Bellevue, Olympia, Seattle'}
    ...
    True
    """
    import jmespath as jp
    return jp.search(query, value)


def p4psd(ax, rpm_mean, fmax=10, y_pos_rel=0.25, color='g', ls='--', ps=
    None, col_text='w'):
    """
    Add the P's on a PSD

    fmax is the maximum value on the plot (ax.xlim). This only works when
    setting the xlim of the plot before calling p4psd.

    Parameters
    ----------

    ax

    rpm_mean

    fmax : int, default=17
        stop plotting p's after fmax (when ps is None)

    ps : iterable of ints, default=None
        specify which p's to plot (ignores fmax)

    y_pos_rel : int or list, default=0.25
    """
    if ps is None:
        pmax = int(60 * fmax / rpm_mean)
        ps = list(range(1, pmax))
    else:
        pmax = len(ps)
    if isinstance(y_pos_rel, float) or isinstance(y_pos_rel, int):
        y_pos_rel = [y_pos_rel] * pmax
    f_min = ax.get_xlim()[0]
    f_max = ax.get_xlim()[1]
    bbox = dict(boxstyle='round', edgecolor=color, facecolor=color)
    for i, p in enumerate(ps):
        p_freq = p * rpm_mean / 60.0
        if p % 3 == 0:
            alpha = 0.5
            ax.axvline(x=p_freq, linewidth=1, color=color, alpha=0.7, ls=ls)
        else:
            alpha = 0.2
            ax.axvline(x=p_freq, linewidth=1, color=color, alpha=0.7, ls=ls)
        x = (p_freq - f_min) / (f_max - f_min)
        y = y_pos_rel[i]
        p_str = '%iP' % p
        bbox['alpha'] = alpha
        ax.text(x, y, p_str, fontsize=8, verticalalignment='bottom',
            horizontalalignment='center', bbox=bbox, color=col_text,
            transform=ax.transAxes)
    return ax


def helical_transition_Re_Srinivasan(Di, Dc):
    """Calculates the transition Reynolds number for flow inside a curved or
    helical coil between laminar and turbulent flow, using the method of [1]_,
    also shown in [2]_ and [3]_. Correlation recommended in [3]_.

    .. math::
        Re_{crit} = 2100\\left[1 + 12\\left(\\frac{D_i}{D_c}\\right)^{0.5}\\right]

    Parameters
    ----------
    Di : float
        Inner diameter of the coil, [m]
    Dc : float
        Diameter of the helix/coil measured from the center of the tube on one
        side to the center of the tube on the other side, [m]

    Returns
    -------
    Re_crit : float
        Transition Reynolds number between laminar and turbulent [-]

    Notes
    -----
    At very low curvatures, converges to Re = 2100.
    Recommended for :math:`0.004 < d_i/D_c < 0.1`.

    Examples
    --------
    >>> helical_transition_Re_Srinivasan(1, 7.)
    11624.704719832524

    References
    ----------
    .. [1] Srinivasan, P. S., Nandapurkar, S. S., and Holland, F. A., "Pressure
       Drop and Heat Transfer in Coils", Chemical Engineering, 218, CE131-119,
       (1968).
    .. [2] El-Genk, Mohamed S., and Timothy M. Schriener. "A Review and
       Correlations for Convection Heat Transfer and Pressure Losses in
       Toroidal and Helically Coiled Tubes." Heat Transfer Engineering 0, no. 0
       (June 7, 2016): 1-28. doi:10.1080/01457632.2016.1194693.
    .. [3] Rohsenow, Warren and James Hartnett and Young Cho. Handbook of Heat
       Transfer, 3E. New York: McGraw-Hill, 1998.
    """
    return 2100.0 * (1.0 + 12.0 * (Di / Dc) ** 0.5)


def _expand_ellipsis(key, ndim):
    """Expand the slicing tuple if the Ellipsis object is present."""
    kl = list(key)
    ecount = kl.count(Ellipsis)
    if ecount > 1:
        raise IndexError('invalid index')
    if ecount < 1:
        return key
    e_index = kl.index(Ellipsis)
    kl_end = kl[e_index + 1:] if e_index < len(key) - 1 else []
    kl_beg = kl[:e_index]
    kl_middle = [slice(None)] * (ndim - len(kl_end) - len(kl_beg))
    return tuple(kl_beg + kl_middle + kl_end)


def error(msg):
    """Log a message in the Event Viewer as an error message"""
    import servicemanager
    servicemanager.LogErrorMsg(str(msg))


def drop_tables(cur):
    """ Drop all tables. """
    cur.execute('DROP TABLE IF EXISTS nodes;')
    cur.execute('DROP TABLE IF EXISTS ancestors;')


@staticmethod
def _reason_data(disposition, count, most_recent):
    """Create a reason data dictionary for this evaluator type."""
    return {'type': 'threshold', 'disposition': disposition, 'count': count,
        'most_recent': most_recent}


def yr_label(yr_range):
    """Create label of start and end years for aospy data I/O."""
    assert yr_range is not None, 'yr_range is None'
    if yr_range[0] == yr_range[1]:
        return '{:04d}'.format(yr_range[0])
    else:
        return '{:04d}-{:04d}'.format(*yr_range)


def strip_get_params(path: str) ->str:
    """ Strip get params from a path """
    if '?' in path:
        return path.split('?')[0]
    return path


def _ctypes_make_list(l, base):
    """
    Makes a list of const char pointers.
    """
    array = (base * len(l))()
    array[:] = l
    return array


@staticmethod
def __stub__(server):
    """Return the GRPC stub class to which this object interfaces."""
    raise NotImplementedError()


@classmethod
def coerce_tuples(cls, generator):
    """This class method converts a generator of ``(K, V)`` tuples (the
        *tuple protocol*), where ``V`` is not yet of the correct type, to a
        generator where it is of the correct type (using the ``coerceitem``
        class property)
        """
    for k, v in generator:
        yield k, cls.coerce_value(v)


def test_buffer():
    """Checks the micropython firmware to see if sys.stdin.buffer exists."""
    import sys
    try:
        _ = sys.stdin.buffer
        return True
    except:
        return False


def index(a):
    """Same as a.__index__()."""
    return a.__index__()


@classmethod
def _get_expected_attrs(cls, context, *args, **kwargs):
    """Return expected attributes when getting a cluster.

        Expected attributes depend on whether we are retrieving all related
        services as well as if we are getting the services summary.
        """
    expected_attrs = []
    if kwargs.get('get_services'):
        expected_attrs.append('services')
    if kwargs.get('services_summary'):
        expected_attrs.extend(('num_hosts', 'num_down_hosts'))
    return expected_attrs


@classmethod
def from_propfindentry(cls, local_cache, propfind_entry):
    """Builds an object from propfind information.

        """
    return cls(local_cache, propfind_entry.name, None, None)


@classmethod
def enable(cls):
    """Enables domain notifications.
        """
    return cls.build_send_payload('enable', {}), None


def remove_and_return_linefeed(src):
    '\n        remove_and_return_linefeed()\n        ________________________________________________________________________\n\n        Remove the linefeed characters from the end of (str)src.\n        This function recognizes three kinds of linefeed characters :\n        ▪ the Linux one (\n)\n        ▪ the Windows one (\r\n)\n        ▪ the ancient OSX one (\r)\n        ________________________________________________________________________\n\n        PARAMETER : (str)src, the source string to be cut\n\n        RETURNED VALUE : ((str)the reduced source string,\n                          (str)the linefeed characters)\n    '
    if src.endswith('\r\n'):
        return src[:-2], '\r\n'
    elif src.endswith('\n'):
        return src[:-1], '\n'
    elif src.endswith('\r'):
        return src[:-1], '\r'
    else:
        return src, ''


def can_paginate(operation_name=None):
    """
    Check if an operation can be paginated.

    :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').

    """
    pass


def _should_retry_unplug_vbd(err):
    """Retry if failed with some specific errors.

    The retrable errors include:
    1. DEVICE_DETACH_REJECTED
       For reasons which we don't understand, we're seeing the device
       still in use, even when all processes using the device should
       be dead.
    2. INTERNAL_ERROR
       Since XenServer 6.2, we also need to retry if we get INTERNAL_ERROR,
       as that error goes away when you retry.
    3. VM_MISSING_PV_DRIVERS
       NOTE(jianghuaw): It requires some time for PV(Paravirtualization)
       driver to be connected at VM booting, so retry if unplug failed
       with VM_MISSING_PV_DRIVERS.
    """
    can_retry_errs = ('DEVICE_DETACH_REJECTED', 'INTERNAL_ERROR',
        'VM_MISSING_PV_DRIVERS')
    return err in can_retry_errs


def set_decor_inner(level, decor, LevelDecor):
    """ Helper method creating LevelDecor objects given a list of decor in dictionary form."""
    LevelDecor.objects.filter(level=level).delete()
    level_decors = []
    for data in decor:
        level_decors.append(LevelDecor(level_id=level.id, x=data['x'], y=
            data['y'], decorName=data['decorName']))
    LevelDecor.objects.bulk_create(level_decors)


def isproperty(obj):
    """
    Is this a property?

    >>> class Foo:
    ...     def got(self):
    ...         return 2
    ...     def get(self):
    ...         return 1
    ...     get = property(get)

    >>> isproperty(Foo.got)
    False
    >>> isproperty(Foo.get)
    True
    """
    return type(obj) == property


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 tags(cls, filename, namespace=None):
    """Extract tags from file."""
    return cls._raster_opener(filename).tags(ns=namespace)


def atomic_push(redis_db, queue_id, item):
    """
    Push item to queue and get item position in
    one atomic operation by using transaction.

    The queue representation in Redis is a `list`.
    """
    pipe = redis_db.pipeline()
    pipe.rpush(queue_id, item)
    pipe.llen(queue_id)
    _, queue_size = pipe.execute()
    return queue_size - 1


@classmethod
def get(cls, data_source_id):
    """
        Gets the data source.

        Parameters
        ----------
        data_source_id : str
            the identifier of the data source.

        Returns
        -------
        data_source : DataSource
            the requested data source.

        Examples
        --------
        .. code-block:: python

            >>> import datarobot as dr
            >>> data_source = dr.DataSource.get('5a8ac9ab07a57a0001be501f')
            >>> data_source
            DataSource('Diagnostics')
        """
    return cls.from_location('{}{}/'.format(cls._path, data_source_id))


@staticmethod
def calculate_quality(input_vector, control_params):
    """
        Function for calculating quality.

        Returns:
            float: quality

        Raises:
            AssertionError: If length of `control_params`
                is not equal length of `input_vector`
        """
    assert len(control_params) == len(input_vector)
    quality = 0
    for i in enumerate(control_params):
        quality += (control_params[i[0]] - input_vector[i[0]]) ** 2
    return quality


def frame_offset(delta: int=0):
    """Move current frame forward/backward by a given number

    :param delta: Delta
    :type delta: int
    """
    pass


@classmethod
def log_message(cls, dummy1, *dummy2):
    """
        Used to silence the direct logging to stdout/stderr
        """
    return


def _resource_from_cache_prefix(resource, cache):
    """
    Combine the resource name with the cache prefix (if any)
    """
    if getattr(cache, 'key_prefix', None):
        name = '{} {}'.format(resource, cache.key_prefix)
    else:
        name = resource
    return name.lower()


def tabstr_to_tab(tab_str):
    """
    translate "\\t" to "	"
    :param tab_str: str
    :return: str
    """
    assert isinstance(tab_str, str)
    if tab_str == '\\t':
        return '\t'
    else:
        return tab_str


def instance(cls):
    """Create a new instance of a class.

    Parameters
    ----------
    cls : type
        The class to create an instance of.

    Returns
    -------
    instance : cls
        A new instance of ``cls``.
    """
    return cls()


def generate_pre_tasks(minimal_facts=True, box_basics=True,
    box_basics_non_sudo=False, freckles_facts=True):
    """Generates a list of tasks that will end up in a playbooks pre_tasks variable.

    Args:
        minimal_facts (bool): whether to run a basic shell script to gather some basic facts (this doesn't require Python on the target machine, but can find out whether Python is available.
        box_basics (bool): whether to install a minimal set to be able to run common Ansible modules on this machine
        box_basics_non_sudo (bool): whether to run the 'non-sudo' version of box basics (not implemented yet)
        freckles_facts (bool): whether to run the freckles facts module

    Returns:
        tuple: a tuple in the form: (task_list, gather_facts_included), gather_facts_included indicates whether the pre_tasks will run gather_facts at some stage (so it doesn't need to be executed twice.
    """
    gather_facts_included = False
    pre_tasks = []
    if minimal_facts or box_basics or freckles_facts:
        temp = [{'name': '[-1000][testing connectivity]', 'raw':
            'sh -c "true"', 'ignore_errors': False, 'changed_when': False},
            {'name': '[getting box basic facts]', 'include_tasks':
            '{{ playbook_dir }}/../task_lists/freckles_basic_facts.yml'}]
        pre_tasks.extend(temp)
    if box_basics or freckles_facts:
        gather_facts_included = True
        temp = [{'name': '[preparing box basics]', 'include_tasks':
            '{{ playbook_dir }}/../task_lists/box_basics.yml'}]
        pre_tasks.extend(temp)
    if freckles_facts:
        pre_tasks.append({'name': '[gathering freckles-specific facts]',
            'freckles_facts': {'executables': ['unzip']}})
    return {'pre_tasks': pre_tasks, 'gather_facts': not gather_facts_included}


def is_compatible(target_type, check_instance):
    """
    Check the target compatibility with the check instance.

    :param target_type: Target subclass, if None, returns True
    :param check_instance: instance of some Check class
    :return: True if the target is None or compatible with the check instance
    """
    if not target_type:
        return True
    return isinstance(check_instance, target_type.get_compatible_check_class())


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

    The ".dev0" means dirty.

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


def unban(email):
    """Remove an email address ban.

        This removes a specific or global email address ban, which would have
        been added with the `ban()` method.  If a ban is lifted which did not
        exist, this method does nothing.

        :param email: The text email address being unbanned or, if the string
            starts with a caret (^), the email address pattern to unban.
        :type email: str
        """


@classmethod
def encode_env_var_value(cls, obj):
    """Convert `obj` into a UTF-8 encoded binary string.

        The result of this method be used as the value of an environment variable in a subsequent
        NailgunClient execution.
        """
    return str(obj).encode()


def amod(a, b):
    """Modulus function which returns numerator if modulus is zero"""
    modded = int(a % b)
    return b if modded == 0 else modded


def symlink_if_necessary(path, destination):
    """forcefully create a symlink with a given value, but only if it doesn't already exist"""
    from py._error import error as pylib_error
    try:
        supervise_link = destination.readlink()
    except (pylib_error.ENOENT, pylib_error.EINVAL):
        supervise_link = None
    if supervise_link != path.strpath:
        from .subprocess import check_call
        check_call(('ln', '-sfn', '--', path.strpath, destination.strpath))


def coalesce(*args):
    """
    Return the first non-null argument.
    """
    for arg in args:
        if arg is not None:
            return arg


def get_cutoff_indices(flow, fhigh, df, N):
    """
    Gets the indices of a frequency series at which to stop an overlap
    calculation.

    Parameters
    ----------
    flow: float
        The frequency (in Hz) of the lower index.
    fhigh: float
        The frequency (in Hz) of the upper index.
    df: float
        The frequency step (in Hz) of the frequency series.
    N: int
        The number of points in the **time** series. Can be odd
        or even.

    Returns
    -------
    kmin: int
    kmax: int
    """
    if flow:
        kmin = int(flow / df)
        if kmin < 0:
            err_msg = 'Start frequency cannot be negative. '
            err_msg += 'Supplied value and kmin {} and {}'.format(flow, kmin)
            raise ValueError(err_msg)
    else:
        kmin = 1
    if fhigh:
        kmax = int(fhigh / df)
        if kmax > int((N + 1) / 2.0):
            kmax = int((N + 1) / 2.0)
    else:
        kmax = int((N + 1) / 2.0)
    if kmax <= kmin:
        err_msg = 'Kmax cannot be less than or equal to kmin. '
        err_msg += 'Provided values of freqencies (min,max) were '
        err_msg += '{} and {} '.format(flow, fhigh)
        err_msg += 'corresponding to (kmin, kmax) of '
        err_msg += '{} and {}.'.format(kmin, kmax)
        raise ValueError(err_msg)
    return kmin, kmax


def util_sat(gpu, util):
    """ Return true if the gpu utilization is at most util """
    return float(gpu.entry['utilization.gpu']) <= util


def batch_get_builds(ids=None):
    """
    Gets information about builds.
    See also: AWS API Documentation

    :example: response = client.batch_get_builds(
        ids=[
            'string',
        ]
    )

    :type ids: list
    :param ids: [REQUIRED]
            The IDs of the builds.
            (string) --

    :rtype: dict
    :return: {
        'builds': [
            {
                'id': 'string',
                'arn': 'string',
                'startTime': datetime(2015, 1, 1),
                'endTime': datetime(2015, 1, 1),
                'currentPhase': 'string',
                'buildStatus': 'SUCCEEDED'|'FAILED'|'FAULT'|'TIMED_OUT'|'IN_PROGRESS'|'STOPPED',
                'sourceVersion': 'string',
                'projectName': 'string',
                'phases': [
                    {
                        'phaseType': 'SUBMITTED'|'PROVISIONING'|'DOWNLOAD_SOURCE'|'INSTALL'|'PRE_BUILD'|'BUILD'|'POST_BUILD'|'UPLOAD_ARTIFACTS'|'FINALIZING'|'COMPLETED',
                        'phaseStatus': 'SUCCEEDED'|'FAILED'|'FAULT'|'TIMED_OUT'|'IN_PROGRESS'|'STOPPED',
                        'startTime': datetime(2015, 1, 1),
                        'endTime': datetime(2015, 1, 1),
                        'durationInSeconds': 123,
                        'contexts': [
                            {
                                'statusCode': 'string',
                                'message': 'string'
                            },
                        ]
                    },
                ],
                'source': {
                    'type': 'CODECOMMIT'|'CODEPIPELINE'|'GITHUB'|'S3',
                    'location': 'string',
                    'buildspec': 'string',
                    'auth': {
                        'type': 'OAUTH',
                        'resource': 'string'
                    }
                },
                'artifacts': {
                    'location': 'string',
                    'sha256sum': 'string',
                    'md5sum': 'string'
                },
                'environment': {
                    'type': 'LINUX_CONTAINER',
                    'image': 'string',
                    'computeType': 'BUILD_GENERAL1_SMALL'|'BUILD_GENERAL1_MEDIUM'|'BUILD_GENERAL1_LARGE',
                    'environmentVariables': [
                        {
                            'name': 'string',
                            'value': 'string'
                        },
                    ]
                },
                'logs': {
                    'groupName': 'string',
                    'streamName': 'string',
                    'deepLink': 'string'
                },
                'timeoutInMinutes': 123,
                'buildComplete': True|False,
                'initiator': 'string'
            },
        ],
        'buildsNotFound': [
            'string',
        ]
    }

    :returns:
    FAILED : The build failed.
    FAULT : The build faulted.
    IN_PROGRESS : The build is still in progress.
    STOPPED : The build stopped.
    SUCCEEDED : The build succeeded.
    TIMED_OUT : The build timed out.

    """
    pass


@classmethod
def add_param_filter(cls, qs, lookup_prefix='', **kwargs):
    """Add filters to queryset using table parameter fields.

        This is called for every simple parameter.

        Usage examples: :class:`DeploymentsByTicket
        <lino_xl.lib.deploy.desktop.DeploymentsByTicket>`, :mod:`lino_book.projects.min3.lib.contacts`.

        """
    return qs.filter(**kwargs)


def resolve_templating_engine(args):
    """ Figures out what templating engine should be used to render the stack
    """
    if args.stack.name == '<stdin>':
        return args.templating_engine
    elif '.mako' in args.stack.name[-5:]:
        return 'mako'
    elif '.jinja' in args.stack.name[-6:]:
        return 'jinja'
    elif '.yaml' in args.stack.name[-5:]:
        return 'yaml'
    raise NotImplementedError(
        "Templating engine not supported. Must be set to 'mako', 'jinja', or '' in the command line or by using the equivalent file extension"
        )


def _overload_dummy(*args, **kwds):
    """Helper for @overload to raise when called."""
    raise NotImplementedError(
        'You should not call an overloaded function. A series of @overload-decorated functions outside a stub module should always be followed by an implementation that is not @overload-ed.'
        )


def do(*args):
    """Helper function for chaining function calls in a Python lambda expression.

    Part of a poor-man's functional programming suite used to define several pfainspector commands as one-liners.

    :type args: anything
    :param args: functions that have already been evaluated
    :rtype: anything
    :return: the last argument
    """
    return args[-1]


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


def transpose_dataframe(a):
    """
    Check if the input is a column-wise Pandas `DataFrame`. If `True`, return a
    transpose dataframe since stumpy assumes that each row represents data from a
    different dimension while each column represents data from the same dimension.
    If `False`, return `a` unchanged. Pandas `Series` do not need to be transposed.

    Note that this function has zero dependency on Pandas (not even a soft dependency).

    Parameters
    ----------
    a : ndarray
        First argument.

    Returns
    -------
    output : a
        If a is a Pandas `DataFrame` then return `a.T`. Otherwise, return `a`
    """
    if type(a).__name__ == 'DataFrame':
        return a.T
    return a


@classmethod
def parse_task(cls, task_node):
    """ create a task from xml node """
    name = task_node.getElementsByTagName('Name')[0].firstChild.data
    priority = int(task_node.getElementsByTagName('Priority')[0].firstChild
        .data)
    status = task_node.nodeName
    return cls(name, priority, status)


@classmethod
def from_dict(cls, node, attributes=None):
    """
        Create a new Properties initialized by a specified dictionary of attributes

        :param node: the node of the customer supposed to be associated with this event
        :param attributes: key-value arguments for generating the structure of the Education's attributes
        :return: a new Properties object
        """
    o = cls(node=node)
    o.attributes = {} if attributes is None else attributes
    return o


@classmethod
def check_new_graph(cls, service, uri, parameters, new_graph, resource=None,
    added=None, removed=None):
    """I check that a graph is a valid representation for a resource.

        This hook method is to be called when a resource of this class is
        either created and updated, to verify if `new_graph` is acceptable.

        :param service:    the service to which `new_graph` has been posted
        :type  service:    :class:`Service`
        :param uri:        the URI of the resource described by `new_graph`
        :type  uri:        :class:`rdflib.URIRef`
        :param parameters: the query string parameters passed to `edit` if any
        :type  parameters: dict or None
        :type  new_graph:  :class:`rdflib.Graph`
        :param new_graph:  graph to check
        :type  new_graph:  :class:`rdflib.Graph`

        The following parameter will always be set when `check_new_graph` is
        used to update and *existing* resource; for creating a new resource, it
        will always be `None`.

        :param resource:  the resource to be updated

        The following parameters only make sense when updating an existing
        resource. They are *not* automatically set by `edit`:meth:, as they may
        not be used. However, any implementation may set them by using
        :func:`compute_added_and_removed` and should therefore pass them along
        the `super` calls.

        :param added:     if not None, an RDF graph containg triples to be
                          added
        :param removed:   if not None, an RDF graph containg triples to be
                          removed

        The return value should be an empty `~.util.Diagnosis`:class: if the
        new graph is acceptable, else it should contain a description of the
        problem(s).

        :rtype: `~.util.Diagnosis`:class:
        """
    raise NotImplementedError


@classmethod
def is_not_list_attribute(cls, attr):
    """
        Returns True if and only if the given attribute is NOT one of the
        basic list attributes defined for all Elements.
        """
    return attr not in cls.list_attributes


def chunkify(iterable, n):
    """Break an interable into chunks of size at most 'n'."""
    chunk = None
    for i, x in enumerate(iterable):
        if i % n == 0:
            if chunk is not None:
                yield chunk
            chunk = []
        chunk.append(x)
    yield chunk


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 as_int(obj, quiet=False):
    """Converts an arbitrary value into a integer."""
    try:
        return int(obj)
    except (ValueError, TypeError):
        pass
    try:
        return int(float(obj))
    except (ValueError, TypeError):
        pass
    if not quiet:
        raise TypeError("Can not translate '%s' (%s) to an integer" % (obj,
            type(obj)))
    return obj


def _dump_to_table(dictionary, table_uri, key_name, value_name):
    """A function to take a flat dictionary and dump to a CSV
        table.

        dictionary - a flat python dictionary of key/value pairs
        table_uri - the URI of a CSV output table
        key_name - a string to use for the key headings
        value_name - a string to use for the value headings

        returns nothing"""
    with open(table_uri, 'wb') as table_file:
        table_file.write('%s, %s\n' % (key_name, value_name))
        for key, value in dictionary.iteritems():
            table_file.write('%s, %s\n' % (key, value))


def split_arguments(args, splitter_name=None, splitter_index=None):
    """Split list of args into (other, split_args, other) between splitter_name/index and `--`

    :param args: list of all arguments
    :type args: list of str
    :param splitter_name: optional argument used to split out specific args
    :type splitter_name: str
    :param splitter_index: specific index at which to split
    :type splitter_index: int

    :returns: tuple (other, split_args)
    """
    if splitter_index is None:
        if splitter_name not in args:
            return args, []
        splitter_index = args.index(splitter_name)
    start_index = splitter_index + 1
    end_index = args.index('--', start_index) if '--' in args[start_index:
        ] else None
    if end_index:
        return args[0:splitter_index], args[start_index:end_index], args[
            end_index + 1:]
    else:
        return args[0:splitter_index], args[start_index:], []


def _get_field_by_name(model_class, field_name):
    """
    Compatible with old API of model_class._meta.get_field_by_name(field_name)
    """
    field = model_class._meta.get_field(field_name)
    return (field, field.model, not field.auto_created or field.concrete,
        field.many_to_many)


def undo_push(message: str='Addanundostep*functionmaybemoved*'):
    """Add an undo state (internal use only)

    :param message: Undo Message
    :type message: str
    """
    pass


@staticmethod
def px_to_mm(measure):
    """Convert pixel to millimeters."""
    return measure * 0.26458333333719


def logical_and(attrs, inputs, proto_obj):
    """Logical and of two input arrays."""
    return 'broadcast_logical_and', attrs, inputs


def read_outflow(file_name):
    """Read outflow values.
    """
    fobj = open(file_name)
    header = fobj.next().split()
    outflow = {}
    for head in header:
        outflow[head] = []
    for line in fobj:
        line = line.split()
        for pos, head in enumerate(header):
            outflow[head].append(float(line[pos]))
    return outflow


def parameters_ui(layout, params):
    """ Create the ui for the rig parameters.
    """
    r = layout.row()
    r.prop(params, 'make_controls')
    r = layout.row()
    r.prop(params, 'make_deforms')


@classmethod
def find_module(cls, fullname, path=None):
    """Find the built-in module.

        If 'path' is ever specified then the search is considered a failure.

        This method is deprecated.  Use find_spec() instead.

        """
    spec = cls.find_spec(fullname, path)
    return spec.loader if spec is not None else None


def to_unicode(s):
    """
    Receive string s and try to return a utf-8 string.
    """
    try:
        return str(s.decode('cp1252'))
    except (UnicodeDecodeError, TypeError):
        try:
            return str(s.decode('ascii'))
        except (UnicodeDecodeError, TypeError):
            return str(s)


def is_readonly():
    """Return True if this reference provides mutable access to the given
        file or directory (i.e. if you can modify it), or False if not. Note
        that even if this reference is read-only, someone else may hold a
        read-write reference to it."""


def chinese(data):
    """
    获取字符串长度，中文算两个字符串，其他算一个
    :param data:   str
    :return:       int
    """
    count = 0
    for s in data:
        if ord(s) > 127:
            count += 2
        else:
            count += 1
    return count


def fts5_term(term):
    """Convert a Google search like query into a FTS5 query, i.e. to not
  trigger the column filter misfeature. We don't try to make invalid queries
  work, just make queries that would be interpreted as column filters or the
  like work.

  EBNF:
  query = word
  word = [not space]+
  query = phrase
  phrase = '"' [^"]* '"'
  query = "(" query ")"
  query = query "AND" query
  query = query "OR" query
  query = "NOT" query
  """
    in_q = False
    implicit_q = False
    out = []
    expect = None
    pending = []
    for c in term:
        if c == "'":
            if pending:
                out.extend(pending)
                pending = None
            out.append("''")
        elif expect:
            if c != expect:
                assert not in_q
                out.append('"')
                out.extend(pending)
                out.append('"')
                out.append(c)
                expect = None
                pending = None
            else:
                pending.append(c)
                expect = {'N': 'D', 'D': None, 'R': None, 'O': 'T', 'T': None}[
                    expect]
                if expect is None:
                    assert not in_q
                    out.extend(pending)
                    expect = None
                    pending = None
        elif c == '"':
            if implicit_q:
                implicit_q = False
            else:
                in_q = not in_q
                out.append(c)
        elif not in_q and c in 'AON':
            expect = {'A': 'N', 'O': 'R', 'N': 'O'}[c]
            pending = [c]
        elif c in ' \t\n()':
            if implicit_q:
                out.append('"')
                implicit_q = False
                in_q = False
            out.append(c)
        elif in_q:
            out.append(c)
        else:
            in_q = True
            implicit_q = True
            out.append('"')
            out.append(c)
    if pending:
        out.extend(pending)
    if in_q:
        out.append('"')
    return ''.join(out)


def dw_Write_Substances(fname, boundflow_labels):
    """
    Writes the B1_sublist.inc file
    input:

        it writes substances for the areas and an initial and mass balance
        check substance

    """
    exfile = open(fname, 'w')
    print('; number of active and inactive substances', file=exfile)
    print('%d         0' % (len(boundflow_labels) + 2), file=exfile)
    print('; active substances', file=exfile)
    print("1             'Initial' ; ", file=exfile)
    print("2             'Check' ; ", file=exfile)
    j = 2
    for i in boundflow_labels:
        j = j + 1
        print("%d            '%s'" % (j, i), file=exfile)
    print('; passive substances', file=exfile)
    exfile.close()


@staticmethod
def json_conversion_message(key, err_msg, line_num, column_num, json_doc):
    """Return a message describing a JSON conversion error at a numbered
        line and column within the JSON document retrieved from the named
        environment variable."""
    json_lines = json_doc.splitlines()
    if len(json_lines) >= line_num:
        error_line = json_lines[line_num - 1]
        truncated_line = error_line[0:column_num - 1]
        detabbed_line = truncated_line.expandtabs()
        char_count = len(detabbed_line)
        pointer_line = char_count * ' ' + '^'
        context_lines = '\n'.join(json_lines[:line_num][-3:]).expandtabs()
        error_location = 'line {:d}:\n{}\n{}'.format(line_num,
            context_lines, pointer_line)
    else:
        error_location = 'line {:d} column {:d}'.format(line_num, column_num)
    return 'In JSON environment variable {}: {} at {}'.format(key, err_msg,
        error_location)


def sin(data=None, name=None, attr=None, out=None, **kwargs):
    """Computes the element-wise sine of the input array.

    The input should be in radians (:math:`2\\pi` rad equals 360 degrees).

    .. math::
       sin([0, \\pi/4, \\pi/2]) = [0, 0.707, 1]

    The storage type of ``sin`` output depends upon the input storage type:

       - sin(default) = default
       - sin(row_sparse) = row_sparse
       - sin(csr) = csr

    Defined in src/operator/tensor/elemwise_unary_op_trig.cc:L47

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

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

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


def lexicographic_blocks(dictionary):
    """Sorts the key/value pairs of `dictionary` according to the lexicographic
    order of the keys.

    This is useful if your keys are instances of :class:`set` and you wish them
    to be ordered according to their list representation instead of ordered
    according to inclusion.

    """
    return sorted(dictionary.items(), key=lambda item: sorted(item[0]))


@classmethod
def from_toml(cls, s, **kwargs):
    """
        Load and decode TOML data from url, filepath or data-string.
        Decoder specific options can be passed using kwargs:
        https://pypi.org/project/toml/
        Return a new dict instance. A ValueError is raised in case of failure.
        """
    return cls(s, format='toml', **kwargs)


def graph_api_url(fb_request, user=None, token=False):
    """
    Format Facebook Graph API URL.
    """
    param = ''
    if user and token:
        param = '?access_token=%s' % user.facebook_access_token
    results = 'https://graph.facebook.com/%s/%s' % (fb_request, param)
    return results


def _split_path(loc):
    """ Split S3 path into bucket and prefix strings """
    bucket = loc.split('s3://')[1].split('/')[0]
    prefix = '/'.join(loc.split('s3://')[1].split('/')[1:])
    return bucket, prefix


def subscribe(receiver):
    """Register an IStatusReceiver to receive new status events. The
        receiver will be given builderChangedState, buildStarted, and
        buildFinished messages."""


def get_edgeVal(G, n1, n2, weightParameter):
    """
    Helper function to obtain the weight of the edge between two nodes, with exception handling, returns 0 if no edge is found
    """
    if weightParameter:
        try:
            valDict = G.edges[n1, n2]
        except KeyError:
            return 0
        else:
            return valDict[weightParameter]
    else:
        return 1


def getWANIntf(ch):
    """
        Looks at the key:networkInterfaces for the chute and finds the WAN interface.

        Returns:
            The dict from networkInterfaces
            None
    """
    intfs = ch.getCache('networkInterfaces')
    if not intfs:
        return None
    for i in intfs:
        if i['type'] == 'wan':
            return i
    return None


@staticmethod
def _exp_distance_edge(edge):
    """
        Given an edge, returns the exp of the (hyperbolic) distance of the
        two cusp neighborhoods at the ends of the edge measured along that
        edge.
        """
    tet, perm = next(edge.embeddings())
    face = 15 - (1 << perm[3])
    ptolemy_sqr = tet.horotriangles[1 << perm[0]].lengths[face
        ] * tet.horotriangles[1 << perm[1]].lengths[face]
    return abs(1 / ptolemy_sqr)


def is_multi_cool(cooler_file):
    """
    Judge a cooler is muliti-resolution cool or not.

    Parameters
    ----------
    cooler_file : str
        Path to cooler file.
    """
    import re
    if re.match('.+::.+$', cooler_file):
        return False
    import h5py
    h5_file = h5py.File(cooler_file)
    is_multi = 'pixels' not in h5_file
    h5_file.close()
    return is_multi


def splitConditionByAny(condition):
    """리스트 안에 있는 ANY에 따라 1차원 condition 리스트를 2차원 리스트로 분리한다"""
    condition_2D = []
    eachConCnt = []
    anycnt = 1
    concnt = 0
    for con in condition:
        if con == 'ANY':
            anycnt += 1
            eachConCnt.append(concnt)
            concnt = -1
        concnt += 1
    eachConCnt.append(concnt)
    start = 0
    for i in range(anycnt):
        condition_2D.append([])
        for j in range(eachConCnt[i]):
            condition_2D[i].append(condition[start])
            start += 1
        start += 1
    return condition_2D


@staticmethod
def get_namespace():
    """
        Returns the name space of the commands
        """
    return 'log'


def label(data, column):
    """ Performs label encoding.

        Example:
            Color: ['blue', 'green', 'blue', 'pink']
            is encoded by
            Color: [1, 2, 1, 3]

        :param data: Data
        :param column: Column to encode
        :return: Encoded data
        :rtype: pd.DataFrame
    """
    data[column] = data[column].astype('category').cat.codes
    return data


def grism_res(pupil='GRISM', module='A'):
    """Grism information

    Based on the pupil input and module, return the spectral
    dispersion and resolution as a tuple (res, dw).

    Parameters
    ----------
    pupil : str
        'GRISM0' or 'GRISM90', otherwise assume res=1000 pix/um
    module : str
        'A' or 'B'
    """
    res = 1000.0
    if 'GRISM90' in pupil and module == 'A':
        res = 1003.12
    if 'GRISM0' in pupil and module == 'A':
        res = 996.48
    if 'GRISM90' in pupil and module == 'B':
        res = 1008.64
    if 'GRISM0' in pupil and module == 'B':
        res = 1009.13
    dw = 1.0 / res
    return res, dw


def readu16(fd, loc=None):
    """
    Read an unsigned 16-bit number
    :param fd: file handle
    :param loc: seek location
    :return: a 4-byte number
    """
    if loc is not None:
        fd.seek(loc)
    data = fd.read(4)
    return data[0] + 256 * data[1]


def get_middle_value(my_list):
    """Return the middle value from a list after sorting.

    :param list my_list: List of sortable values"""
    return sorted(my_list)[len(my_list) // 2]


def odd_even(x):
    """
		odd_even tells if a number is odd (return True) or even (return False)

		Parameters
		----------
		x: the integer number to test

		Returns
		-------
		bool : boolean
    """
    if int(x) % 2 == 0:
        bool = False
    else:
        bool = True
    return bool


def escape(t):
    """HTML-escape the text in `t`.

    This is only suitable for HTML text, not attributes.

    """
    return t.replace('&', '&').replace('<', '<')


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


def ghost_curves_create():
    """Create snapshot (Ghosts) of selected F-Curves as background aid for active Graph Editor

    """
    pass


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 resample_discard(arr, divisor, ofs=0):
    """
    Resample with an integral divisor, discarding all other samples
    """
    return arr[ofs::divisor]


def condense_script(html):
    """Condense script html tags.

    >>> condense_script('
a b c')
    '
a b c'
    """
    return html.replace('


@classmethod
def _res_cls(cls, name):
    """
        Resolves the possibly namespace name for the current class
        recurring to a recursive approach to the attribute resolution.

        :type name: String
        :param name: The name of the possibly namespace attribute that
        should be used to retrieve the associated entity class (eg:
        product.name, order.id, etc.).
        :rtype: Tuple
        :return: The target class that represents the reference attribute
        described by the namespace (path) based name and the name of the
        final attribute contained in it.
        """
    if not '.' in name:
        return cls, name
    name_s = name.split('.')
    for part in name_s[:-1]:
        info = getattr(cls, part) if hasattr(cls, part) else dict()
        part_type = info.get('type', None)
        cls = part_type._target()
    return cls, name_s[-1]


def nolog(*allargs):
    """Dummy function, assigned to log when logging is disabled."""
    pass


def ireq_satisfied_by_existing_pin(ireq, existing_pin):
    """
    Return True if the given InstallationRequirement is satisfied by the
    previously encountered version pin.
    """
    version = next(iter(existing_pin.req.specifier)).version
    return version in ireq.req.specifier


@classmethod
def fullmatch(cls, string, *args, **kwargs):
    """
        A wrapper for ``re.regex.fullmatch``: Tries to match the argument string completely.
        Takes optional parameters like ``re.regex.fullmatch``.

        :param string: the string which to match
        :return: an instance of this class, if the string is a match; ``None`` otherwise

        :see: https://docs.python.org/3.6/library/re.html#re.regex.fullmatch
        """
    return cls._delegate(cls._pattern.fullmatch, string, *args, **kwargs)


def _replace_prompt(path):
    """Return True if the user wants to replace the file."""
    while True:
        result = input('{} already exists. Replace? [yN] '.format(path))
        result = result.lower()
        if result in ('y', 'yes'):
            return True
        elif result in ('n', 'no', ''):
            return False
        else:
            print("Invalid answer. Please answer 'yes' or 'no'.")


def remove_vectored_io_slice_suffix_from_name(name, slice):
    """Remove vectored io (stripe) slice suffix from a given name
    :param str name: entity name
    :param int slice: slice num
    :rtype: str
    :return: name without suffix
    """
    suffix = '.bxslice-{}'.format(slice)
    if name.endswith(suffix):
        return name[:-len(suffix)]
    else:
        return name


@classmethod
def Yaxis(cls):
    """Construct a unit vector along the Y axis.

        Returns
        -------
        :class:`compas.geometry.Vector`
            A vector with components ``x = 0.0, y = 1.0, z = 0.0``.

        Examples
        --------
        >>> Vector.Yaxis()
        Vector(0.000, 1.000, 0.000)
        """
    return cls(0.0, 1.0, 0.0)


@staticmethod
def read(fileobj):
    """Read data from the file object."""
    return fileobj.read()


def reduce_deg(deg):
    """ Return *deg* in the range [-180, 180) """
    return (deg + 180) % 360 - 180


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


def get_resource_class_module(cls):
    """ get module name by resource class
    """
    assert isinstance(cls, type), type(cls)
    return cls.__module__


def delete_vault(accountId=None, vaultName=None):
    """
    This operation deletes a vault. Amazon Glacier will delete a vault only if there are no archives in the vault as of the last inventory and there have been no writes to the vault since the last inventory. If either of these conditions is not satisfied, the vault deletion fails (that is, the vault is not removed) and Amazon Glacier returns an error. You can use  DescribeVault to return the number of archives in a vault, and you can use Initiate a Job (POST jobs) to initiate a new inventory retrieval for a vault. The inventory contains the archive IDs you use to delete archives using Delete Archive (DELETE archive) .
    This operation is idempotent.
    An AWS account has full permission to perform all operations (actions). However, AWS Identity and Access Management (IAM) users don't have any permissions by default. You must grant them explicit permission to perform specific actions. For more information, see Access Control Using AWS Identity and Access Management (IAM) .
    For conceptual information and underlying REST API, see Deleting a Vault in Amazon Glacier and Delete Vault in the Amazon Glacier Developer Guide .
    See also: AWS API Documentation

    Examples
    The example deletes a vault named my-vault:
    Expected Output:

    :example: response = client.delete_vault(
        vaultName='string'
    )

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

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

    :return: response = client.delete_vault(
        accountId='-',
        vaultName='my-vault',
    )

    print(response)

    """
    pass


def create_route(DryRun=None, RouteTableId=None, DestinationCidrBlock=None,
    GatewayId=None, DestinationIpv6CidrBlock=None,
    EgressOnlyInternetGatewayId=None, InstanceId=None, NetworkInterfaceId=
    None, VpcPeeringConnectionId=None, NatGatewayId=None):
    """
    Creates a route in a route table within a VPC.
    You must specify one of the following targets: Internet gateway or virtual private gateway, NAT instance, NAT gateway, VPC peering connection, network interface, or egress-only Internet gateway.
    When determining how to route traffic, we use the route with the most specific match. For example, traffic is destined for the IPv4 address 192.0.2.3 , and the route table includes the following two IPv4 routes:
    Both routes apply to the traffic destined for 192.0.2.3 . However, the second route in the list covers a smaller number of IP addresses and is therefore more specific, so we use that route to determine where to target the traffic.
    For more information about route tables, see Route Tables in the Amazon Virtual Private Cloud User Guide .
    See also: AWS API Documentation

    Examples
    This example creates a route for the specified route table. The route matches all traffic (0.0.0.0/0) and routes it to the specified Internet gateway.
    Expected Output:

    :example: response = client.create_route(
        DryRun=True|False,
        RouteTableId='string',
        DestinationCidrBlock='string',
        GatewayId='string',
        DestinationIpv6CidrBlock='string',
        EgressOnlyInternetGatewayId='string',
        InstanceId='string',
        NetworkInterfaceId='string',
        VpcPeeringConnectionId='string',
        NatGatewayId='string'
    )

    :type DryRun: boolean
    :param DryRun: Checks whether you have the required permissions for the action, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation . Otherwise, it is UnauthorizedOperation .

    :type RouteTableId: string
    :param RouteTableId: [REQUIRED]
            The ID of the route table for the route.

    :type DestinationCidrBlock: string
    :param DestinationCidrBlock: The IPv4 CIDR address block used for the destination match. Routing decisions are based on the most specific match.

    :type GatewayId: string
    :param GatewayId: The ID of an Internet gateway or virtual private gateway attached to your VPC.

    :type DestinationIpv6CidrBlock: string
    :param DestinationIpv6CidrBlock: The IPv6 CIDR block used for the destination match. Routing decisions are based on the most specific match.

    :type EgressOnlyInternetGatewayId: string
    :param EgressOnlyInternetGatewayId: [IPv6 traffic only] The ID of an egress-only Internet gateway.

    :type InstanceId: string
    :param InstanceId: The ID of a NAT instance in your VPC. The operation fails if you specify an instance ID unless exactly one network interface is attached.

    :type NetworkInterfaceId: string
    :param NetworkInterfaceId: The ID of a network interface.

    :type VpcPeeringConnectionId: string
    :param VpcPeeringConnectionId: The ID of a VPC peering connection.

    :type NatGatewayId: string
    :param NatGatewayId: [IPv4 traffic only] The ID of a NAT gateway.

    :rtype: dict
    :return: {
        'Return': True|False
    }

    :returns:
    DryRun (boolean) -- Checks whether you have the required permissions for the action, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation . Otherwise, it is UnauthorizedOperation .
    RouteTableId (string) -- [REQUIRED]
    The ID of the route table for the route.

    DestinationCidrBlock (string) -- The IPv4 CIDR address block used for the destination match. Routing decisions are based on the most specific match.
    GatewayId (string) -- The ID of an Internet gateway or virtual private gateway attached to your VPC.
    DestinationIpv6CidrBlock (string) -- The IPv6 CIDR block used for the destination match. Routing decisions are based on the most specific match.
    EgressOnlyInternetGatewayId (string) -- [IPv6 traffic only] The ID of an egress-only Internet gateway.
    InstanceId (string) -- The ID of a NAT instance in your VPC. The operation fails if you specify an instance ID unless exactly one network interface is attached.
    NetworkInterfaceId (string) -- The ID of a network interface.
    VpcPeeringConnectionId (string) -- The ID of a VPC peering connection.
    NatGatewayId (string) -- [IPv4 traffic only] The ID of a NAT gateway.

    """
    pass


def load_gevent(finder, module):
    """gevent must be loaded as a package."""
    finder.IncludePackage('gevent')


def _Minus(lhs=None, rhs=None, name=None, attr=None, out=None, **kwargs):
    """Subtracts arguments element-wise.

    The storage type of ``elemwise_sub`` output depends on storage types of inputs

       - elemwise_sub(row_sparse, row_sparse) = row_sparse
       - elemwise_sub(csr, csr) = csr
       - elemwise_sub(default, csr) = default
       - elemwise_sub(csr, default) = default
       - elemwise_sub(default, rsp) = default
       - elemwise_sub(rsp, default) = default
       - otherwise, ``elemwise_sub`` generates output with default storage

    Parameters
    ----------
    lhs : Symbol
        first input
    rhs : Symbol
        second input

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

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


@staticmethod
def _file_can_be_imported(entry):
    """ Verify if a directory entry is a non-magic Python file."""
    if entry.is_file() and not entry.name.startswith('__'
        ) and entry.name.endswith('.py'):
        return True
    return False


@classmethod
def from_map_dataset(cls, dataset, acceptance, acceptance_off, counts_off=
    None, name=None):
    """Create spectrum dataseton off from another dataset.

        Parameters
        ----------
        dataset : `MapDataset`
            Spectrum dataset defining counts, edisp, aeff, livetime etc.
        acceptance : `Map`
            Relative background efficiency in the on region.
        acceptance_off : `Map`
            Relative background efficiency in the off region.
        counts_off : `Map`
            Off counts map . If the dataset provides a background model,
            and no off counts are defined. The off counts are deferred from
            counts_off / alpha.
        name : str
            Name of the returned dataset.

        Returns
        -------
        dataset : `MapDatasetOnOff`
            Map dataset on off.

        """
    kwargs = {'name': name}
    if counts_off is None and dataset.background_model is not None:
        alpha = acceptance / acceptance_off
        kwargs['counts_off'] = dataset.background_model.evaluate() / alpha
    return cls(counts=dataset.counts, exposure=dataset.exposure, counts_off
        =counts_off, edisp=dataset.edisp, gti=dataset.gti, mask_safe=
        dataset.mask_safe, mask_fit=dataset.mask_fit, acceptance=acceptance,
        acceptance_off=acceptance_off, name=dataset.name, evaluation_mode=
        dataset.evaluation_mode)


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

        :param EnterpriseSettingsLockingType val:
        :rtype: EventType
        """
    return cls('enterprise_settings_locking', val)


@classmethod
def names(cls):
    """Returns all provider names in registry."""
    return cls._REGISTRY.keys()


def to_hex(color):
    """
    Color utility, converts a whitespace separated triple of
    numbers into a hex code color.
    """
    if not color[0] == '#':
        rgb = tuple(map(int, color.split(' ')))
        color = '#%02x%02x%02x' % rgb
    return color