def filter_traceback(tb_list):
    """Given a traceback as a list of strings, looks for common boilerplate and removes it."""
    """
        File "asynq/async_task.py", line 169, in asynq.async_task.AsyncTask._continue
        File "asynq/async_task.py", line 237, in asynq.async_task.AsyncTask._continue_on_generator
        File "asynq/async_task.py", line 209, in asynq.async_task.AsyncTask._continue_on_generator
    """
    TASK_CONTINUE = ['asynq.async_task.AsyncTask._continue',
        'asynq.async_task.AsyncTask._continue_on_generator',
        'asynq.async_task.AsyncTask._continue_on_generator'
        ], '___asynq_continue___'
    """
        File "asynq/decorators.py", line 161, in asynq.decorators.AsyncDecorator.__call__
        File "asynq/futures.py", line 54, in asynq.futures.FutureBase.value
        File "asynq/futures.py", line 63, in asynq.futures.FutureBase.value
        File "asynq/futures.py", line 153, in asynq.futures.FutureBase.raise_if_error
        File "<...>/python3.6/site-packages/qcore/errors.py", line 93, in reraise
           six.reraise(type(error), error, error._traceback)
        File "<...>/python3.6/site-packages/six.py", line 693, in reraise
           raise value
    """
    FUTURE_BASE = ['asynq.decorators.AsyncDecorator.__call__',
        'asynq.futures.FutureBase.value', 'asynq.futures.FutureBase.value',
        'asynq.futures.FutureBase.raise_if_error', 'reraise', 'six.reraise',
        'reraise', 'value'], '___asynq_future_raise_if_error___'
    """
        File "asynq/decorators.py", line 153, in asynq.decorators.AsyncDecorator.asynq
        File "asynq/decorators.py", line 203, in asynq.decorators.AsyncProxyDecorator._call_pure
        File "asynq/decorators.py", line 203, in asynq.decorators.AsyncProxyDecorator._call_pure
        File "asynq/decorators.py", line 204, in asynq.decorators.AsyncProxyDecorator._call_pure
        File "asynq/decorators.py", line 275, in asynq.decorators.async_call
    """
    CALL_PURE = ['asynq.decorators.AsyncDecorator.asynq',
        'asynq.decorators.AsyncProxyDecorator._call_pure',
        'asynq.decorators.AsyncProxyDecorator._call_pure',
        'asynq.decorators.AsyncProxyDecorator._call_pure',
        'asynq.decorators.async_call'], '___asynq_call_pure___'
    REPLACEMENTS = [TASK_CONTINUE, FUTURE_BASE, CALL_PURE]
    output = []
    i = 0
    while i < len(tb_list):
        did_replacement = False
        for text_to_match, replacement in REPLACEMENTS:
            matches = True
            j = 0
            while j < len(text_to_match) and i + j < len(tb_list):
                if text_to_match[j] not in tb_list[i + j]:
                    matches = False
                    break
                j += 1
            if matches and j == len(text_to_match):
                output.append('  ' + replacement + '\n')
                i = i + j
                did_replacement = True
                break
        if not did_replacement:
            output.append(tb_list[i])
            i += 1
    return output


def fixed_cgi_decode(s):
    """Decode the CGI-encoded string `s`:
       * replace "+" by " "
       * replace "%xx" by the character with hex number xx.
       Return the decoded string.  Raise `ValueError` for invalid inputs."""
    hex_values = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6,
        '7': 7, '8': 8, '9': 9, 'a': 10, 'b': 11, 'c': 12, 'd': 13, 'e': 14,
        'f': 15, 'A': 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14, 'F': 15}
    t = ''
    i = 0
    while i < len(s):
        c = s[i]
        if c == '+':
            t += ' '
        elif c == '%' and i + 2 < len(s):
            digit_high, digit_low = s[i + 1], s[i + 2]
            i += 2
            if digit_high in hex_values and digit_low in hex_values:
                v = hex_values[digit_high] * 16 + hex_values[digit_low]
                t += chr(v)
            else:
                raise ValueError('Invalid encoding')
        else:
            t += c
        i += 1
    return t


def is_str(s):
    """
    Checks if a variable if a string
    :param s: a string
    :return: boolean
    """
    return isinstance(s, str)


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 head_object(Bucket=None, IfMatch=None, IfModifiedSince=None,
    IfNoneMatch=None, IfUnmodifiedSince=None, Key=None, Range=None,
    VersionId=None, SSECustomerAlgorithm=None, SSECustomerKey=None,
    SSECustomerKeyMD5=None, RequestPayer=None, PartNumber=None):
    """
    The HEAD operation retrieves metadata from an object without returning the object itself. This operation is useful if you're only interested in an object's metadata. To use HEAD, you must have READ access to the object.
    See also: AWS API Documentation

    :example: response = client.head_object(
        Bucket='string',
        IfMatch='string',
        IfModifiedSince=datetime(2015, 1, 1),
        IfNoneMatch='string',
        IfUnmodifiedSince=datetime(2015, 1, 1),
        Key='string',
        Range='string',
        VersionId='string',
        SSECustomerAlgorithm='string',
        SSECustomerKey='string',
        RequestPayer='requester',
        PartNumber=123
    )

    :type Bucket: string
    :param Bucket: [REQUIRED]

    :type IfMatch: string
    :param IfMatch: Return the object only if its entity tag (ETag) is the same as the one specified, otherwise return a 412 (precondition failed).

    :type IfModifiedSince: datetime
    :param IfModifiedSince: Return the object only if it has been modified since the specified time, otherwise return a 304 (not modified).

    :type IfNoneMatch: string
    :param IfNoneMatch: Return the object only if its entity tag (ETag) is different from the one specified, otherwise return a 304 (not modified).

    :type IfUnmodifiedSince: datetime
    :param IfUnmodifiedSince: Return the object only if it has not been modified since the specified time, otherwise return a 412 (precondition failed).

    :type Key: string
    :param Key: [REQUIRED]

    :type Range: string
    :param Range: Downloads the specified range bytes of an object. For more information about the HTTP Range header, go to http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.

    :type VersionId: string
    :param VersionId: VersionId used to reference a specific version of the object.

    :type SSECustomerAlgorithm: string
    :param SSECustomerAlgorithm: Specifies the algorithm to use to when encrypting the object (e.g., AES256).

    :type SSECustomerKey: string
    :param SSECustomerKey: Specifies the customer-provided encryption key for Amazon S3 to use in encrypting data. This value is used to store the object and then it is discarded; Amazon does not store the encryption key. The key must be appropriate for use with the algorithm specified in the x-amz-server-side -encryption -customer-algorithm header.

    :type SSECustomerKeyMD5: string
    :param SSECustomerKeyMD5: Specifies the 128-bit MD5 digest of the encryption key according to RFC 1321. Amazon S3 uses this header for a message integrity check to ensure the encryption key was transmitted without error.   Please note that this parameter is automatically populated if it is not provided. Including this parameter is not required

    :type RequestPayer: string
    :param RequestPayer: Confirms that the requester knows that she or he will be charged for the request. Bucket owners need not specify this parameter in their requests. Documentation on downloading objects from requester pays buckets can be found at http://docs.aws.amazon.com/AmazonS3/latest/dev/ObjectsinRequesterPaysBuckets.html

    :type PartNumber: integer
    :param PartNumber: Part number of the object being read. This is a positive integer between 1 and 10,000. Effectively performs a 'ranged' HEAD request for the part specified. Useful querying about the size of the part and the number of parts in this object.

    :rtype: dict
    :return: {
        'DeleteMarker': True|False,
        'AcceptRanges': 'string',
        'Expiration': 'string',
        'Restore': 'string',
        'LastModified': datetime(2015, 1, 1),
        'ContentLength': 123,
        'ETag': 'string',
        'MissingMeta': 123,
        'VersionId': 'string',
        'CacheControl': 'string',
        'ContentDisposition': 'string',
        'ContentEncoding': 'string',
        'ContentLanguage': 'string',
        'ContentType': 'string',
        'Expires': datetime(2015, 1, 1),
        'WebsiteRedirectLocation': 'string',
        'ServerSideEncryption': 'AES256'|'aws:kms',
        'Metadata': {
            'string': 'string'
        },
        'SSECustomerAlgorithm': 'string',
        'SSECustomerKeyMD5': 'string',
        'SSEKMSKeyId': 'string',
        'StorageClass': 'STANDARD'|'REDUCED_REDUNDANCY'|'STANDARD_IA',
        'RequestCharged': 'requester',
        'ReplicationStatus': 'COMPLETE'|'PENDING'|'FAILED'|'REPLICA',
        'PartsCount': 123
    }

    :returns:
    (dict) --
    DeleteMarker (boolean) -- Specifies whether the object retrieved was (true) or was not (false) a Delete Marker. If false, this response header does not appear in the response.
    AcceptRanges (string) --
    Expiration (string) -- If the object expiration is configured (see PUT Bucket lifecycle), the response includes this header. It includes the expiry-date and rule-id key value pairs providing object expiration information. The value of the rule-id is URL encoded.
    Restore (string) -- Provides information about object restoration operation and expiration time of the restored object copy.
    LastModified (datetime) -- Last modified date of the object
    ContentLength (integer) -- Size of the body in bytes.
    ETag (string) -- An ETag is an opaque identifier assigned by a web server to a specific version of a resource found at a URL
    MissingMeta (integer) -- This is set to the number of metadata entries not returned in x-amz-meta headers. This can happen if you create metadata using an API like SOAP that supports more flexible metadata than the REST API. For example, using SOAP, you can create metadata whose values are not legal HTTP headers.
    VersionId (string) -- Version of the object.
    CacheControl (string) -- Specifies caching behavior along the request/reply chain.
    ContentDisposition (string) -- Specifies presentational information for the object.
    ContentEncoding (string) -- Specifies what content encodings have been applied to the object and thus what decoding mechanisms must be applied to obtain the media-type referenced by the Content-Type header field.
    ContentLanguage (string) -- The language the content is in.
    ContentType (string) -- A standard MIME type describing the format of the object data.
    Expires (datetime) -- The date and time at which the object is no longer cacheable.
    WebsiteRedirectLocation (string) -- If the bucket is configured as a website, redirects requests for this object to another object in the same bucket or to an external URL. Amazon S3 stores the value of this header in the object metadata.
    ServerSideEncryption (string) -- The Server-side encryption algorithm used when storing this object in S3 (e.g., AES256, aws:kms).
    Metadata (dict) -- A map of metadata to store with the object in S3.
    (string) --
    (string) --

    SSECustomerAlgorithm (string) -- If server-side encryption with a customer-provided encryption key was requested, the response will include this header confirming the encryption algorithm used.
    SSECustomerKeyMD5 (string) -- If server-side encryption with a customer-provided encryption key was requested, the response will include this header to provide round trip message integrity verification of the customer-provided encryption key.
    SSEKMSKeyId (string) -- If present, specifies the ID of the AWS Key Management Service (KMS) master encryption key that was used for the object.
    StorageClass (string) --
    RequestCharged (string) -- If present, indicates that the requester was successfully charged for the request.
    ReplicationStatus (string) --
    PartsCount (integer) -- The count of parts this object has.

    """
    pass


