@staticmethod
def hint_check_unbalanced_parens(ans, term):
    """
        ans = student answer
        term = ignored

        Returns True if parentheses are unbalanced
        """
    stack = []
    pushChars, popChars = '({[', ')}]'
    for c in ans:
        if c in pushChars:
            stack.append(c)
        elif c in popChars:
            if not len(stack):
                return True
            else:
                stackTop = stack.pop()
                balancingBracket = pushChars[popChars.index(c)]
                if stackTop != balancingBracket:
                    return True
    return len(stack) > 0


def is_cve_tracker(bug_obj):
    """ Check if a bug is a CVE tracker.

    A CVE tracker bug must have `SecurityTracking` and `Security` keywords.

    :param bug_obj: bug object
    :returns: True if the bug is a CVE tracker.
    """
    return ('SecurityTracking' in bug_obj.keywords and 'Security' in
        bug_obj.keywords)


@classmethod
def _preprocessSource(klass, source, file, preprocessors):
    """Iterates through the .compile() classmethod's preprocessors argument
        and pipes the source code through each each preprocessor.

        It returns the tuple (source, file) which is then used by
        Template.compile to finish the compilation.
        """
    if not isinstance(preprocessors, (list, tuple)):
        preprocessors = [preprocessors]
    for preprocessor in preprocessors:
        preprocessor = klass._normalizePreprocessorArg(preprocessor)
        source, file = preprocessor.preprocess(source, file)
    return source, file


@staticmethod
def minimumRequiredVersion():
    """
		Returns the minimum required version of Windows 10 / Windows Server, which is release 1607

		(1607 is the first build to support Windows containers, as per:
		<https://docs.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/version-compatibility>)
		"""
    return '10.0.14393'


def get_stroke_glide_indices(A_g_hf, fs_a, J, t_max):
    """Get stroke and glide indices from high-pass accelerometer data

    Args
    ----
    A_g_hf: 1-D ndarray
        Animal frame triaxial accelerometer matrix at sampling rate fs_a.

    fs_a: int
        Number of accelerometer samples per second

    J: float
        Frequency threshold for detecting a fluke stroke in m/s^2.  If J is not
        given, fluke strokes will not be located but the rotations signal (pry)
        will be computed.

    t_max: int
        Maximum duration allowable for a fluke stroke in seconds.  A fluke
        stroke is counted whenever there is a cyclic variation in the pitch
        deviation with peak-to-peak magnitude greater than +/-J and consistent
        with a fluke stroke duration of less than t_max seconds, e.g., for
        Mesoplodon choose t_max=4.

    Returns
    -------
    GL: 1-D ndarray
        Matrix containing the start time (first column) and end time (2nd
        column) of any glides (i.e., no zero crossings in t_max or more
        seconds). Times are in seconds.

    Note
    ----
    If no J or t_max is given, J=[], or t_max=[], GL returned as None
    """
    import numpy
    from . import dsp
    if A_g_hf.ndim > 1:
        raise IndexError(
            'A_g_hf multidimensional: Glide index determination requires 1-D acceleration array as input'
            )
    n_max = t_max * fs_a
    zc = dsp.findzc(A_g_hf, J, n_max / 2)
    ind = numpy.where(zc[1:, (0)] - zc[0:-1, (1)] > n_max)[0]
    gl_ind = numpy.vstack([zc[ind, 0] - 1, zc[ind + 1, 1] + 1]).T
    gl_mean_idx = numpy.round(numpy.mean(gl_ind, 1)).astype(int)
    gl_ind = numpy.round(gl_ind).astype(int)
    for i in range(len(gl_mean_idx)):
        col = range(gl_mean_idx[i], gl_ind[i, 0], -1)
        test = numpy.where(numpy.isnan(A_g_hf[col]))[0]
        if test.size != 0:
            gl_mean_idx[i] = numpy.nan
            gl_ind[i, 0] = numpy.nan
            gl_ind[i, 1] = numpy.nan
        else:
            over_J1 = numpy.where(abs(A_g_hf[col]) >= J)[0][0]
            gl_ind[i, 0] = gl_mean_idx[i] - over_J1 + 1
            col = range(gl_mean_idx[i], gl_ind[i, 1])
            over_J2 = numpy.where(abs(A_g_hf[col]) >= J)[0][0]
            gl_ind[i, 1] = gl_mean_idx[i] + over_J2 - 1
    GL = gl_ind
    GL = GL[(numpy.where(GL[:, (1)] - GL[:, (0)] > n_max / 2)[0]), :]
    return GL


def reject_assignment(AssignmentId=None, RequesterFeedback=None):
    """
    The RejectAssignment operation rejects the results of a completed assignment.
    You can include an optional feedback message with the rejection, which the Worker can see in the Status section of the web site. When you include a feedback message with the rejection, it helps the Worker understand why the assignment was rejected, and can improve the quality of the results the Worker submits in the future.
    Only the Requester who created the HIT can reject an assignment for the HIT.
    See also: AWS API Documentation

    :example: response = client.reject_assignment(
        AssignmentId='string',
        RequesterFeedback='string'
    )

    :type AssignmentId: string
    :param AssignmentId: [REQUIRED]
            The ID of the assignment. The assignment must correspond to a HIT created by the Requester.

    :type RequesterFeedback: string
    :param RequesterFeedback: A message for the Worker, which the Worker can see in the Status section of the web site.

    :rtype: dict
    :return: {}

    :returns:
    (dict) --

    """
    pass


def SizeForOutput(size):
    """Return the size suitable for output in a SQL statement. Note that a
       negative size is assumed to be unlimited."""
    if size < 0:
        return 'unlimited'
    kilobytes, remainder = divmod(size, 1024)
    if not remainder:
        megabytes, remainder = divmod(kilobytes, 1024)
        if not remainder:
            return '%gm' % megabytes
        else:
            return '%gk' % kilobytes
    else:
        return '%g' % size


@staticmethod
def storageFormat(data):
    """ convert data from format returned by get, to raw database format
          this is the placeholder for routines specific to derived classes"""
    return data


def describe_servers(ServerName=None, NextToken=None, MaxResults=None):
    """
    Lists all configuration management servers that are identified with your account. Only the stored results from Amazon DynamoDB are returned. AWS OpsWorks for Chef Automate does not query other services.
    This operation is synchronous.
    A ResourceNotFoundException is thrown when the server does not exist. A ValidationException is raised when parameters of the request are not valid.
    See also: AWS API Documentation

    :example: response = client.describe_servers(
        ServerName='string',
        NextToken='string',
        MaxResults=123
    )

    :type ServerName: string
    :param ServerName: Describes the server with the specified ServerName.

    :type NextToken: string
    :param NextToken: NextToken is a string that is returned in some command responses. It indicates that not all entries have been returned, and that you must run at least one more request to get remaining items. To get remaining results, call DescribeServers again, and assign the token from the previous results as the value of the nextToken parameter. If there are no more results, the response object's nextToken parameter value is null . Setting a nextToken value that was not returned in your previous results causes an InvalidNextTokenException to occur.

    :type MaxResults: integer
    :param MaxResults: To receive a paginated response, use this parameter to specify the maximum number of results to be returned with a single call. If the number of available results exceeds this maximum, the response includes a NextToken value that you can assign to the NextToken request parameter to get the next set of results.

    :rtype: dict
    :return: {
        'Servers': [
            {
                'AssociatePublicIpAddress': True|False,
                'BackupRetentionCount': 123,
                'ServerName': 'string',
                'CreatedAt': datetime(2015, 1, 1),
                'CloudFormationStackArn': 'string',
                'DisableAutomatedBackup': True|False,
                'Endpoint': 'string',
                'Engine': 'string',
                'EngineModel': 'string',
                'EngineAttributes': [
                    {
                        'Name': 'string',
                        'Value': 'string'
                    },
                ],
                'EngineVersion': 'string',
                'InstanceProfileArn': 'string',
                'InstanceType': 'string',
                'KeyPair': 'string',
                'MaintenanceStatus': 'SUCCESS'|'FAILED',
                'PreferredMaintenanceWindow': 'string',
                'PreferredBackupWindow': 'string',
                'SecurityGroupIds': [
                    'string',
                ],
                'ServiceRoleArn': 'string',
                'Status': 'BACKING_UP'|'CONNECTION_LOST'|'CREATING'|'DELETING'|'MODIFYING'|'FAILED'|'HEALTHY'|'RUNNING'|'RESTORING'|'SETUP'|'UNDER_MAINTENANCE'|'UNHEALTHY'|'TERMINATED',
                'StatusReason': 'string',
                'SubnetIds': [
                    'string',
                ],
                'ServerArn': 'string'
            },
        ],
        'NextToken': 'string'
    }

    :returns:
    CHEF_PIVOTAL_KEY : A base64-encoded RSA private key that is generated by AWS OpsWorks for Chef Automate. This private key is required to access the Chef API.
    CHEF_STARTER_KIT : A base64-encoded ZIP file. The ZIP file contains a Chef starter kit, which includes a README, a configuration file, and the required RSA private key. Save this file, unzip it, and then change to the directory where you've unzipped the file contents. From this directory, you can run Knife commands.

    """
    pass


def _get_representation_attrs(frame, units, kwargs):
    """
    Find instances of the "representation attributes" for specifying data
    for this frame.  Pop them off of kwargs, run through the appropriate class
    constructor (to validate and apply unit), and put into the output
    valid_kwargs.  "Representation attributes" are the frame-specific aliases
    for the underlying data values in the representation, e.g. "ra" for "lon"
    for many equatorial spherical representations, or "w" for "x" in the
    cartesian representation of Galactic.

    This also gets any *differential* kwargs, because they go into the same
    frame initializer later on.
    """
    frame_attr_names = frame.representation_component_names.keys()
    repr_attr_classes = frame.representation_type.attr_classes.values()
    valid_kwargs = {}
    for frame_attr_name, repr_attr_class, unit in zip(frame_attr_names,
        repr_attr_classes, units):
        value = kwargs.pop(frame_attr_name, None)
        if value is not None:
            valid_kwargs[frame_attr_name] = repr_attr_class(value, unit=unit)
    differential_type = frame.differential_type
    if differential_type is not None:
        for frame_name, repr_name in frame.get_representation_component_names(
            's').items():
            diff_attr_class = differential_type.attr_classes[repr_name]
            value = kwargs.pop(frame_name, None)
            if value is not None:
                valid_kwargs[frame_name] = diff_attr_class(value)
    return valid_kwargs


def _truncate_middle(string, max_length):
    """
    Truncate a string to a maximum length, replacing the skipped middle section
    with an ellipsis.

    Parameters
    ----------
    string : str
        The string to optionally truncate
    max_length : int
        The maximum length
    """
    if len(string) <= max_length:
        return string
    n2 = max_length // 2 - 3
    n1 = max_length - n2 - 3
    return '...'.join((string[:n1], string[-n2:]))


def get_class_name(obj):
    """Get class name in dot separete notation

        >>> from datetime import datetime
        >>> obj = datetime.datetime(2000, 1, 1)
        >>> get_class_name(obj) -> "datetime.datetime"

        >>> from collections import deque
        >>> obj = deque([1, 2, 3])
        >>> get_class_name(obj) -> "collections.deque"
    """
    return obj.__class__.__module__ + '.' + obj.__class__.__name__


