def delete_item(TableName=None, Key=None, Expected=None,
    ConditionalOperator=None, ReturnValues=None, ReturnConsumedCapacity=
    None, ReturnItemCollectionMetrics=None, ConditionExpression=None,
    ExpressionAttributeNames=None, ExpressionAttributeValues=None):
    """
    Deletes a single item in a table by primary key. You can perform a conditional delete operation that deletes the item if it exists, or if it has an expected attribute value.
    In addition to deleting an item, you can also return the item's attribute values in the same operation, using the ReturnValues parameter.
    Unless you specify conditions, the DeleteItem is an idempotent operation; running it multiple times on the same item or attribute does not result in an error response.
    Conditional deletes are useful for deleting items only if specific conditions are met. If those conditions are met, DynamoDB performs the delete. Otherwise, the item is not deleted.
    See also: AWS API Documentation

    Examples
    This example deletes an item from the Music table.
    Expected Output:

    :example: response = client.delete_item(
        TableName='string',
        Key={
            'string': {
                'S': 'string',
                'N': 'string',
                'B': b'bytes',
                'SS': [
                    'string',
                ],
                'NS': [
                    'string',
                ],
                'BS': [
                    b'bytes',
                ],
                'M': {
                    'string': {'... recursive ...'}
                },
                'L': [
                    {'... recursive ...'},
                ],
                'NULL': True|False,
                'BOOL': True|False
            }
        },
        Expected={
            'string': {
                'Value': {
                    'S': 'string',
                    'N': 'string',
                    'B': b'bytes',
                    'SS': [
                        'string',
                    ],
                    'NS': [
                        'string',
                    ],
                    'BS': [
                        b'bytes',
                    ],
                    'M': {
                        'string': {'... recursive ...'}
                    },
                    'L': [
                        {'... recursive ...'},
                    ],
                    'NULL': True|False,
                    'BOOL': True|False
                },
                'Exists': True|False,
                'ComparisonOperator': 'EQ'|'NE'|'IN'|'LE'|'LT'|'GE'|'GT'|'BETWEEN'|'NOT_NULL'|'NULL'|'CONTAINS'|'NOT_CONTAINS'|'BEGINS_WITH',
                'AttributeValueList': [
                    {
                        'S': 'string',
                        'N': 'string',
                        'B': b'bytes',
                        'SS': [
                            'string',
                        ],
                        'NS': [
                            'string',
                        ],
                        'BS': [
                            b'bytes',
                        ],
                        'M': {
                            'string': {'... recursive ...'}
                        },
                        'L': [
                            {'... recursive ...'},
                        ],
                        'NULL': True|False,
                        'BOOL': True|False
                    },
                ]
            }
        },
        ConditionalOperator='AND'|'OR',
        ReturnValues='NONE'|'ALL_OLD'|'UPDATED_OLD'|'ALL_NEW'|'UPDATED_NEW',
        ReturnConsumedCapacity='INDEXES'|'TOTAL'|'NONE',
        ReturnItemCollectionMetrics='SIZE'|'NONE',
        ConditionExpression='string',
        ExpressionAttributeNames={
            'string': 'string'
        },
        ExpressionAttributeValues={
            'string': {
                'S': 'string',
                'N': 'string',
                'B': b'bytes',
                'SS': [
                    'string',
                ],
                'NS': [
                    'string',
                ],
                'BS': [
                    b'bytes',
                ],
                'M': {
                    'string': {'... recursive ...'}
                },
                'L': [
                    {'... recursive ...'},
                ],
                'NULL': True|False,
                'BOOL': True|False
            }
        }
    )

    :type TableName: string
    :param TableName: [REQUIRED]
            The name of the table from which to delete the item.

    :type Key: dict
    :param Key: [REQUIRED]
            A map of attribute names to AttributeValue objects, representing the primary key of the item to delete.
            For the primary key, you must provide all of the attributes. For example, with a simple primary key, you only need to provide a value for the partition key. For a composite primary key, you must provide values for both the partition key and the sort key.
            (string) --
            (dict) --Represents the data for an attribute.
            Each attribute value is described as a name-value pair. The name is the data type, and the value is the data itself.
            For more information, see Data Types in the Amazon DynamoDB Developer Guide .
            S (string) --An attribute of type String. For example:
            'S': 'Hello'
            N (string) --An attribute of type Number. For example:
            'N': '123.45'
            Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and libraries. However, DynamoDB treats them as number type attributes for mathematical operations.
            B (bytes) --An attribute of type Binary. For example:
            'B': 'dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk'
            SS (list) --An attribute of type String Set. For example:
            'SS': ['Giraffe', 'Hippo' ,'Zebra']
            (string) --
            NS (list) --An attribute of type Number Set. For example:
            'NS': ['42.2', '-19', '7.5', '3.14']
            Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and libraries. However, DynamoDB treats them as number type attributes for mathematical operations.
            (string) --
            BS (list) --An attribute of type Binary Set. For example:
            'BS': ['U3Vubnk=', 'UmFpbnk=', 'U25vd3k=']
            (bytes) --
            M (dict) --An attribute of type Map. For example:
            'M': {'Name': {'S': 'Joe'}, 'Age': {'N': '35'}}
            (string) --
            (dict) --Represents the data for an attribute.
            Each attribute value is described as a name-value pair. The name is the data type, and the value is the data itself.
            For more information, see Data Types in the Amazon DynamoDB Developer Guide .

            L (list) --An attribute of type List. For example:
            'L': ['Cookies', 'Coffee', 3.14159]
            (dict) --Represents the data for an attribute.
            Each attribute value is described as a name-value pair. The name is the data type, and the value is the data itself.
            For more information, see Data Types in the Amazon DynamoDB Developer Guide .
            NULL (boolean) --An attribute of type Null. For example:
            'NULL': true
            BOOL (boolean) --An attribute of type Boolean. For example:
            'BOOL': true

    :type Expected: dict
    :param Expected: This is a legacy parameter. Use ConditionExpresssion instead. For more information, see Expected in the Amazon DynamoDB Developer Guide .
            (string) --
            (dict) --Represents a condition to be compared with an attribute value. This condition can be used with DeleteItem , PutItem or UpdateItem operations; if the comparison evaluates to true, the operation succeeds; if not, the operation fails. You can use ExpectedAttributeValue in one of two different ways:
            Use AttributeValueList to specify one or more values to compare against an attribute. Use ComparisonOperator to specify how you want to perform the comparison. If the comparison evaluates to true, then the conditional operation succeeds.
            Use Value to specify a value that DynamoDB will compare against an attribute. If the values match, then ExpectedAttributeValue evaluates to true and the conditional operation succeeds. Optionally, you can also set Exists to false, indicating that you do not expect to find the attribute value in the table. In this case, the conditional operation succeeds only if the comparison evaluates to false.
            Value and Exists are incompatible with AttributeValueList and ComparisonOperator . Note that if you use both sets of parameters at once, DynamoDB will return a ValidationException exception.
            Value (dict) --Represents the data for the expected attribute.
            Each attribute value is described as a name-value pair. The name is the data type, and the value is the data itself.
            For more information, see Data Types in the Amazon DynamoDB Developer Guide .
            S (string) --An attribute of type String. For example:
            'S': 'Hello'
            N (string) --An attribute of type Number. For example:
            'N': '123.45'
            Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and libraries. However, DynamoDB treats them as number type attributes for mathematical operations.
            B (bytes) --An attribute of type Binary. For example:
            'B': 'dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk'
            SS (list) --An attribute of type String Set. For example:
            'SS': ['Giraffe', 'Hippo' ,'Zebra']
            (string) --
            NS (list) --An attribute of type Number Set. For example:
            'NS': ['42.2', '-19', '7.5', '3.14']
            Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and libraries. However, DynamoDB treats them as number type attributes for mathematical operations.
            (string) --
            BS (list) --An attribute of type Binary Set. For example:
            'BS': ['U3Vubnk=', 'UmFpbnk=', 'U25vd3k=']
            (bytes) --
            M (dict) --An attribute of type Map. For example:
            'M': {'Name': {'S': 'Joe'}, 'Age': {'N': '35'}}
            (string) --
            (dict) --Represents the data for an attribute.
            Each attribute value is described as a name-value pair. The name is the data type, and the value is the data itself.
            For more information, see Data Types in the Amazon DynamoDB Developer Guide .

            L (list) --An attribute of type List. For example:
            'L': ['Cookies', 'Coffee', 3.14159]
            (dict) --Represents the data for an attribute.
            Each attribute value is described as a name-value pair. The name is the data type, and the value is the data itself.
            For more information, see Data Types in the Amazon DynamoDB Developer Guide .
            NULL (boolean) --An attribute of type Null. For example:
            'NULL': true
            BOOL (boolean) --An attribute of type Boolean. For example:
            'BOOL': true
            Exists (boolean) --Causes DynamoDB to evaluate the value before attempting a conditional operation:
            If Exists is true , DynamoDB will check to see if that attribute value already exists in the table. If it is found, then the operation succeeds. If it is not found, the operation fails with a ConditionalCheckFailedException .
            If Exists is false , DynamoDB assumes that the attribute value does not exist in the table. If in fact the value does not exist, then the assumption is valid and the operation succeeds. If the value is found, despite the assumption that it does not exist, the operation fails with a ConditionalCheckFailedException .
            The default setting for Exists is true . If you supply a Value all by itself, DynamoDB assumes the attribute exists: You don't have to set Exists to true , because it is implied.
            DynamoDB returns a ValidationException if:
            Exists is true but there is no Value to check. (You expect a value to exist, but don't specify what that value is.)
            Exists is false but you also provide a Value . (You cannot expect an attribute to have a value, while also expecting it not to exist.)
            ComparisonOperator (string) --A comparator for evaluating attributes in the AttributeValueList . For example, equals, greater than, less than, etc.
            The following comparison operators are available:
            EQ | NE | LE | LT | GE | GT | NOT_NULL | NULL | CONTAINS | NOT_CONTAINS | BEGINS_WITH | IN | BETWEEN
            The following are descriptions of each comparison operator.
            EQ : Equal. EQ is supported for all data types, including lists and maps. AttributeValueList can contain only one AttributeValue element of type String, Number, Binary, String Set, Number Set, or Binary Set. If an item contains an AttributeValue element of a different type than the one provided in the request, the value does not match. For example, {'S':'6'} does not equal {'N':'6'} . Also, {'N':'6'} does not equal {'NS':['6', '2', '1']} .
            NE : Not equal. NE is supported for all data types, including lists and maps. AttributeValueList can contain only one AttributeValue of type String, Number, Binary, String Set, Number Set, or Binary Set. If an item contains an AttributeValue of a different type than the one provided in the request, the value does not match. For example, {'S':'6'} does not equal {'N':'6'} . Also, {'N':'6'} does not equal {'NS':['6', '2', '1']} .
            LE : Less than or equal.  AttributeValueList can contain only one AttributeValue element of type String, Number, or Binary (not a set type). If an item contains an AttributeValue element of a different type than the one provided in the request, the value does not match. For example, {'S':'6'} does not equal {'N':'6'} . Also, {'N':'6'} does not compare to {'NS':['6', '2', '1']} .
            LT : Less than.  AttributeValueList can contain only one AttributeValue of type String, Number, or Binary (not a set type). If an item contains an AttributeValue element of a different type than the one provided in the request, the value does not match. For example, {'S':'6'} does not equal {'N':'6'} . Also, {'N':'6'} does not compare to {'NS':['6', '2', '1']} .
            GE : Greater than or equal.  AttributeValueList can contain only one AttributeValue element of type String, Number, or Binary (not a set type). If an item contains an AttributeValue element of a different type than the one provided in the request, the value does not match. For example, {'S':'6'} does not equal {'N':'6'} . Also, {'N':'6'} does not compare to {'NS':['6', '2', '1']} .
            GT : Greater than.  AttributeValueList can contain only one AttributeValue element of type String, Number, or Binary (not a set type). If an item contains an AttributeValue element of a different type than the one provided in the request, the value does not match. For example, {'S':'6'} does not equal {'N':'6'} . Also, {'N':'6'} does not compare to {'NS':['6', '2', '1']} .
            NOT_NULL : The attribute exists. NOT_NULL is supported for all data types, including lists and maps.
            Note
            This operator tests for the existence of an attribute, not its data type. If the data type of attribute 'a ' is null, and you evaluate it using NOT_NULL , the result is a Boolean true . This result is because the attribute 'a ' exists; its data type is not relevant to the NOT_NULL comparison operator.
            NULL : The attribute does not exist. NULL is supported for all data types, including lists and maps.
            Note
            This operator tests for the nonexistence of an attribute, not its data type. If the data type of attribute 'a ' is null, and you evaluate it using NULL , the result is a Boolean false . This is because the attribute 'a ' exists; its data type is not relevant to the NULL comparison operator.
            CONTAINS : Checks for a subsequence, or value in a set. AttributeValueList can contain only one AttributeValue element of type String, Number, or Binary (not a set type). If the target attribute of the comparison is of type String, then the operator checks for a substring match. If the target attribute of the comparison is of type Binary, then the operator looks for a subsequence of the target that matches the input. If the target attribute of the comparison is a set ('SS ', 'NS ', or 'BS '), then the operator evaluates to true if it finds an exact match with any member of the set. CONTAINS is supported for lists: When evaluating 'a CONTAINS b ', 'a ' can be a list; however, 'b ' cannot be a set, a map, or a list.
            NOT_CONTAINS : Checks for absence of a subsequence, or absence of a value in a set. AttributeValueList can contain only one AttributeValue element of type String, Number, or Binary (not a set type). If the target attribute of the comparison is a String, then the operator checks for the absence of a substring match. If the target attribute of the comparison is Binary, then the operator checks for the absence of a subsequence of the target that matches the input. If the target attribute of the comparison is a set ('SS ', 'NS ', or 'BS '), then the operator evaluates to true if it does not find an exact match with any member of the set. NOT_CONTAINS is supported for lists: When evaluating 'a NOT CONTAINS b ', 'a ' can be a list; however, 'b ' cannot be a set, a map, or a list.
            BEGINS_WITH : Checks for a prefix.  AttributeValueList can contain only one AttributeValue of type String or Binary (not a Number or a set type). The target attribute of the comparison must be of type String or Binary (not a Number or a set type).
            IN : Checks for matching elements in a list. AttributeValueList can contain one or more AttributeValue elements of type String, Number, or Binary. These attributes are compared against an existing attribute of an item. If any elements of the input are equal to the item attribute, the expression evaluates to true.
            BETWEEN : Greater than or equal to the first value, and less than or equal to the second value.  AttributeValueList must contain two AttributeValue elements of the same type, either String, Number, or Binary (not a set type). A target attribute matches if the target value is greater than, or equal to, the first element and less than, or equal to, the second element. If an item contains an AttributeValue element of a different type than the one provided in the request, the value does not match. For example, {'S':'6'} does not compare to {'N':'6'} . Also, {'N':'6'} does not compare to {'NS':['6', '2', '1']}
            AttributeValueList (list) --One or more values to evaluate against the supplied attribute. The number of values in the list depends on the ComparisonOperator being used.
            For type Number, value comparisons are numeric.
            String value comparisons for greater than, equals, or less than are based on ASCII character code values. For example, a is greater than A , and a is greater than B . For a list of code values, see http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters .
            For Binary, DynamoDB treats each byte of the binary data as unsigned when it compares binary values.
            For information on specifying data types in JSON, see JSON Data Format in the Amazon DynamoDB Developer Guide .
            (dict) --Represents the data for an attribute.
            Each attribute value is described as a name-value pair. The name is the data type, and the value is the data itself.
            For more information, see Data Types in the Amazon DynamoDB Developer Guide .
            S (string) --An attribute of type String. For example:
            'S': 'Hello'
            N (string) --An attribute of type Number. For example:
            'N': '123.45'
            Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and libraries. However, DynamoDB treats them as number type attributes for mathematical operations.
            B (bytes) --An attribute of type Binary. For example:
            'B': 'dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk'
            SS (list) --An attribute of type String Set. For example:
            'SS': ['Giraffe', 'Hippo' ,'Zebra']
            (string) --
            NS (list) --An attribute of type Number Set. For example:
            'NS': ['42.2', '-19', '7.5', '3.14']
            Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and libraries. However, DynamoDB treats them as number type attributes for mathematical operations.
            (string) --
            BS (list) --An attribute of type Binary Set. For example:
            'BS': ['U3Vubnk=', 'UmFpbnk=', 'U25vd3k=']
            (bytes) --
            M (dict) --An attribute of type Map. For example:
            'M': {'Name': {'S': 'Joe'}, 'Age': {'N': '35'}}
            (string) --
            (dict) --Represents the data for an attribute.
            Each attribute value is described as a name-value pair. The name is the data type, and the value is the data itself.
            For more information, see Data Types in the Amazon DynamoDB Developer Guide .

            L (list) --An attribute of type List. For example:
            'L': ['Cookies', 'Coffee', 3.14159]
            (dict) --Represents the data for an attribute.
            Each attribute value is described as a name-value pair. The name is the data type, and the value is the data itself.
            For more information, see Data Types in the Amazon DynamoDB Developer Guide .
            NULL (boolean) --An attribute of type Null. For example:
            'NULL': true
            BOOL (boolean) --An attribute of type Boolean. For example:
            'BOOL': true

    :type ConditionalOperator: string
    :param ConditionalOperator: This is a legacy parameter. Use ConditionExpression instead. For more information, see ConditionalOperator in the Amazon DynamoDB Developer Guide .

    :type ReturnValues: string
    :param ReturnValues: Use ReturnValues if you want to get the item attributes as they appeared before they were deleted. For DeleteItem , the valid values are:
            NONE - If ReturnValues is not specified, or if its value is NONE , then nothing is returned. (This setting is the default for ReturnValues .)
            ALL_OLD - The content of the old item is returned.
            Note
            The ReturnValues parameter is used by several DynamoDB operations; however, DeleteItem does not recognize any values other than NONE or ALL_OLD .

    :type ReturnConsumedCapacity: string
    :param ReturnConsumedCapacity: Determines the level of detail about provisioned throughput consumption that is returned in the response:
            INDEXES - The response includes the aggregate ConsumedCapacity for the operation, together with ConsumedCapacity for each table and secondary index that was accessed. Note that some operations, such as GetItem and BatchGetItem , do not access any indexes at all. In these cases, specifying INDEXES will only return ConsumedCapacity information for table(s).
            TOTAL - The response includes only the aggregate ConsumedCapacity for the operation.
            NONE - No ConsumedCapacity details are included in the response.

    :type ReturnItemCollectionMetrics: string
    :param ReturnItemCollectionMetrics: Determines whether item collection metrics are returned. If set to SIZE , the response includes statistics about item collections, if any, that were modified during the operation are returned in the response. If set to NONE (the default), no statistics are returned.

    :type ConditionExpression: string
    :param ConditionExpression: A condition that must be satisfied in order for a conditional DeleteItem to succeed.
            An expression can contain any of the following:
            Functions: attribute_exists | attribute_not_exists | attribute_type | contains | begins_with | size  These function names are case-sensitive.
            Comparison operators: = | | | | = | = | BETWEEN | IN
            Logical operators: AND | OR | NOT
            For more information on condition expressions, see Specifying Conditions in the Amazon DynamoDB Developer Guide .

    :type ExpressionAttributeNames: dict
    :param ExpressionAttributeNames: One or more substitution tokens for attribute names in an expression. The following are some use cases for using ExpressionAttributeNames :
            To access an attribute whose name conflicts with a DynamoDB reserved word.
            To create a placeholder for repeating occurrences of an attribute name in an expression.
            To prevent special characters in an attribute name from being misinterpreted in an expression.
            Use the # character in an expression to dereference an attribute name. For example, consider the following attribute name:
            Percentile
            The name of this attribute conflicts with a reserved word, so it cannot be used directly in an expression. (For the complete list of reserved words, see Reserved Words in the Amazon DynamoDB Developer Guide ). To work around this, you could specify the following for ExpressionAttributeNames :
            {'#P':'Percentile'}
            You could then use this substitution in an expression, as in this example:
            #P = :val
            Note
            Tokens that begin with the : character are expression attribute values , which are placeholders for the actual value at runtime.
            For more information on expression attribute names, see Accessing Item Attributes in the Amazon DynamoDB Developer Guide .
            (string) --
            (string) --

    :type ExpressionAttributeValues: dict
    :param ExpressionAttributeValues: One or more values that can be substituted in an expression.
            Use the : (colon) character in an expression to dereference an attribute value. For example, suppose that you wanted to check whether the value of the ProductStatus attribute was one of the following:
            Available | Backordered | Discontinued
            You would first need to specify ExpressionAttributeValues as follows:
            { ':avail':{'S':'Available'}, ':back':{'S':'Backordered'}, ':disc':{'S':'Discontinued'} }
            You could then use these values in an expression, such as this:
            ProductStatus IN (:avail, :back, :disc)
            For more information on expression attribute values, see Specifying Conditions in the Amazon DynamoDB Developer Guide .
            (string) --
            (dict) --Represents the data for an attribute.
            Each attribute value is described as a name-value pair. The name is the data type, and the value is the data itself.
            For more information, see Data Types in the Amazon DynamoDB Developer Guide .
            S (string) --An attribute of type String. For example:
            'S': 'Hello'
            N (string) --An attribute of type Number. For example:
            'N': '123.45'
            Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and libraries. However, DynamoDB treats them as number type attributes for mathematical operations.
            B (bytes) --An attribute of type Binary. For example:
            'B': 'dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk'
            SS (list) --An attribute of type String Set. For example:
            'SS': ['Giraffe', 'Hippo' ,'Zebra']
            (string) --
            NS (list) --An attribute of type Number Set. For example:
            'NS': ['42.2', '-19', '7.5', '3.14']
            Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and libraries. However, DynamoDB treats them as number type attributes for mathematical operations.
            (string) --
            BS (list) --An attribute of type Binary Set. For example:
            'BS': ['U3Vubnk=', 'UmFpbnk=', 'U25vd3k=']
            (bytes) --
            M (dict) --An attribute of type Map. For example:
            'M': {'Name': {'S': 'Joe'}, 'Age': {'N': '35'}}
            (string) --
            (dict) --Represents the data for an attribute.
            Each attribute value is described as a name-value pair. The name is the data type, and the value is the data itself.
            For more information, see Data Types in the Amazon DynamoDB Developer Guide .

            L (list) --An attribute of type List. For example:
            'L': ['Cookies', 'Coffee', 3.14159]
            (dict) --Represents the data for an attribute.
            Each attribute value is described as a name-value pair. The name is the data type, and the value is the data itself.
            For more information, see Data Types in the Amazon DynamoDB Developer Guide .
            NULL (boolean) --An attribute of type Null. For example:
            'NULL': true
            BOOL (boolean) --An attribute of type Boolean. For example:
            'BOOL': true

    :rtype: dict
    :return: {
        'Attributes': {
            'string': {
                'S': 'string',
                'N': 'string',
                'B': b'bytes',
                'SS': [
                    'string',
                ],
                'NS': [
                    'string',
                ],
                'BS': [
                    b'bytes',
                ],
                'M': {
                    'string': {'... recursive ...'}
                },
                'L': [
                    {'... recursive ...'},
                ],
                'NULL': True|False,
                'BOOL': True|False
            }
        },
        'ConsumedCapacity': {
            'TableName': 'string',
            'CapacityUnits': 123.0,
            'Table': {
                'CapacityUnits': 123.0
            },
            'LocalSecondaryIndexes': {
                'string': {
                    'CapacityUnits': 123.0
                }
            },
            'GlobalSecondaryIndexes': {
                'string': {
                    'CapacityUnits': 123.0
                }
            }
        },
        'ItemCollectionMetrics': {
            'ItemCollectionKey': {
                'string': {
                    'S': 'string',
                    'N': 'string',
                    'B': b'bytes',
                    'SS': [
                        'string',
                    ],
                    'NS': [
                        'string',
                    ],
                    'BS': [
                        b'bytes',
                    ],
                    'M': {
                        'string': {'... recursive ...'}
                    },
                    'L': [
                        {'... recursive ...'},
                    ],
                    'NULL': True|False,
                    'BOOL': True|False
                }
            },
            'SizeEstimateRangeGB': [
                123.0,
            ]
        }
    }

    :returns:
    (string) --

    """
    pass


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

    The ".dev0" means dirty.

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