def tag_index_array_pointer(parent=None, new_value=None, magic=0, **kwargs):
    """
    Calculates the pointer value for a tag_index array based on file offset.
    """
    if new_value is None:
        return parent.tag_index_offset - magic
    parent.tag_index_offset = new_value + magic


def free_logger(logger):
    """
	Frees the resources held by the loggers created through make_logger or make_mem_logger.
	This is used for file cleanup and for handler removal (logger objects are re-used).
	"""
    try:
        for x in logger.handlers:
            x.close()
            logger.removeHandler(x)
    except Exception:
        pass


@classmethod
def adsr(cls, attack_length, attack_level, decay_length, sustain_level,
    sustain_length, release_length, attack_shape=None, decay_shape=None,
    release_shape=None):
    """
        Construct a standard attack/decay/sustain/release envelope
        :param attack_length: rise time
        :param attack_level: level reached after attack before decay
        :param decay_length: length of decay portion of the curve
        :param sustain_level: sustain level reached after decay and before release
        :param sustain_length: length of sustain portion of curve
        :param release_length: release time
        :param attack_shape: sets curve shape for attack portion of the curve
        :param decay_shape: sets curve shape for decay portion of the curve
        :param release_shape: sets curve shape for release portion of the curve
        :return: an Envelope constructed accordingly
       """
    curve_shapes = (None if attack_shape is decay_shape is release_shape is
        None else (0 if attack_shape is None else attack_shape, 0 if
        decay_shape is None else decay_shape, 0, 0 if release_shape is None
         else release_shape))
    return cls.from_levels_and_durations((0, attack_level, sustain_level,
        sustain_level, 0), (attack_length, decay_length, sustain_length,
        release_length), curve_shapes=curve_shapes)


def sorted_rle_gather_1d(rle_data, ordered_indices):
    """
    Gather brle_data at ordered_indices.

    This is equivalent to `rle_to_dense(brle_data)[ordered_indices]` but avoids
    the decoding.

    Parameters
    ----------
    brle_data: iterable of run-length-encoded data.
    ordered_indices: iterable of ints in ascending order.

    Returns
    ----------
    `brle_data` iterable of values at the dense indices, same length as
    ordered indices.
    """
    data_iter = iter(rle_data)
    index_iter = iter(ordered_indices)
    index = next(index_iter)
    start = 0
    while True:
        while start <= index:
            try:
                value = next(data_iter)
                start += next(data_iter)
            except StopIteration:
                raise IndexError(
                    'Index %d out of range of raw_values length %d' % (
                    index, start))
        try:
            while index < start:
                yield value
                index = next(index_iter)
        except StopIteration:
            break


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


def find_samp_rec(s, data, az_type):
    """
    find the orientation info for samp s
    """
    datablock, or_error, bed_error = [], 0, 0
    orient = {}
    orient['sample_dip'] = ''
    orient['sample_azimuth'] = ''
    orient['sample_description'] = ''
    for rec in data:
        if rec['er_sample_name'].lower() == s.lower():
            if 'sample_orientation_flag' in list(rec.keys()) and rec[
                'sample_orientation_flag'] == 'b':
                orient['sample_orientation_flag'] = 'b'
                return orient
            if 'magic_method_codes' in list(rec.keys()) and az_type != '0':
                methods = rec['magic_method_codes'].replace(' ', '').split(':')
                if az_type in methods and 'sample_azimuth' in list(rec.keys()
                    ) and rec['sample_azimuth'] != '':
                    orient['sample_azimuth'] = float(rec['sample_azimuth'])
                if 'sample_dip' in list(rec.keys()) and rec['sample_dip'
                    ] != '':
                    orient['sample_dip'] = float(rec['sample_dip'])
                if 'sample_bed_dip_direction' in list(rec.keys()) and rec[
                    'sample_bed_dip_direction'] != '':
                    orient['sample_bed_dip_direction'] = float(rec[
                        'sample_bed_dip_direction'])
                if 'sample_bed_dip' in list(rec.keys()) and rec[
                    'sample_bed_dip'] != '':
                    orient['sample_bed_dip'] = float(rec['sample_bed_dip'])
            else:
                if 'sample_azimuth' in list(rec.keys()):
                    orient['sample_azimuth'] = float(rec['sample_azimuth'])
                if 'sample_dip' in list(rec.keys()):
                    orient['sample_dip'] = float(rec['sample_dip'])
                if 'sample_bed_dip_direction' in list(rec.keys()):
                    orient['sample_bed_dip_direction'] = float(rec[
                        'sample_bed_dip_direction'])
                if 'sample_bed_dip' in list(rec.keys()):
                    orient['sample_bed_dip'] = float(rec['sample_bed_dip'])
                if 'sample_description' in list(rec.keys()):
                    orient['sample_description'] = rec['sample_description']
        if orient['sample_azimuth'] != '':
            break
    return orient


def psi_Ca_H_HCO3_HMW84(T, P):
    """c-c'-a: calcium hydrogen bicarbonate [HMW84]."""
    psi = 0.0
    valid = T == 298.15
    return psi, valid


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

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

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


def split_lists(iterable, chunk_size):
    """Generate sequences of `chunk_size` elements from `iterable`."""
    iterable = iter(iterable)
    while True:
        chunk = []
        try:
            for _ in range(chunk_size):
                chunk.append(iterable.next())
            yield chunk
        except StopIteration:
            if chunk:
                yield chunk
            break


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


def put_user_policy(UserName=None, PolicyName=None, PolicyDocument=None):
    """
    Adds or updates an inline policy document that is embedded in the specified IAM user.
    An IAM user can also have a managed policy attached to it. To attach a managed policy to a user, use  AttachUserPolicy . To create a new managed policy, use  CreatePolicy . For information about policies, see Managed Policies and Inline Policies in the IAM User Guide .
    For information about limits on the number of inline policies that you can embed in a user, see Limitations on IAM Entities in the IAM User Guide .
    See also: AWS API Documentation

    Examples
    The following command attaches a policy to the IAM user named Bob.
    Expected Output:

    :example: response = client.put_user_policy(
        UserName='string',
        PolicyName='string',
        PolicyDocument='string'
    )

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

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

    :type PolicyDocument: string
    :param PolicyDocument: [REQUIRED]
            The policy document.
            The regex pattern used to validate this parameter is a string of characters consisting of any printable ASCII character ranging from the space character (u0020) through end of the ASCII character range as well as the printable characters in the Basic Latin and Latin-1 Supplement character set (through u00FF). It also includes the special characters tab (u0009), line feed (u000A), and carriage return (u000D).

    :return: response = client.put_user_policy(
        PolicyDocument='{"Version":"2012-10-17","Statement":{"Effect":"Allow","Action":"*","Resource":"*"}}',
        PolicyName='AllAccessPolicy',
        UserName='Bob',
    )

    print(response)

    """
    pass


def get_name(friendly=False):
    """Get name of this resource

    :return: name of this resource
    :rtype: str
    """
    if friendly:
        return 'InfluxDB connection'
    return 'influxdb'


def check_proxy(host, port):
    """ Is there even an appearance of something resembling a proxy on the set
    up port?

    """
    if host is None or port is None:
        print('No proxy set up at options.yaml')
        return False
    try:
        import socket
        proxy = socket.socket()
        proxy.connect((host, port))
        return True
    except ConnectionRefusedError:
        print('No proxy on %s:%s?' % (host, str(port)))
        return False
    finally:
        proxy.close()


def cp2png(checkplotpickle):
    """
    This runs cp2png from checkplot.py.

    """
    from astrobase.checkplot import checkplot_pickle_to_png
    if checkplotpickle.endswith('.gz'):
        outfile = checkplotpickle.replace('.pkl.gz', '.png')
    else:
        outfile = checkplotpickle.replace('.pkl', '.png')
    return checkplot_pickle_to_png(checkplotpickle, outfile)


@classmethod
def from_xarray(cls, arr: 'xarray.Dataset') ->'Histogram1D':
    """Convert form xarray.Dataset

        Parameters
        ----------
        arr: The data in xarray representation
        """
    kwargs = {'frequencies': arr['frequencies'], 'binning': arr['bins'],
        'errors2': arr['errors2'], 'overflow': arr.attrs['overflow'],
        'underflow': arr.attrs['underflow'], 'keep_missed': arr.attrs[
        'keep_missed']}
    return cls(**kwargs)


def first_letter(name):
    """A simple name compression that returns the first letter of the name.

    Args:
        name (str): A forename, surname, or other name.

    Returns:
        (str): The upper case of the first letter of the name
    """
    return name[0].upper() if name else ''


def validate_int(value, label, low=None, high=None):
    """Validates that the given value represents an integer.

    There are several ways to represent an integer in Python (e.g. 2, 2L, 2.0). This method allows
    for all such representations except for booleans. Booleans also behave like integers, but
    always translate to 1 and 0. Passing a boolean to an API that expects integers is most likely
    a developer error.
    """
    if value is None or isinstance(value, bool):
        raise ValueError('Invalid type for integer value: {0}.'.format(value))
    try:
        val_int = int(value)
    except TypeError:
        raise ValueError('Invalid type for integer value: {0}.'.format(value))
    else:
        if val_int != value:
            raise ValueError('{0} must be a numeric value and a whole number.'
                .format(label))
        if low is not None and val_int < low:
            raise ValueError('{0} must not be smaller than {1}.'.format(
                label, low))
        if high is not None and val_int > high:
            raise ValueError('{0} must not be larger than {1}.'.format(
                label, high))
        return val_int


@classmethod
def crop(cls, inputs, resize_to, data_format='channels_last'):
    """ Crop input tensor to a shape of a given image.
        If resize_to does not have a fully defined shape (resize_to.get_shape() has at least one None),
        the returned tf.Tensor will be of unknown shape except the number of channels.

        Parameters
        ----------
        inputs : tf.Tensor
            input tensor
        resize_to : tf.Tensor
            a tensor which shape the inputs should be resized to
        data_format : str {'channels_last', 'channels_first'}
            data format
        """
    static_shape = cls.spatial_shape(resize_to, data_format, False)
    dynamic_shape = cls.spatial_shape(resize_to, data_format, True)
    if None in cls.shape(inputs) + static_shape:
        return cls._dynamic_crop(inputs, static_shape, dynamic_shape,
            data_format)
    return cls._static_crop(inputs, static_shape, data_format)


def __call__():
    """Load required transforms and generators.
        """


def select_more(use_face_step: bool=True):
    """Select more vertices, edges or faces connected to initial selection

    :param use_face_step: Face Step, Connected faces (instead of edges)
    :type use_face_step: bool
    """
    pass