@staticmethod
def _encode_bool(_value):
    """Encode a boolean option value"""
    return b''


def lfu_key_func(x):
    """
    Least Frequently Used key function.

    :param x: (:class:`~hazelcast.near_cache.DataRecord`)
    :return: (int), access hit count of x.
    """
    return x.access_hit


def molformat(fname: str) ->str:
    """
    Extract an OpenBabel-friendly format from file name.

    Parameters
    ----------
    fname : str
        File name

    Returns
    -------
    str
        File extension in an OpenBabel-friendly format

    Notes
    -----
    File types in OpenBabel do not always correspond to the file extension. This
    function converts the file extension to an OpenBabel file type.

    The following table shows the different conversions performed by this function:

    ========= =========
    Extension File Type
    --------- ---------
    xyz       XYZ
    ========= =========
    """
    ext = format(fname)
    if ext == 'xyz':
        ext = ext.upper()
    return ext


def build_result_string(port, target, should_be_blocked, was_blocked):
    """
    Builds and returns a test result string
    """
    was_successful = should_be_blocked == was_blocked
    title = 'Test %s:%s%s%s' % (target, '-' if should_be_blocked else '',
        port, ' succeeded' if was_successful else ' failed')
    details = (
        'Could%s reach %s on port %s. Expected target to %sbe reachable' %
        ("n't" if was_blocked else '', target, port, 'not ' if
        should_be_blocked else ''))
    return '%s\n%s' % (title, details)


@classmethod
def verify(cls, clear_password, hashed_password):
    """True if `clear_password` and `hashed_password` match"""
    try:
        salt, _ = hashed_password.split(cls.sep, 1)
    except Exception:
        return False
    else:
        return cls.Hasher.compare_hexdigest(hashed_password, cls.hashed(
            clear_password, salt))


def save_homefile():
    """Make the current file the default .blend file

    """
    pass


@staticmethod
def is_token_authenticated(handler):
    """Is the request token-authenticated?"""
    if getattr(handler, '_cached_hub_user', None) is None:
        handler.get_current_user()
    return getattr(handler, '_token_authenticated', False)


def channels_click(extend: bool=False, children_only: bool=False):
    """Handle mouse-clicks over animation channels

    :param extend: Extend Select
    :type extend: bool
    :param children_only: Select Children Only
    :type children_only: bool
    """
    pass


def date():
    """Return date object with same year, month and day."""


def to_boolean(bool_):
    """
    Convert to boolean from String

    Return: a boolean value

    If the string is not a representation of a boolean value, the method returns False.
    """
    if bool_ is None:
        return False
    if bool_ is True or bool_ is False:
        return bool_
    else:
        return bool_[0].upper() == 'T' or bool_[0].upper() == 'Y'


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


def fmt(template, *args, **kargs):
    """
    Guarantee that template is always unicode, as embedding unicode in ascii
    can cause errors.
    """
    return str(template).format(*args, **kargs)


def to_bool(s):
    """
    Convert string `s` into a boolean.

    `s` can be 'true', 'True', 1, 'false', 'False', 0.

    Examples:

    >>> to_bool("true")
    True
    >>> to_bool("0")
    False
    >>> to_bool(True)
    True
    """
    if isinstance(s, bool):
        return s
    elif s.lower() in ['true', '1']:
        return True
    elif s.lower() in ['false', '0']:
        return False
    else:
        raise ValueError("Can't cast '%s' to bool" % s)


def ut(cd, dp, rhog, rhos):
    """
    Calculate terminal velocity of a single particle based on Equation 28 on
    page 80 in the Kunii and Levenspiel book [1]_ where :math:`C_D` is an
    experimentally determined drag coefficient.

    .. math:: u_t = \\left( \\frac{4 d_p\\, (\\rho_s - \\rho_g) g}{3 \\rho_g\\, C_D} \\right)^{1/2}

    Parameters
    ----------
    cd : float
        Drag coefficient [-]
    dp : float
        Diameter of particle [m]
    rhog : float
        Density of gas [kg/m^3]
    rhos : float
        Density of solid [kg/m^3]

    Returns
    -------
    ut : float
        Terminal velocity [m/s]

    Example
    -------
    >>> ut(11.6867, 0.00016, 1.2, 2600)
    0.6227

    References
    ----------
    .. [1] Daizo Kunii and Octave Levenspiel. Fluidization Engineering.
           Butterworth-Heinemann, 2nd edition, 1991.
    """
    g = 9.81
    tm1 = 4 * dp * (rhos - rhog) * g
    tm2 = 3 * rhog * cd
    ut = (tm1 / tm2) ** (1 / 2)
    return ut


def format_datetime(date):
    """
    Convert datetime to UTC ISO 8601
    """
    if date.utcoffset() is None:
        return date.isoformat() + 'Z'
    utc_offset_sec = date.utcoffset()
    utc_date = date - utc_offset_sec
    utc_date_without_offset = utc_date.replace(tzinfo=None)
    return utc_date_without_offset.isoformat() + 'Z'


def comma_delimited(s):
    """Split a comma-delimited string."""
    for part in s.split(','):
        stripped = part.strip()
        if stripped:
            yield stripped


@staticmethod
def send_get_state(protocol):
    """
        Prepare and send get_state.

        :param protocol:
        """
    request_data = {'method': 'get_state'}
    protocol.send_data(request_data)


def _retrieve_linked_keypad_battery_state(detail):
    """Get the latest state of the sensor."""
    if detail.keypad is None:
        return None
    return detail.keypad.battery_percentage


def rgb2hsv(red, green, blue):
    """Transform a RGB color to a HSV color."""
    cmax = max(red, green, blue)
    cmin = min(red, green, blue)
    delta = cmax - cmin
    if delta == 0:
        hue = 0
    elif cmax == red:
        hue = 60 * ((green - blue) / delta % 6)
    elif cmax == green:
        hue = 60 * ((blue - red) / delta + 2)
    elif cmax == blue:
        hue = 60 * ((red - green) / delta + 4)
    saturation = 0 if delta == 0 else delta / cmax
    return hue, saturation, cmax


def execsitecustomize():
    """Run custom site specific code, if available."""
    try:
        import sitecustomize
    except ImportError:
        pass


def create_change_set(StackName=None, TemplateBody=None, TemplateURL=None,
    UsePreviousTemplate=None, Parameters=None, Capabilities=None,
    ResourceTypes=None, RoleARN=None, NotificationARNs=None, Tags=None,
    ChangeSetName=None, ClientToken=None, Description=None, ChangeSetType=None
    ):
    """
    Creates a list of changes that will be applied to a stack so that you can review the changes before executing them. You can create a change set for a stack that doesn't exist or an existing stack. If you create a change set for a stack that doesn't exist, the change set shows all of the resources that AWS CloudFormation will create. If you create a change set for an existing stack, AWS CloudFormation compares the stack's information with the information that you submit in the change set and lists the differences. Use change sets to understand which resources AWS CloudFormation will create or change, and how it will change resources in an existing stack, before you create or update a stack.
    To create a change set for a stack that doesn't exist, for the ChangeSetType parameter, specify CREATE . To create a change set for an existing stack, specify UPDATE for the ChangeSetType parameter. After the CreateChangeSet call successfully completes, AWS CloudFormation starts creating the change set. To check the status of the change set or to review it, use the  DescribeChangeSet action.
    When you are satisfied with the changes the change set will make, execute the change set by using the  ExecuteChangeSet action. AWS CloudFormation doesn't make changes until you execute the change set.
    See also: AWS API Documentation

    :example: response = client.create_change_set(
        StackName='string',
        TemplateBody='string',
        TemplateURL='string',
        UsePreviousTemplate=True|False,
        Parameters=[
            {
                'ParameterKey': 'string',
                'ParameterValue': 'string',
                'UsePreviousValue': True|False
            },
        ],
        Capabilities=[
            'CAPABILITY_IAM'|'CAPABILITY_NAMED_IAM',
        ],
        ResourceTypes=[
            'string',
        ],
        RoleARN='string',
        NotificationARNs=[
            'string',
        ],
        Tags=[
            {
                'Key': 'string',
                'Value': 'string'
            },
        ],
        ChangeSetName='string',
        ClientToken='string',
        Description='string',
        ChangeSetType='CREATE'|'UPDATE'
    )

    :type StackName: string
    :param StackName: [REQUIRED]
            The name or the unique ID of the stack for which you are creating a change set. AWS CloudFormation generates the change set by comparing this stack's information with the information that you submit, such as a modified template or different parameter input values.

    :type TemplateBody: string
    :param TemplateBody: A structure that contains the body of the revised template, with a minimum length of 1 byte and a maximum length of 51,200 bytes. AWS CloudFormation generates the change set by comparing this template with the template of the stack that you specified.
            Conditional: You must specify only TemplateBody or TemplateURL .

    :type TemplateURL: string
    :param TemplateURL: The location of the file that contains the revised template. The URL must point to a template (max size: 460,800 bytes) that is located in an S3 bucket. AWS CloudFormation generates the change set by comparing this template with the stack that you specified.
            Conditional: You must specify only TemplateBody or TemplateURL .

    :type UsePreviousTemplate: boolean
    :param UsePreviousTemplate: Whether to reuse the template that is associated with the stack to create the change set.

    :type Parameters: list
    :param Parameters: A list of Parameter structures that specify input parameters for the change set. For more information, see the Parameter data type.
            (dict) --The Parameter data type.
            ParameterKey (string) --The key associated with the parameter. If you don't specify a key and value for a particular parameter, AWS CloudFormation uses the default value that is specified in your template.
            ParameterValue (string) --The value associated with the parameter.
            UsePreviousValue (boolean) --During a stack update, use the existing parameter value that the stack is using for a given parameter key. If you specify true , do not specify a parameter value.

    :type Capabilities: list
    :param Capabilities: A list of values that you must specify before AWS CloudFormation can update certain stacks. Some stack templates might include resources that can affect permissions in your AWS account, for example, by creating new AWS Identity and Access Management (IAM) users. For those stacks, you must explicitly acknowledge their capabilities by specifying this parameter.
            The only valid values are CAPABILITY_IAM and CAPABILITY_NAMED_IAM . The following resources require you to specify this parameter: AWS::IAM::AccessKey , AWS::IAM::Group , AWS::IAM::InstanceProfile , AWS::IAM::Policy , AWS::IAM::Role , AWS::IAM::User , and AWS::IAM::UserToGroupAddition . If your stack template contains these resources, we recommend that you review all permissions associated with them and edit their permissions if necessary.
            If you have IAM resources, you can specify either capability. If you have IAM resources with custom names, you must specify CAPABILITY_NAMED_IAM . If you don't specify this parameter, this action returns an InsufficientCapabilities error.
            For more information, see Acknowledging IAM Resources in AWS CloudFormation Templates .
            (string) --

    :type ResourceTypes: list
    :param ResourceTypes: The template resource types that you have permissions to work with if you execute this change set, such as AWS::EC2::Instance , AWS::EC2::* , or Custom::MyCustomInstance .
            If the list of resource types doesn't include a resource type that you're updating, the stack update fails. By default, AWS CloudFormation grants permissions to all resource types. AWS Identity and Access Management (IAM) uses this parameter for condition keys in IAM policies for AWS CloudFormation. For more information, see Controlling Access with AWS Identity and Access Management in the AWS CloudFormation User Guide.
            (string) --

    :type RoleARN: string
    :param RoleARN: The Amazon Resource Name (ARN) of an AWS Identity and Access Management (IAM) role that AWS CloudFormation assumes when executing the change set. AWS CloudFormation uses the role's credentials to make calls on your behalf. AWS CloudFormation uses this role for all future operations on the stack. As long as users have permission to operate on the stack, AWS CloudFormation uses this role even if the users don't have permission to pass it. Ensure that the role grants least privilege.
            If you don't specify a value, AWS CloudFormation uses the role that was previously associated with the stack. If no role is available, AWS CloudFormation uses a temporary session that is generated from your user credentials.

    :type NotificationARNs: list
    :param NotificationARNs: The Amazon Resource Names (ARNs) of Amazon Simple Notification Service (Amazon SNS) topics that AWS CloudFormation associates with the stack. To remove all associated notification topics, specify an empty list.
            (string) --

    :type Tags: list
    :param Tags: Key-value pairs to associate with this stack. AWS CloudFormation also propagates these tags to resources in the stack. You can specify a maximum of 10 tags.
            (dict) --The Tag type enables you to specify a key-value pair that can be used to store information about an AWS CloudFormation stack.
            Key (string) --
            Required . A string used to identify this tag. You can specify a maximum of 128 characters for a tag key. Tags owned by Amazon Web Services (AWS) have the reserved prefix: aws: .
            Value (string) --
            Required . A string containing the value for this tag. You can specify a maximum of 256 characters for a tag value.

    :type ChangeSetName: string
    :param ChangeSetName: [REQUIRED]
            The name of the change set. The name must be unique among all change sets that are associated with the specified stack.
            A change set name can contain only alphanumeric, case sensitive characters and hyphens. It must start with an alphabetic character and cannot exceed 128 characters.

    :type ClientToken: string
    :param ClientToken: A unique identifier for this CreateChangeSet request. Specify this token if you plan to retry requests so that AWS CloudFormation knows that you're not attempting to create another change set with the same name. You might retry CreateChangeSet requests to ensure that AWS CloudFormation successfully received them.

    :type Description: string
    :param Description: A description to help you identify this change set.

    :type ChangeSetType: string
    :param ChangeSetType: The type of change set operation. To create a change set for a new stack, specify CREATE . To create a change set for an existing stack, specify UPDATE .
            If you create a change set for a new stack, AWS Cloudformation creates a stack with a unique stack ID, but no template or resources. The stack will be in the ` REVIEW_IN_PROGRESS http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-describing-stacks.html#d0e11995`_ state until you execute the change set.
            By default, AWS CloudFormation specifies UPDATE . You can't use the UPDATE type to create a change set for a new stack or the CREATE type to create a change set for an existing stack.

    :rtype: dict
    :return: {
        'Id': 'string',
        'StackId': 'string'
    }

    """
    pass


