def add_suffix(event, fields, suffix, separator='_'):
    """ Adds a suffix to a field or list of fields

    :param event: A dict with the entire event
    :param field_or_field_list: A single field or list of fields for which to add a suffix
    :param suffix: The suffix to add to the fields
    :param separator: The character to place between the name and the suffix
    :return: An altered event with the altered field names

    Examples:

    .. code-block:: python

        # Example #1
        event = {'a_field': 'a_value'}
        event = add_suffix(event, fields='a_field', suffix='an_ending')
        event = {'a_field_an_ending': 'a_value'}

        # Example #2
        event = {'a_field': 'a_value'}
        event = add_suffix(event, fields='a_field', suffix='an_ending', separator='---')
        event = {'a_field---an_ending': 'a_value'}

        # Example #3
        event = {'a_field': 'a_value',
                'another_field': 'another_value'}
        event = add_suffix(event, fields=['a_field', 'another_field'], suffix='an_ending')
        event = {'a_field_an_ending': 'a_value',
                'another_field_an_ending': 'another_value'}

    """
    if type(fields) is not list:
        fields = [fields]
    for k, v in event.items():
        if k in fields:
            event[k + separator + suffix] = event[k]
            del event[k]
    return event


def load():
    """Required for `pluggy` to load a plugin from setuptools entrypoints."""


def ssl_required(f):
    """This forces the view function be available only through HTTPS."""
    f._force_https = True
    return f


def from_vector(vector):
    """Convert MLlib Vector to numpy array
    """
    return vector.toArray()


@classmethod
def _inner_dataset_template(cls, dataset):
    """
        Returns a Dataset template used as a wrapper around the data
        contained within the multi-interface dataset.
        """
    from . import Dataset
    vdims = dataset.vdims if getattr(dataset, 'level', None) is None else []
    return Dataset(dataset.data[0], datatype=cls.subtypes, kdims=dataset.
        kdims, vdims=vdims)


def pytest_tempdir_basename():
    """
    Return the temporary directory basename for the salt test suite.
    """
    return 'saltfactories'


def wave_speed_flv(frequency, wave_length):
    """Usage: Finding the wave speed using frequency and wave length.
    v=f×λ"""
    return frequency * wave_length


def getServerInfo(pbclient=None, dc_id=None):
    """ gets info of servers of a data center"""
    if pbclient is None:
        raise ValueError("argument 'pbclient' must not be None")
    if dc_id is None:
        raise ValueError("argument 'dc_id' must not be None")
    server_info = []
    servers = pbclient.list_servers(dc_id, 1)
    for server in servers['items']:
        props = server['properties']
        info = dict(id=server['id'], name=props['name'], state=server[
            'metadata']['state'], vmstate=props['vmState'])
        server_info.append(info)
    return server_info


@classmethod
def _match(cls, url, **kwargs):
    """Return True if this handler can handle the input URL"""
    return url.scheme.startswith('ftp')


def message_get_many(transport, request, queue_name, messages, callback=None):
    """Gets many messages by id

    :param transport: Transport instance to use
    :type transport: `transport.base.Transport`
    :param request: Request instance ready to be sent.
    :type request: `transport.request.Request`
    :param queue_name: Queue reference name.
    :type queue_name: `six.text_type`
    :param messages: Messages references.
    :param messages: list of `six.text_type`
    :param callback: Optional callable to use as callback.
        If specified, this request will be sent asynchronously.
        (IGNORED UNTIL ASYNC SUPPORT IS COMPLETE)
    :type callback: Callable object.
    """
    request.operation = 'message_get_many'
    request.params['queue_name'] = queue_name
    request.params['ids'] = messages
    resp = transport.send(request)
    return resp.deserialized_content


def remove_hdmx_table(tt):
    """Removes hdmx table from a fontTools.ttLib.TTFont object"""
    try:
        del tt['hdmx']
    except KeyError:
        pass


def quantify(iterable, pred=bool):
    """Count how many times the predicate is true"""
    return sum(map(pred, iterable))


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

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

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


@classmethod
def getSiteExampleURLs(cls):
    """
        Return a string of space separated example URLs.
        Needs to be overriden in each adapter class.  It's the adapter
        writer's responsibility to make sure the example(s) pass the
        validateURL method.
        """
    return 'no such example'


def is_iterable(obj):
    """Tests if an object implements the iterable protocol.
    This function is intentionally not capitalized, because
    it does not check w.r.t. (capital) Iterable class from
    typing or collections.
    """
    try:
        itr = iter(obj)
        del itr
        return True
    except:
        return False


@classmethod
def from_string(cls, str):
    """Creates an instance of the Enum from a given string.

        """
    return getattr(cls, str.upper(), None)


def delete_db_parameter_group(DBParameterGroupName=None):
    """
    Deletes a specified DBParameterGroup. The DBParameterGroup to be deleted cannot be associated with any DB instances.
    See also: AWS API Documentation

    Examples
    The following example deletes a DB parameter group.
    Expected Output:

    :example: response = client.delete_db_parameter_group(
        DBParameterGroupName='string'
    )

    :type DBParameterGroupName: string
    :param DBParameterGroupName: [REQUIRED]
            The name of the DB parameter group.
            Constraints:
            Must be the name of an existing DB parameter group
            You cannot delete a default DB parameter group
            Cannot be associated with any DB instances

    :return: response = client.delete_db_parameter_group(
        DBParameterGroupName='mydbparamgroup3',
    )

    print(response)

    """
    pass


def add_arg(func, *args, **kwargs):
    """Bind CLI arguments to a shell.py `do_foo` function."""
    if not hasattr(func, 'arguments'):
        func.arguments = []
    if (args, kwargs) not in func.arguments:
        func.arguments.insert(0, (args, kwargs))


@staticmethod
def get_self_host(request_data):
    """
        Returns the current host.

        :param request_data: The request as a dict
        :type: dict

        :return: The current host
        :rtype: string
        """
    if 'http_host' in request_data:
        current_host = request_data['http_host']
    elif 'server_name' in request_data:
        current_host = request_data['server_name']
    else:
        raise Exception('No hostname defined')
    if ':' in current_host:
        current_host_data = current_host.split(':')
        possible_port = current_host_data[-1]
        try:
            int(possible_port)
            current_host = current_host_data[0]
        except ValueError:
            current_host = ':'.join(current_host_data)
    return current_host


@staticmethod
def debug(content, *args, **kwargs):
    """Set in :meth:`environment.Environment.initialize_reporting` to the updated version of
        :meth:`reporting.ReportingHandler.debug`"""
    print(content, *args, **kwargs)


def reveal():
    """Reveal all hidden UV vertices

    """
    pass


@classmethod
def is_readable(cls):
    """
        Check if this instrument is able to read any properties
        """
    return not callable(getattr(cls, 'set_value', None)) or len(cls.
        get_readable_properties()) > 0


def setencoding(value):
    """Set the default encoding for input strings (usually 'utf-8')."""
    global NX_ENCODING
    NX_ENCODING = value


def convert_to_unicode(input_string):
    """Convert input string to unicode."""
    if isinstance(input_string, bytes):
        return input_string.decode('utf-8')
    return input_string


def csv_skip_last_row(iterator):
    """Skip last CSV row.

    Args:
        iterator:

    Returns:

    """
    prev = next(iterator)
    for item in iterator:
        yield prev
        prev = item


def raster_ds_set_nodata(raster_ds, input_nodata):
    """Set raster dataset nodata value for all bands

    Parameters
    ----------
    raster_ds :

    Returns
    -------
    None

    """
    band_cnt = raster_ds.RasterCount
    for band_i in range(band_cnt):
        band = raster_ds.GetRasterBand(band_i + 1)
        band.SetNoDataValue(input_nodata)


def get_category(category_name, default=None, sort_key=None):
    """ Get a sequence of dictionaries in the form
        ``[{'introspectable':IIntrospectable, 'related':[sequence of related
        IIntrospectables]}, ...]`` where each introspectable is part of the
        category associated with ``category_name`` .

        If the category named ``category_name`` does not exist in the
        introspector the value passed as ``default`` will be returned.

        If ``sort_key`` is ``None``, the sequence will be returned in the
        order the introspectables were added to the introspector.  Otherwise,
        sort_key should be a function that accepts an IIntrospectable and
        returns a value from it (ala the ``key`` function of Python's
        ``sorted`` callable)."""


def full_angles_to_k_approx(kinetic_energy, phi, psi, alpha, beta, theta,
    chi, inner_potential):
    """
    Small angle approximation of the momentum conversion functions. Depending on the value of alpha,
    which we do not small angle approximate, this takes a few different forms.

    :param kinetic_energy:
    :param phi:
    :param psi:
    :param alpha:
    :param beta:
    :param theta:
    :param chi:
    :param inner_potential:
    :return:
    """
    raise NotImplementedError()


def parenthesize(s):
    """

    >>> parenthesize('1')
    '1'
    >>> parenthesize('1 + 2')
    '(1 + 2)'
    """
    if ' ' in s:
        return '(%s)' % s
    else:
        return s


def Concat(*data, **kwargs):
    """Joins input arrays along a given axis.

    .. note:: `Concat` is deprecated. Use `concat` instead.

    The dimensions of the input arrays should be the same except the axis along
    which they will be concatenated.
    The dimension of the output array along the concatenated axis will be equal
    to the sum of the corresponding dimensions of the input arrays.

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

    - concat(csr, csr, ..., csr, dim=0) = csr
    - otherwise, ``concat`` generates output with default storage

    Example::

       x = [[1,1],[2,2]]
       y = [[3,3],[4,4],[5,5]]
       z = [[6,6], [7,7],[8,8]]

       concat(x,y,z,dim=0) = [[ 1.,  1.],
                              [ 2.,  2.],
                              [ 3.,  3.],
                              [ 4.,  4.],
                              [ 5.,  5.],
                              [ 6.,  6.],
                              [ 7.,  7.],
                              [ 8.,  8.]]

       Note that you cannot concat x,y,z along dimension 1 since dimension
       0 is not the same for all the input arrays.

       concat(y,z,dim=1) = [[ 3.,  3.,  6.,  6.],
                             [ 4.,  4.,  7.,  7.],
                             [ 5.,  5.,  8.,  8.]]

    Defined in src/operator/nn/concat.cc:L383
    This function support variable length of positional input.

    Parameters
    ----------
    data : Symbol[]
        List of arrays to concatenate
    dim : int, optional, default='1'
        the dimension to be concated.

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

    Returns
    -------
    Symbol
        The result symbol.

    Examples
    --------
    Concat two (or more) inputs along a specific dimension:

    >>> a = Variable('a')
    >>> b = Variable('b')
    >>> c = Concat(a, b, dim=1, name='my-concat')
    >>> c
    <Symbol my-concat>
    >>> SymbolDoc.get_output_shape(c, a=(128, 10, 3, 3), b=(128, 15, 3, 3))
    {'my-concat_output': (128L, 25L, 3L, 3L)}

    Note the shape should be the same except on the dimension that is being
    concatenated.
    """
    return 0,