def get_ntm_strike(price, atm, intervals):
    """ATMの次に近い権利行使価格を算出

    ATMのIVを算出するための権利行使価格

    Parameters
    ----------
    price: int, float
        原資産価格
    atm: int
        ATMの権利行使価格
    intervals: int
        権利行使価格の刻み幅

    Returns
    -------
    int
        ATMの次に近い権利行使価格
    """
    if price == atm:
        return atm
    lower = atm - intervals
    upper = atm + intervals
    diff_lower = abs(price - lower)
    diff_upper = abs(price - upper)
    return {diff_lower: lower, diff_upper: upper}[min(diff_lower, diff_upper)]


def append(a, vancestors):
    """
    Append ``a`` to the list of the virtual ancestors, unless it is already
    included.
    """
    add = True
    for j, va in enumerate(vancestors):
        if issubclass(va, a):
            add = False
            break
        if issubclass(a, va):
            vancestors[j] = a
            add = False
    if add:
        vancestors.append(a)


def _thread_done(gt, *args, **kwargs):
    """Callback function to be passed to GreenThread.link() when we spawn()
    Calls the :class:`ThreadGroup` to notify if.

    """
    kwargs['group'].thread_done(kwargs['thread'])


def unhex(s):
    """Get the integer value of a hexadecimal number."""
    bits = 0
    for c in s:
        c = bytes((c,))
        if b'0' <= c <= b'9':
            i = ord('0')
        elif b'a' <= c <= b'f':
            i = ord('a') - 10
        elif b'A' <= c <= b'F':
            i = ord(b'A') - 10
        else:
            assert False, 'non-hex digit ' + repr(c)
        bits = bits * 16 + (ord(c) - i)
    return bits


@staticmethod
def password_url(base_url, prefix):
    """Calculates actual url identifying the password. Takes
        configured prefix under consideration (so can be shorter
        than repo url)"""
    if not prefix or prefix == b'*':
        return base_url
    scheme, hostpath = base_url.split(b'://', 1)
    p = prefix.split(b'://', 1)
    if len(p) > 1:
        prefix_host_path = p[1]
    else:
        prefix_host_path = prefix
    password_url = scheme + b'://' + prefix_host_path
    return password_url


@classmethod
def start(cls, resources, background=False):
    """Start a virtual machine."""
    if not isinstance(resources, (list, tuple)):
        resources = [resources]
    opers = []
    for item in resources:
        oper = cls.call('hosting.vm.start', cls.usable_id(item))
        if isinstance(oper, list):
            opers.extend(oper)
        else:
            opers.append(oper)
    if background:
        return opers
    instance_info = "'%s'" % ', '.join(resources)
    cls.echo('Starting your Virtual Machine(s) %s.' % instance_info)
    cls.display_progress(opers)


@classmethod
def greater_or_equal_constraint(cls, variables, lowerbound):
    """Clauses encoding a "greater than or equal to" constraint

        E.g. X1 + X2 + X3 + X4 > 1

        (X1 v X2 v X3)
        (X1 v X2 v X4)
        (X1 v X3 v X4)
        (X2 v X3 v X4)

        Parameters
        ----------
        variables : list of variables
           variables in the constraint
        lowerbound: int
           lower bound of the constraint

        Returns
        -------
            a list of clauses

        Examples
        --------
        >>> tuple(CNF.greater_than_constraint(['a','b','c'],1)) == tuple(CNF.greater_or_equal_constraint(['a','b','c'],2))
        True
        >>> list(CNF.greater_or_equal_constraint(['a','b','c'],3))
        [[(True, 'a')], [(True, 'b')], [(True, 'c')]]
        >>> list(CNF.greater_or_equal_constraint(['a'],0))
        []
        >>> list(CNF.greater_or_equal_constraint(['a','b','c'],4))
        [[]]
        """
    return cls._inequality_constraint_builder(variables, lowerbound - 1,
        greater=True)


def mapparms(old, new):
    """
    Linear map parameters between domains.

    Return the parameters of the linear map ``offset + scale*x`` that maps
    `old` to `new` such that ``old[i] -> new[i]``, ``i = 0, 1``.

    Parameters
    ----------
    old, new : array_like
        Domains. Each domain must (successfully) convert to a 1-d array
        containing precisely two values.

    Returns
    -------
    offset, scale : scalars
        The map ``L(x) = offset + scale*x`` maps the first domain to the
        second.

    See Also
    --------
    getdomain, mapdomain

    Notes
    -----
    Also works for complex numbers, and thus can be used to calculate the
    parameters required to map any line in the complex plane to any other
    line therein.

    Examples
    --------
    >>> from numpy_demo.polynomial import polyutils as pu
    >>> pu.mapparms((-1,1),(-1,1))
    (0.0, 1.0)
    >>> pu.mapparms((1,-1),(-1,1))
    (-0.0, -1.0)
    >>> i = complex(0,1)
    >>> pu.mapparms((-i,-1),(1,i))
    ((1+1j), (1-0j))

    """
    oldlen = old[1] - old[0]
    newlen = new[1] - new[0]
    off = (old[1] * new[0] - old[0] * new[1]) / oldlen
    scl = newlen / oldlen
    return off, scl


def select_ungrouped(extend: bool=False):
    """Select vertices without a group

    :param extend: Extend, Extend the selection
    :type extend: bool
    """
    pass


def create_binary_test_index_list(failure_indices):
    """ Old characterize specific ML method """
    id_index_pair = []
    for key, value in failure_indices.items():
        zero_list = [(0) for _ in range(13)]
        for index in value.keys():
            zero_list[index - 1] = 1
        zero_list.insert(0, key)
        row_content = list(zip(*zip(zero_list)))[0]
        id_index_pair.append(row_content)
    return id_index_pair


def set_model_parameters(model, new_params):
    """Adjusts the dictionary of model-level parameters / attributes.

    :param model: An Open ABM supported model / environment instance
    :param new_params: A python dictionary of parameters / attributes replacing old parameter values.

    :return: A model instance

    """
    if isinstance(new_params, dict):
        for key in new_params.keys():
            if key in vars(model).keys():
                vars(model)[key] = new_params[key]
    else:
        print('new_params must be in the form of a Python dictionary!')
    return model


def get_bone_filename(name, topping):
    """
    Return file name with extension by bone name and number of `topping` flag.
    """
    bones = {'django0': 'django.py', 'django1': 'django-toppings.py',
        'unittest0': 'unit.py', 'unittest1': 'unit-toppings.py'}
    return bones[name + str(topping)]


def test(event):
    """ echo test response. """
    event.reply('yoo %s' % event.origin)


def post_install(context):
    """Post install script"""


def is_gz_file(filepath):
    """Return a boolean according to the compression state of the file"""
    with open(filepath, 'rb') as test_f:
        return test_f.read(3) == b'\x1f\x8b\x08'


def set_defaults(conf, executor_thread_pool_size=None):
    """Set defaults for configuration variables.

    Overrides default options values.

    :param conf: Config instance specified to set default options in it. Using
     of instances instead of a global config object prevents conflicts between
     options declaration.
    :type conf: oslo.config.cfg.ConfigOpts instance.

    :keyword executor_thread_pool_size: Size of executor thread pool.
    :type executor_thread_pool_size: int
    :default executor_thread_pool_size: None

    """
    if executor_thread_pool_size is not None:
        conf.set_default('executor_thread_pool_size', executor_thread_pool_size
            )


def assert_not_awaited(_mock_self):
    """
        Assert that the mock was never awaited.

        .. versionadded:: 0.12
        """
    self = _mock_self
    if self.await_count != 0:
        msg = "Expected '%s' to not have been awaited. Awaited %s times." % (
            self._mock_name or 'mock', self.await_count)
        raise AssertionError(msg)


def get_docker_log_line_content(log_line):
    """
    Get string from Docker log line object

    :param log_line: docker log line object
    :type log_line: str or dict
    :return: str -- log line
    """
    str_line = ''
    if isinstance(log_line, str):
        str_line = log_line
    elif isinstance(log_line, dict):
        if 'stream' in log_line and isinstance(log_line['stream'], str):
            str_line = log_line['stream']
        else:
            str_line = repr(log_line)
    return str_line.rstrip('\n')


def is_network_appbase_ready(props):
    """Checks if the network is appbase ready"""
    if 'DPAY_BLOCKCHAIN_VERSION' in props:
        return False
    elif 'DPAY_BLOCKCHAIN_VERSION' in props:
        return True


def ifset(var, a, b=''):
    """Checks the environment variable var; if it is set (non-empty), return a, otherwise return b.  Used in LexFormats to create tables with variations set by the environment."""
    import os
    if os.environ.get(var, ''):
        return a
    else:
        return b


def find_options_in_recipes(recipes, choice_search, action_kw,
    condition_position=0):
    """
    Looks through the master config at recipes and entries to determine if
    there are place the developer made distince choices, this is used in the
    inimake script to walk users through making their own config file from
    scratch.

    This function looks through and finds sections or items that match the
    conditional. Then it looks through the adj_config to determine if any
    sections/items are being removed as a result, then it finds those.
    If a section/item appears in a recipe condition and a removed by
    another trigger it is extremely likely these are choices.

    Args:
        mcfg: Recipes object from master config
        conditional: list of 3 focusing on what were looking for
        action_kw: action keyword is a string of what to look for in matching
                   choices where ever true is used will popoulate with every
                   item/section

    Returns:
        final_choices:

    """
    decisions = {}
    conditional = ['any' for i in range(3)]
    final_choices = []
    pos = condition_position
    for r in recipes:
        choices = []
        for t_name, trigger in r.triggers.items():
            for condition in trigger.conditions:
                if condition[pos] != 'any':
                    for k, v in r.adj_config.items():
                        if action_kw in v.keys():
                            choices.append(condition[pos])
                            for kk, vv in v.items():
                                actions = [k, kk, vv]
                                if kk == action_kw:
                                    choices.append(actions[pos])
        if choices:
            final_choices.append(tuple(set(sorted(choices))))
    return list(set(final_choices))


def p_simple_container_type(p):
    """simple_container_type : map_type
                             | list_type
                             | set_type"""
    p[0] = p[1]


def check_length(value, length):
    """
    Checks length of value

    @param value: value to check
    @type value: C{str}

    @param length: length checking for
    @type length: C{int}

    @return: None when check successful

    @raise ValueError: check failed
    """
    _length = len(value)
    if _length != length:
        raise ValueError('length must be %d, not %d' % (length, _length))


def _stream_compress_identity(reply, *args):
    """Streaming compressor which returns original data unchanged."""
    return reply


def dag(qob):
    """Conjugate transpose.
    """
    try:
        return qob.H
    except AttributeError:
        return qob.conj().T


def pick_redirect_uris(request_args=None, service=None, **kwargs):
    """Pick one redirect_uri base on response_mode out of a list of such."""
    _context = service.service_context
    if 'redirect_uri' in request_args:
        pass
    elif _context.callback:
        try:
            _response_type = request_args['response_type']
        except KeyError:
            _response_type = _context.behaviour['response_types'][0]
            request_args['response_type'] = _response_type
        try:
            _response_mode = request_args['response_mode']
        except KeyError:
            _response_mode = ''
        if _response_mode == 'form_post':
            request_args['redirect_uri'] = _context.callback['form_post']
        elif _response_type == 'code':
            request_args['redirect_uri'] = _context.callback['code']
        else:
            request_args['redirect_uri'] = _context.callback['implicit']
    else:
        request_args['redirect_uri'] = _context.redirect_uris[0]
    return request_args, {}