def template_to_dict_alt(tree, title):
    """
    Returns parse tree template as {<title>: <parts>}
    This is a more general parse tree infobox template parser.
    """
    box = []
    part = []
    for item in tree.iter():
        if item.tag == 'part':
            if part:
                box.append(part)
            part = []
        if item.tag == 'name' or item.tag == 'value':
            for attr in item.keys():
                part.append({attr: item.get(attr)})
            if item.text:
                part.append(item.text.strip())
            if item.tail:
                part.append(item.tail.strip())
    if part:
        box.append(part)
    return {title.strip(): box}


def array_core(ary):
    """
    Extract the repeated core of a broadcast array.

    Broadcast arrays are by definition non-contiguous due to repeated
    dimensions, i.e., dimensions with stride 0. In order to ascertain memory
    contiguity and copy the underlying data from such arrays, we must create
    a view without the repeated dimensions.

    """
    if not ary.strides:
        return ary
    core_index = []
    for stride in ary.strides:
        core_index.append(0 if stride == 0 else slice(None))
    return ary[tuple(core_index)]


@classmethod
def exterior_interiors(cls, polygon):
    """
        Extracts exterior rings and all interior rings from a polygon
        """
    exterior = polygon.find('.//{{{}}}exterior'.format(cls.gml))
    interiors = polygon.findall('.//{{{}}}interior'.format(cls.gml))
    return exterior, interiors


def viscosity_sutherland(temp):
    """compute visocity as in sutherland

    Args:
        temp (TYPE): Description

    Returns:
        TYPE: Description

    """
    alpha = 1.716e-05
    beta = 1.5
    t_0 = 273.15
    t_1 = 110.4
    mu_wall = alpha * (temp / t_0) ** beta * (t_0 + t_1) / (temp + t_1)
    return mu_wall


def get_verifycapstr():
    """Return the (string) verify-cap URI for the uploaded object."""


def upgrade():
    """Upgrade database."""


def cMultiplyRealInplace():
    """
    Return the kernel source of cMultiplyRealInplace.
    """
    R = """
    KERNEL void cMultiplyRealInplace(
    const unsigned int batch,
    GLOBAL_MEM const float *a,
    GLOBAL_MEM float2 *outb)
    {
    const unsigned int gid = get_global_id(0);
    // const unsigned int voxel_id = gid / batch;
    const unsigned int voxel_id = (float)gid / (float)batch;
    float mul = a[voxel_id];
    float2 orig = outb[gid];
    orig.x=orig.x*mul;
    orig.y=orig.y*mul;
    outb[gid]=orig;
    };
    """
    return R


def is_privatekey(key):
    """
    监测private key长度是否正确
    必须是64位的长度
    """
    import re
    prog = re.compile('^[a-zA-Z0-9]{64}$')
    tf = prog.match(key)
    return tf


def select_one(src, rel, dst):
    """
    Create an SQL query that selects one ID from a
    relation table given a source and destination node.

    :param src: The source node.
    :param rel: The relation.
    :param dst: The destination node.
    """
    smt = 'SELECT src FROM %s WHERE src = ? AND dst = ? LIMIT 1'
    return smt % rel, (src, dst)


@classmethod
def color_palette(cls):
    """Return the ordered colored palette dictionary."""
    return cls.to_dict(colors_only=True)


def escape_tab(s: str) ->str:
    """Replaces each tab character (\\t) in the input with \\\\t"""
    return s.replace('\t', '\\t')


@classmethod
def get_apod(cls, date=None, hd=False):
    """
        Returns Astronomy Picture of the Day

        Args:
            date: date instance (default = today)

            hd: bool if high resolution should be included

        Returns:
            json
        """
    instance = cls('planetary/apod')
    filters = {'date': date, 'hd': hd}
    return instance.get_resource(**filters)


def uint8_tag(name, value):
    """Create a DMAP tag with uint8 data."""
    return name.encode('utf-8') + b'\x00\x00\x00\x01' + value.to_bytes(1,
        byteorder='big')


def iterable(arr):
    """Returns an iterable"""
    try:
        iter(arr)
        return arr
    except:
        return arr,


def write_hdf(fname, sheets):
    """
        Write hdf file (usually called from write_report).
        inputs:
            fname: output file path
            sheets: tuple of name,dataframe pairs to add.
    """
    for sheetname, sheetdf in sheets:
        sheetdf.to_hdf(fname, sheetname)


def ms_to_hours(ms):
    """Convert milliseconds to hours"""
    return round(ms / 60.0 / 60.0 / 1000.0, 2)


@classmethod
def _Liquid_Entropy(cls, T):
    """Auxiliary equation for the specific entropy for saturated liquid

        Parameters
        ----------
        T : float
            Temperature, [K]

        Returns
        -------
        s : float
            Saturated liquid entropy, [kJ/kgK]

        References
        ----------
        IAPWS, Revised Supplementary Release on Saturation Properties of
        Ordinary Water Substance September 1992,
        http://www.iapws.org/relguide/Supp-sat.html, Eq.8
        """
    phi = cls._phi_sat(T)
    rho = cls._Liquid_Density(T)
    dpdT = cls._dPdT_sat(T)
    s = phi + dpdT / rho * 1000
    return s


def get_tsv_headers(path: str) ->list:
    """helper function to get tsv file headers.
    """
    fd = open(path, 'r')
    headers = fd.readline().replace('\n', '').split('\t')
    fd.close()
    return headers


def execute(interactive: bool=False):
    """Execute the current console line as a python expression

    :param interactive: interactive
    :type interactive: bool
    """
    pass


def sha1_of_file(filepath):
    """
    Get sha1 of file
    :param filepath: File to hash
    :return: sha1 hash of file or None
    """
    import hashlib
    try:
        with open(filepath, 'rb') as file_to_hash:
            return hashlib.sha1(file_to_hash.read()).hexdigest()
    except:
        return None


def _unescape_specification(specification):
    """
    Unescapes the interface string: replaces '%2F' by slashes '/'

    :param specification: Specification name
    :return: The unescaped name
    """
    return specification.replace('%2F', '/')


@classmethod
def create(cls, connection, database_name):
    """
        Create a database

        :param connection: the connection to the database
        :param database_name: the new database name
        """
    raise NotImplementedError