def matches(window, window_spec):
    """Return True if the given window matches the given window spec.

    False otherwise.

    A window spec is a dict containing items that will be matched against
    the window object's attributes, for example:

        {'window_id': '0x02a00001',
         'desktop': '0',
         'pid': '4346',
         'wm_class': '.Firefox',
         'machine': 'mistakenot',
         'title': 'The Mock Class - Mock 1.0.1 documentation - Firefox'}

    A window object matches a spec if it has an attribute matching each of
    the items in the spec.

    A spec doesn't have to contain all of the attributes. For example
    {'wm_class': '.Firefox'} will match all windows with a wm_class
    attribute matching ".Firefox".

    Attribute matching is done by looking for substrings. For example a
    wm_class of ".Firefox" will match a window with a wm_class of
    "Navigator.Firefox".

    Window specs can also contain a "command" key (the command to be run to
    launch the app if it doesn't have any open windows) - this key will be
    ignored and the window will match the spec as long as all the other keys
    match.

    """
    for key in window_spec.keys():
        if key == 'command':
            continue
        if window_spec[key].lower() not in getattr(window, key, '').lower():
            return False
    return True


def number_of_occurences(source_string, symbols=None):
    """
        function number_of_occurences()

        Count the number of time the symbol(s) occured in <source_string>.

        source_string   : str
        symbols         : list of strings
    """
    if source_string is None:
        return 0
    nbr = 0
    for char in source_string:
        if char in symbols:
            nbr += 1
    return nbr