def rotate_right(root, y):
    """Apply right rotation on y, and return the new root."""
    assert root and y and y.left
    x = y.left
    y.left = x.right
    if y.left:
        y.left.parent = y
    x.right = y
    x.parent = y.parent
    y.parent = x
    if not x.parent:
        root = x
    elif x.parent.right == y:
        x.parent.right = x
    elif x.parent.left == y:
        x.parent.left = x
    return root


@classmethod
def handle(cls, file_request):
    """Handle a file request.

        :param file_request: file request
        :return: result of sending out the notification after creating the file
        """
    instance = cls.restore(file_request)
    return instance.create_file(file_request)


def list_tmpdir(flist):
    """ this read from file list of instances on tmp/tree and return the ones matching constraints """
    keys = ['variable', 'mip', 'model', 'experiment', 'ensemble', 'realm',
        'version', 'path']
    f = open(flist, 'r')
    inst_list = []
    lines = f.readlines()
    for line in lines[1:]:
        values = line[:-1].split(',')
        inst_list.append(dict(zip(keys, values)))
    f.close()
    return inst_list


def reset_globals():
    """
    Reset mas.glob related global variables.

    Must be called whenever (and before) pynusmv.init.init.deinit_nusmv
    is called.
    """
    global __mas
    __mas = None