def create_client_from_parsed_globals(session, service_name, parsed_globals,
    overrides=None):
    """Creates a service client, taking parsed_globals into account

    Any values specified in overrides will override the returned dict. Note
    that this override occurs after 'region' from parsed_globals has been
    translated into 'region_name' in the resulting dict.
    """
    client_args = {}
    if 'region' in parsed_globals:
        client_args['region_name'] = parsed_globals.region
    if 'endpoint_url' in parsed_globals:
        client_args['endpoint_url'] = parsed_globals.endpoint_url
    if 'verify_ssl' in parsed_globals:
        client_args['verify'] = parsed_globals.verify_ssl
    if overrides:
        client_args.update(overrides)
    return session.create_client(service_name, **client_args)


def files_in_DS(s, DS, regex=False):
    """ Returns a list of all files from a given dataset
            that will be used in at least one job in this submission
            If regex==True, the list is converted to a regex string
        """
    assert DS in s.input_datasets(
        ), 'ERROR: dataset %s was not requested in the xml file' % DS
    files = []
    for j in s.jobs:
        if DS in j.infiles.keys():
            files += j.infiles[DS]
    if regex:
        return '|'.join(sorted(list(set(files))))
    else:
        return sorted(list(set(files)))


def logical_implication(a, b):
    """ if a is True, b must be True """
    return not a or b


def inv_scale(x, data_mean, data_std):
    """Inverse tranform of mean/variance scaling.

    Given mean and variances, apply mean-variance denormalization to data.

    Args:
        x (array): Input data
        data_mean (array): Means for each feature dimention.
        data_std (array): Standard deviation for each feature dimention.

    Returns:
        array: Denormalized data.

    See also:
        :func:`nnmnkwii.preprocessing.scale`
    """
    return data_std * x + data_mean


@staticmethod
def prepare_extra_data_map(extra_data_map):
    """Prepare extra data map.

        Replace any occurances of "dimensions." or "meta." or "value_meta."
        to "dimensions#", "meta#" or "value_meta#" in extra_data_map.

        """
    prepared_extra_data_map = {}
    for column_name in list(extra_data_map):
        column_value = extra_data_map[column_name]
        if column_name.startswith('dimensions.'):
            column_name = column_name.replace('dimensions.', 'dimensions#')
        elif column_name.startswith('meta.'):
            column_name = column_name.replace('meta.', 'meta#')
        elif column_name.startswith('value_meta.'):
            column_name = column_name.replace('value_meta.', 'value_meta#')
        elif column_name.startswith('extra_data_map.'):
            column_name = column_name.replace('extra_data_map.', '')
        prepared_extra_data_map[column_name] = column_value
    return prepared_extra_data_map


def primes(limit):
    """ Returns a list of primes < limit """
    sieve = [True] * limit
    for i in range(3, int(limit ** 0.5) + 1, 2):
        if sieve[i]:
            sieve[i * i::2 * i] = [False] * ((limit - i * i - 1) // (2 * i) + 1
                )
    return [2] + [i for i in range(3, limit, 2) if sieve[i]]


def _get_disposable_app_filename(clientInfo):
    """
    Get name of file used to store creds.
    """
    return clientInfo.get('file', clientInfo['name'] + '.client_data.json')


@classmethod
def header_hash(cls, header):
    """Given a header return the hash."""
    import x11_hash
    return x11_hash.getPoWHash(header)


@classmethod
def get_canonical_name(cls):
    """
        Return the plugin name
        """
    type_ = cls.get_plugin_type()
    name = cls.get_plugin_name()
    return '%s:%s' % (type_, name)


def _item_from(container, index):
    """Attempts to fetch a index/key from a given container."""
    if index is None:
        return container
    return container[index]


def store_access(store, element):
    """Get the access for the element"""
    for k in store:
        if element in store[k]:
            return k
    return None


def get_followers(item_type, item_id):
    """List all users that subscribe to <item_type> <item_id>"""


@classmethod
def get_friendly_name(cls):
    """Returns a human-readable name of the curve that can be
        used in messages."""
    return 'precision-recall curve'


def view_all(fit_view: bool=False):
    """View whole image with markers

    :param fit_view: Fit View, Fit frame to the viewport
    :type fit_view: bool
    """
    pass


def Nu_KTA(Re, Pr, voidage):
    """Calculates Nusselt number of a fluid passing over a bed of particles
    using a correlation shown in [1]_ and also cited in the review of [2]_.

    .. math::
        Nu = 1.27\\frac{Pr^{1/3}}{\\epsilon^{1.18}}Re^{0.36}
        + 0.033\\frac{Pr^{0.5}}{\\epsilon^{1.07}}Re^{0.86}

    Parameters
    ----------
    Re : float
        Reynolds number with pebble diameter as characteristic dimension, [-]
    Pr : float
        Prandtl number of the fluid [-]
    voidage : float
        Void fraction of bed packing [-]

    Returns
    -------
    Nu : float
        Nusselt number for heat transfer to the packed bed [-]

    Notes
    -----
    100 < Re < 1E5;
    0.36 < ε < 0.42;
    D/d > 20 with D as bed diameter, d as particle diameter;
    H > 4d with H as bed height.

    Examples
    --------
    >>> Nu_KTA(2000, 0.7, 0.4)
    102.08516480718129

    References
    ----------
    .. [1] Reactor Core Design of High-Temperature Gas-Cooled Reactors Part 2:
       Heat Transfer in Spherical Fuel Elements (June 1983).
       http://www.kta-gs.de/e/standards/3100/3102_2_engl_1983_06.pdf
    .. [2] Abdulmohsin, Rahman S., and Muthanna H. Al-Dahhan. "Characteristics
       of Convective Heat Transport in a Packed Pebble-Bed Reactor." Nuclear
       Engineering and Design 284 (April 1, 2015): 143-52.
       doi:10.1016/j.nucengdes.2014.11.041.
    """
    return (1.27 * Pr ** (1 / 3.0) * Re ** 0.36 / voidage ** 1.18 + 0.033 *
        Pr ** 0.5 / voidage ** 1.07 * Re ** 0.86)


@staticmethod
def intersection_point(center_x, center_y, source_x, source_y, width,
    height=None):
    """Determines where the shape centered at (center_x, center_y)
        intersects with a line drawn from (source_x, source_y) to
        (center_x, center_y).

        Can be overridden in derived classes. Must always be defined as a static
        method using C{staticmethod(...)}

        @param width: the width of the shape
        @param height: the height of the shape. If C{None}, defaults to the width
        @return: the intersection point (the closest to (source_x, source_y) if
            there are more than one) or (center_x, center_y) if there is no
            intersection
        """
    return center_x, center_y


def pshell_setup(env):
    """Start a server span when pshell starts up.

    This simply starts a server span after the shell initializes, which
    gives shell users access to all the :term:`context object` goodness.

    To use it, add configuration to your app's INI file like so:

        [pshell]
        setup = baseplate.integration.pyramid:pshell_setup

    See the `Pyramid documentation`_.

    .. _Pyramid documentation: http://docs.pylonsproject.org/projects/pyramid/en/latest/       narr/commandline.html#extending-the-shell

    """
    env['request'].start_server_span('shell')


def _filterfnodes(tagfnode, nodes):
    """return a list of unique fnodes

    The order of this list matches the order of "nodes". Preserving this order
    is important as reading tags in different order provides different
    results."""
    seen = set()
    fnodes = []
    for no in nodes:
        fnode = tagfnode.get(no)
        if fnode and fnode not in seen:
            seen.add(fnode)
            fnodes.append(fnode)
    return fnodes


def check_comp(comp=None):
    """
    Checks if the given competition url is properly formatted
    """
    if comp == None:
        return None
    if comp.endswith('/'):
        comp = comp[:-1]
    if comp.startswith('/'):
        pass
    else:
        comp = '/' + comp
    return comp


def _where(where_clauses_and_values):
    """Return a SQL WHERE clause from list with clauses and values

    :param where_clauses_and_values: list of tuples with format
        (where_clause, param1, ...)
    :type where_clauses_and_values: list of tuples

    :returns: SQL WHERE string with placeholders for the parameters, and list
        of parameters
    :rtype: string
    """
    where_clauses = []
    values = []
    for clause_and_values in where_clauses_and_values:
        where_clauses.append('(' + clause_and_values[0] + ')')
        values += clause_and_values[1:]
    where_clause = u' AND '.join(where_clauses)
    if where_clause:
        where_clause = u'WHERE ' + where_clause
    return where_clause, values


def clean_file(filename, new_name=None):
    """Remove/rename file if exists.
    Fails silently when the file does not exist.
    Useful for, for example, writing output files that
    are meant to overwrite existing ones.
    """
    import os
    if new_name is None:
        try:
            os.remove(filename)
        except OSError:
            pass
    else:
        try:
            os.rename(filename, new_name)
        except OSError:
            pass


def make_port_list(args):
    """Return a list of the ports asked for by flags to the script"""
    ports = []
    if args.ssh == True:
        ports.append(22)
    if args.https == True:
        ports.append(443)
        ports.append(80)
    if args.port != None:
        ports.append(args.port)
    return ports


def replace_last(full, sub, rep=''):
    """
    replaces the last instance of a substring in the full string with rep
    :param full: the base string in which the replacement should happen
    :param sub: to be replaced
    :param rep: replacement substring default empty
    :return:
    """
    end = ''
    count = 0
    for c in reversed(full):
        count = count + 1
        end = c + end
        if sub in end:
            return full[:-count] + end.replace(sub, rep)
    return full


def default_params():
    """
    Sets the default ploting parameters used in both
    image/map plots as well as wiggle plots.

    This function takes no arguments.
    """
    plotParams = {}
    plotParams['pltformat'] = 'pdf'
    plotParams['view_mode'] = 'light'
    plotParams['isolevel'] = 0.7
    plotParams['xlabel'] = ''
    plotParams['ylabel'] = ''
    plotParams['zlabel'] = ''
    plotParams['xu'] = ''
    plotParams['yu'] = ''
    plotParams['zu'] = ''
    plotParams['colormap'] = 'magma'
    plotParams['colorbar'] = False
    plotParams['shading'] = 'flat'
    plotParams['vmin'] = 0.0
    plotParams['vmax'] = 1.0
    plotParams['levels'] = 100
    plotParams['invert_xaxis'] = False
    plotParams['invert_yaxis'] = False
    plotParams['invert_zaxis'] = False
    plotParams['show_scatterer'] = False
    plotParams['show_sources'] = True
    plotParams['show_receivers'] = True
    plotParams['pclip'] = 1.0
    plotParams['tu'] = ''
    plotParams['au'] = ''
    plotParams['data_title'] = 'Data'
    plotParams['impulse_title'] = 'Impulse Response'
    plotParams['fu'] = ''
    plotParams['fmin'] = 0
    plotParams['fmax'] = None
    plotParams['freq_title'] = 'Mean Amplitude Spectrum'
    plotParams['freq_ylabel'] = 'Amplitude'
    return plotParams