@staticmethod
def _dpi(px_per_meter):
    """
        Return the integer pixels per inch from *px_per_meter*, defaulting to
        96 if *px_per_meter* is zero.
        """
    if px_per_meter == 0:
        return 96
    return int(round(px_per_meter * 0.0254))


def fixer_intFloats(value):
    """
	Converts floats like `2.0` into integers.
	"""
    if type(value) is float and int(value) == value:
        return int(value)
    return value


@classmethod
def mainWindows(cls):
    """
        Class method to get references to all main windows.

        @return references to all main window (list of WebBrowserWindow)
        """
    return cls.BrowserWindows


def get_mapped_architectures(sln_setting_2_project_setting, arch):
    """ Get all projects architectures that mapped onto given solution one """
    archs = set()
    for setting in sln_setting_2_project_setting:
        if setting[1] == arch:
            archs.add(sln_setting_2_project_setting[setting][1])
    return archs


@classmethod
def cmd_name(cls):
    """convert child class' __module__ to name of argparse command"""
    name_str = cls.__module__.rsplit('.', 1)[-1]
    if not name_str.endswith(cls._module_postfix):
        raise ImportError(
            f'{name_str} module name must end with "{cls._module_postfix}".')
    return name_str[:-len(cls._module_postfix)]


@classmethod
def make(cls, kvs):
    """Factory method to instantiate a MetricsBase object from the list of key-value pairs."""
    return cls(metric_json=dict(kvs))


@staticmethod
def _lex_lte(x, y, bits):
    """
        Lexicographical LTE comparison

        :param x: The first operand (integer)
        :param y: The second operand (integer)
        :param bits: bit-width of the operands
        :return: True or False
        """
    return x & 2 ** bits - 1 <= y & 2 ** bits - 1


@classmethod
def _get_targets(cls, tree):
    """Get targets of a tree

        Parameters
        ----------
            tree : :class:`ParsedTree <ckipnlp.container.util.parsed_tree.ParsedTree>`
                the parser tree.

        Yields
        ------
            int
                the identifier of target nodes.
            -2
                if the tree is not VP and pos of the first leaf node starts with 'Cb'
            -1
                if the tree is not VP

        Notes
        -----
            A node can be a coreference target if either:

            1. POS-tag is `Nh`
            2. is one of the pronoun words from E-HowNet

        """
    root = tree[tree.root]
    leaves = tree.leaves()
    if root.data.pos == 'VP':
        if leaves[0].data.pos.startswith('Cb'):
            yield -2
        else:
            yield -1
    for node in leaves:
        if cls._is_pronoun_word(node):
            yield node.identifier


def key_by_args_and_func_kw(old_f, args, kw, cache_data):
    """Function to produce a key hash for the cache_data hash based on the function and the arguments
       provided."""
    return repr((old_f, args, kw))


def SetDefaultSASDModel():
    """Fills in default items for the SASD Models dictionary"""
    return {'Back': [0.0, False], 'Size': {'MinDiam': 50, 'MaxDiam': 10000,
        'Nbins': 100, 'logBins': True, 'Method': 'MaxEnt', 'Distribution':
        [], 'Shape': ['Spheroid', 1.0], 'MaxEnt': {'Niter': 100,
        'Precision': 0.01, 'Sky': -3}, 'IPG': {'Niter': 100, 'Approach':
        0.8, 'Power': -1}, 'Reg': {}}, 'Pair': {'Method': 'Moore',
        'MaxRadius': 100.0, 'NBins': 100, 'Errors': 'User', 'Percent error':
        2.5, 'Background': [0, False], 'Distribution': [], 'Moore': 10,
        'Dist G': 100.0, 'Result': []}, 'Particle': {'Matrix': {'Name':
        'vacuum', 'VolFrac': [0.0, False]}, 'Levels': []}, 'Shapes': {
        'outName': 'run', 'NumAA': 100, 'Niter': 1, 'AAscale': 1.0, 'Symm':
        1, 'bias-z': 0.0, 'inflateV': 1.0, 'AAglue': 0.0, 'pdbOut': False,
        'boxStep': 4.0}, 'Current': 'Size dist.', 'BackFile': ''}


def add_edge_attrs(graph, s, t, attrs):
    """Add attributes of an edge in a graph.

    Parameters
    ----------
    graph : regraph.Graph
    s : hashable, source node id.
    t : hashable, target node id.
    attrs : dict
        Dictionary with attributes to remove.

    Raises
    ------
    GraphError
        If an edge between `s` and `t` does not exist.
    """
    graph.add_edge_attrs(s, t, attrs)


def write_NEM(filename, vertices, faces):
    """Writes mesh files used by the Mesh tool included in Nemoh

    Parameters
    ----------
    filename : str
        name of the mesh file to be written on disk
    vertices: ndarray
        numpy array of the coordinates of the mesh's nodes
    faces: ndarray
        numpy array of the faces' nodes connectivities

    Note
    ----
    This file format is different from that used by Nemoh itself. It is only used by the Mesh tool.
    """
    ofile = open(filename, 'w')
    ofile.write('%u\n' % vertices.shape[0])
    ofile.write('%u\n' % faces.shape[0])
    for vertex in vertices:
        ofile.write('%15.6f\t%15.6f\t%15.6f\n' % (vertex[0], vertex[1],
            vertex[2]))
    for face in (faces + 1):
        ofile.write('%10u\t%10u\t%10u\t%10u\n' % (face[0], face[1], face[2],
            face[3]))
    ofile.close()


def _redeployed_method(method_name, reduced_instance, *args, **kwargs):
    """A helper function, that is passed to the separate processes for executing
    the given method.
    This function is necessary, because objects with connectors cannot be pickled,
    so that their methods cannot be passed to a process directly. Instead only the
    relevant data is serialized and passed to the process, where this function
    unwraps this data and executes the method.
    :param method_name: the string name of the method that shall be executed
    :param reduced_instance: a tuple with the class, in which the method is defined
                             and the ``__dict__`` of the instance of which the
                             method shall be executed
    :param `*args,**kwargs`: arguments for the method
    """
    class_, state = reduced_instance
    instance = class_.__new__(class_)
    instance.__dict__.update(state)
    method = getattr(instance, method_name)
    return method(*args, **kwargs)