def rename(name: str='RenamedMarker'):
    """Rename first selected time marker

    :param name: Name, New name for marker
    :type name: str
    """
    pass


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

        :param NoPasswordLinkViewReportFailedDetails val:
        :rtype: EventDetails
        """
    return cls('no_password_link_view_report_failed_details', val)


def drop_two_sided_faces(eptm):
    """Removes all the two (or one?) sided faces from the epithelium

    Note that they are not collapsed, but simply eliminated
    Does not reindex
    """
    num_sides = eptm.edge_df.groupby('face').size()
    if num_sides.min() > 2:
        return
    two_sided = eptm.face_df[num_sides < 3].index
    edges = eptm.edge_df[eptm.edge_df['face'].isin(two_sided)].index
    eptm.edge_df.drop(edges, axis=0, inplace=True)
    eptm.face_df.drop(two_sided, axis=0, inplace=True)


def supportsPolicy(obj, policy):
    """Determine if an object is set to use a specific versioning policy
        """


def hours(daterange=None, ticket=None, milestone=None, project=None, client
    =None):
    """ Returns the sum of the hours of the contained time entries,
            optionally only for a given ticket, milestone, project or client
        """


@classmethod
def get(cls, dataset_id):
    """Get information about a dataset.

        Parameters
        ----------
        dataset_id : string
            the id of the dataset

        Returns
        -------
        dataset : Dataset
            the queried dataset
        """
    path = '{}{}/'.format(cls._path, dataset_id)
    return cls.from_location(path)


def init_model(N, y0):
    """
    Initialize the SEIR model.

    :param int y0: Infected rate at initial time step.
    :param int N: Population

    :returns: Model at initial time step
    :rtype: tuple(int, int, int)
    """
    return N - y0, y0, 0, 0


@classmethod
def from_element(cls, api, element):
    """Create a PhotoSet object from XML element from API."""
    title = element.find('title').text
    description = element.find('description').text
    attrs = element.attrib
    return cls(api, attrs['id'], title, description, attrs=attrs)


def add_to_list_if_not_none(item, list):
    """
    Add a value to a list if it is not None

    :param item: the item to add
    :param list: the list to append it to
    :return: nothing
    """
    if item is not None:
        list.append(item)


@staticmethod
def _is_primary_key(table_columns, pColumn_name):
    """Check if column is primary key"""
    for column in table_columns:
        column_name = column[8]
        column_primary_Key = column[5]
        if column_name == pColumn_name and column_primary_Key == 'PrimaryKey':
            return True
    return False


def urlconcat(*parts):
    """
    Concatenate URL parts properly handling slashes.

    This is a replacement for urljoin that have an specific and not wanted behaviour regaring slash handling.

    What we want is the following:

    * url_concat(http://alpha/bravo, zulu)    => http://alpha/bravo/zulu
    * url_concat(http://alpha/bravo/, zulu)   => http://alpha/bravo/zulu
    * url_concat(http://alpha/bravo//, zulu)  => http://alpha/bravo/zulu
    """
    result = []
    for i_part in parts:
        result.append(i_part.strip('/'))
    return '/'.join(result)


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


def evolution(island):
    """
    Infinite generator for evolution of some population.
    This generator yields population:
        population - tuple together containing tuples/individuals

    population_0 = create()
    population_1 = evolve(population_0, info_0)
    .
    .
    population_k = evolve(population_k-1, info_k-1)
    .
    .

    Since population is a tuple/an immutable type, a population cannot be
    influenced by outside functions. Population can be used only to gather
    statistics

    If no immigration and emmigration is used this island evolution
    becomes a classical genetic algorithm.
    """
    population = island.create_population()
    while True:
        for _ in range(island.migration_interval if island.migrate else 1):
            yield population
            if island.assimilate:
                population = island.assimilate(population)
            population = island.evolve(population)
        if island.migrate:
            island.migrate(population)


def for_loop(function, argument_list):
    """Apply a univariate function to a list of arguments in a serial fashion.

    Uses Python's built-in for statement.

    Args:
        function: A callable object that accepts one argument
        argument_list: An iterable object of input arguments

    Returns:
        List of output results

    Example:
        >>> def square(x):
        ...     return x**2
        ...
        >>> for_loop(square, [1, 2, 3, 4, 5])
        [1, 4, 9, 16, 25]

    References:
        - https://docs.python.org/3/reference/compound_stmts.html#the-for-statement
        - https://docs.python.org/3/tutorial/controlflow.html#for-statements
    """
    result_list = []
    for arg in argument_list:
        result_list.append(function(arg))
    return result_list


def to_value(unit_system: str, unit_category: str, str_input: str,
    str_ref_unit: str=None) ->float:
    """Convert a given input string into a float value.

    :param unit_system: The unit system, from bpy.utils.units.systems.
    :type unit_system: str
    :param unit_category: The category of data we are converting (length, area, rotation, etc.), from bpy.utils.units.categories.
    :type unit_category: str
    :param str_input: The string to convert to a float value.
    :type str_input: str
    :param str_ref_unit: A reference string from which to extract a default unit, if none is found in str_input.
    :type str_ref_unit: str
    :return:  The converted/interpreted value.
    """
    pass


def fill():
    """Add bone between selected joint(s) and/or 3D-Cursor

    """
    pass


@classmethod
def wordToNumber(cls, s):
    """
        方法numberTranslator的辅助方法，可将[零-九]正确翻译为[0-9]
        :param s: 大写数字
        :return: 对应的整形数，如果不是数字返回-1
        """
    if s == u'零' or s == '0':
        return 0
    elif s == u'一' or s == '1':
        return 1
    elif s == u'二' or s == u'两' or s == '2':
        return 2
    elif s == u'三' or s == '3':
        return 3
    elif s == u'四' or s == '4':
        return 4
    elif s == u'五' or s == '5':
        return 5
    elif s == u'六' or s == '6':
        return 6
    elif s == u'七' or s == u'天' or s == u'日' or s == u'末' or s == '7':
        return 7
    elif s == u'八' or s == '8':
        return 8
    elif s == u'九' or s == '9':
        return 9
    else:
        return -1


def list_workflow_types(domain=None, name=None, registrationStatus=None,
    nextPageToken=None, maximumPageSize=None, reverseOrder=None):
    """
    Returns information about workflow types in the specified domain. The results may be split into multiple pages that can be retrieved by making the call repeatedly.
    Access Control
    You can use IAM policies to control this action's access to Amazon SWF resources as follows:
    If the caller does not have sufficient permissions to invoke the action, or the parameter values fall outside the specified constraints, the action fails. The associated event attribute's cause parameter will be set to OPERATION_NOT_PERMITTED. For details and example IAM policies, see Using IAM to Manage Access to Amazon SWF Workflows .
    See also: AWS API Documentation

    :example: response = client.list_workflow_types(
        domain='string',
        name='string',
        registrationStatus='REGISTERED'|'DEPRECATED',
        nextPageToken='string',
        maximumPageSize=123,
        reverseOrder=True|False
    )

    :type domain: string
    :param domain: [REQUIRED]
            The name of the domain in which the workflow types have been registered.

    :type name: string
    :param name: If specified, lists the workflow type with this name.

    :type registrationStatus: string
    :param registrationStatus: [REQUIRED]
            Specifies the registration status of the workflow types to list.

    :type nextPageToken: string
    :param nextPageToken: If a NextPageToken was returned by a previous call, there are more results available. To retrieve the next page of results, make the call again using the returned token in nextPageToken . Keep all other arguments unchanged.
            The configured maximumPageSize determines how many results can be returned in a single call.

    :type maximumPageSize: integer
    :param maximumPageSize: The maximum number of results that will be returned per call. nextPageToken can be used to obtain futher pages of results. The default is 1000, which is the maximum allowed page size. You can, however, specify a page size smaller than the maximum.
            This is an upper limit only; the actual number of results returned per call may be fewer than the specified maximum.

    :type reverseOrder: boolean
    :param reverseOrder: When set to true , returns the results in reverse order. By default the results are returned in ascending alphabetical order of the name of the workflow types.

    :rtype: dict
    :return: {
        'typeInfos': [
            {
                'workflowType': {
                    'name': 'string',
                    'version': 'string'
                },
                'status': 'REGISTERED'|'DEPRECATED',
                'description': 'string',
                'creationDate': datetime(2015, 1, 1),
                'deprecationDate': datetime(2015, 1, 1)
            },
        ],
        'nextPageToken': 'string'
    }

    :returns:
    domain (string) -- [REQUIRED]
    The name of the domain in which the workflow types have been registered.

    name (string) -- If specified, lists the workflow type with this name.
    registrationStatus (string) -- [REQUIRED]
    Specifies the registration status of the workflow types to list.

    nextPageToken (string) -- If a NextPageToken was returned by a previous call, there are more results available. To retrieve the next page of results, make the call again using the returned token in nextPageToken . Keep all other arguments unchanged.
    The configured maximumPageSize determines how many results can be returned in a single call.

    maximumPageSize (integer) -- The maximum number of results that will be returned per call. nextPageToken can be used to obtain futher pages of results. The default is 1000, which is the maximum allowed page size. You can, however, specify a page size smaller than the maximum.
    This is an upper limit only; the actual number of results returned per call may be fewer than the specified maximum.

    reverseOrder (boolean) -- When set to true , returns the results in reverse order. By default the results are returned in ascending alphabetical order of the name of the workflow types.

    """
    pass


def remove_role_from_instance_profile(InstanceProfileName=None, RoleName=None):
    """
    Removes the specified IAM role from the specified EC2 instance profile.
    For more information about IAM roles, go to Working with Roles . For more information about instance profiles, go to About Instance Profiles .
    See also: AWS API Documentation

    Examples
    The following command removes the role named Test-Role from the instance profile named ExampleInstanceProfile.
    Expected Output:

    :example: response = client.remove_role_from_instance_profile(
        InstanceProfileName='string',
        RoleName='string'
    )

    :type InstanceProfileName: string
    :param InstanceProfileName: [REQUIRED]
            The name of the instance profile to update.
            This parameter allows (per its regex pattern ) a string of characters consisting of upper and lowercase alphanumeric characters with no spaces. You can also include any of the following characters: =,.@-

    :type RoleName: string
    :param RoleName: [REQUIRED]
            The name of the role to remove.
            This parameter allows (per its regex pattern ) a string of characters consisting of upper and lowercase alphanumeric characters with no spaces. You can also include any of the following characters: _+=,.@-

    :return: response = client.remove_role_from_instance_profile(
        InstanceProfileName='ExampleInstanceProfile',
        RoleName='Test-Role',
    )

    print(response)

    """
    pass


def identifier(s):
    """
    Return s as a quoted postgres identifier
    """
    return u'"' + s.replace(u'"', u'""').replace(u'\x00', '') + u'"'


@classmethod
def initialize(cls, frontend_dir: str):
    """Initializes engine.

        This method is called when the frontend is created, and will be only called once.
        It should install all frontend specific stuff, e.g. using Js libraries using 'yarn/npm install' etc.
        It can assume that the BASE_DIR/frontend_dir/ exists, and uses the package manager
        defined in settings.FRONTEND_PKG_MANAGER.
        :param frontend_dir: relative directory within BASE_DIR where the frontend lives.
        """


def get_uri_extension():
    """
        @return: URIExtensionData
        """


def setexprOperator2(op):
    """
    Returns a function which performs set to set comparison operations
    """
    if op == 'is':
        return lambda x, y: x == y
    if op == 'is not':
        return lambda x, y: x != y
    if op == 'subset':
        return lambda x, y: x <= y
    if op == 'superset':
        return lambda x, y: x >= y
    if op == 'proper subset':
        return lambda x, y: x < y
    if op == 'proper superset':
        return lambda x, y: x > y
    raise Exception('operator %s not found' % op)


def getdraw(im=None, hints=None):
    """
    (Experimental) A more advanced 2D drawing interface for PIL images,
    based on the WCK interface.

    :param im: The image to draw in.
    :param hints: An optional list of hints.
    :returns: A (drawing context, drawing resource factory) tuple.
    """
    handler = None
    if not hints or 'nicest' in hints:
        try:
            from . import _imagingagg as handler
        except ImportError:
            pass
    if handler is None:
        from . import ImageDraw2 as handler
    if im:
        im = handler.Draw(im)
    return im, handler


def state_move_down():
    """Move boid state down in the list

    """
    pass


@classmethod
def check_expiration_dates_types(cls):
    """Location types to check for expiration dates"""
    return ['supplier', 'customer', 'production']


def explicit(_current, indent):
    """
    Another simple policy that matches whatever indent is used.
    """
    return len(indent)


def make_time_index_intervals(twitter_df, col='date', start=None, end=None,
    freq='CBH', num_offset=1):
    """Takes a df, rounds first timestamp down to nearest hour, last timestamp rounded up to hour.
    Creates 30 minute intervals based that encompass all data."""
    import pandas as pd
    if freq == 'CBH':
        freq = pd.offsets.CustomBusinessHour(n=num_offset, start='09:30',
            end='16:30')
        ofst = pd.offsets.CustomBusinessHour(n=num_offset, start='09:30',
            end='16:30')
        ofst_early = pd.offsets.CustomBusinessHour(n=-num_offset, start=
            '09:30', end='16:30')
    if freq == 'T':
        ofst = pd.offsets.Minute(n=num_offset)
        ofst_early = pd.offsets.Minute(n=-num_offset)
    if freq == 'H':
        ofst = pd.offsets.Hour(n=num_offset)
        ofst_early = pd.offsets.Hour(n=-num_offset)
    if start is None:
        start_idx = ofst.rollback(twitter_df[col].iloc[0])
    else:
        start_idx = pd.to_datetime(start)
    if end is None:
        end_idx = ofst.rollforward(twitter_df[col].iloc[-1])
    else:
        end_idx = pd.to_datetime(end)
    time_range = pd.date_range(start=start_idx, end=end_idx, freq=freq)
    time_intervals = pd.interval_range(start=start_idx, end=end_idx, freq=
        freq, name='interval_index', closed='left')
    return time_intervals


def equals(v1, v2) ->bool:
    """Compare two objects by value. Unlike the standard Python equality operator,
    this function does not consider 1 == True or 0 == False. All other equality
    operations are the same and performed using Python's equality operator."""
    if isinstance(v1, (bool, type(None))) or isinstance(v2, (bool, type(None))
        ):
        return v1 is v2
    return v1 == v2


def is_factor(obj):
    """ Is obj a Factor?
    """
    return hasattr(obj, '_factor_flag')


def seek_file_end(file):
    """Seek to the end of the file."""
    try:
        file.seek(0, 2)
    except ValueError:
        while True:
            data = file.read(4096)
            if not data:
                break


@classmethod
def from_json(cls, json_data):
    """Build and return a new Group object from json data (used internally)"""
    return cls(group_id=json_data['grpId'], name=json_data['grpName'],
        description=json_data.get('grpDescription', ''), path=json_data[
        'grpPath'], parent_id=json_data['grpParentId'])


def grayscale(image):
    """
    Convert the image to grayscale.

    :param image: The image to convert.
    :return: An image.
    """
    return image.convert('L')


def lookupMailRename(name, timeout=None):
    """
        Perform an MR record lookup.

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

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

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


def convert_bsymbol(bsymbol):
    """
    Convert Bloomberg Symbol to Cybos Symbol
    :param bsymbol: Bloomberg Symbol ex) 005380 KS Equity
    :return: A005380
    """
    str = bsymbol.split()
    return 'A' + str[0]


def shape(attrs, inputs, proto_obj):
    """Returns shape of input array."""
    return 'shape_array', attrs, inputs


def calc_pad(pad, in_siz, out_siz, stride, ksize):
    """Calculate padding width.
    Args:
        pad: padding method, "SAME", "VALID", or manually speicified.
        ksize: kernel size [I, J].
    Returns:
        pad_: Actual padding width.
    """
    if pad == 'SAME':
        return (out_siz - 1) * stride + ksize - in_siz
    elif pad == 'VALID':
        return 0
    else:
        return pad


def _maximal_matching_qubo(G, edge_mapping, magnitude=1.0):
    """Generates a QUBO that when combined with one as generated by _matching_qubo,
    induces a maximal matching on the given graph G.
    The variables in the QUBO are the edges, as given my edge_mapping.

    ground_energy = -1 * magnitude * |edges|
    infeasible_gap >= magnitude
    """
    Q = {}
    for u, v in G.edges:
        for edge in G.edges(u):
            x = edge_mapping[edge]
            if (x, x) not in Q:
                Q[x, x] = -1 * magnitude
            else:
                Q[x, x] -= magnitude
        for edge in G.edges(v):
            x = edge_mapping[edge]
            if (x, x) not in Q:
                Q[x, x] = -1 * magnitude
            else:
                Q[x, x] -= magnitude
        for e0 in G.edges(v):
            x0 = edge_mapping[e0]
            for e1 in G.edges(u):
                x1 = edge_mapping[e1]
                if x0 < x1:
                    if (x0, x1) not in Q:
                        Q[x0, x1] = magnitude
                    else:
                        Q[x0, x1] += magnitude
                elif (x1, x0) not in Q:
                    Q[x1, x0] = magnitude
                else:
                    Q[x1, x0] += magnitude
    return Q


@staticmethod
def grad(x):
    """Return gradient of activation function."""
    return 1.0


def copy_to_selected_button(all: bool=True):
    """Copy property from this object to selected objects or bones

    :param all: All, Copy to selected all elements of the array
    :type all: bool
    """
    pass


@staticmethod
def beta_r(r):
    """
        anisotropy as a function of radius

        :param r: 3d radius
        :return: beta
        """
    return 1.0


def instantiate_tasks(task_class_list, inject):
    """Instantiates a list of Tasks. Generates a name for each task based on
    the class name, and if available the language and api_name settings.
    """
    tasks = []
    for task_class in task_class_list:
        name = task_class.__name__
        if inject.get('language'):
            name += '-' + inject['language']
        if inject.get('api_name'):
            name += '-' + inject['api_name']
        if inject.get('api_version'):
            name += '-' + inject['api_version']
        tasks.append(task_class(name, inject=inject))
    return tasks


def deregister_event_topic(DirectoryId=None, TopicName=None):
    """
    Removes the specified directory as a publisher to the specified SNS topic.
    See also: AWS API Documentation

    :example: response = client.deregister_event_topic(
        DirectoryId='string',
        TopicName='string'
    )

    :type DirectoryId: string
    :param DirectoryId: [REQUIRED]
            The Directory ID to remove as a publisher. This directory will no longer send messages to the specified SNS topic.

    :type TopicName: string
    :param TopicName: [REQUIRED]
            The name of the SNS topic from which to remove the directory as a publisher.

    :rtype: dict
    :return: {}

    """
    pass


def is_gp(l):
    """
    Calculates the log of the sequence and checks if this is an AP
    @arg l  The list to check
    @ret    Boolean
    """
    if len(l) < 2:
        return True
    for i in range(len(l) - 2):
        if l[i] * l[i + 2] != l[i + 1] ** 2:
            return False
    for i in range(len(l) - 1):
        if l[i] == 0 and l[i + 1] != 0:
            return False
    return True


def setLanguage(language):
    """
        Sets the language for the current translation - same as DC
        """


def setTracebackClearing(clear=True):
    """
    Enable or disable traceback clearing.
    By default, clearing is disabled and Python will indefinitely store unhandled exception stack traces.
    This function is provided since Python's default behavior can cause unexpected retention of
    large memory-consuming objects.
    """
    global clear_tracebacks
    clear_tracebacks = clear


def check_domain_state(conn, guestname, logger):
    """ if a guest with the same name exists, remove it """
    running_guests = []
    ids = conn.listDomainsID()
    for id in ids:
        obj = conn.lookupByID(id)
        running_guests.append(obj.name())
    if guestname in running_guests:
        logger.info('A guest with the same name %s is running!' % guestname)
        logger.info('destroy it...')
        domobj = conn.lookupByName(guestname)
        domobj.destroy()
    defined_guests = conn.listDefinedDomains()
    if guestname in defined_guests:
        logger.info('undefine the guest with the same name %s' % guestname)
        domobj = conn.lookupByName(guestname)
        domobj.undefine()
    return 0


def prepare(prefix):
    """
    Prepare the environment.
    """
    return True


@classmethod
def x_unit_vector(cls):
    """Returns the unit vector (1 | 0 | 0)"""
    return cls(1, 0, 0)


def error_if_not_writable(h5file):
    """ Raise an IOError if an SDAFile indicates 'Writable' as 'no'. """
    writable = h5file.attrs.get('Writable')
    if writable == b'no':
        msg = "File '{}' is not writable".format(h5file.filename)
        raise IOError(msg)


def _write_bdf_dict_cards(bdf_file, cards, size, is_double, is_long_ids):
    """writes a dictionary"""
    if bdf_file is None:
        return
    if is_long_ids:
        for card in cards:
            bdf_file.write(card.write_card_16(is_double))
    else:
        for card in cards:
            bdf_file.write(card.write_card(size, is_double))


@classmethod
def set_connection(cls, connection):
    """Set a connection for the RGWAdmin session to use."""
    cls.connection = connection


def _days_before_year(year):
    """year -> number of days before January 1st of year."""
    y = year - 1
    return y * 365 + y // 4 - y // 100 + y // 400


def _stable_ids_from_ambig(ambig_map):
    """Create stable IDs from an ambiguity map"""
    ambig_assoc = {}
    ri = {}
    for k, v in ambig_map.items():
        for unambig in v:
            tag, untagged = unambig.split('_', 1)
            stab = '%s.%s' % (untagged, tag)
            ambig_assoc[stab] = k
            ri[unambig] = stab
    return ambig_assoc, ri


@staticmethod
def _extract_parent_dirs(given_rel_dir, parent_dir_set):
    """
        This method extracts the parent directories of the givenDir
        and populates the parent_dir_set.
        """
    sub_paths = given_rel_dir.split('/')
    temp_path = ''
    for sub_path in sub_paths:
        temp_path += sub_path + '/'
        parent_dir_set.add(temp_path)
    return parent_dir_set


def direct_from_halo_catalog(**kwargs):
    """
    Function returns the concentrations that are already present
    in an input halo catalog.

    Parameters
    ----------
    table : object
        `~astropy.table.Table` storing halo catalog.

    concentration_key : string
        Name of the table column storing the concentration

    Returns
    -------
    concentration : array_like
        Concentrations of the input halos.
    """
    try:
        table = kwargs['table']
        concentration_key = kwargs['concentration_key']
    except KeyError:
        msg = """The ``direct_from_halo_catalog`` function accepts two keyword arguments:
``table`` and ``concentration_key``"""
        raise KeyError(msg)
    try:
        concentration = table[concentration_key]
    except:
        msg = """The ``{0}`` key does not appear in the input halo catalog.
However, you have selected the ``direct_from_halo_catalog`` option
to model the concentration-mass relation.
The available keys are:

{1}
"""
        raise KeyError(msg.format(concentration_key, list(table.keys())))
    return concentration


def computeContribs(urls, rank):
    """Calculates URL contributions to the rank of other URLs."""
    num_urls = len(urls)
    for url in urls:
        yield url, rank / num_urls


@classmethod
def wrap_class(cls, klass):
    """Wrapp a classes docstring to conceal it from instances."""
    klass.__doc__ = cls(klass.__doc__)
    return klass


def CONCAT(src_column, dict_value_column=None):
    """
  Builtin aggregator that combines values from one or two columns in one group
  into either a dictionary value or list value.

  If only one column is given, then the values of this column are
  aggregated into a list.  Order is not preserved.  For example:

  >>> sf.groupby(["user"],
  ...     {"friends": gl.aggregate.CONCAT("friend")})

  would form a new column "friends" containing values in column
  "friend" aggregated into a list of friends.

  If `dict_value_column` is given, then the aggregation forms a dictionary with
  the keys taken from src_column and the values taken from `dict_value_column`.
  For example:

  >>> sf.groupby(["document"],
  ...     {"word_count": gl.aggregate.CONCAT("word", "count")})

  would aggregate words from column "word" and counts from column
  "count" into a dictionary with keys being words and values being
  counts.
  """
    if dict_value_column == None:
        return '__builtin__concat__list__', [src_column]
    else:
        return '__builtin__concat__dict__', [src_column, dict_value_column]


def _convertbits(data, frombits, tobits, pad=True):
    """General power-of-2 base conversion."""
    acc = 0
    bits = 0
    ret = bytearray()
    maxv = (1 << tobits) - 1
    max_acc = (1 << frombits + tobits - 1) - 1
    for value in data:
        acc = (acc << frombits | value) & max_acc
        bits += frombits
        while bits >= tobits:
            bits -= tobits
            ret.append(acc >> bits & maxv)
    if pad and bits:
        ret.append(acc << tobits - bits & maxv)
    return ret


@classmethod
def _get_reserved_fieldnames(cls):
    """ Returns a list of fieldnames to hide when calling
            "to_view_dict" on view model

        :return:
        """
    return {'obj_type', 'doc_id', 'doc_ref'}


def compute_fans(kernel_shape):
    """Computes the number of input and output units for a weight shape.
    Args:
        shape: Integer shape tuple or TF tensor shape.
    Returns:
        A tuple of scalars (fan_in, fan_out).
    """
    shape = kernel_shape
    if len(shape) < 1:
        fan_in = fan_out = 1
    elif len(shape) == 1:
        fan_in = fan_out = shape[0]
    elif len(shape) == 2:
        fan_in = shape[0]
        fan_out = shape[1]
    else:
        receptive_field_size = 1.0
        for dim in shape[:-2]:
            receptive_field_size *= dim
        fan_in = shape[-2] * receptive_field_size
        fan_out = shape[-1] * receptive_field_size
    return fan_in, fan_out


def quiet(code, *args):
    """Return the result of evaluating the given code with the given arguments catching any
    exceptions and returning False if an exception occurs"""
    try:
        return code(*args)
    except:
        pass
    return False


def dropout_mask(x, sz, p):
    """create a mask to zero out p persent of the activation, by keeping the
    same module of the tensor."""
    return x.new(*sz).bernoulli_(1 - p).div_(1 - p)


def slugify(value):
    """
    Normalizes string, converts to lowercase, removes non-alpha characters,
    and converts spaces to hyphens.type(
    """
    import re
    import unicodedata
    from six import text_type
    value = text_type(value)
    value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore'
        ).decode('utf8')
    value = re.sub('[^\\w\\s-]', '-', value).strip().lower()
    value = re.sub('[-\\s]+', '-', value)
    return value


def package_details_payload(code, year, destination):
    """Returns the details endpoint payload json (as dict)"""
    return dict(Anio=str(year), Tracking=code, Destino=destination)


def listAllowedFormats(content=None, content_type=None):
    """ List the allowed values of the 'Format' DCMI element.

        o These items should be usable as HTTP 'Content-type' values.

        o Return only values appropriate for content's type, or all values if
          both 'content' and 'content_type' are None.
        """


def traverse(object, path, default=None, request=None):
    """
        Traverse *path* relative to the given object.

        :param str path: a string with path segments separated by '/'.
        :keyword request: Passed in when traversing from
            presentation code.  This allows paths like "@@foo" to work.
        :raises zope.location.interfaces.LocationError: if *path* cannot be found

        .. note:: Calling `traverse` with a path argument taken from an
            untrusted source, such as an HTTP request form variable,
            is a bad idea.  It could allow a maliciously constructed
            request to call code unexpectedly.  Consider using
            `traverseName` instead.
        """


@staticmethod
def shutdown(port, verbosity):
    """Finalize connector."""
    pass


def getMembers():
    """Returns a list of IMember in the dimension."""


def convert_float(inpt):
    """Return float value from inpt

    >>> convert_float('1')
    1.0
    """
    return float(inpt)


def _next_rdelim(items, pos):
    """Return position of next matching closing delimiter."""
    for num, item in enumerate(items):
        if item > pos:
            break
    else:
        raise RuntimeError('Mismatched delimiters')
    del items[num]
    return item


def num_misses(df):
    """Total number of misses."""
    return df.noraw.Type.isin(['MISS']).sum()


def isalias(array1, array2):
    """
    Return True if the two input arrays point to the same memory location.

    """
    return array1.__array_interface__['data'][0] == array2.__array_interface__[
        'data'][0]


def canpush():
    """Returns a boolean indicating if this peer can be pushed to."""


def update_parameter(old_parameter, new_parameter):
    """
    Works as the 'update' of dictionnaries but instead of replacing a list
    by another one, this method add each element of a list to the other by
    skipping duplicate.
    """
    for key in new_parameter:
        if key in old_parameter:
            if isinstance(old_parameter[key], list):
                for string_ in new_parameter[key]:
                    if string_ not in old_parameter[key]:
                        old_parameter[key].append(string_)
            else:
                old_parameter[key] = new_parameter[key]
        else:
            old_parameter[key] = new_parameter[key]


def start(st_reg_number):
    """Checks the number valiaty for the Maranhão state"""
    divisor = 11
    if len(st_reg_number) > 9:
        return False
    if len(st_reg_number) < 9:
        return False
    if st_reg_number[0:2] != '12':
        return False
    sum_total = 0
    peso = 9
    for i in range(len(st_reg_number) - 1):
        sum_total = sum_total + int(st_reg_number[i]) * peso
        peso = peso - 1
        rest_division = sum_total % divisor
        digit = divisor - rest_division
    if rest_division < 2:
        digit = 0
    if rest_division > 1:
        digit = 11 - rest_division
    return digit == int(st_reg_number[len(st_reg_number) - 1])


def check_gcc():
    """Check that gcc is installed"""
    from sh import which
    shOut = which('gcc')
    if not shOut is None:
        from sh import gcc
        version = str(gcc('--version'))
        return version, True
    else:
        print(
            'ERROR: you must install gcc version 5.1 or above before continuing.'
            )
        return None, False


@classmethod
def episode_visible_to(kls, episode, user):
    """
        Predicate function to determine whether an episode of this category
        is visible to a particular user.

        Defaults implementation checks for Profile.restricted_only and
        returns true if we have a regular user.
        """
    from opal.models import UserProfile
    profile = UserProfile.objects.get(user=user)
    if profile.restricted_only:
        return False
    return True


def frame_id(event):
    """
    Gets a unique identifier for a Pilatus data frame retrieved from files (or HiDRA).

    Returns a label that unambiguosly identifies, within an event, the frame currently
    being processed. For the Pilatus detector, the index of the frame within the event
    is used as identifier. However, each Pilatus event only contains one frame, so this
    function always returns the string "0".

    Arguments:

        event (:class:`~onda.utils.data_event.DataEvent`): an object storing the event
            data.

    Returns:

        str: a unique frame identifier (within an event).
    """
    del event
    return str(0)


def theta_Cl_HSO4_HMW84(T, P):
    """a-a': chloride bisulfate [HMW84]."""
    theta = -0.006
    valid = T == 298.15
    return theta, valid


def argsort(arr):
    """对数组进行排序, 返回以索引的数组"""
    return arr.argsort()


@staticmethod
def _reduce_datetimes(row):
    """Receives a row, converts datetimes to strings."""
    row = list(row)
    for i, val in enumerate(row):
        if hasattr(val, 'strftime'):
            row[i] = val.strftime('%Y-%m-%d %H:%M:%S')
        elif hasattr(val, 'isoformat'):
            row[i] = val.isoformat()
    return tuple(row)


def tilt_image(image, degrees):
    """Will tilt an image by degrees

    Parameters:
    :param image: the image you loaded (from load_img)
    :param degrees: the degrees to tilt
    :return the tilted image
    """
    return image.rotate(degrees, expand=1)


def getUrls():
    """Generador, acá se pueden obtener las url a procesar desde la base de datos"""
    yield 'http://www.some_news_site.cl'
    yield 'http://www.another_news_site.cl'


def _new_module(name):
    """Create a new module with the given name."""
    import types
    return types.ModuleType(name)


def filter_data(df, filter_name, verbose=False):
    """Filter certain entries with given name."""
    df = df[df.stop_name.apply(lambda cell: filter_name.encode('utf-8') in
        cell)]
    if verbose:
        msg = '- Filtered down to %d entries containing "%s".'
        print(msg % (len(df), filter_name))
    return df


def _getfield_is_safe(oldtype, newtype, offset):
    """ Checks safety of getfield for object arrays.

    As in _view_is_safe, we need to check that memory containing objects is not
    reinterpreted as a non-object datatype and vice versa.

    Parameters
    ----------
    oldtype : data-type
        Data type of the original ndarray.
    newtype : data-type
        Data type of the field being accessed by ndarray.getfield
    offset : int
        Offset of the field being accessed by ndarray.getfield

    Raises
    ------
    TypeError
        If the field access is invalid

    """
    if newtype.hasobject or oldtype.hasobject:
        if offset == 0 and newtype == oldtype:
            return
        if oldtype.names is not None:
            for name in oldtype.names:
                if oldtype.fields[name][1] == offset and oldtype.fields[name][0
                    ] == newtype:
                    return
        raise TypeError('Cannot get/set field of an object array')
    return


@classmethod
def names(cls):
    """Implement :meth:`~.solver.Solver.names`."""
    return 'gurobi', 'Gurobi', 'Gurobi Optimizer'


@classmethod
def save_all(cls, objs):
    """
        在一个请求中 save 多个 leancloud.Object 对象实例。

        :param objs: 需要 save 的对象
        :type objs: list
        """
    if not objs:
        return
    return cls()._deep_save(objs, [])


def autopack_toggle():
    """Automatically pack all external files into the .blend file

    """
    pass


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 render_git_describe_long(pieces):
    """TAG-DISTANCE-gHEX[-dirty].

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

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


def capacitor_film_decodevalue(value):
    """
    The last 3 numbers (X) of the code

    140-pF 2A XXX J

    """
    valuestr = str(value)
    expon = int(valuestr[-1])
    pF = int(valuestr[:-1]) * 10 ** expon
    if pF > 1000000:
        return '%.2f uF' % (pF / 1000000)
    elif pF > 1000:
        return '%.2f nF' % (pF / 1000)
    else:
        return '%d pF' % pF


def getSet(unique_name):
    """Returns a ISet with the given unique name in the cube."""


def prefetch(oids):
    """Prefetch data for the given object ids

        The oids argument is an iterable that should be iterated no
        more than once.
        """


def buffer_to_bytes(buf):
    """Cast a buffer or memoryview object to bytes"""
    if isinstance(buf, memoryview):
        return buf.tobytes()
    if not isinstance(buf, bytes):
        return bytes(buf)
    return buf


def get_corner_coordinates(gdal_ds=None, gt=None, cols=None, rows=None):
    """Returns (ULxy, LLxy, LRxy, URxy) in the same coordinate units like the given geotransform."""
    assert gdal_ds or gt and cols and rows, "GEOP.get_corner_coordinates: Missing argument! Please provide either 'gdal_ds' or 'gt', 'cols' AND 'rows'."
    gdal_ds_GT = gdal_ds.GetGeoTransform() if gdal_ds else gt
    ext = []
    xarr = [0, gdal_ds.RasterXSize if gdal_ds else cols]
    yarr = [0, gdal_ds.RasterYSize if gdal_ds else rows]
    for px in xarr:
        for py in yarr:
            x = gdal_ds_GT[0] + px * gdal_ds_GT[1] + py * gdal_ds_GT[2]
            y = gdal_ds_GT[3] + px * gdal_ds_GT[4] + py * gdal_ds_GT[5]
            ext.append([x, y])
        yarr.reverse()
    return ext


@classmethod
def _forced_interrupt(cls, signum):
    """Return True if `force_n` interrupts have been recieved in the past
        `force_timeout` seconds"""
    with cls._lock:
        signals_raised = cls._signals_raised.get(signum, [])
        return cls.force_n <= len(signals_raised
            ) and cls.force_timeout > signals_raised[-1][-1] - signals_raised[
            -cls.force_n][-1]


def scene_to_dict(scene, use_base64=False):
    """
    Export a Scene object as a dict.

    Parameters
    -------------
    scene : trimesh.Scene
      Scene object to be exported

    Returns
    -------------
    as_dict : dict
      Scene as a dict
    """
    export = {'graph': scene.graph.to_edgelist(), 'geometry': {},
        'scene_cache': {'bounds': scene.bounds.tolist(), 'extents': scene.
        extents.tolist(), 'centroid': scene.centroid.tolist(), 'scale':
        scene.scale}}
    if use_base64:
        file_type = 'dict64'
    else:
        file_type = 'dict'
    for geometry_name, geometry in scene.geometry.items():
        if hasattr(geometry, 'export'):
            exported = {'data': geometry.export(file_type=file_type),
                'file_type': file_type}
            export['geometry'][geometry_name] = exported
        else:
            export['geometry'][geometry_name] = geometry
    return export


def rl_testrule(x):
    """
    Rule for tests. Do nothing.
    """
    return x


def p_switch_case_list_colon(p):
    """switch_case_list : COLON case_list ENDSWITCH SEMI
                        | COLON SEMI case_list ENDSWITCH SEMI"""
    if len(p) == 5:
        p[0] = p[2]
    else:
        p[0] = p[3]


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


def set_name_ds(name_ds):
    """Set the dataset name in regression; return generic name if user
    provides no explicit name."

    Parameters
    ----------

    name_ds     : string
                  User provided dataset name.

    Returns
    -------

    name_ds     : string

    """
    if not name_ds:
        name_ds = 'unknown'
    return name_ds


def add_data_export_arg(parser):
    """
    Add export argument.

    Export argument configures data export to a text file in table format.

    Is defined by ``-x`` and ``--export``.

    Parameters
    ----------
    parser : `argparse.ArgumentParser <https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser>`_
        The argument parser to which add the export argument.
    """
    parser.add_argument('-x', '--export', help=
        "Export calculated values to a CSV file. Defaults to 'results.csv', alternatively, you can give a specific file name."
        , default=False, const='results.csv', nargs='?')


def imapUTF7Decode(st):
    """Returns utf7 encoded version of imap utf-7 string"""
    return st.decode('imap4-utf-7')


def fake_experimenter(label):
    """
    Marshal faked experimenter when id is -1
    Load omero.client.ui.menu.dropdown.everyone.label as username
    """
    return {'id': -1, 'omeName': label, 'firstName': label, 'lastName': ''}


def clean(threshold: float=0.001, channels: bool=False):
    """Simplify F-Curves by removing closely spaced keyframes

    :param threshold: Threshold
    :type threshold: float
    :param channels: Channels
    :type channels: bool
    """
    pass


def radians(data=None, name=None, attr=None, out=None, **kwargs):
    """Converts each element of the input array from degrees to radians.

    .. math::
       radians([0, 90, 180, 270, 360]) = [0, \\pi/2, \\pi, 3\\pi/2, 2\\pi]

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

       - radians(default) = default
       - radians(row_sparse) = row_sparse
       - radians(csr) = csr

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

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

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

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


def safe_list_get(l, idx, default):
    """fetch items safely from a list, if it isn't long enough return a default value"""
    try:
        return l[idx]
    except IndexError:
        return default


def value_to_bool(config_val, evar):
    """
    Massages the 'true' and 'false' strings to bool equivalents.

    :param str config_val: The env var value.
    :param EnvironmentVariable evar: The EVar object we are validating
        a value for.
    :rtype: bool
    :return: True or False, depending on the value.
    """
    if not config_val:
        return False
    if config_val.strip().lower() == 'true':
        return True
    else:
        return False


def to_datetime(string):
    """
    Not yet implemented.
    """
    raise NotImplementedError


def encode_root(v):
    """encodes a trie root into serialization"""
    return v


def _use_constant_crc_init(sym):
    """
    Return True if the inintial value is constant.
    """
    return sym['crc_init_value'] is not None


def relate(category_name, discriminator):
    """ Indicate an intent to relate this IIntrospectable with another
        IIntrospectable (the one associated with the ``category_name`` and
        ``discriminator``) during action execution.
        """


def security_group_rule_exists(security_group, values):
    """
    Indicates whether the specified rule values are already
    defined in the given security group.
    """
    for rule in security_group['rules']:
        is_duplicate = True
        keys = 'group_id', 'cidr', 'from_port', 'to_port', 'protocol'
        for key in keys:
            if rule.get(key) != values.get(key):
                is_duplicate = False
                break
        if is_duplicate:
            return True
    return False


@classmethod
def from_dict(cls, connection, data):
    """
        Returns a Chart object from a dictionary item,
        which is usually from AppOptics's API
        """
    obj = cls(connection, data['name'], id=data['id'], type=data.get('type',
        'line'), space_id=data.get('space_id'), streams=data.get('streams'),
        min=data.get('min'), max=data.get('max'), label=data.get('label'),
        use_log_yaxis=data.get('use_log_yaxis'), use_last_value=data.get(
        'use_last_value'), related_space=data.get('related_space'))
    return obj


def is_symmetric(sp):
    """ A SkewPartition is *symmetric* if its inner and outer shapes are symmetric.

    Return ``True`` if and only if the :class:`SkewPartition` ``sp`` is equal to its own conjugate.

    EXAMPLES::

        sage: SkewPartition([[], []]).is_symmetric()
        sage: True
        sage: SkewPartition([[1], []]).is_symmetric()
        sage: True
        sage: SkewPartition([[4, 3, 3, 1], [1]]).is_symmetric()
        sage: True
        sage: SkewPartition([[4, 3, 3, 1], [1, 1]]).is_symmetric()
        sage: False
        sage: SkewPartition([[5, 3, 3, 1], [2, 2]]).is_symmetric()
        sage: False

    ..  SEEALSO::

        :meth:`Partition.is_symmetric`
    """
    return sp == sp.conjugate()


def leftoverrow(sizes, x, y, dx, dy):
    """
    Compute relative x-axis start, y-axis start, width, and height of overall
    treemap area when remaining width exceeds remaining height (dx >= dy)

    :param sizes: List of values normalized with respect to overall height (dy)
        and width values (dx)
    :param x: Remaining area start point on treemap x-axis
    :param y: Remaining area start point on treemap y-axis
    :param dx: Remaining treemap width
    :param dy: Remaining treemap height
    :return: Tuple of remaining area dimensions

    """
    covered_area = sum(sizes)
    width = covered_area / dy
    leftover_x = x + width
    leftover_y = dy
    leftover_dx = dx - width
    leftover_dy = dy
    return leftover_x, leftover_y, leftover_dx, leftover_dy


@classmethod
def from_dict(cls, label=None, label2=None, icon=None, thumbnail=None, path
    =None, selected=None, info=None, properties=None, context_menu=None,
    replace_context_menu=False, is_playable=None, info_type='video',
    stream_info=None, **kwargs):
    """A ListItem constructor for setting a lot of properties not
        available in the regular __init__ method. Useful to collect all
        the properties in a dict and then use the **dct to call this
        method.
        """
    listitem = cls(label, label2, path=path)
    listitem.art = {'icon': icon, 'thumb': thumbnail, 'poster': kwargs.get(
        'poster'), 'banner': kwargs.get('banner'), 'fanart': kwargs.get(
        'fanart'), 'landscape': kwargs.get('landscape')}
    if selected is not None:
        listitem.selected = selected
    if info:
        listitem.set_info(info_type, info)
    if is_playable:
        listitem.playable = True
    if properties:
        if hasattr(properties, 'items'):
            properties = properties.items()
        for key, val in properties:
            listitem.set_property(key, val)
    if stream_info:
        for stream_type, stream_values in stream_info.items():
            listitem.add_stream_info(stream_type, stream_values)
    if context_menu:
        listitem.add_context_menu_items(context_menu, replace_context_menu)
    return listitem


def add_protocol(apps, schema_editor):
    """
    Adds the one and only projector
    """
    Protocol = apps.get_model('openslides_protocol', 'Protocol')
    Protocol.objects.bulk_create([Protocol(protocol=[])])


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


def asbytes(s):
    """Turns unicode into bytes, if needed.

    Assumes UTF-8.
    """
    if isinstance(s, bytes):
        return s
    else:
        return s.encode('utf-8')


def update(pic):
    """Update Picture pic's display window."""
    pic.update()


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 hide(unselected: bool=False):
    """Hide selected curves from Graph Editor view

    :param unselected: Unselected, Hide unselected rather than selected curves
    :type unselected: bool
    """
    pass


@staticmethod
def _get_parent_dn(dn):
    """
        Gets the dn of the parent object
        Meant to be overridden by inheriting classes.
        Raises exception if not overridden.

        :returns: string containing dn
        """
    return dn.split('/lnkcnt-')[0]


def has_void_args(argv):
    """
    Check if the command line has no arguments or only the --conf optional argument.
    """
    n_args = len(argv)
    return n_args == 1 or n_args == 2 and argv[1].startswith('--conf='
        ) or n_args == 3 and argv[1] == '--conf'


def uninstall(context):
    """Uninstall script"""


def prody_contacts(**kwargs):
    """Identify contacts of a target structure with one or more ligands.
    Contacting atoms (or extended subset of atoms, such as residues) are
    outputted in PDB file format.

    :arg target: target PDB identifier or filename

    :arg ligand: ligand PDB identifier(s) or filename(s)

    :arg select: atom selection string for target structure

    :arg radius: contact radius (Å), default is ``4.0``

    :arg extend: output same ``'residue'``, ``'chain'``, or ``'segment'`` along
        with contacting atoms

    :arg prefix: prefix for output file, default is *target* filename

    :arg suffix: output filename suffix, default is *ligand* filename"""
    import prody
    LOGGER = prody.LOGGER
    target = prody.parsePDB(kwargs['target'])
    title = kwargs.get('prefix') or target.getTitle()
    selstr = kwargs.get('select')
    if selstr:
        target = target.select(selstr)
    contacts = prody.Contacts(target)
    suffix = kwargs.get('suffix', '_contacts')
    extend = kwargs.get('extend')
    radius = float(kwargs.get('radius', 4.0))
    ligands = kwargs.get('ligand')
    if len(ligands) > 1:
        outfn = lambda fn: title + suffix + '_' + fn + '.pdb'
    else:
        outfn = lambda fn: title + suffix + '.pdb'
    for pdb in ligands:
        ligand = prody.parsePDB(pdb)
        sel = contacts(radius, ligand)
        if sel:
            LOGGER.info('{0} atoms from {1} contact {2}.'.format(len(sel),
                pdb, str(target)))
            if extend:
                sel = target.select('same ' + extend + ' as sel', sel=sel)
                LOGGER.info(
                    'Selection is extended to {0} atoms of the same {1}(s).'
                    .format(len(sel), extend))
            pdbfn = outfn(ligand.getTitle())
            LOGGER.info('Writing contacts into ' + pdbfn)
            prody.writePDB(pdbfn, sel)


@classmethod
def link_with_text(cls, text, nth=1):
    """Returns an XPath to find an HTML <a> containing the text in `text`."""
    return cls('(//a[normalize-space(.)=normalize-space("%s")])[%s]' % (
        text, nth))


def int2width(*n):
    """Find the max length among the int args and add a few for comma-1,000 {:,} repr"""
    w = max(map(len, map(str, n)))
    c = int((w - 1) / 3)
    return w + c


def strip_balanced_edge_parens(s):
    """
    Return a string where a pair of balanced leading and trailing parenthesis is
    stripped.

    For instance:
    >>> strip_balanced_edge_parens('(This is a super string)')
    'This is a super string'
    >>> strip_balanced_edge_parens('(This is a super string')
    '(This is a super string'
    >>> strip_balanced_edge_parens('This is a super string)')
    'This is a super string)'
    >>> strip_balanced_edge_parens('(This is a super (string')
    '(This is a super (string'
    >>> strip_balanced_edge_parens('(This is a super (string)')
    '(This is a super (string)'
    """
    if s.startswith('(') and s.endswith(')'):
        c = s[1:-1]
        if '(' not in c and ')' not in c:
            return c
    return s


def parse_port_text(port_text):
    """

    >>> slurm_ports = parse_port_text("8888/tcp -> 0.0.0.0:32769")
    >>> slurm_ports[8888]['host']
    '0.0.0.0'
    """
    ports = None
    if port_text is not None:
        ports = {}
        for line in port_text.strip().split('\n'):
            if ' -> ' not in line:
                raise Exception('Cannot parse host and port from line [%s]' %
                    line)
            tool, host = line.split(' -> ', 1)
            hostname, port = host.split(':')
            port = int(port)
            tool_p, tool_prot = tool.split('/')
            tool_p = int(tool_p)
            ports[tool_p] = dict(tool_port=tool_p, host=hostname, port=port,
                protocol=tool_prot)
    return ports


def fib(n):
    """Fibonacci example function

    Args:
      n (int): integer

    Returns:
      int: n-th Fibonacci number
    """
    assert n > 0
    a, b = 1, 1
    for i in range(n - 1):
        a, b = b, a + b
    return a


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

        :param OpenNoteSharedType val:
        :rtype: EventType
        """
    return cls('open_note_shared', val)


def set(id, value):
    """Change component associated to this id.
        """


def _disposition_init(cls, original_filename):
    """Construct and initialize a new FileDisposition object."""
    disp = cls()
    disp.original_filename = original_filename
    disp.canonical_filename = original_filename
    disp.source_filename = None
    disp.trace = False
    disp.reason = ''
    disp.file_tracer = None
    disp.has_dynamic_filename = False
    return disp


def flatten_appointment_search(appointment_search):
    """
    Expects a messy list of appointment searches record from paginate_search().
    Unpacks nested results into one, long manageable list.
    """
    out_data = []
    for i in appointment_search:
        if len(i) == 1:
            if len(i[0]['items']) == 1:
                out_data.append(i[0]['items'][0])
            else:
                for n, x in enumerate(i[0]['items']):
                    out_data.append(i[0]['items'][n])
        elif len(i) > 1:
            for x in i:
                for n, y in enumerate(x['items']):
                    out_data.append(x['items'][n])
    return out_data


def deregister_rds_db_instance(RdsDbInstanceArn=None):
    """
    Deregisters an Amazon RDS instance.
    See also: AWS API Documentation

    :example: response = client.deregister_rds_db_instance(
        RdsDbInstanceArn='string'
    )

    :type RdsDbInstanceArn: string
    :param RdsDbInstanceArn: [REQUIRED]
            The Amazon RDS instance's ARN.

    """
    pass


def default_thread_section(tooth_height: float, tooth_depth: float):
    """
    An isosceles triangle, tooth_height vertically, tooth_depth wide:
    """
    res = [[0, -tooth_height / 2], [tooth_depth, 0], [0, tooth_height / 2]]
    return res


def update_tilespecs(resolved, x):
    """update tilespecs with new solution

    Parameters
    ----------
    resolved : :class:`renderapi.resolvedtiles.ResolvedTiles`
        resolved tilespecs to update
    x : :class:`numpy.ndarray`
        results of solve
    """
    index = 0
    for i in range(len(resolved.tilespecs)):
        index += resolved.tilespecs[i].tforms[-1].from_solve_vec(x[index:, :])
    return


def remove_nodes(network, rm_nodes):
    """
    Create DataFrames of nodes and edges that do not include specified nodes.

    Parameters
    ----------
    network : pandana.Network
    rm_nodes : array_like
        A list, array, Index, or Series of node IDs that should *not*
        be saved as part of the Network.

    Returns
    -------
    nodes, edges : pandas.DataFrame

    """
    rm_nodes = set(rm_nodes)
    ndf = network.nodes_df
    edf = network.edges_df
    nodes_to_keep = ~ndf.index.isin(rm_nodes)
    edges_to_keep = ~(edf['from'].isin(rm_nodes) | edf['to'].isin(rm_nodes))
    return ndf.loc[nodes_to_keep], edf.loc[edges_to_keep]


def _get_all_motion_types(tr, motion_type):
    """ Get a dict of all motion types. First detrend """
    assert motion_type == 'velocity'
    tr.detrend('linear')
    acc = tr.copy()
    dis = tr.copy()
    dis.integrate()
    dis.detrend('linear')
    acc.differentiate()
    acc.detrend('linear')
    return dict(displacement=dis, velocity=tr, acceleration=acc)


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


def sameuuid(a: str, b: str) ->bool:
    """Compare two UUIDs."""
    return a and b and a.lower() == b.lower()


@classmethod
def personalInformationManager(cls):
    """
        Class method to get a reference to the personal information manager.

        @return reference to the personal information manager
            (PersonalInformationManager)
        """
    if cls._personalInformationManager is None:
        from .PersonalInformationManager import PersonalInformationManager
        cls._personalInformationManager = (PersonalInformationManager.
            PersonalInformationManager())
    return cls._personalInformationManager


def view_cancel():
    """Cancel show render view

    """
    pass


def quintic_bucket_warp(x, n, l1, l2, l3, x0, w1, w2, w3):
    """Warps the length scale with a piecewise quintic "bucket" shape.

    Parameters
    ----------
    x : float or array-like of float
        Locations to evaluate length scale at.
    n : non-negative int
        Derivative order to evaluate. Only first derivatives are supported.
    l1 : positive float
        Length scale to the left of the bucket.
    l2 : positive float
        Length scale in the bucket.
    l3 : positive float
        Length scale to the right of the bucket.
    x0 : float
        Location of the center of the bucket.
    w1 : positive float
        Width of the left side quintic section.
    w2 : positive float
        Width of the bucket.
    w3 : positive float
        Width of the right side quintic section.
    """
    x1 = x0 - w2 / 2.0 - w1 / 2.0
    x2 = x0 + w2 / 2.0 + w3 / 2.0
    x_shift_1 = 2.0 * (x - x1) / w1
    x_shift_3 = 2.0 * (x - x2) / w3
    if n == 0:
        return l1 * (x <= x1 - w1 / 2.0) + (0.5 * (l2 - l1) * (3.0 / 8.0 *
            x_shift_1 ** 5 - 5.0 / 4.0 * x_shift_1 ** 3 + 15.0 / 8.0 *
            x_shift_1) + (l1 + l2) / 2.0) * ((x > x1 - w1 / 2.0) & (x < x1 +
            w1 / 2.0)) + l2 * ((x >= x1 + w1 / 2.0) & (x <= x2 - w3 / 2.0)) + (
            0.5 * (l3 - l2) * (3.0 / 8.0 * x_shift_3 ** 5 - 5.0 / 4.0 *
            x_shift_3 ** 3 + 15.0 / 8.0 * x_shift_3) + (l2 + l3) / 2.0) * ((
            x > x2 - w3 / 2.0) & (x < x2 + w3 / 2.0)) + l3 * (x >= x2 + w3 /
            2.0)
    elif n == 1:
        return 0.5 * (l2 - l1) * (5.0 * 3.0 / 8.0 * x_shift_1 ** 4 - 3.0 *
            5.0 / 4.0 * x_shift_1 ** 2 + 15.0 / 8.0) / w1 * ((x > x1 - w1 /
            2.0) & (x < x1 + w1 / 2.0)) + 0.5 * (l3 - l2) * (5.0 * 3.0 /
            8.0 * x_shift_3 ** 4 - 3.0 * 5.0 / 4.0 * x_shift_3 ** 2 + 15.0 /
            8.0) / w3 * ((x > x2 - w3 / 2.0) & (x < x2 + w3 / 2.0))
    else:
        raise NotImplementedError('Only up to first derivatives are supported!'
            )


def circuit_built(circuit):
    """
        A circuit has been extended to all hops (usually 3 for user
        circuits).
        """


@classmethod
def refresh(cls, obj):
    """
        Updates the attributes attributes of the object passed by parameter.
        :param obj:
        :return:
        """
    cls.alchemy_db().session.refresh(cls, obj)


def braid(*iterables):
    """Return the elements of each iterator in turn until some is exhausted.
    This function is similar to the roundrobin example
    in itertools documentation.
    >>> a = iter([1,2,3,4])
    >>> b = iter(['a', 'b'])
    >>> c = iter([1,1,1,1,'a', 'c'])
    >>> d = iter([1,1,1,1,1,1])
    >>> list(braid(a, b, c, d))
    [1, 'a', 1, 1, 2, 'b', 1, 1]
    """
    for itbl in zip(*iterables):
        for it in itbl:
            yield it


def ReserveRate():
    """Valuation Reserve Rate per Sum Assured"""
    return None


def update_schedule_items(*args, **kw):
    """We save all the schedule items associated with this slot, so
       the last_update time is updated to reflect any changes to the
       timing of the slots"""
    slot = kw.pop('instance', None)
    if not slot:
        return
    for item in slot.scheduleitem_set.all():
        item.save(update_fields=['last_updated'])
    next_slot = slot.slot_set.all()
    if next_slot.count():
        for item in next_slot[0].scheduleitem_set.all():
            item.save(update_fields=['last_updated'])


def edge_loops_from_edges(mesh, edges=None):
    """closed loops have matching start and end values.

    """
    pass


@staticmethod
def strip_prefix(path, locale):
    """
        Strips the locale prefix from the path. This static method is used to
        recalculate the request path that should be passed to Bottle. The
        return value of this method replaces the ``PATH_INFO`` key in the
        environment dictionary, and the original path is saved in
        ``ORIGINAL_PATH`` key.

        :param path:    request path
        :param locale:  selected locale
        :returns:       request path without the locale prefix
        """
    return path[len(locale) + 1:]


def graft(coll, branch, index):
    """Graft list branch into coll at index
    """
    pre = coll[:index]
    post = coll[index:]
    ret = pre + branch + post
    return ret


def removeBase(event):
    """ Make Zope not to inject a <base> tag into the returned HTML
    https://dev.plone.org/ticket/13705
    """
    event.request.response.base = None


def pem2b64(pem):
    """
    Strip the header and footer of a .pem. BEWARE: Won't work with explanatory
    strings above the header.
    @params pem A string representing the pem
    """
    pem = pem.decode('ascii')
    return '\n'.join(pem.strip().split('\n')[1:-1])


def _convertbits(data, frombits, tobits, pad=True):
    """General power-of-2 base conversion."""
    acc = 0
    bits = 0
    ret = bytearray()
    maxv = (1 << tobits) - 1
    max_acc = (1 << frombits + tobits - 1) - 1
    for value in data:
        acc = (acc << frombits | value) & max_acc
        bits += frombits
        while bits >= tobits:
            bits -= tobits
            ret.append(acc >> bits & maxv)
    if pad and bits:
        ret.append(acc << tobits - bits & maxv)
    return ret


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

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

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


def _a_encode_list(values, mapping):
    """
    [1,2,3] --> ['3', 'l', '1', 'i', '1', '1', 'i', '2', '1', 'i', '3']
    """
    assert isinstance(values, list), 'VALUE has invalid type: %s' % type(values
        )
    encoded = [str(len(values)).encode('UTF-8'), b'l']
    extend = encoded.extend
    for value in values:
        extend(mapping[type(value).__name__](value, mapping))
    return encoded


def __substract(I, M):
    """Substract the image M to the image of I. See
    https://docs.gimp.org/en/gimp-concepts-layer-modes.html
    and
    https://github.com/jamieowen/glsl-blend/blob/master/substract.glsl
    Renormalized images are assumed, i.e. colors range = [0, 1]

    Parameters
    ----------
    I : np.ndarray
        Left side operator
    M : np.ndarray
        Right side operator

    Returns
    -------
    E : np.ndarray
        Substracted image
    """
    E = I - M
    E[E < 0] = 0
    return E


def plotConstraints(control, axis=None, show=True):
    """
    Plots constraints used for coil current control

    axis     - Specify the axis on which to plot
    show     - Call matplotlib.pyplot.show() before returning

    """
    import matplotlib.pyplot as plt
    if axis is None:
        fig = plt.figure()
        axis = fig.add_subplot(111)
    for r, z in control.xpoints:
        axis.plot(r, z, 'bx')
    if control.xpoints:
        axis.plot([], [], 'bx', label='X-point constraints')
    for r1, z1, r2, z2 in control.isoflux:
        axis.plot([r1, r2], [z1, z2], ':b^')
    if control.isoflux:
        axis.plot([], [], ':b^', label='Isoflux constraints')
    if show:
        plt.legend()
        plt.show()
    return axis


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

        :param ShowcaseTrashedType val:
        :rtype: EventType
        """
    return cls('showcase_trashed', val)


def next_instruction_is_function_or_class(lines):
    """Is the first non-empty, non-commented line of the cell either a function or a class?"""
    for i, line in enumerate(lines):
        if not line.strip():
            if i > 0 and not lines[i - 1].strip():
                return False
            continue
        if line.startswith('def ') or line.startswith('class '):
            return True
        if line.startswith(('#', '@', ' ')):
            continue
        return False
    return False


def unique_name(key: 'bpy.context.object', name: str, name_dict: dict,
    name_max=-1, clean_func=None, sep: str='.'):
    """Helper function for storing unique names which may have special characters stripped and restricted to a maximum length.

    :param key: unique item this name belongs to, name_dict[key] will be reused when available. This can be the object, mesh, material, etc instance its self.
    :type key: 'bpy.context.object'
    :param name: The name used to create a unique value in name_dict.
    :type name: str
    :param name_dict: This is used to cache namespace to ensure no collisions occur, this should be an empty dict initially and only modified by this function.
    :type name_dict: dict
    :param clean_func: Function to call on name before creating a unique value.
    :param sep: Separator to use when between the name and a number when a duplicate name is found.
    :type sep: str
    """
    pass


def delitem(a, b):
    """Same as del a[b]."""
    del a[b]


@staticmethod
def backderivative_at(sub_expr1, sub_expr2, var):
    """
        calculate 1st derivative of var using back propagation

        INPUTS
        =======
        sub_expr1: expression or constant
        sub_expr2: expression or constant
        var: variable of interest

        RETURNS
        ========
        derivative of var with respect to sub_expr1
        """
    if var == sub_expr1:
        return 1
    if var == sub_expr2:
        return -1


def int_from_32bit_array(val):
    """Converts an integer from a 32 bit bytearray

    :param val: the value to convert to an int
    :type val: int

    :rtype: int
    """
    rval = 0
    for fragment in bytearray(val):
        rval <<= 8
        rval |= fragment
    return rval


def setpnumber_connect(postnrid):
    """Add onblur handler that connects the above event handler."""
    return "connect($('%s'), 'onblur', setpnumber);" % postnrid


def test_view(test, urlconf, user):
    """
    Run a view test. Add in *args, **kwargs if appropriate.
    """
    args = [] if 'args' not in test.func_code.co_varnames else urlconf.args
    kwargs = {
        } if 'kwargs' not in test.func_code.co_varnames else urlconf.kwargs
    return test(user, *args, **kwargs)


def config2(input, intype='int'):
    """NIRCam CONFIG2 (0x4011) Register

    Return a dictionary of configuration parameters depending on the
    value of CONFIG2 register (4011).

    Parameters
    ----------
    input : int, str
        Value of CONFIG2, nominally as an int. Binary and Hex values
        can also be passed as strings.
    intype: str
        Input type (int, hex, or bin) for integer, hex, string,
        or binary string.

    """
    if 'hex' in intype:
        if '0x' in input:
            input = int(input, 0)
        else:
            input = int(input, 16)
    if 'bin' in intype:
        if '0b' in input:
            input = int(input, 0)
        else:
            input = int(input, 2)
    input = '{0:016b}'.format(input)
    nff_dict = {'000': 1, '001': 4, '010': 16, '011': 64, '100': 256, '101':
        512, '110': 1024, '111': 2048}
    input2 = input[::-1]
    d = {}
    d['00_window_vert'] = True if bool(int(input2[0])) else False
    d['01_window_horz'] = True if bool(int(input2[1])) else False
    d['02_global_reset'] = True if bool(int(input2[2])) else False
    d['03_rows_reset'] = True if bool(int(input2[3])) else False
    d['04_rows_nff'] = nff_dict.get(input2[4:7][::-1])
    d['07_idle_window'] = True if bool(int(input2[7])) else False
    d['08_pa_reset'] = 'row' if bool(int(input2[8])) else 'frame'
    d['09_perm_reset'] = True if bool(int(input2[9])) else False
    d['10_single_step'] = True if bool(int(input2[10])) else False
    d['11_test_patt'] = True if bool(int(input2[11])) else False
    d['12_fgs_wind'] = True if bool(int(input2[12])) else False
    d['13_power_idl'] = True if bool(int(input2[13])) else False
    d['14_power_drop'] = True if bool(int(input2[14])) else False
    d['15_pa_reset'] = 'int' if bool(int(input2[15])) else 'frame'
    return d


def loadFile(filename, reload=False, policy=u''):
    """Return an IModel as contained in the given XML file, which is read
        relative to the current module (unless it is an absolute path).

        If reload is True, reload a schema even if it's cached. If policy
        is given, it can be used to select a custom schema parsing policy.
        Policies must be registered as named utilities providing
        ISchemaPolicy.
        """


def test(isamAppliance, userid, password, check_mode=False, force=False):
    """
    Testing the management authentication
    """
    ret_obj = isamAppliance.invoke_post('Testing the management authentication'
        , '/isam/management_authentication/', {'user': userid, 'password':
        password})
    ret_obj['changed'] = False
    return ret_obj


def _numbery(val):
    """Returns True if a value looks like a number."""
    try:
        float(val)
        return True
    except (ValueError, TypeError):
        return False


def cast_str_to_int_float_bool_or_str(str_):
    """
    Convert str_ into the following data types (return the first successful): int, float, bool, or str.
    :param str_: str;
    :return: int, float, bool, or str;
    """
    value = str_.strip()
    for var_type in [int, float]:
        try:
            converted_var = var_type(value)
            return converted_var
        except ValueError:
            pass
    if value == 'True':
        return True
    elif value == 'False':
        return False
    return str(value)


def set_labels(var_name, labels):
    """Set labels to a var."""
    query = ''
    for label in labels:
        query += 'SET {}:{}\n'.format(var_name, label)
    return query


@classmethod
def from_path(cls, path, parent=None, meta=None):
    """
        Given a :class:`pathlib.Path`, create a Node from that path as well as
        any children. Children are loaded in Unicode codepoint order - this
        order is preserved in ``Node.children`` if you're unsure what that
        means.

        If the path is not a file or a dir, an :class:`AssertionError` is
        raised

        :param path:
            A :class:`pathlib.Path` that is either the ``content_path`` or a
            child of it.
        :param parent:
            Either another :class:`Node` or ``None``
        :param meta:
            A dict-like object that will be passed to a :class:`Config`
            instance
        """
    assert path.is_file() or path.is_dir()
    node = cls(path, parent=parent, meta=meta)
    if path.is_dir():
        children = []
        dir_files = sorted(path.iterdir(), key=lambda p: p.name)
        for child in dir_files:
            if child.name in cls._meta_names and child.is_file():
                with child.open() as co:
                    node.meta.load(co)
            else:
                children.append(child)
        for child in children:
            ignored = False
            globs = node.meta.get('ignore', [])
            if not isinstance(globs, (list, tuple)):
                globs = [globs]
            for glob in globs:
                if child in path.glob(glob):
                    ignored = True
                    break
            if not ignored:
                cls.from_path(child, node)
    return node


@classmethod
def open_dialog(cls, parent, app, connection):
    """
        Certify and identity
        :param sakia.gui.component.controller.ComponentController parent: the parent
        :param sakia.app.Application app: the application
        :param sakia.data.entities.Connection connection: the connection certifying the identity
        :return:
        """
    dialog = cls.create(parent, app, connection=connection)
    dialog.handle_next_step(init=True)
    return dialog.exec()


def edge_rotate(use_ccw: bool=False):
    """Rotate selected edge or adjoining faces

    :param use_ccw: Counter Clockwise
    :type use_ccw: bool
    """
    pass


def print_bold(msg, end='\n'):
    """Convenience function to print a message in bold style

    Optionally you can also specify how the bold text should end. By default
    it ends with a new line character.

    :arg msg: Message to be converted to bold style
    :arg end: Tell how the printed string should end (newline, space etc)
    """
    print('\x1b[1m' + msg + '\x1b[0m', end=end)


def describe_orderable_replication_instances(MaxRecords=None, Marker=None):
    """
    Returns information about the replication instance types that can be created in the specified region.
    See also: AWS API Documentation

    :example: response = client.describe_orderable_replication_instances(
        MaxRecords=123,
        Marker='string'
    )

    :type MaxRecords: integer
    :param MaxRecords: The maximum number of records to include in the response. If more records exist than the specified MaxRecords value, a pagination token called a marker is included in the response so that the remaining results can be retrieved.
            Default: 100
            Constraints: Minimum 20, maximum 100.

    :type Marker: string
    :param Marker: An optional pagination token provided by a previous request. If this parameter is specified, the response includes only records beyond the marker, up to the value specified by MaxRecords .

    :rtype: dict
    :return: {
        'OrderableReplicationInstances': [
            {
                'EngineVersion': 'string',
                'ReplicationInstanceClass': 'string',
                'StorageType': 'string',
                'MinAllocatedStorage': 123,
                'MaxAllocatedStorage': 123,
                'DefaultAllocatedStorage': 123,
                'IncludedAllocatedStorage': 123
            },
        ],
        'Marker': 'string'
    }

    """
    pass


def cfs_to_mmday(cfs, SA_sq_ft):
    """
    cfs: (float) flow rate in cubic feet per second
    SA_sq_ft: (float) surface area in square feet
    """
    return cfs / SA_sq_ft * 24 * 60 * 60 * 304.8


def instance(cls, *args, **kwargs):
    """Alternate constructor that returns a fresh instance"""
    return type.__call__(cls, *args, **kwargs)


def head_and_count(iterator):
    """Print the first 10 and store the first 100000 solutions."""
    count = 0
    res = []
    for _ in iterator:
        res.append(_)
        count += 1
        if count > 100000:
            print('More than 100k solutions.')
            break
        if count < 10:
            print(_)
    else:
        print('%d solutions.' % count)
    return res


def get_input(prompt='', default=None, input=input):
    """Get user input with an optional default value."""
    if default is not None:
        ri = input('{} [{}]> '.format(prompt, default))
        if not ri:
            return default
        else:
            return ri
    else:
        return input('{}> '.format(prompt))


def unquote_header_value(value):
    """Unquotes a header value.

    This does not use the real unquoting but what browsers are actually
    using for quoting.

    :param value: the header value to unquote.
    """
    if value and value[0] == value[-1] == '"':
        value = value[1:-1]
    return value


def set_solution_scale(distance: float=0.0):
    """Set object solution scale using distance between two selected tracks

    :param distance: Distance, Distance between selected tracks
    :type distance: float
    """
    pass


def valfilter(predicate, d, factory=dict):
    """ Filter items in dictionary by values that are true.

    >>> iseven = lambda x: x % 2 == 0
    >>> d = {1: 2, 2: 3, 3: 4, 4: 5}
    >>> valfilter(iseven, d)
    {1: 2, 3: 4}

    See Also:
        valfilterfalse
    """
    rv = factory()
    for k, v in d.items():
        if predicate(v):
            rv[k] = v
    return rv


def mapped_columns(*column_maps):
    """
    Given any number of column_maps
    return a list of unique column names
    """
    result = set()
    for column_map in column_maps:
        result |= set(column_map.values())
    return list(result)


def count_pending_activity_tasks(domain=None, taskList=None):
    """
    Returns the estimated number of activity tasks in the specified task list. The count returned is an approximation and is not guaranteed to be exact. If you specify a task list that no activity task was ever scheduled in then 0 will be returned.
    Access Control
    You can use IAM policies to control this action's access to Amazon SWF resources as follows:
    If the caller does not have sufficient permissions to invoke the action, or the parameter values fall outside the specified constraints, the action fails. The associated event attribute's cause parameter will be set to OPERATION_NOT_PERMITTED. For details and example IAM policies, see Using IAM to Manage Access to Amazon SWF Workflows .
    See also: AWS API Documentation

    :example: response = client.count_pending_activity_tasks(
        domain='string',
        taskList={
            'name': 'string'
        }
    )

    :type domain: string
    :param domain: [REQUIRED]
            The name of the domain that contains the task list.

    :type taskList: dict
    :param taskList: [REQUIRED]
            The name of the task list.
            name (string) -- [REQUIRED]The name of the task list.

    :rtype: dict
    :return: {
        'count': 123,
        'truncated': True|False
    }

    :returns:
    domain (string) -- [REQUIRED]
    The name of the domain that contains the task list.

    taskList (dict) -- [REQUIRED]
    The name of the task list.

    name (string) -- [REQUIRED]The name of the task list.

    """
    pass


def utf8ize(x):
    """
    Converts to utf8 if non-empty
    :param x:
    :return:
    """
    if x is None:
        return None
    return x.encode('utf-8')