@staticmethod
def normalize_exception(exc):
    """
        Given a SyntaxError from a marker evaluation, normalize the error
        message:
         - Remove indications of filename and line number.
         - Replace platform-specific error messages with standard error
           messages.
        """
    subs = {'unexpected EOF while parsing': 'invalid syntax',
        'parenthesis is never closed': 'invalid syntax'}
    exc.filename = None
    exc.lineno = None
    exc.msg = subs.get(exc.msg, exc.msg)
    return exc


def getCSSClass(klass=None, error=None, required=None, classPattern=
    '%(class)s', errorPattern='%(class)s-error', requiredPattern=
    '%(class)s-required'):
    """Setup given css class (klass) with error and required postfix

        If no klass name is given the widget.wrapper class name/names get used.
        It is also possible if more then one (empty space separated) names
        are given as klass argument.

        This method can get used from your form or widget template or widget
        layout template without to re-implement the widget itself just because
        you a different CSS class concept.

        """


def release_local(local):
    """Releases the contents of the local for the current context.
    This makes it possible to use locals without a manager.

    Example::

        >>> loc = Local()
        >>> loc.foo = 42
        >>> release_local(loc)
        >>> hasattr(loc, 'foo')
        False

    With this function one can release :class:`Local` objects as well
    as :class:`StackLocal` objects.  However it is not possible to
    release data held by proxies that way, one always has to retain
    a reference to the underlying local object in order to be able
    to release it.

    .. versionadded:: 0.6.1
    """
    local.__release_local__()


def translate_interface_name(name):
    """ Define shortcutting interface name """
    if 'tengigabitethernet' in name.lower():
        name = name.replace('TenGigabitEthernet', 'Te')
        return name
    if 'gigabitethernet' in name.lower():
        name = name.replace('GigabitEthernet', 'Gi')
        return name
    if 'fastethernet' in name.lower():
        name = name.replace('FastEthernet', 'Fa')
        return name
    if 'ethernet' in name.lower():
        name = name.replace('Ethernet', 'Eth')
        return name
    return name


def fwrite(path, string):
    """
    This function writes a string to a file, and takes care of
    opening it and closing it. If the file does not exist, it
    will be created.

    >>> from rtslib.utils import *
    >>> fwrite("/tmp/test", "hello")
    >>> fread("/tmp/test")
    'hello'

    @param path: The file to write to.
    @type path: string
    @param string: The string to write to the file.
    @type string: string

    """
    with open(path, 'w') as file_fd:
        file_fd.write(str(string))


def sort(seq):
    """
    Tool function for normal order, should not be used separately

    Args:
        seq (list): array

    Returns:
        list: integer e.g. swapped array, number of swaps
    """
    swap_counter = 0
    changed = True
    while changed:
        changed = False
        for i in range(len(seq) - 1):
            if seq[i] > seq[i + 1]:
                swap_counter += 1
                seq[i], seq[i + 1] = seq[i + 1], seq[i]
                changed = True
    return seq, swap_counter


def boxed(item):
    """
    Return item in a container if it is a scalar, else the item itself.
    Aka box it up, unless it's already boxed.
    """
    return item if isinstance(item, (list, set)) else [item]


def _get_template(isamAppliance):
    """
    Retrieve a URL Mapping Template
    """
    return isamAppliance.invoke_get('Retrieve a URL Mapping Template',
        '/wga_templates/dynurl_template.json')


def validate(config):
    """ Checks validity of configuration. """
    config['max_depth'] = int(config['max_depth'])
    if isinstance(config['number'], int):
        config['number'] = tuple((config['number'],))


def cmp(node, fulltext):
    """Compare fulltext to another revision.

        Returns True if the fulltext is different from what is stored.
        """


def exec_kwargs(kwargs: dict) ->dict:
    """Calls any value of kwargs that represents a callable and updates
    value to the callable's return value"""
    for kw, val in kwargs.items():
        if callable(val):
            kwargs[kw] = val()
    return kwargs


def iter_with_last_flag(iterable):
    """Iterate over an iterable and yield a 2-tuple containing the current item and a Boolean
    indicating if it is the last item.

    """
    last_index = len(iterable) - 1
    for i, x in enumerate(iterable):
        yield x, i == last_index


def duplicate_move(OBJECT_OT_duplicate=None, TRANSFORM_OT_translate=None):
    """Duplicate selected objects and move them

    :param OBJECT_OT_duplicate: Duplicate Objects, Duplicate selected objects
    :param TRANSFORM_OT_translate: Translate, Translate (move) selected items
    """
    pass


def extract_host_from_request(request):
    """Extracts host from possible Django request"""
    host = None
    if not request.is_secure():
        host = request.META['HTTP_HOST']
    else:
        host = request.META['HTTPS_HOST']
    if ':' in host:
        host = host.split(':')[0]
    return host


def _version_split(version):
    """
    Split a version string into major, minor, and bugfix numbers (with bugfix
    optional, defaulting to 0).
    """
    for prerel in ('.dev', 'a', 'b', 'rc'):
        if prerel in version:
            version = version.split(prerel)[0]
    versplit = version.split('.')
    major = int(versplit[0])
    minor = int(versplit[1])
    bugfix = 0 if len(versplit) < 3 else int(versplit[2])
    return major, minor, bugfix


def post_install(context):
    """Post install script"""


def ShareGrads(enabled=True):
    """Enable gradients sharing globally.

    Parameters
    ----------
    enabled : boolean
        Whether to share grads.

    Returns
    -------
    None

    Examples
    --------
    >>> import dragon.memonger as opt
    >>> opt.ShareGrads()

    """
    from dragon.config import option
    option['share_grads'] = enabled


@classmethod
def create(cls, action, **kwargs):
    """Create new database row using the provided action need.

        :param action: An object containing a method equal to ``'action'`` and
            a value.
        :param argument: The action argument. If this parameter is not passed,
            then the ``action.argument`` will be used instead. If the
            ``action.argument`` does not exist, ``None`` will be set as
            argument for the new action need.
        :returns: An :class:`invenio_access.models.ActionNeedMixin` instance.
        """
    assert action.method == 'action'
    argument = kwargs.pop('argument', None) or getattr(action, 'argument', None
        )
    return cls(action=action.value, argument=argument, **kwargs)


def pulse_train(time, start, duration, repeat_time, end):
    """ Implements vensim's PULSE TRAIN function

    In range [-inf, start) returns 0
    In range [start + n * repeat_time, start + n * repeat_time + duration) return 1
    In range [start + n * repeat_time + duration, start + (n+1) * repeat_time) return 0
    """
    t = time()
    if start <= t < end:
        return 1 if (t - start) % repeat_time < duration else 0
    else:
        return 0


def serialize_criterion(criterions):
    """Transform an cirterin dict in a magento GET params:
    >>>serialize_criterion({'name': 'tata'})
    {'filter[0][attribute]': 'name', 'filter[0][in]': 'tata'}
    """
    result = dict()
    for index, (attr, attr_value) in enumerate(criterions.items()):
        key1 = 'filter[%s][attribute]' % index
        result[key1] = attr
        key2 = 'filter[%s][in]' % index
        result[key2] = attr_value
    return result


@classmethod
def create_criteria(cls, query):
    """Return a criteria from a dictionary containing a query.

        Query should be a dictionary, keyed by field name. If the value is
        a list, it will be divided into multiple criteria as required.
        """
    criteria = []
    for name, value in query.items():
        if isinstance(value, list):
            for inner_value in value:
                criteria += cls.create_criteria({name: inner_value})
        else:
            criteria.append({'criteria': {'field': name, 'value': value}})
    return criteria or None


def backward_elimination(variables, train_model, score_model, verbose=False):
    """ Variable selection using backward elimination

    Input:
        variables: complete list of variables to consider in model building
        train_model: function that returns a fitted model for a given set of variables
        score_model: function that returns the score of a model; better models have lower scores

    Returns:
        (best_model, best_variables)
    """
    best_variables = list(variables)
    best_model = train_model(best_variables)
    best_score = score_model(best_model, best_variables)
    if verbose:
        print('Variables: ' + ', '.join(variables))
        print('Start: score={:.2f}'.format(best_score))
    while len(best_variables) > 1:
        step = [(best_score, None, best_model)]
        for removeVar in best_variables:
            step_var = list(best_variables)
            step_var.remove(removeVar)
            step_model = train_model(step_var)
            step_score = score_model(step_model, step_var)
            step.append((step_score, removeVar, step_model))
        step.sort(key=lambda x: x[0])
        best_score, removed_step, best_model = step[0]
        if verbose:
            print('Step: score={:.2f}, remove {}'.format(best_score,
                removed_step))
        if removed_step is None:
            break
        best_variables.remove(removed_step)
    return best_model, best_variables


@classmethod
def decode(cls, value):
    """
        read bytes from redis and turn it back into an integer.

        :param value: bytes
        :return: int
        """
    return None if value is None else int(float(value))


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


def mom_defuzzify(type1_set):
    """
    Mean of Maxima defuzzification method

    References:
    -----------
    Mamdani, E. H., H. J. Efstathiou, and K. Sugiyama.
    "Developments in fuzzy logic control." Decision and Control, 1984.
    The 23rd IEEE Conference on. Vol. 23. IEEE, 1984.

    Arguments:
    ----------
    type1_set   -- Type1FuzzySet, the set whose centroid is to be computed

    Returns:
    --------
    centroid    -- float, the centroid of this set

    Raises:
    -------
    """
    max_domain_elements = []
    max_dom = 0
    for domain_element in type1_set.domain_elements():
        if type1_set[domain_element] > max_dom:
            max_dom = type1_set[domain_element]
            max_domain_elements.clear()
            max_domain_elements.append(domain_element)
        elif type1_set[domain_element] == max_dom:
            max_domain_elements.append(domain_element)
    centroid = sum(max_domain_elements) / len(max_domain_elements)
    return centroid


def SSLatt2text(SSGCen):
    """Lattice centering vectors to text"""
    lattTxt = ''
    lattDir = {(4): '1/3', (6): '1/2', (8): '2/3', (0): '0'}
    for vec in SSGCen:
        lattTxt += ' '
        for item in vec:
            lattTxt += '%s,' % lattDir[int(item * 12)]
        lattTxt = lattTxt.rstrip(',')
        lattTxt += ';'
    lattTxt = lattTxt.rstrip(';').lstrip(' ')
    return lattTxt


def value_quality(value):
    """Calculate value quality."""
    if not value:
        return 0
    if '[translate me]' in value:
        return 1
    if '[auto]' in value:
        return 2
    return 3