def date_format(date, api):
    """
    Convert datetime.datetime object to string
    compatible with a given API.
    """
    if api == 'ipea':
        return date.strftime('%Y-%m-%dT00:00:00') + '-00:00'
    if api == 'bcb':
        return date.strftime('%d/%m/%Y')
    if api == 'ibge':
        return date.strftime('%Y%m')


def compute_pelvis_origin(left_asis, right_asis):
    """
    Compute the origin of the pelvis.

    Parameters
    ----------
    left_asis : numpy.ndarray
        1 or 2D (Nx3) array of positions of the left asis marker.
    right_asis : numpy.ndarray
        1 or 2D (Nx3) array of positions of the right asis marker.

    Returns
    -------
    origin : numpy.ndarray
        Array of the position of the pelvis origin.

    References
    ----------
    Ren et al.  "Whole body inverse dynamics over a complete gait cycle based only on measured kinematics."
    *J. of Biomech*. 2008
    """
    origin = (left_asis + right_asis) / 2
    return origin


def lib_relocate():
    """Relocate the library under cursor

    """
    pass


@classmethod
def add_item(cls, *args, **kwargs):
    """Instantiates a new choice and adds it to this list. Signature is
        that of the :meth:`Choice.__init__` method (which might have
        been overridden if you defined a customized
        :attr:`item_class`.

        """
    return cls.add_item_instance(cls.item_class(*args, **kwargs))


def __delitem__(username):
    """
        Given a key of user login name, purge/remove a
        user from the system.

        Note: it is expected that callers will check permissions
        accordingly in the context of the site being managed; this
        component does not check permissions.
        """


def _format_cell(cell, digits):
    """Return a formatted version of this cell of the data table.

    .. note::

        This is a private function called by :func:`print_normal`
        and :func:`print_latex`.

    :param cell:   cell to format
    :param digits: maximum number of digits to display
    :type cell:    `string`
    :type digits:  `integer`

    :return:       the formatted cell
    :rtype:        `string`

    """
    try:
        value = str(float(cell))
        if value[0] is '0':
            return value[1:digits + 2]
        elif value[0] is '-':
            if value[1] is '0':
                return ''.join(['-', value[2:digits + 3]])
            return value[:digits + 2]
        return value[:digits + 1]
    except ValueError:
        return cell


def parse_evidence(evidence):
    """
    From an evidence string/element return a dictionary or obs/counts

    Updated where to handle 0 coverage in an 'N' call! In this case we set
    N = -1

    :param evidence: an evidence string. It looks something like this -
                        Ax27 AGCAx1 AGCAATTAATTAAAATAAx
    """
    obs_count = {}
    elem = evidence.split(' ')
    if elem == ['']:
        obs_count['N'] = -1
    else:
        for e in elem:
            obs, count = e.split('x')
            obs_count[obs] = int(count)
    return obs_count


def write_settings_src(f, settings, embedded_flag):
    """
    Write settings structure to file
    """
    f.write('// Define settings structure\n')
    f.write('OSQPSettings settings = {')
    f.write('(c_float)%.20f, ' % settings['rho'])
    f.write('(c_float)%.20f, ' % settings['sigma'])
    f.write('%d, ' % settings['scaling'])
    if embedded_flag != 1:
        f.write('%d, ' % settings['adaptive_rho'])
        f.write('%d, ' % settings['adaptive_rho_interval'])
        f.write('(c_float)%.20f, ' % settings['adaptive_rho_tolerance'])
    f.write('%d, ' % settings['max_iter'])
    f.write('(c_float)%.20f, ' % settings['eps_abs'])
    f.write('(c_float)%.20f, ' % settings['eps_rel'])
    f.write('(c_float)%.20f, ' % settings['eps_prim_inf'])
    f.write('(c_float)%.20f, ' % settings['eps_dual_inf'])
    f.write('(c_float)%.20f, ' % settings['alpha'])
    f.write('(enum linsys_solver_type) LINSYS_SOLVER, ')
    f.write('%d, ' % settings['scaled_termination'])
    f.write('%d, ' % settings['check_termination'])
    f.write('%d, ' % settings['warm_start'])
    f.write('};\n\n')


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


def pack():
    """Pack the sound into the current blend file

    """
    pass


def _as_list(arr):
    """Make sure input is a list of mxnet NDArray"""
    if not isinstance(arr, (list, tuple)):
        return [arr]
    return arr


@classmethod
def allocate(cls, context, builder, list_type, nitems):
    """
        Allocate a ListInstance with its storage.  Same as allocate_ex(),
        but return an initialized *instance*.  If allocation failed,
        control is transferred to the caller using the target's current
        call convention.
        """
    ok, self = cls.allocate_ex(context, builder, list_type, nitems)
    with builder.if_then(builder.not_(ok), likely=False):
        context.call_conv.return_user_exc(builder, MemoryError, (
            'cannot allocate list',))
    return self


def prune_stats(stats, big_stats, threshold):
    """Prune statistics dict for efficiency of max()
    The frequency of a symbol pair never increases, so pruning is generally safe
    (until we the most frequent pair is less frequent than a pair we previously pruned)
    big_stats keeps full statistics for when we need to access pruned items
    """
    for item, freq in list(stats.items()):
        if freq < threshold:
            del stats[item]
            if freq < 0:
                big_stats[item] += freq
            else:
                big_stats[item] = freq


def make_compat_bytes(in_str):
    """In Py2, does nothing. In Py3, converts to bytes, encoding to unicode."""
    assert isinstance(in_str, str), str(type(in_str))
    return in_str.encode()


def workerConnected(workerName):
    """The worker has connected."""


def decimal(odds):
    """
    Turn decimal odds into a probability.

    >>> decimal(1.8)
    .5405
    """
    return round(1.0 / odds, 4)


def ptcrb_cleaner_multios(item):
    """
    Discard multiple entries for "OS".

    :param item: The item to clean.
    :type item: str
    """
    if item.count('OS') > 1:
        templist = item.split('OS')
        templist[0] = 'OS'
        item = ''.join([templist[0], templist[1]])
    return item


def qci(mask, tfilter=None):
    """
    Compute the quality control index (QCI) for each column, defined as:

    :math:`QCI=\\dfrac{\\sum_{t\\in T}X_{dt}}{|T|}`

    where
    :math:`T` is the set of timestamps in the analysis.
    :math:`X_{dt}` is a data point for column :math:`d` time t` that passed
    all quality control test.
    :math:`|T|` is the number of data points in the analysis.

    Parameters
    ----------
    mask : pandas DataFrame
        Test results mask, returned from pm.mask

    tfilter : pandas Series (optional)
        Time filter containing boolean values for each time index

    Returns
    -------
    pandas Series
        Quality control index
    """
    if tfilter is not None:
        mask = mask[tfilter]
    qci = mask.sum() / mask.shape[0]
    return qci


@classmethod
def _pk_key(cls):
    """Internal. Returns the attribute name that acts as primary key of the model. Can be overridden by subclasses.

        :returns: str -- the name of the primary key attribute for the model
        """
    return 'uuid'


def jwt_response_payload_handler(token, user=None, request=None):
    """
    Returns the response data for both the login and refresh views.
    Override to return a custom response such as including the
    serialized representation of the User.

    Example:

    def jwt_response_payload_handler(token, user=None, request=None):
        return {
            'token': token,
            'user': UserSerializer(user, context={'request': request}).data
        }

    """
    return {'token': token}


def get_config_route(request, config_key: str) ->str:
    """Resolve ``config_key`` to a URL, usually for redirection."""
    settings = request.registry.settings
    try:
        return request.route_url(settings[config_key])
    except KeyError:
        return settings[config_key]


def compute_partition(node, partitions):
    """Compute partition for a node based on its properties"""
    partition_id = None
    if type(partitions) == dict:
        for partition, id in partitions.items():
            if node.has_property(partition):
                partition_id = id
                break
    elif type(partitions) == list:
        for partition in partitions:
            if node.has_property(partition):
                partition_id = partition
                break
    return partition_id