def openbis_definitions(entity):
    """
    attrs_new: Attributes, that can appear when creating new entities
    attrs_up: Attributes that can be updated
    attrs: Attributes that are displayed when fetched
    multi: multivalue-elements which appear in an entity. E.g. parents or children in a Sample.
    identifier: to update entities, the identifier must be specified. Usually identityName + "Id"
    (Entity-Name in camel-case, starting with lowercase letter, with Id added)
    """
    entities = {'space': {'attrs_new': 'code description'.split(),
        'attrs_up': 'description freeze freezeForProjects freezeForSamples'
        .split(), 'attrs':
        'code permId description frozen frozenForProjects frozenForSamples registrator registrationDate modificationDate'
        .split(), 'multi': ''.split(), 'identifier': 'spaceId', 'create': {
        '@type': 'as.dto.space.create.SpaceCreation'}, 'update': {'@type':
        'as.dto.space.update.SpaceUpdate'}, 'delete': {'@type':
        'as.dto.space.delete.SpaceDeletionOptions'}, 'fetch': {'@type':
        'as.dto.space.fetchoptions.SpaceFetchOptions'}}, 'project': {
        'attrs_new': 'code description space attachments'.split(),
        'attrs_up':
        'description space attachments freeze freezeForExperiments freezeForSamples'
        .split(), 'attrs':
        'code description permId identifier space leader registrator registrationDate modifier modificationDate attachments frozen frozenForExperiments frozenForSamples'
        .split(), 'multi': ''.split(), 'identifier': 'projectId', 'create':
        {'@type': 'as.dto.project.create.ProjectCreation'}, 'update': {
        '@type': 'as.dto.project.update.ProjectUpdate'}}, 'experiment': {
        'attrs_new': 'code type project tags attachments'.split(),
        'attrs_up':
        'project tags attachments freeze freezeForDataSets freezeForSamples'
        .split(), 'attrs':
        'code permId identifier type project tags registrator registrationDate modifier modificationDate attachments frozen frozenForDataSets frozenForSamples'
        .split(), 'multi': 'tags attachments'.split(), 'identifier':
        'experimentId', 'create': {'@type':
        'as.dto.experiment.create.ExperimentCreation'}, 'update': {'@type':
        'as.dto.experiment.update.ExperimentUpdate'}}, 'externalDms': {
        'attrs_new': 'code label address addressType creationId'.split(),
        'attrs_up': 'label address'.split(), 'attrs':
        'code permId label address addressType urlTemplate'.split(),
        'identifier': 'externalDmsId', 'create': {'@type':
        'as.dto.externaldms.create.ExternalDmsCreation'}, 'update': {
        '@type': 'as.dto.externaldms.update.ExternalDmsUpdate'}}, 'sample':
        {'attrs_new':
        'code type project parents children container components space experiment tags attachments'
        .split(), 'attrs_up':
        'project parents children container components space experiment tags attachments freeze freezeForComponents freezeForChildren freezeForParents freezeForDataSets'
        .split(), 'attrs':
        'code permId identifier type project parents children components space experiment tags registrator registrationDate modifier modificationDate attachments container frozen frozenForComponents frozenForChildren frozenForParents frozenForDataSets'
        .split(), 'ids2type': {'parentIds': {'permId': {'@type':
        'as.dto.sample.id.SamplePermId'}}, 'childIds': {'permId': {'@type':
        'as.dto.sample.id.SamplePermId'}}, 'componentIds': {'permId': {
        '@type': 'as.dto.sample.id.SamplePermId'}}}, 'identifier':
        'sampleId', 'create': {'@type':
        'as.dto.sample.create.SampleCreation'}, 'update': {'@type':
        'as.dto.sample.update.SampleUpdate'}, 'delete': {'@type':
        'as.dto.sample.delete.SampleDeletionOptions'}, 'cre_type':
        'as.dto.sample.create.SampleCreation', 'multi':
        'parents children components tags attachments'.split()},
        'sampleType': {'attrs_new':
        'code description autoGeneratedCode generatedCodePrefix subcodeUnique listable showContainer showParents showParentMetadata validationPlugin'
        .split(), 'attrs_up':
        'description autoGeneratedCode generatedCodePrefix subcodeUnique listable showContainer showParents showParentMetadata, validationPlugin'
        .split(), 'attrs':
        'permId code description autoGeneratedCode generatedCodePrefix subcodeUnique listable showContainer showParents showParentMetadata modificationDate validationPlugin'
        .split(), 'default_attribute_values': {'autoGeneratedCode': False,
        'generatedCodePrefix': 'S', 'subcodeUnique': False, 'description':
        '', 'listable': True, 'showContainer': False, 'showParents': True,
        'showParentMetadata': False}, 'search': {'@type':
        'as.dto.sample.search.SampleTypeSearchCriteria'}, 'create': {
        '@type': 'as.dto.sample.create.SampleTypeCreation'}, 'update': {
        '@type': 'as.dto.sample.update.SampleTypeUpdate'}, 'delete': {
        '@type': 'as.dto.sample.delete.SampleTypeDeletionOptions'},
        'identifier': 'typeId'}, 'materialType': {'attrs_new':
        'code description validationPlugin'.split(), 'attrs_up':
        'description validationPlugin'.split(), 'attrs':
        'permId code description validationPlugin'.split(), 'search': {
        '@type': 'as.dto.material.search.MaterialTypeSearchCriteria'},
        'fetch': {'@type':
        'as.dto.material.fetchoptions.MaterialTypeFetchOptions'}, 'create':
        {'@type': 'as.dto.material.create.MaterialTypeCreation'}, 'update':
        {'@type': 'as.dto.material.update.MaterialTypeUpdate'}, 'delete': {
        '@type': 'as.dto.material.delete.MaterialTypeDeletionOptions'},
        'identifier': 'typeId'}, 'dataSetType': {'attrs_new':
        'code description mainDataSetPattern mainDataSetPath disallowDeletion validationPlugin'
        .split(), 'attrs_up':
        'description mainDataSetPattern mainDataSetPath disallowDeletion validationPlugin'
        .split(), 'attrs':
        'permId code description mainDataSetPattern mainDataSetPath disallowDeletion modificationDate validationPlugin'
        .split(), 'search': {'@type':
        'as.dto.dataset.search.DataSetTypeSearchCriteria'}, 'fetch': {
        '@type': 'as.dto.dataset.fetchoptions.DataSetTypeFetchOptions'},
        'create': {'@type': 'as.dto.dataset.create.DataSetTypeCreation'},
        'update': {'@type': 'as.dto.dataset.update.DataSetTypeUpdate'},
        'delete': {'@type':
        'as.dto.dataset.delete.DataSetTypeDeletionOptions'}, 'identifier':
        'typeId'}, 'experimentType': {'attrs_new':
        'code description validationPlugin'.split(), 'attrs_up':
        'description modificationDate validationPlugin'.split(), 'attrs':
        'permId code description modificationDate validationPlugin'.split(),
        'search': {'@type':
        'as.dto.experiment.search.ExperimentTypeSearchCriteria'}, 'fetch':
        {'@type':
        'as.dto.experiment.fetchoptions.ExperimentTypeFetchOptions'},
        'create': {'@type':
        'as.dto.experiment.create.ExperimentTypeCreation'}, 'update': {
        '@type': 'as.dto.experiment.update.ExperimentTypeUpdate'}, 'delete':
        {'@type': 'as.dto.experiment.delete.ExperimentTypeDeletionOptions'},
        'identifier': 'typeId'}, 'propertyType': {'attrs':
        'code label description managedInternally internalNameSpace dataType vocabulary materialType schema transformation semanticAnnotations registrator registrationDate'
        .split(), 'attrs_new':
        'code label description managedInternally internalNameSpace dataType vocabulary materialType schema transformation metaData'
        .split(), 'attrs_up':
        'label description schema transformation metaData'.split(),
        'search': {'@type':
        'as.dto.property.search.PropertyTypeSearchCriteria'}, 'create': {
        '@type': 'as.dto.property.create.PropertyTypeCreation'}, 'update':
        {'@type': 'as.dto.property.update.PropertyTypeUpdate'}, 'delete': {
        '@type': 'as.dto.property.delete.PropertyTypeDeletionOptions'},
        'dataType': ['INTEGER', 'VARCHAR', 'MULTILINE_VARCHAR', 'REAL',
        'TIMESTAMP', 'BOOLEAN', 'CONTROLLEDVOCABULARY', 'MATERIAL',
        'HYPERLINK', 'XML'], 'identifier': 'typeId'}, 'SemanticAnnotation':
        {'attrs_new':
        'permId entityType propertyType predicateOntologyId predicateOntologyVersion predicateAccessionId descriptorOntologyId descriptorOntologyVersion descriptorAccessionId'
        .split(), 'attrs_up':
        'entityType propertyType predicateOntologyId predicateOntologyVersion predicateAccessionId descriptorOntologyId descriptorOntologyVersion descriptorAccessionId '
        .split(), 'attrs':
        'permId entityType propertyType predicateOntologyId predicateOntologyVersion predicateAccessionId descriptorOntologyId descriptorOntologyVersion descriptorAccessionId creationDate'
        .split(), 'ids2type': {'propertyTypeId': {'permId':
        'as.dto.property.id.PropertyTypePermId'}, 'entityTypeId': {'permId':
        'as.dto.entity.id.EntityTypePermId'}}, 'identifier': 'permId',
        'cre_type': 'as.dto.sample.create.SampleCreation', 'multi':
        'parents children components tags attachments'.split()}, 'dataSet':
        {'attrs_new':
        'type code kind experiment sample parents children components containers tags'
        .split(), 'attrs_up':
        'parents children experiment sample components containers tags freeze freezeForChildren freezeForParents freezeForComponents freezeForContainers'
        .split(), 'attrs':
        'code permId type kind experiment sample parents children components containers tags accessDate dataProducer dataProductionDate registrator registrationDate modifier modificationDate dataStore measured frozen frozenForChildren frozenForParents frozenForComponents frozenForContainers'
        .split(), 'ids2type': {'parentIds': {'permId': {'@type':
        'as.dto.dataset.id.DataSetPermId'}}, 'childIds': {'permId': {
        '@type': 'as.dto.dataset.id.DataSetPermId'}}, 'componentIds': {
        'permId': {'@type': 'as.dto.dataset.id.DataSetPermId'}},
        'containerIds': {'permId': {'@type':
        'as.dto.dataset.id.DataSetPermId'}}}, 'multi':
        'parents children containers components'.split(), 'identifier':
        'dataSetId'}, 'material': {'attrs_new':
        'code description type creation tags'.split(), 'attrs_up':
        'description type creation tags'.split(), 'attrs':
        'code description type creation registrator registrationDate modifier modificationDate tags'
        .split(), 'multi': ''.split(), 'identifier': 'materialId'}, 'tag':
        {'attrs_new': 'code description'.split(), 'attrs_up': 'description'
        .split(), 'attrs': 'permId code description registrationDate owner'
        .split(), 'multi': ''.split(), 'identifier': 'tagId'}, 'vocabulary':
        {'attrs_new':
        'code description managedInternally internalNameSpace chosenFromList urlTemplate terms'
        .split(), 'attrs_up':
        'description managedInternally internalNameSpace chosenFromList urlTemplate'
        .split(), 'attrs':
        'code description managedInternally internalNameSpace chosenFromList urlTemplate registrator registrationDate modifier modificationDate'
        .split(), 'multi': ''.split(), 'identifier': 'vocabularyId',
        'search': {'@type':
        'as.dto.vocabulary.search.VocabularySearchCriteria'}, 'create': {
        '@type': 'as.dto.vocabulary.create.VocabularyCreation'}, 'update':
        {'@type': 'as.dto.vocabulary.upate.VocabularyUpdate'}, 'delete': {
        '@type': 'as.dto.vocabulary.delete.VocabularyDeletionOptions'},
        'fetch': {'@type':
        'as.dto.vocabulary.fetchoptions.VocabularyFetchOptions'}},
        'vocabularyTerm': {'attrs_new':
        'code vocabularyCode label description official ordinal'.split(),
        'attrs_up': 'label description official previousTermId'.split(),
        'attrs':
        'code vocabularyCode label description official ordinal registrator registrationDate modifier modificationDate'
        .split(), 'multi': ''.split(), 'identifier': 'vocabularyTermId',
        'create': {'@type':
        'as.dto.vocabulary.create.VocabularyTermCreation'}, 'update': {
        '@type': 'as.dto.vocabulary.upate.VocabularyTermUpdate'}, 'delete':
        {'@type': 'as.dto.vocabulary.delete.VocabularyTermDeletionOptions'},
        'fetch': {'@type':
        'as.dto.vocabulary.fetchoptions.VocabularyTermFetchOptions'}},
        'plugin': {'attrs_new':
        'name description pluginType script available entityKind'.split(),
        'attrs_up': 'description script available'.split(), 'attrs':
        'permId name description registrator registrationDate pluginKind entityKinds pluginType script available'
        .split(), 'multi': ''.split(), 'identifier': 'pluginId',
        'pluginType': ['DYNAMIC_PROPERTY', 'MANAGED_PROPERTY',
        'ENTITY_VALIDATION'], 'entityKind': ['MATERIAL', 'EXPERIMENT',
        'SAMPLE', 'DATA_SET']}, 'person': {'attrs_new': 'userId space'.
        split(), 'attrs_up': 'space'.split(), 'attrs':
        'permId userId firstName lastName email space registrationDate '.
        split(), 'multi': ''.split(), 'identifier': 'userId'},
        'authorizationGroup': {'attrs_new': 'code description userIds'.
        split(), 'attrs_up': 'code description userIds'.split(), 'attrs':
        'permId code description registrator registrationDate modificationDate users'
        .split(), 'multi': 'users'.split(), 'identifier': 'groupId'},
        'roleAssignment': {'attrs':
        'id user authorizationGroup role roleLevel space project registrator registrationDate'
        .split(), 'attrs_new':
        'role roleLevel user authorizationGroup role space project'.split(),
        'attrs_up':
        'role roleLevel user authorizationGroup role space project'.split(),
        'role': ['POWER_USER', 'OBSERVER', 'USER', 'DISABLED', 'ADMIN',
        'ETL_SERVER']}, 'attr2ids': {'space': 'spaceId', 'project':
        'projectId', 'sample': 'sampleId', 'samples': 'sampleIds',
        'dataSet': 'dataSetId', 'dataSets': 'dataSetIds', 'experiment':
        'experimentId', 'experiments': 'experimentIds', 'material':
        'materialId', 'materials': 'materialIds', 'materialType':
        'materialTypeId', 'container': 'containerId', 'containers':
        'containerIds', 'component': 'componentId', 'components':
        'componentIds', 'parents': 'parentIds', 'children': 'childIds',
        'tags': 'tagIds', 'userId': 'userId', 'users': 'userIds',
        'description': 'description', 'vocabulary': 'vocabularyId',
        'validationPlugin': 'validationPluginId'}, 'ids2type': {'spaceId':
        {'permId': {'@type': 'as.dto.space.id.SpacePermId'}}, 'projectId':
        {'permId': {'@type': 'as.dto.project.id.ProjectPermId'}},
        'experimentId': {'permId': {'@type':
        'as.dto.experiment.id.ExperimentPermId'}}, 'tagIds': {'code': {
        '@type': 'as.dto.tag.id.TagCode'}}}, 'dataSetFile': {'search': {
        '@type': 'dss.dto.datasetfile.search.DataSetFileSearchCriteria'}}}
    return entities[entity]