@classmethod
def merge(cls, spans):
    """Merges overlapping and touches spans in the given list of spans.

        Note that this modifies the original list.

        >>> spans = [Span(1,2), Span(3)]
        >>> Span.merge(spans)
        >>> spans
        [<1-3>]
        """
    i = 0
    while i < len(spans) - 1:
        here = spans[i]
        j = i + 1
        while j < len(spans):
            there = spans[j]
            if there.start > here.end + 1:
                break
            if here.touches(there) or here.overlaps(there):
                here = here.to(there)
                spans[i] = here
                del spans[j]
            else:
                j += 1
        i += 1
    return spans


def mem():
    """Returns memory usage tuple of ints: (rss, vsz).

    :rtype: tuple
    """
    return 0, 0


def Nu_Wakao_Kagei(Re, Pr):
    """Calculates Nusselt number of a fluid passing over a bed of particles
    using a correlation shown in [1]_ and also cited in the review of [2]_.
    Relatively rough, as it has no dependence on voidage.

    .. math::
        Nu = 2 + 1.1Pr^{1/3}Re^{0.6}

    Parameters
    ----------
    Re : float
        Reynolds number with pebble diameter as characteristic dimension, [-]
    Pr : float
        Prandtl number of the fluid []

    Returns
    -------
    Nu : float
        Nusselt number for heat transfer to the packed bed [-]

    Notes
    -----
    Fit for Re from 3 to 3000; claimed reasonableness of fit to to 1E6.

    Examples
    --------
    >>> Nu_Wakao_Kagei(2000, 0.7)
    95.40641328041248

    References
    ----------
    .. [1] Wakao, Noriaki, and Seiichirō Kagei. Heat and Mass Transfer in
       Packed Beds. Taylor & Francis, 1982.
    .. [2] Abdulmohsin, Rahman S., and Muthanna H. Al-Dahhan. "Characteristics
       of Convective Heat Transport in a Packed Pebble-Bed Reactor." Nuclear
       Engineering and Design 284 (April 1, 2015): 143-52.
       doi:10.1016/j.nucengdes.2014.11.041.
    """
    return 2 + 1.1 * Pr ** (1 / 3.0) * Re ** 0.6


def simplejson_datetime_serializer(obj):
    """
    Designed to be passed as the default kwarg in simplejson.dumps.  Serializes dates and datetimes to ISO strings.
    """
    if hasattr(obj, 'isoformat'):
        return obj.isoformat()
    else:
        raise TypeError(
            'Object of type %s with value of %s is not JSON serializable' %
            (type(obj), repr(obj)))