def arctanh(data=None, name=None, attr=None, out=None, **kwargs):
    """Returns the element-wise inverse hyperbolic tangent of the input array, \\
    computed element-wise.

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

       - arctanh(default) = default
       - arctanh(row_sparse) = row_sparse
       - arctanh(csr) = csr

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

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

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

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


@staticmethod
def _fate(future):
    """Return a word describing the state of the given future."""
    if not future.done():
        return 'unfinished'
    elif future.cancelled():
        return 'cancelled'
    elif future.exception() is not None:
        return 'failed'
    else:
        return 'success'


def scroll_up(deltax: int=0, deltay: int=0, page: bool=False):
    """Scroll the view up

    :param deltax: Delta X
    :type deltax: int
    :param deltay: Delta Y
    :type deltay: int
    :param page: Page, Scroll up one page
    :type page: bool
    """
    pass


def abscisse(v):
    """
    Renvoie l'abscisse du vecteur ``v``.
        Arguments:
            v (array): Un vecteur du plan ou de l'espace
    """
    return v[0]


def expected_jk_variance(K):
    """Compute the expected value of the jackknife variance estimate
    over K windows below. This expected value formula is based on the
    asymptotic expansion of the trigamma function derived in
    [Thompson_1994]

    Parameters
    ---------

    K : int
      Number of tapers used in the multitaper method

    Returns
    -------

    evar : float
      Expected value of the jackknife variance estimator

    """
    kf = float(K)
    return 1 / kf * (kf - 1) / (kf - 0.5) * ((kf - 1) / (kf - 2)) ** 2 * (kf -
        3) / (kf - 2)


def list_named_queries(NextToken=None, MaxResults=None):
    """
    Provides a list of all available query IDs.
    For code samples using the AWS SDK for Java, see Examples and Code Samples in the Amazon Athena User Guide .
    See also: AWS API Documentation

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

    :type NextToken: string
    :param NextToken: The token that specifies where to start pagination if a previous request was truncated.

    :type MaxResults: integer
    :param MaxResults: The maximum number of queries to return in this request.

    :rtype: dict
    :return: {
        'NamedQueryIds': [
            'string',
        ],
        'NextToken': 'string'
    }

    :returns:
    (string) --

    """
    pass


def seekable(fileobj):
    """Backwards compat function to determine if a fileobj is seekable

    :param fileobj: The file-like object to determine if seekable

    :returns: True, if seekable. False, otherwise.
    """
    if hasattr(fileobj, 'seekable'):
        return fileobj.seekable()
    elif hasattr(fileobj, 'seek') and hasattr(fileobj, 'tell'):
        try:
            fileobj.seek(0, 1)
            return True
        except (OSError, IOError):
            return False
    return False


@classmethod
def tag_lines(cls, string, tag, is_re=False):
    """Get lines matching tag.

        :returns: list of tag lines.

        See :meth:`tag_split`.
        """
    result = []
    for section in cls.tag_split(string, tag, is_re):
        if section[0]:
            result.append(section[1])
    return result


def convertToRowAndColumn(x, y, shape, xScale=None, yScale=None, safe=True):
    """Return (row, column) of a pixel defined by (x, y) in an image.

    :param float x: Abscissa of point
    :param float x: Ordinate of point
    :param shape: Shape of image (nRows, nColumns)
    :param xScale: Tuple of linear scaling parameters (a, b),
        x = a + b * column
    :param yScale: Tuple of linear scaling parameters (a, b),
        y = a + b * row
    :param bool safe: If True, always return coordinates within the image's
        bounds.
    :return: 2-tuple (r, c)
    """
    if xScale is None:
        c = x
    else:
        c = (x - xScale[0]) / xScale[1]
    if yScale is None:
        r = y
    else:
        r = (y - yScale[0]) / yScale[1]
    if safe:
        c = min(int(c), shape[1] - 1)
        c = max(c, 0)
        r = min(int(r), shape[0] - 1)
        r = max(r, 0)
    else:
        c = int(c)
        r = int(r)
    return r, c


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 coocMatBayesianMean(coocMat, numFights):
    """
    Using "Laplace's method"
    """
    return (coocMat * numFights + 1.0) / (numFights + 2.0)


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


def outside(arr, lowval, highval, type=')('):
    """
    test values of an array are outside the specified values

    parameters
    ----------
    arr: array
        numpy array
    lowval: scalar
        lower value
    highval: scalar
        high value
    type: string, optional
        Interval type, one of )(  ][  ](  )[

        default is )( meaning total exclusion for integers. The
        distinction is often less meaningful for floating points

    returns
    -------
    bool array with True for values outside the range and False otherwise

    example
    -------

    # select elements that equal 25 or are outside 10 and 100, exclusive
    a=numpy.arange(200)
    w,=numpy.where( (a==5) | outside(a,10,100) )

    # select elements that are outside 10 and 100, inclusive
    a=numpy.arange(200)
    w,=numpy.where( outside(a,10,100,'][') )

    """
    if type == ')(':
        logic = (arr < lowval) | (arr > highval)
    elif type == '][':
        logic = (arr <= lowval) | (arr >= highval)
    elif type == '](':
        logic = (arr <= lowval) | (arr > highval)
    elif type == ')[':
        logic = (arr < lowval) | (arr >= highval)
    else:
        raise ValueError("bad range type: '%s'" % type)
    return logic


def get_error(err_id):
    """ get error by id, for error references return their referred error
        """


def CDLHIKKAKEMOD(df):
    """
    Modified Hikkake Pattern
    """


def uuid_encode(uuid):
    """ Turns a UUID instance into a uuid string. """
    if not uuid:
        return ''
    if isinstance(uuid, str):
        return uuid
    return uuid.hex


def byte_to_zwave_brightness(value):
    """Convert brightness in 0-255 scale to 0-99 scale.

    `value` -- (int) Brightness byte value from 0-255.
    """
    if value > 0:
        return max(1, round(value / 255 * 99))
    return 0


@staticmethod
def _read_ptrs(fp, ptr, ptr_size):
    """Read a NULL-terminated array of pointers"""
    fp.seek(ptr)
    chunk = fp.read(50 * ptr_size)
    chunks = [chunk]
    while chunk.find(b'\x00' * ptr_size) == -1:
        chunk = fp.read(50 * ptr_size)
        if not chunk or len(chunks) > 10:
            break
        chunks.append(chunk)
    data = b''.join(chunks)
    data = data[:data.find(b'\x00' * ptr_size)]
    return int(len(data) / ptr_size), data


def split_path(path, minsegs=1, maxsegs=None, rest_with_last=False):
    """Validate and split the given HTTP request path.

    **Examples**::

        ['a'] = split_path('/a')
        ['a', None] = split_path('/a', 1, 2)
        ['a', 'c'] = split_path('/a/c', 1, 2)
        ['a', 'c', 'o/r'] = split_path('/a/c/o/r', 1, 3, True)

    :param path: HTTP Request path to be split
    :param minsegs: Minimum number of segments to be extracted
    :param maxsegs: Maximum number of segments to be extracted
    :param rest_with_last: If True, trailing data will be returned as part
                           of last segment.  If False, and there is
                           trailing data, raises ValueError.
    :returns: list of segments with a length of maxsegs (non-existant
              segments will return as None)
    :raises: ValueError if given an invalid path
    """
    if not maxsegs:
        maxsegs = minsegs
    if minsegs > maxsegs:
        raise ValueError('minsegs > maxsegs: %d > %d' % (minsegs, maxsegs))
    if rest_with_last:
        segs = path.split('/', maxsegs)
        minsegs += 1
        maxsegs += 1
        count = len(segs)
        if segs[0] or count < minsegs or count > maxsegs or '' in segs[1:
            minsegs]:
            return None, None, None
    else:
        minsegs += 1
        maxsegs += 1
        segs = path.split('/', maxsegs)
        count = len(segs)
        if segs[0] or count < minsegs or count > maxsegs + 1 or '' in segs[
            1:minsegs] or count == maxsegs + 1 and segs[maxsegs]:
            raise ValueError('Invalid path: %s' % path)
    segs = segs[1:maxsegs]
    segs.extend([None] * (maxsegs - 1 - len(segs)))
    return segs


def _repr_none(dumper, data_unused):
    """Fix yaml None representation (use ~)."""
    return dumper.represent_scalar('tag:yaml.org,2002:null', '~')


def moc_observation_id(s):
    """
    Remove the forward slash in MOC observation ids

    :param s: MOC observation id
    :return: reformatted id

    >>> moc_observation_id('FHA/00469')
    'FHA00469'
    """
    return s.replace('/', '')


@classmethod
def start(cls, now, number, **options):
    """
        Return the starting datetime: ``number`` of years before ``now``.
        """
    return cls.mask(now).replace(year=now.year - number + 1)


@classmethod
def get_taxes_data_using_ps_data(cls, order_record):
    """Create taxes using details order_record

        :param order_row_record: Objectified XML record sent by pystashop
        :returns: Sale line dictionary of values
        """
    pass


def p_program_char(p):
    """ program : program include_file
                | program line
                | program init
                | program undef
                | program ifdef
                | program require
                | program pragma
                | program errormsg
                | program warningmsg
    """
    p[0] = p[1] + p[2]


def reserved(cls):
    """
	Decorator. This package, class, or function is empty but is declared for future use.
	"""
    return cls


@classmethod
def list_actions(cls):
    """Get a list of exposed actions that are callable via the
        ``do_action()`` method."""
    actions = ['start', 'stop', 'restart', 'status']
    for func_name in dir(cls):
        func = getattr(cls, func_name)
        if not hasattr(func, '__call__') or getattr(func,
            '__daemonocle_exposed__', False) is not True:
            continue
        action = func_name.replace('_', '-')
        if action not in actions:
            actions.append(action)
    return actions


def checkUnique(l):
    """Make sure that l does not contain repeated elements"""
    for i, item1 in enumerate(l):
        for j, item2 in enumerate(l):
            if i != j and item1 == item2:
                raise Exception('Repeated item ' + str(item1))


def encode_long(x):
    """Encode a long to a two's complement little-endian binary string.
    Note that 0 is a special case, returning an empty string, to save a
    byte in the LONG1 pickling context.

    >>> encode_long(0)
    b''
    >>> encode_long(255)
    b'\\xff\\x00'
    >>> encode_long(32767)
    b'\\xff\\x7f'
    >>> encode_long(-256)
    b'\\x00\\xff'
    >>> encode_long(-32768)
    b'\\x00\\x80'
    >>> encode_long(-128)
    b'\\x80'
    >>> encode_long(127)
    b'\\x7f'
    >>>
    """
    if x == 0:
        return b''
    nbytes = (x.bit_length() >> 3) + 1
    result = x.to_bytes(nbytes, byteorder='little', signed=True)
    if x < 0 and nbytes > 1:
        if result[-1] == 255 and result[-2] & 128 != 0:
            result = result[:-1]
    return result


def upload_tw_task(tw_task, trello_list):
    """
    Upload all contents of task to list creating a new card and storing cardid

    :tw_task: TaskWarrior task object
    :trello_list: Trello list object
    """
    new_trello_card = trello_list.add_card(tw_task['description'])
    if tw_task['due']:
        new_trello_card.set_due(tw_task['due'])
    tw_task['trelloid'] = new_trello_card.id
    tw_task.save()


@classmethod
def get_active(cls):
    """
        Return the manager of the active figure, or *None*.
        """
    if len(cls._activeQue) == 0:
        return None
    else:
        return cls._activeQue[-1]


def nfa_union(nfa_1: dict, nfa_2: dict) ->dict:
    """ Returns a NFA that reads the union of the NFAs in input.

    Let :math:`A_1 = (Σ,S_1,S_1^0,ρ_1,F_1)` and :math:`A_2 =(Σ,
    S_2,S_2^0,ρ_2,F_2)` be two NFAs. here is a NFA
    :math:`A_∨` that nondeterministically chooses :math:`A_1` or
    :math:`A_2` and runs it on the input word.
    It is defined as:

    :math:`A_∨ = (Σ, S, S_0 , ρ, F )`

    where:

    • :math:`S = S_1 ∪ S_2`
    • :math:`S_0 = S_1^0 ∪ S_2^0`
    • :math:`F = F_1 ∪ F_2`
    • :math:`ρ = ρ_1 ∪ ρ_2` , that is :math:`(s, a, s' ) ∈ ρ` if
      :math:`[ s ∈ S_1\\ and\\ (s, a, s' ) ∈ ρ_1 ]` OR :math:`[ s ∈
      S_2\\ and\\ (s, a, s' ) ∈ ρ_2 ]`

    Pay attention to avoid having the NFAs with state names in common, in case
    use :mod:`PySimpleAutomata.NFA.rename_nfa_states` function.

    :param dict nfa_1: first input NFA;
    :param dict nfa_2: second input NFA.
    :return: *(dict)* representing the united NFA.
    """
    union = {'alphabet': nfa_1['alphabet'].union(nfa_2['alphabet']),
        'states': nfa_1['states'].union(nfa_2['states']), 'initial_states':
        nfa_1['initial_states'].union(nfa_2['initial_states']),
        'accepting_states': nfa_1['accepting_states'].union(nfa_2[
        'accepting_states']), 'transitions': nfa_1['transitions'].copy()}
    for trans in nfa_2['transitions']:
        for elem in nfa_2['transitions'][trans]:
            union['transitions'].setdefault(trans, set()).add(elem)
    return union


def p_struct_body(t):
    """struct_body : LBRACE declaration_list RBRACE"""
    t[0] = t[2]


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

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


def find(match_result_df, unit_id, df_all):
    """
    This function is used to find the main matched group of the unit_id

    Args:
        match_result_df: The algorithm's pre-calculated dataframe with all
            the groups of each unit
        unit_id: the id of the unit that we want to match
        df_all: The cleaned, user-provided dataframe with all rows/columns.
            There are no changes made to this throughout the code. In the
            paper, it's called 'D'.

    Returns:
        mmg_matches: the subset of df_all with only units that in the mmg
    """
    if len(match_result_df.columns) == 0 or len(match_result_df) == 0:
        return False
    if unit_id not in match_result_df.index:
        return False
    group_of_unit = match_result_df.loc[unit_id]
    mmg_matches = df_all[match_result_df.columns]
    for colname, group_val in group_of_unit.iteritems():
        if group_val == '*':
            continue
        else:
            mmg_matches = mmg_matches.loc[mmg_matches[colname] == group_val]
    return mmg_matches


@classmethod
def set_agpl_internal_use(cls):
    """Deprecated after change to LGPLv3 and has no effect."""
    pass


def _do_get_latest_featuregroup_version(featuregroup_name,
    featurestore_metadata):
    """
    Utility method to get the latest version of a particular featuregroup

    Args:
        :featuregroup_name: the featuregroup to get the latest version of
        :featurestore_metadata: metadata of the featurestore

    Returns:
        the latest version of the featuregroup in the feature store
    """
    featuregroups = featurestore_metadata.featuregroups.values()
    matches = list(filter(lambda fg: fg.name == featuregroup_name,
        featuregroups))
    versions = list(map(lambda fg: int(fg.version), matches))
    if len(versions) > 0:
        return max(versions)
    else:
        return 0


def save_session_data(strategy, request, response, *args, **kwargs):
    """Save some data in the session"""
    session_state = strategy.request_data().get('session_state')
    if session_state:
        request.session['session_state'] = session_state
    id_token = response.get('id_token')
    if id_token:
        request.session['id_token'] = id_token


def __getattr__(name):
    """ Returns the current property value
        """


@classmethod
def setup_instance(cls, remote):
    """Prepares an instance to mount this type of share."""
    pass


def sec_to_timestring(seconds):
    """Transform seconds into a formatted time string.

    Parameters
    -----------
    seconds : int
        Seconds to be transformed.
    Returns
    -----------
    time : string
        A well formatted time string.
    """
    m, s = divmod(seconds, 60)
    h, m = divmod(m, 60)
    return '%02d:%02d:%02d' % (h, m, s)


@staticmethod
def calculate_purchase_cost(cost_per_share, num_of_shares):
    """
        This method calculates the purchase cost, which is the paid value for every stock share hold by the user at
        the time that stock shares were bought.
        """
    return float(cost_per_share * num_of_shares)


def delete_rule(RuleId=None, ChangeToken=None):
    """
    Permanently deletes a  Rule . You can't delete a Rule if it's still used in any WebACL objects or if it still includes any predicates, such as ByteMatchSet objects.
    If you just want to remove a Rule from a WebACL , use  UpdateWebACL .
    To permanently delete a Rule from AWS WAF, perform the following steps:
    See also: AWS API Documentation

    Examples
    The following example deletes a rule with the ID WAFRule-1-Example.
    Expected Output:

    :example: response = client.delete_rule(
        RuleId='string',
        ChangeToken='string'
    )

    :type RuleId: string
    :param RuleId: [REQUIRED]
            The RuleId of the Rule that you want to delete. RuleId is returned by CreateRule and by ListRules .

    :type ChangeToken: string
    :param ChangeToken: [REQUIRED]
            The value returned by the most recent call to GetChangeToken .

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

    :returns:
    RuleId (string) -- [REQUIRED]
    The RuleId of the  Rule that you want to delete. RuleId is returned by  CreateRule and by  ListRules .

    ChangeToken (string) -- [REQUIRED]
    The value returned by the most recent call to  GetChangeToken .

    """
    pass


def median(x):
    """
	Calculates the median value of an array
	"""
    x.sort()
    n = len(x)
    if n < 1:
        print('List too short.')
        return
    if n % 2 == 1:
        return x[n // 2]
    else:
        return sum(x[n // 2 - 1:n // 2 + 1]) / 2.0


@classmethod
def register(cls, name, searcher):
    """ register principal searcher:

        .. code-block:: python

          def searcher(term):
              ...

          ptah.principal_searcher.register('test', searcher)

        """
    cls(name, 2)(searcher)


def disperse(n, k):
    """
    Disperses a number n between m different groups.
    The sum of all groups must be smaller or equal to n.
    (Yes, the sum can be smaller - that is, a group of zeros is also an answer)

    The answer will have (n + k)! / (n! k!) groups.

    :param n: The number to disperse between groups
    :type n: int
    :param k: The amount of groups to disperse n into
    :type k: int

    :return: All of the options of dispersion - length of (n + k)! / (n! k!)
    :rtype: list of tuples (of ints)
    """
    options = [()]
    for group in range(k):
        new_options = []
        for option in options:
            remainder = n - sum(option)
            for i in range(remainder + 1):
                new_options.append(option + (i,))
        del options
        options = new_options
    return options


def write_bdfs_list(bdf_files, cards, size, is_double, is_long_ids):
    """writes a list by ifile"""
    assert isinstance(cards, list), cards
    if is_long_ids:
        for card in cards:
            bdf_files[card.ifile].write_card_16(size, is_double)
    else:
        for card in cards:
            bdf_files[card.ifile].write_card(size, is_double)


def select_linked_to():
    """Select nodes linked to the selected ones

    """
    pass


def fan_in_out_capacities(topology):
    """Calculate fan-in and fan-out capacities for all nodes of the topology.

    The fan-in capacity of a node is the sum of capacities of all incoming
    links, while the fan-out capacity is the sum of capacities of all outgoing
    links.

    Parameters
    ----------
    topology : Topology
        The topology object whose fan-in and fan-out capacities are calculated.
        This topology must be annotated with link capacities.

    Returns
    -------
    fan_in_out_capacities : tuple (fan_in, fan_out)
        A tuple of two dictionaries, representing, respectively the fan-in and
        fan-out capacities keyed by node.

    Notes
    -----
    This function works correctly for both directed and undirected topologies.
    If the topology is undirected, the returned dictionaries of fan-in and
    fan-out capacities are identical.

    Examples
    --------
    >>> import fnss
    >>> topology = fnss.star_topology(3)
    >>> fnss.set_capacities_constant(topology, 10, 'Mbps')
    >>> in_cap, out_cap = fnss.fan_in_out_capacities(topology)
    >>> in_cap
    {0: 30, 1: 10, 2: 10, 3: 10}
    >>> out_cap
    {0: 30, 1: 10, 2: 10, 3: 10}
    """
    if not topology.is_directed():
        topology = topology.to_directed()
    fan_in = {}
    fan_out = {}
    for node in topology.nodes():
        node_fan_in = 0
        node_fan_out = 0
        for predecessor in topology.predecessors(node):
            node_fan_in += topology.adj[predecessor][node]['capacity']
        for successor in topology.successors(node):
            node_fan_out += topology.adj[node][successor]['capacity']
        fan_in[node] = node_fan_in
        fan_out[node] = node_fan_out
    return fan_in, fan_out


def symboles(ligne):
    """
    Retourne les couples (), [] ou [) correspondant au type de ligne
    @param ligne: droite, demi-droite ou segment
    @type ligne: string
    """
    if ligne == 'une droite':
        retour = ['(', ')']
    elif ligne == 'une demi-droite':
        retour = ['[', ')']
    else:
        retour = ['[', ']']
    return retour


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

        :param LegalHoldsRemoveMembersDetails val:
        :rtype: EventDetails
        """
    return cls('legal_holds_remove_members_details', val)


def is_valid_method_param(met):
    """ Checks if method is compatible with GROMACS """
    methods = ['linkage', 'jarvis-patrick', 'monte-carlo',
        'diagonalization', 'gromos']
    return met in methods


@staticmethod
def expand_vlans(vlans):
    """
        Will expand a comma separated list of vlan ids into a list of discrete vlan ids
        :rtype : list
        :param vlans: str of comma separated vlan lists
        """
    vlan_ranges = vlans.split(',')
    vlan_list = []
    for v_range in vlan_ranges:
        if '-' in v_range:
            [v_low, v_hi] = v_range.split('-')
            vlan_list.extend(range(int(v_low), int(v_hi) + 1))
        else:
            vlan_list.append(v_range)
    return vlan_list


def drop_sessions():
    """
        Drop current db sessions
    """
    global sessions
    sessions = {}
    return True


def randomize_unitofwork():
    """Use random-ordering sets within the unit of work in order
    to detect unit of work sorting issues.

    This is a utility function that can be used to help reproduce
    inconsistent unit of work sorting issues.   For example,
    if two kinds of objects A and B are being inserted, and
    B has a foreign key reference to A - the A must be inserted first.
    However, if there is no relationship between A and B, the unit of work
    won't know to perform this sorting, and an operation may or may not
    fail, depending on how the ordering works out.   Since Python sets
    and dictionaries have non-deterministic ordering, such an issue may
    occur on some runs and not on others, and in practice it tends to
    have a great dependence on the state of the interpreter.  This leads
    to so-called "heisenbugs" where changing entirely irrelevant aspects
    of the test program still cause the failure behavior to change.

    By calling ``randomize_unitofwork()`` when a script first runs, the
    ordering of a key series of sets within the unit of work implementation
    are randomized, so that the script can be minimized down to the
    fundamental mapping and operation that's failing, while still reproducing
    the issue on at least some runs.

    This utility is also available when running the test suite via the
    ``--reversetop`` flag.

    """
    from sqlalchemy.orm import unitofwork, session, mapper, dependency
    from sqlalchemy.util import topological
    from sqlalchemy.testing.util import RandomSet
    (topological.set) = (unitofwork.set) = (session.set) = (mapper.set) = (
        dependency.set) = RandomSet


def bytes_to_num(data):
    """ *data* must be at least 4 bytes long, big-endian order. """
    assert len(data) >= 4
    num = data[3]
    num += data[2] << 8 & 65280
    num += data[1] << 16 & 16711680
    num += data[0] << 24 & 4278190080
    return num


def add(s, instance):
    """
    Add an instance to the session (and so to the database), returning the instance.
    You likely don't need this - see the more specific helpers below.

    The instance can of any class that subclasses the Field class from SQLAlchemy.
    In practice, that means most classes in the ch2.sql.tables module.
    However, only some classes make sense in the context of a configuration, and
    more specific helpers probably already exist for those.
    """
    s.add(instance)
    return instance


@classmethod
def _x_request_elements_filter(cls, request_type, request_elements, credentials
    ):
    """
        Google doesn't accept client ID and secret to be at the same time in
        request parameters and in the basic authorization header in the
        access token request.
        """
    if request_type is cls.ACCESS_TOKEN_REQUEST_TYPE:
        params = request_elements[2]
        del params['client_id']
        del params['client_secret']
    return request_elements


def to_drawing(g, d=None, edges=[]):
    """
    draws Graph to a `Drawing`
    :param g: :class:`Graph`
    :param d: existing :class:`Drawing` to draw onto, or None to create a new Drawing
    :param edges: iterable of edges (with data) that will be added, in the same order. By default all edges are drawn
    :return: :class:`Drawing`

    Graph edges with an 'entity' property
    """
    from . import drawing, geom
    if d is None:
        d = drawing.Drawing()
    if not edges:
        edges = g.edges(data=True)
    for edge in edges:
        u, v, data = edge[0], edge[1], edge[-1]
        try:
            e = data['entity']
        except KeyError:
            u = g.pos(u)
            v = g.pos(v)
            e = geom.Segment2(u, v)
        d.append(e)
    return d


def p_UnionMemberTypes(p):
    """UnionMemberTypes : or UnionMemberType UnionMemberTypes"""
    p[0] = [p[2]] + p[3]


def _aespad(data):
    """ipmi demands a certain pad scheme, per table 13-20 AES-CBC encrypted

    payload fields.
    """
    currlen = len(data) + 1
    neededpad = currlen % 16
    if neededpad:
        neededpad = 16 - neededpad
    padval = 1
    pad = bytearray(neededpad)
    while padval <= neededpad:
        pad[padval - 1] = padval
        padval += 1
    pad.append(neededpad)
    return pad


def lcstr(astr):
    """Convert a string to lower-case"""
    return astr.lower()


def sort_layer_list(net, layer_list):
    """sort layers in the list as the order in the net"""
    layer_index_list = []
    for layer in layer_list:
        for layer_index, layer0 in enumerate(net.blobs.keys()):
            if layer0 == layer:
                layer_index_list.append(layer_index)
                break
    layer_index_list_sorted = sorted(layer_index_list)
    layer_list_sorted = []
    for layer_index in layer_index_list_sorted:
        list_index = layer_index_list.index(layer_index)
        layer = layer_list[list_index]
        layer_list_sorted.append(layer)
    return layer_list_sorted


def _make_linear_gradient(X, Y, angle):
    """Generates index map for linear gradients."""
    import numpy as np
    theta = np.radians(angle % 360)
    Z = 0.5 * (np.cos(theta) * X - np.sin(theta) * Y + 1)
    return Z


def _remove_suffix_apple(path):
    """
    Strip off .so or .dylib.

    >>> _remove_suffix_apple("libpython.so")
    'libpython'
    >>> _remove_suffix_apple("libpython.dylib")
    'libpython'
    >>> _remove_suffix_apple("libpython3.7")
    'libpython3.7'
    """
    if path.endswith('.dylib'):
        return path[:-len('.dylib')]
    if path.endswith('.so'):
        return path[:-len('.so')]
    return path


def update_track_tags(fileinfo, release):
    """Return True if the track tags were changed."""
    changed = False
    for track in release['media'][0]['tracks']:
        track_number = track['number']
        tags = fileinfo.tags.track_tags(track_number)
        tags['TITLE'] = track['title']
        if 'artist' in track:
            tags['ARTIST'] = track['artist']
        if fileinfo.tags.update_track(track_number, tags):
            changed = True
    return changed


def compare_files(a, b):
    """Returns true if equal in contents"""
    BUFSIZE = 4096
    while True:
        ai = a.read(BUFSIZE)
        bi = b.read(BUFSIZE)
        if ai != bi:
            return False
        if not ai:
            return True


def pipe(obj, func, *args, **kwargs):
    """
    Apply a function ``func`` to object ``obj`` either by passing obj as the
    first argument to the function or, in the case that the func is a tuple,
    interpret the first element of the tuple as a function and pass the obj to
    that function as a keyword argument whose key is the value of the second
    element of the tuple.

    Parameters
    ----------
    func : callable or tuple of (callable, str)
        Function to apply to this object or, alternatively, a
        ``(callable, data_keyword)`` tuple where ``data_keyword`` is a
        string indicating the keyword of `callable`` that expects the
        object.
    *args : iterable, optional
        Positional arguments passed into ``func``.
    **kwargs : dict, optional
        A dictionary of keyword arguments passed into ``func``.

    Returns
    -------
    object : the return type of ``func``.
    """
    if isinstance(func, tuple):
        func, target = func
        if target in kwargs:
            msg = f'{target} is both the pipe target and a keyword argument'
            raise ValueError(msg)
        kwargs[target] = obj
        return func(*args, **kwargs)
    else:
        return func(obj, *args, **kwargs)


def _is_dunder(name):
    """Returns True if a __dunder__ name, False otherwise."""
    return name[:2] == name[-2:] == '__' and name[2:3] != '_' and name[-3:-2
        ] != '_' and len(name) > 4


def get_full_version(value=None):
    """
    Returns a tuple of the iviewer version.
    """
    if value is None:
        from .version import VERSION as value
    return value


def cube_row(color):
    """
    Format color tuple as string for a CUBE file line
    """
    return ' '.join(map(lambda x: str(x / 255), color))


def files_in_dictionary(result):
    """
        Parsing function that returns a dictionary containing one entry for
        each file. Typically used to perform parsing externally.
        """
    return result['output']


def SizeBenefitLiving(t):
    """Living benefit per policy"""
    return 0


def from_jd(jd):
    """Return tuple of ISO (year, week, day) for Julian day"""
    gpsweek = int((jd - 2444244.5) / 7)
    dow = ((jd - 2444244.5) / 7 - gpsweek) * 7
    dow = int(round(dow * 86400) / 86400)
    return gpsweek, dow


def drop_color(color: float=(0.0, 0.0, 0.0), gamma: bool=False):
    """Drop colors to buttons

    :param color: Color, Source color
    :type color: float
    :param gamma: Gamma Corrected, The source color is gamma corrected
    :type gamma: bool
    """
    pass


@classmethod
def get(cls):
    """
        .. note:: Experimental

        Return the currently active :class:`BarrierTaskContext`.
        This can be called inside of user functions to access contextual information about
        running tasks.

        .. note:: Must be called on the worker, not the driver. Returns None if not initialized.
        """
    return cls._taskContext


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

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


def ftos(Float_Value):
    """
    string ftos(float)

    convert float to string
    Instead of using python's ftos(), use this one to control the precision
    my Float to String mini function

    Precision = %.4f
    Unnecessary 0 will be discarded
    """
    S = '%.4f' % Float_Value
    n = len(S)
    if S[n - 5] == '.':
        if S[n - 4:n] == '0000':
            S = S[0:n - 5]
        elif S[n - 3:n] == '000':
            S = S[0:n - 3]
        elif S[n - 2:n] == '00':
            S = S[0:n - 2]
        elif S[n - 1] == '0':
            S = S[0:n - 1]
    return S


@staticmethod
def get_opt(opt_name, args):
    """Return option name and value.

        :param opt_name: name of the option, e.g., "username"
        :param args: parsed arguments
        """
    return opt_name, getattr(args, 'os_%s' % opt_name, None)


def _client_error_status(ex):
    """Get the HTTP status for the given ClientError"""
    resp = ex.response
    return resp.get('Error', {}).get('HTTPStatusCode') or resp.get(
        'ResponseMetadata', {}).get('HTTPStatusCode')


def export_agent_data(model):
    """Helper function for export_data, but accessible to user if preferred.

    :param model: An Open ABM supported model / environment instance

    :return: Agent-level data
    :rtype: Pandas Dataframe

    """
    data = model.datacollector.get_agent_vars_dataframe()
    return data


def _find_contraction(positions, input_sets, output_set):
    """
    Finds the contraction for a given set of input and output sets.

    Parameters
    ----------
    positions : iterable
        Integer positions of terms used in the contraction.
    input_sets : list
        List of sets that represent the lhs side of the einsum subscript
    output_set : set
        Set that represents the rhs side of the overall einsum subscript

    Returns
    -------
    new_result : set
        The indices of the resulting contraction
    remaining : list
        List of sets that have not been contracted, the new set is appended to
        the end of this list
    idx_removed : set
        Indices removed from the entire contraction
    idx_contraction : set
        The indices used in the current contraction

    Examples
    --------

    # A simple dot product test case
    >>> pos = (0, 1)
    >>> isets = [set('ab'), set('bc')]
    >>> oset = set('ac')
    >>> _find_contraction(pos, isets, oset)
    ({'a', 'c'}, [{'a', 'c'}], {'b'}, {'a', 'b', 'c'})

    # A more complex case with additional terms in the contraction
    >>> pos = (0, 2)
    >>> isets = [set('abd'), set('ac'), set('bdc')]
    >>> oset = set('ac')
    >>> _find_contraction(pos, isets, oset)
    ({'a', 'c'}, [{'a', 'c'}, {'a', 'c'}], {'b', 'd'}, {'a', 'b', 'c', 'd'})
    """
    idx_contract = set()
    idx_remain = output_set.copy()
    remaining = []
    for ind, value in enumerate(input_sets):
        if ind in positions:
            idx_contract |= value
        else:
            remaining.append(value)
            idx_remain |= value
    new_result = idx_remain & idx_contract
    idx_removed = idx_contract - new_result
    remaining.append(new_result)
    return new_result, remaining, idx_removed, idx_contract


@staticmethod
def bernoulli(tensor):
    """Generate random ArithmeticSharedTensor bernoulli on {0, 1}"""
    raise NotImplementedError('HomomorphicProvider not implemented')


def determinant(q_form):
    """
    The determinant of a tensor, given in quadratic form

    Parameters
    ----------
    q_form : ndarray
        The quadratic form of a tensor, or an array with quadratic forms of
        tensors. Should be of shape (x, y, z, 3, 3) or (n, 3, 3) or (3, 3).

    Returns
    -------
    det : array
        The determinant of the tensor in each spatial coordinate
    """
    aei = q_form[..., 0, 0] * q_form[..., 1, 1] * q_form[..., 2, 2]
    bfg = q_form[..., 0, 1] * q_form[..., 1, 2] * q_form[..., 2, 0]
    cdh = q_form[..., 0, 2] * q_form[..., 1, 0] * q_form[..., 2, 1]
    ceg = q_form[..., 0, 2] * q_form[..., 1, 1] * q_form[..., 2, 0]
    bdi = q_form[..., 0, 1] * q_form[..., 1, 0] * q_form[..., 2, 2]
    afh = q_form[..., 0, 0] * q_form[..., 1, 2] * q_form[..., 2, 1]
    return aei + bfg + cdh - ceg - bdi - afh


def overlap(exc, interval):
    """
  Check whether the time interval definded in exc
  (exc.startTime to exc.endTime) has non-zero overlap
  with time interval given as the second argument.
  """
    start, end = interval
    return (start <= exc.startTime < end or start < exc.endTime <= end or
        exc.startTime <= start and exc.endTime >= end)


def clear_silva_addables_forbidden():
    """Clear any forbidden addables. All addables show up in the
        SMI again.
        """


def lamda_to_hitran(level, mol):
    """Convert levels from Lamda to HITRAN notation

    Parameters
    ----------
    level : str
        LAMDA level notation
    mol : str
        molecule name
    """
    import re
    if mol == 'aCH3OH':
        m = re.match('(\\d+)_(-?)(\\d+)', level)
        if m.group(2) == '-':
            quanta = m.group(1).rjust(3) + m.group(3).rjust(3) + '  A-     '
        else:
            quanta = m.group(1).rjust(3) + m.group(3).rjust(3) + '  A+     '
    elif mol == 'eCH3OH':
        m = re.match('(\\d+)_(-?)(\\d+)', level)
        if m.group(2) == '-':
            quanta = m.group(1).rjust(3) + m.group(3).rjust(3) + '  E2     '
        else:
            quanta = m.group(1).rjust(3) + m.group(3).rjust(3) + '  E1     '
    elif mol == 'H2O' or mol == 'HDO':
        m = re.match('(\\d+)_(\\d+)_(\\d+)', level)
        quanta = m.group(1).rjust(3) + m.group(2).rjust(3) + m.group(3).rjust(3
            ) + '      '
    return quanta.encode('utf-8')


def editmode_toggle():
    """Toggle object’s editmode

    """
    pass


def index_rules_by_type(rules):
    """
    Indexes a list of rules by type name,
    while maintaining rule order for each rule type

    Sample Input:
    [
        <TimeRule: Time Rule>,
        <TimeRule: Time Rule>,
        <UserIsLoggedInRule: Logged in Rule>
    ]

    Sample Output:
    {
        'TimeRule': [ <TimeRule: Time Rule>, <TimeRule: Time Rule> ],
        'UserIsLoggedInRule': [ <UserIsLoggedInRule: Logged in Rule> ]
    }
    """
    indexed_rules = {}
    for rule in rules:
        type_name = type(rule).__name__
        if type_name in indexed_rules:
            indexed_rules[type_name].append(rule)
        else:
            indexed_rules[type_name] = [rule]
    return indexed_rules


@staticmethod
def custom_value_proc(value):
    """Custom value_proc function for the click.prompt which it will call to do value conversion.

        Simply return the value, because we want to take care of value conversion ourselves in the `simple_prompt_loop`.
        If we let `click.prompt` do it, it will raise an exception when the user passes a control character, like the
        question mark, to bring up the help message and the type of the option is not a string, causing conversion to
        fail.
        """
    return value


def filter_objects(entries: list, **kwargs) ->list:
    """Filters a list of objects of any type according to given keyword arguments"""
    filtered_entries = []
    for entry in entries:
        for key, value in kwargs.items():
            if getattr(entry, key) != value:
                break
        else:
            filtered_entries.append(entry)
    return filtered_entries


@staticmethod
def toggle_pause(env, _gui):
    """Pause/unpause simulation."""
    env.toggle_pause()


@classmethod
def class_key(cls):
    """Nice order of classes"""
    return 3, 1, cls.__name__


def add_marker_slide(CLIP_OT_add_marker=None, TRANSFORM_OT_translate=None):
    """Add new marker and slide it with mouse until mouse button release

    :param CLIP_OT_add_marker: Add Marker, Place new marker at specified location
    :param TRANSFORM_OT_translate: Translate, Translate (move) selected items
    """
    pass


def commit(transactionid):
    """STOMP commit command.

    Do whatever is required to make the series of actions
    permanent for this transactionid.

    transactionid:
        This is the id that all actions in this transaction.

    """
    return 'COMMIT\ntransaction:%s\n\n\x00\n' % transactionid


def get_payment_receipt_identifier(method_name):
    """If the printer requires an identifier to open a payment receipt,
        this method should return that identifier.

        @param method_name: get receipt for specific method name.
        """


def layer_isolate(affect_visibility: bool=False):
    """Toggle whether the active layer is the only one that can be edited and/or visible

    :param affect_visibility: Affect Visibility, In addition to toggling the editability, also affect the visibility
    :type affect_visibility: bool
    """
    pass


@classmethod
def get(cls, alarm: int):
    """
        Get the attribute of this enum for an alarm number.

        :param alarm: the alarm number
        :return: the enum for the desired alarm number
        """
    try:
        return getattr(cls, 'Alarm{}'.format(alarm))
    except AttributeError:
        return cls.not_defined


@staticmethod
def check_args(args):
    """ Returns True if an argument was given False otherwise. Used in setup """
    for arg in vars(args):
        if getattr(args, arg):
            return True
    return False


def _depluralise_filters_key(kwargs):
    """Filter/Filters -> Filter"""
    if 'filters' in kwargs:
        kwargs['filter'] = kwargs.pop('filters')
    return kwargs


def psi_Na_Cl_NO3_PK74(T, P):
    """c-a-a': sodium chloride nitrate [PK74]."""
    psi = -0.006
    valid = T == 298.15
    return psi, valid


@classmethod
def detect(cls, value):
    """
        Possible formats
        - name, web name, (CornflowerBlue)
        - hex, hexadecimal (#AABBCC)
        - rgb, tuple (R,G,B)
        - xy, list pair [x, y]
        """
    pass


def tweets_to_file(tweets, tweetfile, append=False, pure_json=False, pretty
    =False):
    """
    Exports a collection (iterable) of tweets to given file. Exports tweets in mongoDB
    extended special bson format.
    To append to given tweetfile, pass append=True
    For pure json (not bson object rep), pass pure_json=True.
    To pretty-print json (value-per-line and spacing), pass pretty=True
    """
    raise DeprecationWarning(
        "'tweets_to_file' is deprecated. Use 'tweets_to_bson' or 'tweets_to_json' instead."
        )
    return


def branchtip(branchtip, ignoremissing=False):
    """Return the tip node for a given branch."""


def get_error_message(response):
    """
    Gets the error message from a JSON response.
    :return: the error message
    :rtype: string
    """
    error_message = 'Unknown error'
    try:
        error_json = response.json()
        if 'error' in error_json:
            if isinstance(error_json['error'], dict
                ) and 'description' in error_json['error']:
                error_message = error_json['error']['description']
            else:
                error_message = error_json['error']
        elif 'error_message' in error_json:
            error_message = error_json['error_message']
        elif 'errorMessage' in error_json:
            error_message = error_json['errorMessage']
        elif 'msg' in error_json:
            error_message = error_json['msg']
        elif 'statusInfo' in error_json:
            error_message = error_json['statusInfo']
        return error_message
    except:
        return response.text or error_message


def jaccard_join(ltable, rtable, l_key_attr, r_key_attr, l_join_attr,
    r_join_attr, tokenizer, threshold, comp_op='>=', allow_empty=True,
    allow_missing=False, l_out_attrs=None, r_out_attrs=None, l_out_prefix=
    'l_', r_out_prefix='r_', out_sim_score=True, n_jobs=1, show_progress=True):
    """Join two tables using Jaccard similarity measure.

    For two sets X and Y, the Jaccard similarity score between them is given by:

        :math:`jaccard(X, Y) = \\frac{|X \\cap Y|}{|X \\cup Y|}`

    In the case where both X and Y are empty sets, we define their Jaccard
    score to be 1.

    Finds tuple pairs from left table and right table such that the Jaccard
    similarity between the join attributes satisfies the condition on input
    threshold. For example, if the comparison operator is '>=', finds tuple
    pairs whose Jaccard similarity between the strings that are the values of
    the join attributes is greater than or equal to the input threshold, as
    specified in "threshold".

    Args:
        ltable (DataFrame): left input table.

        rtable (DataFrame): right input table.

        l_key_attr (string): key attribute in left table.

        r_key_attr (string): key attribute in right table.

        l_join_attr (string): join attribute in left table.

        r_join_attr (string): join attribute in right table.

        tokenizer (Tokenizer): tokenizer to be used to tokenize join
            attributes.

        threshold (float): Jaccard similarity threshold to be satisfied.

        comp_op (string): comparison operator. Supported values are '>=', '>'
            and '=' (defaults to '>=').

        allow_empty (boolean): flag to indicate whether tuple pairs with empty
            set of tokens in both the join attributes should be included in the
            output (defaults to True).

        allow_missing (boolean): flag to indicate whether tuple pairs with
            missing value in at least one of the join attributes should be
            included in the output (defaults to False). If this flag is set to
            True, a tuple in ltable with missing value in the join attribute
            will be matched with every tuple in rtable and vice versa.

        l_out_attrs (list): list of attribute names from the left table to be
            included in the output table (defaults to None).

        r_out_attrs (list): list of attribute names from the right table to be
            included in the output table (defaults to None).

        l_out_prefix (string): prefix to be used for the attribute names coming
            from the left table, in the output table (defaults to 'l\\_').

        r_out_prefix (string): prefix to be used for the attribute names coming
            from the right table, in the output table (defaults to 'r\\_').

        out_sim_score (boolean): flag to indicate whether similarity score
            should be included in the output table (defaults to True). Setting
            this flag to True will add a column named '_sim_score' in the
            output table. This column will contain the similarity scores for the
            tuple pairs in the output.

        n_jobs (int): number of parallel jobs to use for the computation
            (defaults to 1). If -1 is given, all CPUs are used. If 1 is given,
            no parallel computing code is used at all, which is useful for
            debugging. For n_jobs below -1, (n_cpus + 1 + n_jobs) are used
            (where n_cpus is the total number of CPUs in the machine). Thus for
            n_jobs = -2, all CPUs but one are used. If (n_cpus + 1 + n_jobs)
            becomes less than 1, then no parallel computing code will be used
            (i.e., equivalent to the default).

        show_progress (boolean): flag to indicate whether task progress should
            be displayed to the user (defaults to True).

    Returns:
        An output table containing tuple pairs that satisfy the join
        condition (DataFrame).
    """
    from py_stringsimjoin import __use_cython__
    if __use_cython__:
        from py_stringsimjoin.join.jaccard_join_cy import jaccard_join_cy
        return jaccard_join_cy(ltable, rtable, l_key_attr, r_key_attr,
            l_join_attr, r_join_attr, tokenizer, threshold, comp_op,
            allow_empty, allow_missing, l_out_attrs, r_out_attrs,
            l_out_prefix, r_out_prefix, out_sim_score, n_jobs, show_progress)
    else:
        from py_stringsimjoin.join.jaccard_join_py import jaccard_join_py
        return jaccard_join_py(ltable, rtable, l_key_attr, r_key_attr,
            l_join_attr, r_join_attr, tokenizer, threshold, comp_op,
            allow_empty, allow_missing, l_out_attrs, r_out_attrs,
            l_out_prefix, r_out_prefix, out_sim_score, n_jobs, show_progress)


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 '+'