def number_of_compliance_plugins(report_host):
    """
    Function returns number of reported compliance plugins for given target.
    :param report_host: report host element
    :return: number of reported compliance plugins
    """
    compliance_plugin_counter = 0
    for report_item in report_host.findall('ReportItem'):
        compliance = report_item.find('compliance')
        if compliance is not None:
            if compliance.text == 'true':
                compliance_plugin_counter += 1
    return compliance_plugin_counter


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


@staticmethod
def getJavaPackage():
    """ Returns package name String. """
    return 'com.microsoft.ml.spark.image.UnrollImage'


@staticmethod
def skipLines(f, skipCount: int):
    """
        >>> f = open( "test_set_small.txt", "r" )
        >>> skipLines( f , 20 )
        20
        """
    lineCount = 0
    if skipCount > 0:
        dummy = f.readline()
        while dummy:
            lineCount = lineCount + 1
            if lineCount == skipCount:
                break
            dummy = f.readline()
    return lineCount


def domain_name(wiki):
    """
    Returns domain name from wiki name
    """
    if '//' in wiki:
        wiki = wiki.split('//')[1]
    return wiki.split('/')[0]


def printAllWidgets(qApplication, ofType=None):
    """ Prints list of all widgets to stdout (for debugging)
    """
    print("Application's widgets {}".format('of type: ' + str(ofType) if
        ofType else ''))
    for widget in qApplication.allWidgets():
        if ofType is None or isinstance(widget, ofType):
            print('  {!r}'.format(widget))


@classmethod
def list_types(cls):
    """
        List all available array types.

        """
    array_types = cls.get_types()
    for array_id, array in array_types.items():
        print(array_id)
        print(f"\tName: {array['name']}")
        print(f"\tType: {array['array_type']}")
        print(f"\tCompany: {array['company']}")
        print(f"\tSource: {array['source']}\n")


def getDeclaredFields(clas):
    """
    Returns an array of Field objects reflecting all the fields declared by
    the class or interface represented by this Class object.
    """
    return clas.__javaclass__.getDeclaredFields()


@classmethod
def concatenate(cls, objects, **kwargs):
    """Concatenate objects to get object that would be recieved if
        the concatenated serialization were deserialized.

        Args:
            objects (list): Objects to be concatenated.
            **kwargs: Additional keyword arguments are ignored.

        Returns:
            list: Set of objects that results from concatenating those provided.

        """
    return objects


def _close_event(event, params):
    """Handle closing of raw browser with selections."""
    import matplotlib.pyplot as plt
    if 'fig_selection' in params:
        plt.close(params['fig_selection'])
    for fig in ['fig_annotation', 'fig_help', 'fig_proj']:
        if params[fig] is not None:
            plt.close(params[fig])
    plt.close(params['fig'])


@classmethod
def revoke_token(cls, token):
    """Revoke an access token."""
    return cls._dev_api().revoke_authorization(token)


def export_manifest(manifest, output_fs, filename='manifest.csv'):
    """Write a manifest file."""
    lines = ['"path","md5","auth md5"']
    for path, file_hash, auth_hash in manifest:
        lines.append('"{}",{},{}'.format(path.replace('"', '\\"'),
            file_hash, auth_hash))
    manifest_data = '\n'.join(lines)
    output_fs.settext(filename, manifest_data, encoding='utf-8')


def parse_file_dict(file_dict):
    """
    Return a dictionary with file as keys and content as values.
    """
    result = {}
    for section in file_dict:
        result.update(file_dict[section])
    return result


def normalize_vendor(vendor):
    """ Return a canonical name for a type of database. """
    if not vendor:
        return 'db'
    elif 'sqlite' in vendor:
        return 'sqlite'
    elif 'postgres' in vendor or vendor == 'psycopg2':
        return 'postgres'
    else:
        return vendor


@classmethod
def _crerate_pass_date(cls, *, year: int, day: int, month: int) ->str:
    """Create date for passport name."""
    if month // 10 == 0:
        month = '0' + str(month)
    if day // 10 == 0:
        day = '0' + str(day)
    pass_date = '{}-{}-{}'.format(year, month, day)
    return pass_date


def indent():
    """Indent selected text

    """
    pass


@staticmethod
def unweighted_edge(edge):
    """unweighted_edge(edge) -> str
            Return a string to output the edge without weight. The string contains the start vertex, end vertex(u,v) and splits with space.
        """
    return '%d %d' % (edge.start, edge.end)


def mapped_keys(cls):
    """ Return a list of the mapped keys. """
    return cls._reverse_name_map.mapped()


def write(dictionary, serializer=None):
    """
        Write a dictionary to the appropriate destination.

        @note: This method is thread-safe.

        @param serializer: Either C{None}, or a
            L{eliot._validation._MessageSerializer} which can be used to
            validate this message.

        @param dictionary: The message to write out. The given dictionary
             will not be mutated.
        @type dictionary: C{dict}
        """


@staticmethod
def get_namespace(env):
    """ Grabs ES namespace from health page """
    from .ff_utils import get_health_page
    health = get_health_page(ff_env=env)
    return health.get('namespace', '')


def _older_than(number, unit):
    """
    Returns a query item matching messages older than a time period.

    Args:
        number (int): The number of units of time of the period.
        unit (str): The unit of time: "day", "month", or "year".

    Returns:
        The query string.

    """
    return f'older_than:{number}{unit[0]}'


def find_all(s, sub, start=0, end=0, limit=-1, reverse=False):
    """
    Find all indexes of sub in s.

    :param s: the string to search
    :param sub: the string to search for
    :param start: the index in s at which to begin the search (same as in ''.find)
    :param end: the index in s at which to stop searching (same as in ''.find)
    :param limit: the maximum number of matches to find
    :param reverse: if False search s forwards; otherwise search backwards

    :return: all occurrences of substring sub in string s
    """
    indexes = []
    if not bool(s and sub):
        return indexes
    lstr = len(s)
    if lstr <= start:
        return indexes
    lsub = len(sub)
    if lstr < lsub:
        return indexes
    if limit == 0:
        return indexes
    elif limit < 0:
        limit = lstr
    end = min(end, lstr) or lstr
    idx = s.rfind(sub, start, end) if reverse else s.find(sub, start, end)
    while idx != -1:
        indexes.append(idx)
        if reverse:
            idx = s.rfind(sub, start, idx - lstr)
        else:
            idx = s.find(sub, idx + lsub, end)
        if len(indexes) >= limit:
            break
    return indexes


def customdata_skin_add():
    """Add a vertex skin layer

    """
    pass


@classmethod
def _parse_section_to_dict(cls, section_options, values_parser=None):
    """Parses section options into a dictionary.

        Optionally applies a given parser to values.

        :param dict section_options:
        :param callable values_parser:
        :rtype: dict
        """
    value = {}
    values_parser = values_parser or (lambda val: val)
    for key, (_, val) in section_options.items():
        value[key] = values_parser(val)
    return value


def set_axis_tick_direction(params):
    """Set the axis direction

    Args:
        params (dict): plotting parameter dictionary

    Returns:
        same as input
    """
    for panel_id, p in params['local'].items():
        obj_axis = params['internal']['canvas']['axes'][panel_id]
        for k in ['x', 'y']:
            attr = 'get_{}axis'.format(k)
            ax = getattr(obj_axis, attr)()
            for m in ['major', 'minor']:
                ax.set_tick_params(which=m, direction=p['tick'][m][
                    'direction'][k])
    return params


def filter_webapp_attack(df, process_time):
    """
    A function that filters out the BASH SHELLSHOCK alert data obtained from FireEye
    :param df: a DataFrame object
    :param process_time:
    :return:
    """
    result = []
    track = []
    for o in df:
        if 'METHODOLOGY - WEB APP ATTACK' in o['message']:
            track.append(o)
        else:
            result.append(o)
    trackfile = open('tracking_webAppAttack_' + process_time + '.txt', 'w')
    numskip = 1
    for item in track:
        trackfile.write('\n\n**** {:d}: Display ID {} ****\n\n{}'.format(
            numskip, item['displayId'], item))
        numskip += 1
    return result


def ocean_bake(modifier: str='', free: bool=False):
    """Bake an image sequence of ocean data

    :param modifier: Modifier, Name of the modifier to edit
    :type modifier: str
    :param free: Free, Free the bake, rather than generating it
    :type free: bool
    """
    pass


def timestamp(event):
    """
    Gets the timestamp of an event retrieved from Karabo at XFEL.

    Arguments:

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

    Returns:

        numpy.float64: the timestamp of the event  in seconds from the Epoch.
    """
    return event.timestamp


@staticmethod
def consolidate_vers(versioned_methods):
    """Consolidates a list of versioned methods dictionaries."""
    if not versioned_methods:
        return {}
    result = versioned_methods.pop(0)
    for base_methods in versioned_methods:
        for name, methods in base_methods.items():
            method_list = result.setdefault(name, [])
            method_list.extend(methods)
            method_list.sort(reverse=True)
    return result