def rebin(x, factor):
    """
    Rebin a vector, or the first dimension of an array,
    by averaging within groups of "factor" adjacent values.

    """
    if factor == 1:
        xx = x
    else:
        xx = x.reshape(len(x) // factor, factor, -1).mean(1).squeeze()
    return xx


def ignoreCode(code, lineFlags):
    """
    Function to check, if the given code should be ignored as per line flags.

    @param code error code to be checked
    @type str
    @param lineFlags list of line flags to check against
    @type list of str
    @return flag indicating to ignore the code
    @rtype bool
    """
    if lineFlags:
        if '__IGNORE_WARNING__' in lineFlags or 'noqa' in lineFlags:
            return True
        for flag in lineFlags:
            if flag.startswith('__IGNORE_WARNING_'):
                ignoredCode = flag[2:-2].rsplit('_', 1)[-1]
                if code.startswith(ignoredCode):
                    return True
    return False


def varint(n):
    """Varint encoding."""
    data = b''
    while n >= 128:
        data += bytes([n & 127 | 128])
        n >>= 7
    data += bytes([n])
    return data


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

    The ".dev0" means dirty.

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


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

    The ".dev0" means dirty.

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


@staticmethod
def before_start(job):
    """
		Make sure we can run the job, set the status & report to slack
		:param job:
		:return:
		"""
    if job.driver not in ('chrome', 'firefox'):
        raise TypeError('desired driver(s) not supported: ' + job.driver)


def parse_lambda_tags_from_arn(arn):
    """Generate the list of lambda tags based on the data in the arn
    Args:
        arn (str): Lambda ARN.
            ex: arn:aws:lambda:us-east-1:123597598159:function:my-lambda[:optional-version]
    """
    split_arn = arn.split(':')
    if len(split_arn) > 7:
        split_arn = split_arn[:7]
    _, _, _, region, account_id, _, function_name = split_arn
    return ['region:{}'.format(region), 'account_id:{}'.format(account_id),
        'functionname:{}'.format(function_name)]


@staticmethod
def undirected_edges(weighted_edges):
    """Turn every edge into an undirected one."""
    undirected_weighted_edges = {}
    for (tail, head), (weight, relative_distance) in weighted_edges.items():
        assert not ((head, tail) in weighted_edges and (tail, head) in
            weighted_edges)
        undirected_weighted_edges[tail, head] = weight, relative_distance
        undirected_weighted_edges[head, tail] = weight, -relative_distance
    return undirected_weighted_edges


def GetAccelIndex(label):
    """
    Returns the mnemonic index of the label and the label stripped of the ampersand mnemonic
    (e.g. 'lab&el' ==> will result in 3 and labelOnly = label).

    :param string `label`: a string possibly containining an ampersand.
    """
    indexAccel = 0
    while True:
        indexAccel = label.find('&', indexAccel)
        if indexAccel == -1:
            return indexAccel, label
        if label[indexAccel:indexAccel + 2] == '&&':
            label = label[0:indexAccel] + label[indexAccel + 1:]
            indexAccel += 1
        else:
            break
    labelOnly = label[0:indexAccel] + label[indexAccel + 1:]
    return indexAccel, labelOnly


def find_element(strategy, locator, root=None):
    """Finds an element on the page.

        :param strategy: Location strategy to use (type depends on the driver implementation)
        :param locator: Location of target element.
        :param root: (optional) root node.
        :type strategy: str
        :type locator: str
        :type root: web element object or None.
        :return: web element object
        :rtype: it depends on the driver implementation
        """


@classmethod
def unregister_parser(cls, cobject):
    """Unregister a parser

        This is the opposite of FTrace.register_parser(), it removes a class
        from the list of classes that will be parsed on the trace

        """
    all_scopes = [cls.thermal_classes, cls.sched_classes, cls.dynamic_classes]
    for scope_classes in all_scopes:
        for name, obj in list(scope_classes.items()):
            if cobject == obj:
                del scope_classes[name]


def filter(properties, initial=None, editable=None, display=None, ignore=[]):
    """ Filter a list of properties
        """


def get_calculation(calculation_id):
    """Get LNG Ageing calculation

     # noqa: E501

    :param calculation_id: The ID of the calculation
    :type calculation_id: str

    :rtype: Calculation
    """
    return 'do some magic!'


def _one_for_each_state(value, n_states: int, name: str) ->list:
    """Duplicate a value for each initial state if there is only one value."""
    if isinstance(value, (tuple, list)):
        if len(value) != n_states:
            raise ValueError(
                f"When `{name}' is a list or tuple, it must contain exactly as many values as initial states of the underlying RNN. Expected: {n_states}, got: {len(value)}"
                )
    else:
        value = [value] * n_states
    return value


@staticmethod
def _get_extra_dict(response, mapping):
    """
        Extract attributes from the element based on rules provided in the
        mapping dictionary.

        :param   response: The JSON response to parse the values from.
        :type    response: ``dict``

        :param   mapping: Dictionary with the extra layout
        :type    mapping: ``dict``

        :rtype:  ``dict``
        """
    extra = {}
    for attribute, values in mapping.items():
        transform_func = values['transform_func']
        value = response.get(values['key_name'])
        extra[attribute] = transform_func(value) if value else None
    return extra


def SizeBenefitAnn(t):
    """Annuity benefit per policy"""
    return 0


def get_domain_notes(domain):
    """
    Combine all domain notes if there are any.
    """
    all_notes = (domain.http.notes + domain.httpwww.notes + domain.https.
        notes + domain.httpswww.notes)
    all_notes = all_notes.replace(',', ';')
    return all_notes


def lerp(a, b, x):
    """linear interpolation"""
    return a + x * (b - a)


def get_links(mlist, msg, msgdata):
    """Get an `IChainIterator` for processing.

        :param mlist: The mailing list.
        :param msg: The message being processed.
        :param msgdata: The message metadata dictionary.
        :return: `IChainIterator`.
        """


def get_assignment(AssignmentId=None):
    """
    The GetAssignment operation retrieves the details of the specified Assignment.
    See also: AWS API Documentation

    :example: response = client.get_assignment(
        AssignmentId='string'
    )

    :type AssignmentId: string
    :param AssignmentId: [REQUIRED]
            The ID of the Assignment to be retrieved.

    :rtype: dict
    :return: {
        'Assignment': {
            'AssignmentId': 'string',
            'WorkerId': 'string',
            'HITId': 'string',
            'AssignmentStatus': 'Submitted'|'Approved'|'Rejected',
            'AutoApprovalTime': datetime(2015, 1, 1),
            'AcceptTime': datetime(2015, 1, 1),
            'SubmitTime': datetime(2015, 1, 1),
            'ApprovalTime': datetime(2015, 1, 1),
            'RejectionTime': datetime(2015, 1, 1),
            'Deadline': datetime(2015, 1, 1),
            'Answer': 'string',
            'RequesterFeedback': 'string'
        },
        'HIT': {
            'HITId': 'string',
            'HITTypeId': 'string',
            'HITGroupId': 'string',
            'HITLayoutId': 'string',
            'CreationTime': datetime(2015, 1, 1),
            'Title': 'string',
            'Description': 'string',
            'Question': 'string',
            'Keywords': 'string',
            'HITStatus': 'Assignable'|'Unassignable'|'Reviewable'|'Reviewing'|'Disposed',
            'MaxAssignments': 123,
            'Reward': 'string',
            'AutoApprovalDelayInSeconds': 123,
            'Expiration': datetime(2015, 1, 1),
            'AssignmentDurationInSeconds': 123,
            'RequesterAnnotation': 'string',
            'QualificationRequirements': [
                {
                    'QualificationTypeId': 'string',
                    'Comparator': 'LessThan'|'LessThanOrEqualTo'|'GreaterThan'|'GreaterThanOrEqualTo'|'EqualTo'|'NotEqualTo'|'Exists'|'DoesNotExist'|'In'|'NotIn',
                    'IntegerValues': [
                        123,
                    ],
                    'LocaleValues': [
                        {
                            'Country': 'string',
                            'Subdivision': 'string'
                        },
                    ],
                    'RequiredToPreview': True|False
                },
            ],
            'HITReviewStatus': 'NotReviewed'|'MarkedForReview'|'ReviewedAppropriate'|'ReviewedInappropriate',
            'NumberOfAssignmentsPending': 123,
            'NumberOfAssignmentsAvailable': 123,
            'NumberOfAssignmentsCompleted': 123
        }
    }

    """
    pass


def match_items(lines, content_old):
    """Create items for mangled lines.

    This function tries to match the lines in ``lines`` with the items (source
    file references and line numbers) in ``content_old``. The
    ``mangle_docstrings`` function changes the actual docstrings, but doesn't
    keep track of where each line came from. The manging does many operations
    on the original lines, which are hard to track afterwards.

    Many of the line changes come from deleting or inserting blank lines. This
    function tries to match lines by ignoring blank lines. All other changes
    (such as inserting figures or changes in the references) are completely
    ignored, so the generated line numbers will be off if ``mangle_docstrings``
    does anything non-trivial.

    This is a best-effort function and the real fix would be to make
    ``mangle_docstrings`` actually keep track of the ``items`` together with
    the ``lines``.

    Examples
    --------
    >>> lines = ['', 'A', '', 'B', '   ', '', 'C', 'D']
    >>> lines_old = ['a', '', '', 'b', '', 'c']
    >>> items_old = [('file1.py', 0), ('file1.py', 1), ('file1.py', 2),
    ...              ('file2.py', 0), ('file2.py', 1), ('file2.py', 2)]
    >>> content_old = ViewList(lines_old, items=items_old)
    >>> match_items(lines, content_old) # doctest: +NORMALIZE_WHITESPACE
    [('file1.py', 0), ('file1.py', 0), ('file2.py', 0), ('file2.py', 0),
     ('file2.py', 2), ('file2.py', 2), ('file2.py', 2), ('file2.py', 2)]
    >>> # first 2 ``lines`` are matched to 'a', second 2 to 'b', rest to 'c'
    >>> # actual content is completely ignored.

    Notes
    -----
    The algorithm tries to match any line in ``lines`` with one in
    ``lines_old``.  It skips over all empty lines in ``lines_old`` and assigns
    this line number to all lines in ``lines``, unless a non-empty line is
    found in ``lines`` in which case it goes to the next line in ``lines_old``.

    """
    items_new = []
    lines_old = content_old.data
    items_old = content_old.items
    j = 0
    for i, line in enumerate(lines):
        while j < len(lines_old) - 1 and not lines_old[j].strip():
            j += 1
        items_new.append(items_old[j])
        if line.strip() and j < len(lines_old) - 1:
            j += 1
    assert len(items_new) == len(lines)
    return items_new


def equal(param1, param2, ignore_case=False):
    """
    Compare two parameters and return if they are equal.
    This parameter doesn't run equal operation if first parameter is None.
    With this approach we don't run equal operation in case user don't
    specify parameter in their task.

    :param param1: user inputted parameter
    :param param2: value of entity parameter
    :return: True if parameters are equal or first parameter is None, otherwise False
    """
    if param1 is not None:
        if ignore_case:
            return param1.lower() == param2.lower()
        return param1 == param2
    return True


@staticmethod
def get_extent_list(extent):
    """convert extent dick to ordered array"""
    return [extent['xmin'], extent['ymin'], extent['xmax'], extent['ymax']]


def eval_function_body(f):
    """Call the decorated function. The function itself is not returned!"""
    return f()


@classmethod
def escape(cls, s):
    """escape filename characters which are valid regex"""
    for c in '.+[]{}()^$':
        s = s.replace(c, '\\' + c)
    return s


def fname(file):
    """Return the filename without extension of ``file``."""
    return file.split('.')[-1]


def denormalize_parameters(p):
    """
	Given a fully normalized parameters dictionary:
	{'host': 'localhost', 'settings' : {'timezone':'utc'}}

	Denormalize it:
	[(('host',), 'localhost'), (('settings','timezone'), 'utc')]
	"""
    for k, v in p.items():
        if k == 'settings':
            for sk, sv in dict(v).items():
                yield ('settings', sk), sv
        else:
            yield (k,), v


def f2dict(f_p, k_position, v_position):
    """
    convert a file with a key-value to a dict
    """
    dict = {}
    f = open(f_p, 'r')
    h_s = f.readline().rstrip().split('\t')
    for l in f:
        try:
            l_s = l.rstrip().split('\t')
            key, value = l_s[k_position], l_s[v_position]
            dict[key] = value
        except:
            continue
    f.close()
    return dict


@staticmethod
def _is_apos(t) ->bool:
    """Return whether or not ``t`` is an apostrophy (') symbol.

        :param t: the string to compare

        """
    return t.orth != t.lemma and t.orth_.find("'") >= 0


def set_default_timeout(timeout=None, connect_timeout=None, read_timeout=None):
    """
    The purpose of this function is to install default socket timeouts that
    different than those used by boto3 and botocore. Clients obtained from the
    `fleece.boto3.client()` function will have these timeouts set, unless
    explicitly overriden.

    The default timeouts set through this option apply to the entire process.
    For that reason, it is recommended that this function is only called once
    during startup, and from the main thread, before any other threads are
    spawned.

    Socket timeouts are automatically retried by boto, according to its own
    retry policies.

    :param timeout timeout for socket connections and reads in seconds. This is
                   a convenience argument that applies the same default to both
                   connection and read timeouts.
    :param connect_timeout timeout for socket connections in seconds.
    :param read_timeout timeout for socket reads in seconds.
    """
    global DEFAULT_TIMEOUT
    global DEFAULT_CONNECT_TIMEOUT
    global DEFAULT_READ_TIMEOUT
    DEFAULT_TIMEOUT = timeout
    DEFAULT_CONNECT_TIMEOUT = connect_timeout
    DEFAULT_READ_TIMEOUT = read_timeout


def check_ipaddr(address):
    """ quick check ip address for common errors """
    if isinstance(address, str) and len(address) < 50 and ('.' in address or
        ':' in address):
        return True
    else:
        return False


def _zone_to_region(zone):
    """Convert a zone (like us-west1-b) to the corresponding region
    (like us-west1)."""
    return '-'.join(zone.split('-')[:-1])


def get_mtime(f):
    """
    Get modification time of a given file
    :param f:
    :return:
    """
    return f.stat().st_mtime


def slice(obj, keys=[], skip=[], full=True):
    """ return a slice of an object. """
    t = type(obj)
    o = t()
    if not keys:
        keys = obj.keys()
    for key in keys:
        if key in skip:
            continue
        if not full and key.startswith('_'):
            continue
        val = obj.get(key, None)
        if val and 'keys' in dir(val):
            o[key] = slice(val)
        else:
            o[key] = val
    return o


def update_shard_count(StreamName=None, TargetShardCount=None, ScalingType=None
    ):
    """
    Updates the shard count of the specified stream to the specified number of shards.
    Updating the shard count is an asynchronous operation. Upon receiving the request, Amazon Kinesis returns immediately and sets the status of the stream to UPDATING . After the update is complete, Amazon Kinesis sets the status of the stream back to ACTIVE . Depending on the size of the stream, the scaling action could take a few minutes to complete. You can continue to read and write data to your stream while its status is UPDATING .
    To update the shard count, Amazon Kinesis performs splits and merges and individual shards. This can cause short-lived shards to be created, in addition to the final shards. We recommend that you double or halve the shard count, as this results in the fewest number of splits or merges.
    This operation has a rate limit of twice per rolling 24 hour period. You cannot scale above double your current shard count, scale below half your current shard count, or exceed the shard limits for your account.
    For the default limits for an AWS account, see Streams Limits in the Amazon Kinesis Streams Developer Guide . If you need to increase a limit, contact AWS Support .
    See also: AWS API Documentation

    :example: response = client.update_shard_count(
        StreamName='string',
        TargetShardCount=123,
        ScalingType='UNIFORM_SCALING'
    )

    :type StreamName: string
    :param StreamName: [REQUIRED]
            The name of the stream.

    :type TargetShardCount: integer
    :param TargetShardCount: [REQUIRED]
            The new number of shards.

    :type ScalingType: string
    :param ScalingType: [REQUIRED]
            The scaling type. Uniform scaling creates shards of equal size.

    :rtype: dict
    :return: {
        'StreamName': 'string',
        'CurrentShardCount': 123,
        'TargetShardCount': 123
    }

    """
    pass


def simplify(units):
    """
    Cancel units that appear in both numerator and denominator, then attempt to replace
    groups of units with single units where possible (ie, J/s => W)
    """
    pass


@staticmethod
def long_name_type():
    """
        Returns the long name type for this port.

        :returns: string
        """
    return 'FastEthernet'


@staticmethod
def _wrap_uid_bytes(bytestream):
    """Return `bytestream` without any trailing null padding."""
    if bytestream[-1:] == b'\x00':
        return bytestream[:-1]
    return bytestream


def WorthShare(Task):
    """
	return False if the sharing overhead is larger than the hardware area being saved.
	"""
    return False


def avg_pool_forward_reshape(x, pool_param):
    """
    A fast implementation of the forward pass for the avg pooling layer that uses
    some clever reshaping.

    This can only be used for square pooling regions that tile the input.
    """
    N, C, H, W = x.shape
    pool_height, pool_width = pool_param['pool_height'], pool_param[
        'pool_width']
    stride = pool_param['stride']
    assert pool_height == pool_width == stride, 'Invalid pool params'
    assert H % pool_height == 0
    assert W % pool_height == 0
    x_reshaped = x.reshape(N, C, H // pool_height, pool_height, W //
        pool_width, pool_width)
    out = x_reshaped.mean(axis=3).mean(axis=4)
    cache = x, x_reshaped, out
    return out, cache


def _is_significant(change, significance):
    """Return True if a change is genuinely significant given our tolerance."""
    try:
        a = float(change['from'])
        b = float(change['to'])
    except ValueError:
        return True
    return int(a * 10 ** significance) != int(b * 10 ** significance)


def formula_2016_01_01(foyer_fiscal, period, parameters):
    """
        Réduction d'impôt sous condition de revenus
        Cette réduction instaurée en 2016 vise à adoucir un effet de seuil d'assujettissement
        à l'impôt pour les foyers fiscaux les plus modestes, elle est plus à considérer comme une
        "décote bis" qu'une réduction fiscale à proprement parler.
        """
    ir_plaf_qf = foyer_fiscal('ir_plaf_qf', period)
    decote = foyer_fiscal('decote', period)
    nb_adult = foyer_fiscal('nb_adult', period)
    nb_parts = foyer_fiscal('nbptr', period)
    rfr = foyer_fiscal('rfr', period)
    P = parameters(period
        ).impot_revenu.plafond_qf.reduction_ss_condition_revenus
    ir_apres_plaf_qf_et_decote = ir_plaf_qf - decote
    plafond1 = P.seuil1 * nb_adult + P.seuil_maj_enf * 2 * (nb_parts - nb_adult
        )
    plafond2 = P.seuil2 * nb_adult + P.seuil_maj_enf * 2 * (nb_parts - nb_adult
        )
    reduction1 = P.taux * ir_apres_plaf_qf_et_decote
    reduction2 = P.taux * ir_apres_plaf_qf_et_decote * (plafond2 - rfr) / (
        plafond2 - plafond1)
    reduction_sous_condition_de_ressources = (rfr < plafond1) * reduction1 + (
        rfr >= plafond1) * (rfr < plafond2) * reduction2
    return reduction_sous_condition_de_ressources


def duration_to_string(duration):
    """
    Converts a duration to a string

    Args:
        duration (int): The duration in seconds to convert

    Returns s (str): The duration as a string
    """
    m, s = divmod(duration, 60)
    h, m = divmod(m, 60)
    return '%d:%02d:%02d' % (h, m, s)


def addall(*args):
    """Add all the positional arguments.

    :returns: sum of all the positional arguments.
    :note: We use ``sum(args)``
    """
    return sum(args)


def offset_hue_color(hsv, offset):
    """
    Offsets the hue value in -360-360 range by the given offset amount and keeps range by looping
    :param hsv: list(float, float, float), list or tuple representing the hue saturation and value color
    :param offset: float, offset value to offset the saturation
    :return: list(float, float, float), offset hue saturation value color
    """
    if offset > 360:
        offset = 360
    elif offset < -360:
        offset = -360
    hsv[0] += offset
    if hsv[0] > 360:
        hsv[0] -= 360
    elif hsv[0] < 0:
        hsv[0] += 360
    return hsv


@staticmethod
def truncate_string(str_to_truncate, max_num):
    """Truncate a string by taking first and last characters.

        :param str_to_truncate: the string to be truncated
        :param max_num: the maximum number of characters
        :returns: string -- truncated string or original string
        """
    if len(str_to_truncate) > max_num:
        new_num = len(str_to_truncate) - max_num // 2
        first_chars = str_to_truncate[:max_num // 2]
        last_chars = str_to_truncate[new_num:]
        str_to_truncate = first_chars + last_chars
    return str_to_truncate


def shutdown(event):
    """ shutdown the UDP echo server. """
    from . import runtime
    udp = runtime.get('udp', None)
    if not udp:
        udp.exit()


def gettime(athlinkstime):
    """
    return epoch time based on athlinks time

    :param athlinkstime: time from athlinks record
    :rtype: int containing epoch time
    """
    while athlinkstime[0] not in '0123456789':
        athlinkstime = athlinkstime[1:]
    while athlinkstime[-1] not in '0123456789':
        athlinkstime = athlinkstime[:-1]
    return int(athlinkstime) / 1000


@classmethod
def list(cls, page_size: int=None, next_token: str=None, sort: str=None,
    amino_acids: str=None, archive_reason: str=None, folder_id: str=None,
    modified_at: str=None, name: str=None, project_id: str=None, schema_id:
    str=None, registry_id: str=None, **kwargs):
    """List :class:`AASequence` models.

        :param page_size: Number of results to return. Defaults to 50, maximum of 100.
        :param next_token: Token for pagination
        :param sort: Method by which to order search results. Valid sorts are modifiedAt
                (modified time, most recent first) and name (entity name, alphabetical).
                 Optionally add :asc or :desc to specify ascending or descending order.
                 Default is modifiedAt.
        :param archive_reason: Archive reason. Restricts DNA Sequences to those with the
                specified archive reason. Use “NOT_ARCHIVED” to filter for unarchived
                DNA Sequences.
        :param folder_id: ID of a folder. Restricts results to those in the folder.
        :param modified_at: Datetime, in RFC 3339 format. Supports the > and <
                operators. Time zone defaults to UTC. Restricts results to those
                modified in the specified range. e.g. > 2017-04-30.
        :param name: Name of a DNA Sequence. Restricts results to those with the
                specified name.
        :param project_id: ID of a project. Restricts results to those in the project.
        :param schema_id: ID of a schema. Restricts results to those of the specified
                schema.
        :param registry_id: ID of a registry. Restricts results to those registered in
                this registry.
        :return:
        """
    return super().list(page_size=page_size, next_token=next_token, sort=
        sort, amino_acids=amino_acids, modified_at=modified_at, name=name,
        folder_id=folder_id, project_id=project_id, schema_id=schema_id,
        archive_reason=archive_reason, registry_id=registry_id, **kwargs)


@staticmethod
def starting_nodes_name(flow_name):
    """Create a starting node name for graph of all failures nodes for generated Python config.

        :param flow_name: flow name for which the starting node should be created
        :return: variable name
        :rtype: str
        """
    return '_%s_failure_starting_nodes' % flow_name


def repeat_last():
    """Repeat last action

    """
    pass


@classmethod
def get_user_by_user_code(cls, user_code):
    """
        根据user_code查询当前用户
        :param user_code:
        :return:
        """
    return cls.objects(user_code=user_code, status__in=[cls.get_status('正常')]
        ).first()


def is_log_start_line(line):
    """
    Is the line the start of a request log from Google App Engine.

    :param line: A string.
    :returns: True if the line doesn't start with a tab.
    """
    if not line[:1] == u'\t':
        return True


def parent_set():
    """Set the mask’s parenting

    """
    pass


def getCountDict(inlist):
    """list -> count dict"""
    outCD = {}
    for element in inlist:
        if element in outCD:
            outCD[element] += 1
        else:
            outCD[element] = 1
    return outCD


def _margeff_cov_params_dummy(model, cov_margins, params, exog, dummy_ind,
    method, J):
    """
    Returns the Jacobian for discrete regressors for use in margeff_cov_params.

    For discrete regressors the marginal effect is

    \\Delta F = F(XB) | d = 1 - F(XB) | d = 0

    The row of the Jacobian for this variable is given by

    f(XB)*X | d = 1 - f(XB)*X | d = 0

    Where F is the default prediction of the model.
    """
    for i in dummy_ind:
        exog0 = exog.copy()
        exog1 = exog.copy()
        exog0[:, (i)] = 0
        exog1[:, (i)] = 1
        dfdb0 = model._derivative_predict(params, exog0, method)
        dfdb1 = model._derivative_predict(params, exog1, method)
        dfdb = dfdb1 - dfdb0
        if dfdb.ndim >= 2:
            dfdb = dfdb.mean(0)
        if J > 1:
            K = dfdb.shape[1] // (J - 1)
            cov_margins[i::K, :] = dfdb
        else:
            cov_margins[(i), :len(dfdb)] = dfdb
    return cov_margins


@staticmethod
def _dpi(units_specifier, px_per_unit):
    """
        Return dots per inch value calculated from *units_specifier* and
        *px_per_unit*.
        """
    if units_specifier == 1 and px_per_unit:
        return int(round(px_per_unit * 0.0254))
    return 72


def get_row_values(model, keys):
    """Get the values needed to fill a row in the table

    Parameters
    ----------

    model : `dmsky.Model`
        Model that we are getting the data from

    keys : list
        Names of the properties we are reading

    Returns
    -------

    vals : dict
        A dictionary we can use to fill an `astropy.table.Column` row

    """
    d = {}
    for k in keys:
        d[k] = getattr(model, k)
    return d


def validate_resource_attributes(resource, attributes, template, check_unit
    =True, exact_match=False):
    """
        Validate that the resource provided matches the template.
        Only passes if the resource contains ONLY the attributes specified
        in the template.

        The template should take the form of a dictionary, as should the
        resources.

        *check_unit*:  Make sure that if a unit is specified in the template, it
                     is the same in the data
        *exact_match*: Enure that all the attributes in the template are in
                     the data also. By default this is false, meaning a subset
                     of the template attributes may be specified in the data.
                     An attribute specified in the data *must* be defined in
                     the template.

        @returns a list of error messages. An empty list indicates no
        errors were found.
    """
    errors = []
    res_type = 'GROUP'
    if resource.get('x') is not None:
        res_type = 'NODE'
    elif resource.get('node_1_id') is not None:
        res_type = 'LINK'
    elif resource.get('nodes') is not None:
        res_type = 'NETWORK'
    tmpl_res = template['resources'][res_type]
    res_user_type = resource.get('type')
    if res_user_type is None:
        errors.append('No type specified on resource %s' % resource['name'])
    elif tmpl_res.get(res_user_type) is None:
        errors.append(
            'Resource %s is defined as having type %s but this type is not specified in the template.'
             % (resource['name'], res_user_type))
    tmpl_attrs = tmpl_res.get(res_user_type)['attributes']
    attrs = {}
    for a in attributes.values():
        attrs[a['id']] = a
    for a in tmpl_attrs.values():
        if a.get('id') is not None:
            attrs[a['id']] = {'name': a['name'], 'unit': a.get('unit'),
                'dimen': a.get('dimension')}
    if exact_match is True:
        tmpl_attr_names = set(tmpl_attrs.keys())
        resource_attr_names = []
        for ra in resource['attributes']:
            attr_name = attrs[ra['attr_id']]['name']
            resource_attr_names.append(attr_name)
        resource_attr_names = set(resource_attr_names)
        in_tmpl_not_in_resource = tmpl_attr_names - resource_attr_names
        in_resource_not_in_tmpl = resource_attr_names - tmpl_attr_names
        if len(in_tmpl_not_in_resource) > 0:
            errors.append(
                'Template has defined attributes %s for type %s but they are not specified in the Data.'
                 % (','.join(in_tmpl_not_in_resource), res_user_type))
        if len(in_resource_not_in_tmpl) > 0:
            errors.append(
                'Resource %s (type %s) has defined attributes %s but this is not specified in the Template.'
                 % (resource['name'], res_user_type, ','.join(
                in_resource_not_in_tmpl)))
    for res_attr in resource['attributes']:
        attr = attrs.get(res_attr['attr_id'])
        if attr is None:
            errors.append(
                'An attribute mismatch has occurred. Attr %s is not defined in the data but is present on resource %s'
                 % (res_attr['attr_id'], resource['name']))
            continue
        if tmpl_attrs.get(attr['name']) is None:
            errors.append(
                'Resource %s has defined attribute %s but this is not specified in the Template.'
                 % (resource['name'], attr['name']))
        else:
            tmpl_attr = tmpl_attrs[attr['name']]
            if tmpl_attr.get('data_type') is not None:
                if res_attr.get('type') is not None:
                    if tmpl_attr.get('data_type') != res_attr.get('type'):
                        errors.append(
                            'Error in data. Template says that %s on %s is a %s, but data suggests it is a %s'
                             % (attr['name'], resource['name'], tmpl_attr.
                            get('data_type'), res_attr.get('type')))
            attr_dimension = 'dimensionless' if attr.get('dimension'
                ) is None else attr.get('dimension')
            tmpl_attr_dimension = 'dimensionless' if tmpl_attr.get('dimension'
                ) is None else tmpl_attr.get('dimension')
            if attr_dimension.lower() != tmpl_attr_dimension.lower():
                errors.append(
                    'Dimension mismatch on resource %s for attribute %s (template says %s on type %s, data says %s)'
                     % (resource['name'], attr.get('name'), tmpl_attr.get(
                    'dimension'), res_user_type, attr_dimension))
            if check_unit is True:
                if tmpl_attr.get('unit') is not None:
                    if attr.get('unit') != tmpl_attr.get('unit'):
                        errors.append(
                            'Unit mismatch for resource %s with unit %s (template says %s for type %s)'
                             % (resource['name'], attr.get('unit'),
                            tmpl_attr.get('unit'), res_user_type))
    return errors