def validate_attachment(req, attachment):
    """Validate an attachment after upload but before being stored
        in Trac environment.

        Must return a list of ``(field, message)`` tuples, one for
        each problem detected. ``field`` can be any of
        ``description``, ``username``, ``filename``, ``content``, or
        `None` to indicate an overall problem with the
        attachment. Therefore, a return value of ``[]`` means
        everything is OK."""


def pin(clear: bool=False):
    """Set/clear selected UV vertices as anchored between multiple unwrap operations

    :param clear: Clear, Clear pinning for the selection instead of setting it
    :type clear: bool
    """
    pass


def getPrincipalsAndPermissions():
    """Get all principal permission settings.

        Get the principal security assertions here in the form
        of a list of three tuple containing
        (permission id, principal id, setting)
        """


def selectSiR(i):
    """
    not all functions are still in this file, the older functions can be found
    (with the same numbering) in h:\\My Documents\\memo's\\python scripts\\wflow    """
    if i == 1:
        name = 'interception_overflow'
    if i == 2:
        name = 'interception_overflow2'
    if i == 3:
        name = 'interception_overflow_Ep'
    return name


def get_patient_fastqs(job, patient_dict, sample_type):
    """
    Convenience function to return only a list of fq_1, fq_2 for a sample type.

    :param dict patient_dict: dict of patient info
    :param str sample_type: key in sample_type to return
    :return: fastqs[sample_type]
    :rtype: list[toil.fileStore.FileID]
    """
    return [patient_dict[sample_type + '_fastq_1'], patient_dict[
        sample_type + '_fastq_2']]


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


@staticmethod
def _x_credentials_parser(credentials, data):
    """
        We need to override this method to fix Facebooks naming deviation.
        """
    credentials.expire_in = data.get('expires')
    if data.get('token_type') == 'bearer':
        credentials.token_type = 'Bearer'
    return credentials


def product(l):
    """Multiply together the elements of a list."""
    prod = 1
    for x in l:
        prod *= x
    return prod


@classmethod
def from_zip(cls, *args, **kwargs):
    """
        Construct Corpus object by loading files from a ZIP file. See method
        :meth:`~tmtoolkit.corpus.Corpus.add_zip()` for available arguments.

        :return: Corpus instance
        """
    return cls().add_zip(*args, **kwargs)


def _siftdown_max(heap, startpos, pos):
    """Maxheap variant of _siftdown"""
    newitem = heap[pos]
    while pos > startpos:
        parentpos = pos - 1 >> 1
        parent = heap[parentpos]
        if parent < newitem:
            heap[pos] = parent
            pos = parentpos
            continue
        break
    heap[pos] = newitem


@classmethod
def get_table_names(cls, schema, inspector):
    """Need to consider foreign tables for PostgreSQL"""
    tables = inspector.get_table_names(schema)
    tables.extend(inspector.get_foreign_table_names(schema))
    return sorted(tables)


@classmethod
def supports_replay_gain(cls):
    """returns True if this class supports ReplayGain"""
    return True


def has_vals_within_set(df, items=None):
    """Asserts that `df` is a subset of items.

    Args:
        df (pd.DataFrame): Any pd.DataFrame.
        items (dict): Mapping of columns (col) to array-like of values (v) that
                      ``df[col]`` is expected to be a subset of.

    Returns:
        Original `df`.

    """
    for col, v in items.items():
        if not df[col].isin(v).all():
            bad = df.loc[~df[col].isin(v), col]
            raise AssertionError('Not in set', bad)
    return df


def escape_string(s):
    """Keep char unchanged if char is number or letter or unicode"""
    chs = []
    for ch in s:
        ch = ch if ord(ch) > 128 or ch.isalnum() else ' '
        chs.append(ch)
    return '_'.join(''.join(chs).split())


def parse_jcamp_value(text):
    """
    Parse value text from Bruker JCAMP-DX file returning the value.
    """
    if '<' in text:
        return text[1:-1]
    elif '.' in text or 'e' in text or 'inf' in text:
        return float(text)
    else:
        return int(text)


def t_saved_query(val):
    """
    Convert/validate: Saved query.
    """
    return val


def main():
    """Function to be called when file executed via terminal."""
    print(__doc__)


def _trac_data_tags(instance, trac_type, state):
    """
    Returns data types for specific type and an object.
    """
    data_str = ''
    if instance:
        data = {'state': state, 'type': trac_type, 'app': instance._meta.
            app_label, 'klass': instance.__class__.__name__, 'pk': instance.id}
        data_str = (
            'trac-state=%(state)s trac-type=%(type)s trac-app=%(app)s trac-class=%(klass)s trac-oid=%(pk)s'
             % data)
    return data_str


def score_formula1(f1, f2):
    """
    Score the SIMILARITY of 2 formulas.
    Inputs are list of characters; output is float or false.
    """
    if f1 == [] or f2 == []:
        return False
    elif abs(len(f1) - len(f2)) >= 2:
        score = -1000
    else:
        score = 0
        for piece1 in f1:
            if piece1 not in f2:
                score -= 5
            elif f1[piece1] == f2[piece1]:
                score += 3
            elif piece1 == 'C':
                score -= abs(f1[piece1] - f2[piece1])
            else:
                score -= abs(f1[piece1] - f2[piece1]) / 3
        for piece2 in f2:
            if piece2 not in f1:
                score -= 5
    return score


def check_upload_file(file_path, upload_info):
    """Check that the file is already in the upload list.

    Args:
        file_path (str): File path.
        upload_info (dict): Upload json info.

    Returns:
        bool.

    """
    for one_file in upload_info.get('asset'):
        if one_file['local'] == file_path:
            return True
    return False


def view_selected():
    """Reset viewable area to show selected keyframes range

    """
    pass


def distribution_version(name):
    """try to get the version of the named distribution,
    returs None on failure"""
    from pkg_resources import get_distribution, DistributionNotFound
    try:
        dist = get_distribution(name)
    except DistributionNotFound:
        pass
    else:
        return dist.version


def translate_es_name(name):
    """Translate Elasticsearch name to PostgreSQL name.

    Replaces dashes with underscores.
    """
    if name == '@timestamp':
        return 'timestamp'
    return name.replace('-', '_')


@classmethod
def create_extension(cls, columns):
    """
        Creates the nesting table's mapper extension.
        """
    return cls.extension(columns + ['_'.join((cls.NAME_PRE, 'id'))])


def _update_frame(pos, fig):
    """Update an image frame in a matplotlib FuncAnimation function.

    Will simulate a mouse button press, and update a matplotlib
    annotation.

    Parameters
    ----------
    pos : tuple
        (x, y, press_mouse_button). If press_button is True, a mouse click
        will be done at (x, y), and the cursor will be moved there. If False,
        the cursor will just be moved.
    fig : matplotlib figure object

    """
    ax = fig.axes[0]
    if pos[2]:
        x, y = ax.transData.transform((pos[0], pos[1]))
        fig.canvas.button_press_event(x, y, 1)
    text = ax.texts[0]
    text.xy = pos[0], pos[1]
    fig.canvas.draw()
    fig.canvas.flush_events()


@classmethod
def _filter_auto_inferred(cls, d, **kwargs):
    """Given a dictionary (like the one outputted by _infer_track_number_n_name), deletes entries unless it finds them declared in kwargs as key_name=True"""
    for k in cls._auto_data:
        if not kwargs.get(k, False) and k in d:
            del d[k]
    return d


def replace_path_chars(path):
    """

    utility to replace graphite path chars

    Examples:
        >>> print(replace_path_chars('|T/e s.t'))
        _T_e_s_t
    """
    if not path:
        return path
    return path.replace('.', '_').replace('|', '_').replace('/', '_').replace(
        ' ', '_')


def parse_repository_tag(repo_path):
    """Splits image identification into base image path, tag/digest
    and it's separator.

    Example:

    >>> parse_repository_tag('user/repo@sha256:digest')
    ('user/repo', 'sha256:digest', '@')
    >>> parse_repository_tag('user/repo:v1')
    ('user/repo', 'v1', ':')
    """
    tag_separator = ':'
    digest_separator = '@'
    if digest_separator in repo_path:
        repo, tag = repo_path.rsplit(digest_separator, 1)
        return repo, tag, digest_separator
    repo, tag = repo_path, ''
    if tag_separator in repo_path:
        repo, tag = repo_path.rsplit(tag_separator, 1)
        if '/' in tag:
            repo, tag = repo_path, ''
    return repo, tag, tag_separator


@classmethod
def post_save(cls, *args, **kwargs):
    """Adding a hook here so it's safe to call the super's post_save."""
    pass


def listSearchCriteriaTypes():
    """List available search criteria types as dict
        """


def generic_find_fk_constraint_name(table, columns, referenced, insp):
    """Utility to find a foreign-key constraint name in alembic migrations"""
    for fk in insp.get_foreign_keys(table):
        if fk['referred_table'] == referenced and set(fk['referred_columns']
            ) == columns:
            return fk['name']


def StringProperty(name: str='', description: str='', default: str='',
    maxlen: int=0, options: set={'ANIMATABLE'}, subtype: str='NONE', update
    =None, get=None, set=None):
    """Returns a new string property definition.

    :param name: Name used in the user interface.
    :type name: str
    :param description: Text used for the tooltip and api documentation.
    :type description: str
    :param default: initializer string.
    :type default: str
    :param maxlen: maximum length of the string.
    :type maxlen: int
    :param options: Enumerator in [‘HIDDEN’, ‘SKIP_SAVE’, ‘ANIMATABLE’, ‘LIBRARY_EDITABLE’, ‘PROPORTIONAL’,’TEXTEDIT_UPDATE’].
    :type options: set
    :param subtype: Enumerator in [‘FILE_PATH’, ‘DIR_PATH’, ‘FILE_NAME’, ‘BYTE_STRING’, ‘PASSWORD’, ‘NONE’].
    :type subtype: str
    :param update: Function to be called when this value is modified, This function must take 2 values (self, context) and return None. Warning there are no safety checks to avoid infinite recursion.
    :param get: Function to be called when this value is ‘read’, This function must take 1 value (self) and return the value of the property.
    :param set: Function to be called when this value is ‘written’, This function must take 2 values (self, value) and return None.
    """
    pass


def peer():
    """Obtain an object conforming to the ``peer`` interface."""


def set_prefs(prefs):
    """This function is called before opening the project"""
    prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject', '.hg',
        '.svn', '_svn', '.git', '__pycache__', '.tox', '.env',
        'node_modules', 'bower_components']
    prefs['save_objectdb'] = True
    prefs['compress_objectdb'] = False
    prefs['automatic_soa'] = True
    prefs['soa_followed_calls'] = 0
    prefs['perform_doa'] = True
    prefs['validate_objectdb'] = True
    prefs['max_history_items'] = 32
    prefs['save_history'] = True
    prefs['compress_history'] = False
    prefs['indent_size'] = 4
    prefs['extension_modules'] = []
    prefs['import_dynload_stdmods'] = True
    prefs['ignore_syntax_errors'] = False
    prefs['ignore_bad_imports'] = False


def get_cmd_names(cmd_name, ctx):
    """
    Given the click core context, return a list representing all the subcommands passed to the CLI

    Parameters
    ----------
    cmd_name : name of current command

    ctx : click.Context

    Returns
    -------
    list(str)
        List containing subcommand names. Ex: ["local", "start-api"]

    """
    if not ctx:
        return []
    if ctx and not getattr(ctx, 'parent', None):
        return [ctx.info_name]
    _parent = ctx.parent
    _cmd_names = []
    if cmd_name != ctx.info_name:
        _cmd_names = [cmd_name]
    _cmd_names.append(ctx.info_name)
    while _parent.parent:
        info_name = _parent.info_name
        _cmd_names.append(info_name)
        _parent = _parent.parent
    _cmd_names.reverse()
    return _cmd_names


@classmethod
def from_string(cls, spec):
    """create modulespec from a string.

        A module specification has one of these forms:
          modulename
          modulename:version

        version may be:
          versionname        : exactly this version
          +versionname       : this version or newer
          -versionname       : this version or older

        Here are some examples:

        >>> Spec.from_string("ALARM")
        Spec('ALARM',None,None)
        >>> Spec.from_string("ALARM:R3-2")
        Spec('ALARM','R3-2','eq')
        >>> Spec.from_string("ALARM:+R3-2")
        Spec('ALARM','R3-2','ge')
        >>> Spec.from_string("ALARM:-R3-2")
        Spec('ALARM','R3-2','le')
        """
    mode = 0
    modulename = None
    versionname = None
    versionflag = None
    for l in spec.split(':'):
        if mode == 0:
            modulename = l
            mode += 1
            continue
        if mode == 1:
            if l != '':
                if l[0] == '-':
                    versionname = l[1:]
                    versionflag = 'le'
                elif l[0] == '+':
                    versionname = l[1:]
                    versionflag = 'ge'
                else:
                    versionname = l
                    versionflag = 'eq'
            mode += 1
            continue
        raise ValueError('unexpected spec: %s' % spec)
    return cls(modulename, versionname, versionflag)


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

        :param PaperDocEditType val:
        :rtype: EventType
        """
    return cls('paper_doc_edit', val)


@staticmethod
def _get_firstname(optional, k2v):
    """Get first name to be used as the display name."""
    if 'geneName' in optional:
        return optional['geneName'][0]
    if 'name' in optional:
        names = optional['name']
        name = names[0] if k2v['databaseName'][:9] != 'KEGG Gene' else names[-1
            ]
        return name if k2v['identifier'] != name else ''
    return ''


def read_iter():
    """Return the path to the final rho*.mag file from the tomodir.
    """
    filename = 'exe/inv.lastmod'
    linestring = open(filename, 'r').readline().strip()
    linestring = linestring.replace('\n', '')
    linestring = linestring.replace('../', '')
    return linestring


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 plus_or_dot(pieces):
    """Return a + if we don't already have one, else return a ."""
    if '+' in pieces.get('closest-tag', ''):
        return '.'
    return '+'


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

        :param bool val:
        :rtype: FileLockingValue
        """
    return cls('enabled', val)


def _addA(env, attr, name, call=lambda x: x):
    """
    Helper method to add attribute if not None
    """
    if attr is not None:
        env.attrib[name] = call(attr)


def shuffle(data=None, name=None, attr=None, out=None, **kwargs):
    """Randomly shuffle the elements.

    This shuffles the array along the first axis.
    The order of the elements in each subarray does not change.
    For example, if a 2D array is given, the order of the rows randomly changes,
    but the order of the elements in each row does not change.

    Parameters
    ----------
    data : Symbol
        Data to be shuffled.

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

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


@staticmethod
def _filter_repeating_items(download_list):
    """ Because of data_filter some requests in download list might be the same. In order not to download them again
        this method will reduce the list of requests. It will also return a mapping list which can be used to
        reconstruct the previous list of download requests.

        :param download_list: List of download requests
        :type download_list: list(sentinelhub.DownloadRequest)
        :return: reduced download list with unique requests and mapping list
        :rtype: (list(sentinelhub.DownloadRequest), list(int))
        """
    unique_requests_map = {}
    mapping_list = []
    unique_download_list = []
    for download_request in download_list:
        if download_request not in unique_requests_map:
            unique_requests_map[download_request] = len(unique_download_list)
            unique_download_list.append(download_request)
        mapping_list.append(unique_requests_map[download_request])
    return unique_download_list, mapping_list


def p_assignment_list_element(p):
    """assignment_list_element : variable
                               | empty
                               | LIST LPAREN assignment_list RPAREN"""
    if len(p) == 2:
        p[0] = p[1]
    else:
        p[0] = p[3]


def dbh_specimen_group(path, contenttype, extension, roottag, nsurl):
    """ Generic XML Handler - Returns xml_generic for all XML files """
    if extension == 'sdg':
        return 'db_specimen_group'
    else:
        return False


def getMaxLen(dictlist):
    """
    parses a list of dict (common output from RHN API) and calculates the longest
    entry for each key it finds.
    Currently does not do recursion, so dicts of dicts are not supported.
    TODO: add this in future release.

    This is useful for formatting output

    returns:
    dict { 'key' : maxlength(int) }

    parameters:
    dictlist(list of dict)  - list of dictionary structures.
    """
    maxlen = {}
    for d in dictlist:
        for k, v in d.items():
            curval = maxlen.get(k, 0)
            try:
                mylen = len(v)
            except:
                mylen = len(str(v))
            if mylen > curval:
                maxlen[k] = mylen
    return maxlen


def _get_type_name(type_):
    """Return a displayable name for the type.

    Args:
        type_: A class object.

    Returns:
        A string value describing the class name that can be used in a natural
        language sentence.
    """
    name = repr(type_)
    if name.startswith('<'):
        name = getattr(type_, '__qualname__', getattr(type_, '__name__', ''))
    return name.rsplit('.', 1)[-1] or repr(type_)


def convert_to_num(version_str):
    """Convert the version string to a number

    >>> convert_to_num(None)
    0

    >>> convert_to_num(10)
    10

    >>> convert_to_num('1.0.0')
    100

    >>> convert_to_num('1.0.0-alpha')
    100
    """
    if not version_str:
        return 0
    if str(version_str).isdigit():
        return version_str
    version_str = version_str.replace('.', '')
    if '-' in version_str:
        version_str = version_str.split('-')[0]
    return int(version_str) if version_str.isdigit() else 0


@staticmethod
def read_file(file_path):
    """
        Reads a file from the specified path and returns list containing its lines.

        :param file_path: The full path of the file to be read.

        :return: List representing each line of the file.
        :rtype: list
        """
    try:
        file_handler = open(file_path, 'r')
        file_data = file_handler.readlines()
        file_handler.close()
        return file_data
    except Exception as ex:
        pass


def line_count_file(file_path, flags=None):
    """ Counts lines for given file in file_name """
    try:
        count = 0
        with open(file_path, encoding='ascii', errors='surrogateescape'
            ) as current_file:
            for line in current_file:
                if line.strip(
                    ) == '' and flags != None and '--noempty' in flags:
                    continue
                count += 1
        return count
    except IOError:
        return -1


def format_send_receive_error(msg, sender, receiver):
    """
    Create a common format for sender, receiver errors
    """
    return '{}\nSender={}\nReceiver={}'.format(msg, sender, receiver)


def is_valid_pbc(pbc):
    """ Checks pbc parameter """
    values = ['none', 'mol', 'res', 'atom', 'nojump', 'cluster', 'whole']
    return pbc in values


def index_summary(idx, name=None):
    """Summarized representation of an Index.
    """
    n = len(idx)
    if name is None:
        name = idx.__class__.__name__
    if n:
        head = idx[0]
        tail = idx[-1]
        summary = ', {} to {}'.format(head, tail)
    else:
        summary = ''
    return '{}: {} entries{}'.format(name, n, summary)


def name(function):
    """Returns the name of a function"""
    return function.__name__


def select_linked():
    """Select keyframes occurring in the same F-Curves as selected ones

    """
    pass


def load_before(cursor, oid, tid):
    """Returns the state and tid of an object before transaction tid.

        Returns (None, None) if no earlier state exists.
        """


def merge(default, to_mutate):
    """
    Mutate a dict (to_mutate) with defaults from the first.
    Obviously, if to_mutate already has a key, don't override it.
    Return the mutated dict.
    """
    for key, value in default.items():
        to_mutate.setdefault(key, value)
    return to_mutate


def getSortOnName(prefix=None):
    """convert the table prefix to the 'sort on' name used in forms"""
    sort_on_name = 'sort_on'
    if prefix is not None:
        if not prefix.endswith('.'):
            prefix += '.'
        sort_on_name = prefix + sort_on_name
    return sort_on_name


def create_cell(project, polygon, height, id=None, with_surfacewater=True):
    """
    Creates a cell from a shapely polygon and stores the geometry in cell.geometry

    :param project: the cmf project of the cell
    :param polygon: the shapely Polygon
    :param height: the height of the cell
    :param id: the id of the cell, only set if not None
    :param with_surfacewater: True, if a surfacewater storage will be created
    :return: The new cell
    """
    center = polygon.centroid.x, polygon.centroid.y, height
    c = project.NewCell(*center, area=polygon.area, with_surfacewater=
        with_surfacewater)
    c.geometry = polygon
    if id is not None:
        c.Id = id
    return c


@classmethod
def atomic(cls):
    """Get the atomic context or decorator."""
    return cls._meta.database.atomic()


def explain_ag(fsm, state, phi):
    """
    Explain why state of fsm satisfies AG phi.

    fsm -- the fsm;
    state -- a state of fsm satisfying AG phi;
    phi -- the set of states of fsm satifying phi.
    """
    pass


def is_derivatized(monosaccharide):
    """Tests whether any of the substituents attached to `monosaccharide` were
    added by derivatization.

    Parameters
    ----------
    monosaccharide : Monosaccharide
        The object to test

    Returns
    -------
    bool
    """
    for pos, sub in monosaccharide.substituents():
        if sub._derivatize:
            return True
    return False


def get_client_region(client):
    """Gets the region from a :class:`boto3.client.Client` object.

    Args:
        client (:class:`boto3.client.Client`): The client to get the region
            from.

    Returns:
        string: AWS region string.
    """
    return client._client_config.region_name


def format_2_str(value, formator):
    """根据 formator 将对象格式化成 str"""
    if formator is None:
        text = str(value)
    elif isinstance(formator, str):
        text = str.format(formator, value)
    elif callable(formator):
        text = formator(value)
    else:
        raise ValueError('%s: %s 无效', value, formator)
    return text


def check_image_valid(im_source, im_search):
    """Check if the input images valid or not."""
    if im_source is not None and im_source.any(
        ) and im_search is not None and im_search.any():
        return True
    else:
        return False


def _format_code(code):
    """
    Format departement code (Add a 0 at the end if the length < 0).

    :returns: formatted code
    :rtype: str

    """
    if len(code) < 3:
        return code + '0'
    return code


def _coerce_itype(itype):
    """Changes string itype to int"""
    if itype in [None, 1, 2, 3, 4]:
        pass
    elif itype.lower() == 'timeseries':
        itype = 1
    elif itype.lower() == 'borehole1d':
        itype = 2
    elif itype.lower() == 'cpt':
        itype = 3
    elif itype.lower() == 'borehole3d':
        itype = 4
    else:
        raise ValueError('Invalid IPF itype')
    return itype


def configure(config):
    """Interactively configure the bot's ``[core]`` config section.

    :param config: the bot's config object
    :type config: :class:`~.config.Config`
    """
    config.core.configure_setting('nick', 'Enter the nickname for your bot.')
    config.core.configure_setting('host', 'Enter the server to connect to.')
    config.core.configure_setting('use_ssl', 'Should the bot connect with SSL?'
        )
    if config.core.use_ssl:
        default_port = 6697
    else:
        default_port = 6667
    config.core.configure_setting('port', 'Enter the port to connect on.',
        default=default_port)
    config.core.configure_setting('owner',
        "Enter your own IRC name (or that of the bot's owner)")
    config.core.configure_setting('channels',
        'Enter the channels to connect to at startup, separated by commas.')
    config.core.configure_setting('commands_on_connect',
        "Enter commands to perform on successful connection to server (one per '?' prompt)."
        )


def get_player_id(jersey: tuple, players: dict) ->str:
    """
    Basically takes a players jersey - a.k.a his team, name, and number, and gets his player ID

    :param jersey: tuple of info
    :param players:
    :return:
    """
    for _, venue in players.items():
        for _, player in venue.items():
            if (player['number'] == jersey[1] or jersey[1] == '') and (
                player['team'] == jersey[0] or jersey[0] == '') and (player
                ['last_name'].upper() == jersey[2] or jersey[2] == ''):
                return player['id']
    print(jersey)
    pass


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


def dict_from_cgi_form(cgi_form):
    """
    Convert CGI FieldStorage into a dictionary
    """
    o = {}
    for key in cgi_form:
        res = cgi_form[key]
        try:
            if res.file:
                o[key] = res.file.read()
            else:
                o[key] = res.value
        except:
            o[key] = res
    return o


def __eval_arg(arg, thrift_types):
    """Evaluate a commandline argument within the scope of the IF types"""
    code_globals = {}
    code_globals.update(thrift_types)
    code = compile(arg, '<command_line>', 'eval', 0, 1)
    return eval(code, code_globals)


def loadTargetState(targetStateConfig, existingTargetState=None):
    """
    extracts a new TargetState object from the specified configuration
    :param targetStateConfig: the config dict.
    :param existingTargetState: the existing state
    :return:
    """
    from analyser.common.targetstatecontroller import TargetState
    targetState = TargetState(
        ) if existingTargetState is None else existingTargetState
    if targetStateConfig is not None:
        val = targetStateConfig.get('fs')
        if val is not None:
            targetState.fs = val
        val = targetStateConfig.get('samplesPerBatch')
        if val is not None:
            targetState.samplesPerBatch = val
        val = targetStateConfig.get('gyroEnabled')
        if val is not None:
            targetState.gyroEnabled = val
        val = targetStateConfig.get('gyroSens')
        if val is not None:
            targetState.gyroSens = val
        val = targetStateConfig.get('accelerometerEnabled')
        if val is not None:
            targetState.accelerometerEnabled = val
        val = targetStateConfig.get('accelerometerSens')
        if val is not None:
            targetState.accelerometerSens = val
    return targetState


def getWrappedOwner():
    """Get the owner, modestly wrapped in the user folder.

        o If the object is not owned, return None.

        o If the owner's user database doesn't exist, return Nobody.

        o If the owner ID does not exist in the user database, return Nobody.
        """


@staticmethod
def conj(x, *args, **kwargs):
    """Return the complex conjugate, element-wise.

            The complex conjugate of a complex number is obtained by changing the sign of its imaginary part.
        """
    raise NotImplementedError


def set_current_hash(h):
    """
    Sets the hash for which a CallDescriptor is currently executing

    """
    global current_hash
    current_hash = h


def getkey(window):
    """Get a keypress from the window.

    @return keycode, character  - character will be None if there is no match
    """
    key = window.getch()
    try:
        char = chr(key)
    except ValueError:
        char = None
    return key, char


@classmethod
def _from_dict(cls, _dict):
    """Initialize a FeatureSentimentResults object from a json dictionary."""
    args = {}
    if 'score' in _dict:
        args['score'] = _dict.get('score')
    return cls(**args)


def latex_declarations(with_solution):
    """Returns the list of declarations to be set in the preamble
       of the LaTeX output.

    """
    data = ['\\usepackage{graphicx}', '\\usepackage{fancyvrb}',
        '\\usepackage{enumerate}', '\\usepackage{color}',
        '\\definecolor{lightgray}{rgb}{1, 1, 1}',
        '\\newcommand{\\light}[1]{\\textcolor{lightgray}{#1}}',
        '\\definecolor{hidden}{rgb}{1, 1, 1}',
        '\\newcommand{\\hidden}[1]{\\textcolor{hidden}{#1}}',
        '\\newif\\ifsolutions']
    if with_solution:
        data.append('\\solutionstrue')
    else:
        data.append('\\solutionsfalse')
    return '\n'.join(data)


def is_locked(lock):
    """Return whether a lock is locked.

    Suppors :class:`Lock`, :class:`RLock`, :class:`threading.Lock` and
    :class:`threading.RLock` instances.
    """
    if hasattr(lock, 'locked'):
        return lock.locked()
    elif hasattr(lock, '_is_owned'):
        return lock._is_owned()
    else:
        raise TypeError('expecting Lock/RLock')


@classmethod
def color(cls, *args):
    """output text using ANSI codes

        this method simply merge arguments, and add RESET if is not the last arguments
        """
    if args[-1] != cls.RESET:
        args = list(args)
        args.append(cls.RESET)
    return u''.join(args)


def intToBin(i):
    """ Integer to two bytes """
    i1 = i % 256
    i2 = int(i / 256)
    return chr(i1) + chr(i2)


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 ht_feet_to_inches(ht_str):
    """Take in height in ft-in format, and return inches

    >>> ht_feet_to_inches("6-0")
    72
    """
    feet, inches = ht_str.split('-')
    return int(feet) * 12 + int(inches)


@classmethod
def get_address_from_public_key(cls, public_key: str) ->str:
    """
        Get the address from the public key.

        :param public_key: the public key
        :return: str
        """
    raise NotImplementedError


def plugins_versions():
    """Show packages version"""
    import pkg_resources
    packages = {}
    for package in pkg_resources.working_set:
        entry_map = package.get_entry_map('rally_plugins')
        if not entry_map:
            continue
        packages[package.project_name] = package.version
    return packages


def any_value(items: list):
    """
    Function that extracts values from a list and checks if they are diff from None,0,{},[],False...
    First value that is diff from them is being returned
    :param items: List of items that is searched for non-null values
    :return: First value that fits the criteria
    """
    for item in items:
        if item:
            return item


def lookupMailBox(name, timeout=None):
    """
        Perform an MB 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 num_or_str(x):
    """The argument is a string; convert to a number if
       possible, or strip it."""
    try:
        return int(x)
    except ValueError:
        try:
            return float(x)
        except ValueError:
            return str(x).strip()


def get_currency_format(lc: str, LO: str, CUR: str) ->str:
    """because of all the if statements, this has very low code coverage
    but it's ok"""
    if lc == 'en':
        if CUR in ['USD', 'CAD', 'AUD']:
            return '$#'
        if CUR == 'GBP':
            return '£#'
        if CUR == 'EUR':
            return '€#'
        if CUR == 'INR':
            return '₹ #'
        if CUR == 'SGD':
            return '$#'
        if CUR == 'CNY':
            return '#元'
        if CUR == 'JPY':
            return '#円'
        if CUR == 'KRW':
            return '#원'
        return '¤#'
    if lc == 'zh':
        if CUR == 'CNY':
            return '#元'
        if CUR == 'HKD':
            return 'HK$#'
        if CUR == 'TWD':
            return '$#'
        if CUR == 'SGD':
            return 'SGD#'
        return '¤#'
    if lc == 'de':
        if CUR == 'EUR':
            if LO == 'AT':
                return '€ #'
            return '# €'
        if CUR == 'CHF':
            return 'CHF #'
        return '¤ #'
    if lc == 'es':
        if CUR == 'ARS':
            return '$ #'
        if CUR == 'EUR':
            return '# €'
        if CUR == 'MXN':
            return '$#'
        return '# ¤'
    if lc == 'nl':
        if LO == 'BE':
            if CUR == 'EUR':
                return '# €'
            return '# ¤'
        if CUR == 'EUR':
            return '€ #'
        return '¤ #'
    if lc == 'pt':
        if CUR == 'BRL':
            return 'R$#'
        if CUR == 'EUR':
            return '# €'
        return '¤#'
    if lc == 'ar':
        if CUR == 'AED':
            return 'د.إ.\u200f #'
        return '¤ #'
    if lc == 'cs':
        if CUR == 'CZK':
            return '# Kč'
        return '# ¤'
    if lc == 'da':
        if CUR == 'DKK':
            return '# kr.'
        return '# ¤'
    if lc == 'fi':
        if CUR == 'EUR':
            return '# €'
        return '# ¤'
    if lc == 'fr':
        if CUR == 'EUR':
            return '# €'
        return '# ¤'
    if lc == 'he':
        if CUR == 'ILS':
            return '# ₪'
        return '# ¤'
    if lc == 'hu':
        if CUR == 'HUF':
            return '# Ft'
        return '# ¤'
    if lc == 'it':
        if CUR == 'EUR':
            return '# €'
        return '# ¤'
    if lc == 'ja':
        if CUR == 'JPY':
            return '#円'
        return '¤#'
    if lc == 'ko':
        if CUR == 'KRW':
            return '#원'
        return '¤#'
    if lc == 'ms':
        if CUR == 'MYR':
            return 'RM#'
        return '¤#'
    if lc == 'nb':
        if CUR == 'NOK':
            return 'kr #'
        return '¤ #'
    if lc == 'pl':
        if CUR == 'PLN':
            return '# zł'
        return '# ¤'
    if lc == 'ru':
        if CUR == 'RUB':
            return '# ₽'
        return '# ¤'
    if lc == 'sv':
        if CUR == 'SEK':
            return '# kr'
        return '# ¤'
    if lc == 'th':
        if CUR == 'THB':
            return 'THB#'
        return '¤#'
    if lc == 'tr':
        if CUR == 'TRY':
            return '# ₺'
        return '# ¤'
    if lc == 'zu':
        if CUR == 'ZAR':
            return 'R#'
        return '¤#'
    return '# ¤'


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 string_list(s):
    """Convert a string to a list of strings using .split()."""
    return s.split()


def get_numpy_include_path():
    """
    Gets the path to the numpy headers.
    """
    import builtins
    if hasattr(builtins, '__NUMPY_SETUP__'):
        del builtins.__NUMPY_SETUP__
    import imp
    import numpy
    imp.reload(numpy)
    try:
        numpy_include = numpy.get_include()
    except AttributeError:
        numpy_include = numpy.get_numpy_include()
    return numpy_include