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 inv_perm(perm):
    """Invert a permutation.

    Args:
        perm (list): Permutation to invert.

    Returns:
        list: Inverse permutation.
    """
    out = [0] * len(perm)
    for i, p in enumerate(perm):
        out[p] = i
    return out


@staticmethod
def get_subtype(object_dictionary):
    """
        Given the hash representation of a subtype of this class,
        use the info in the hash to return the class of the subtype.
        """
    type = object_dictionary['contentType']
    if type == 'BASE64':
        return 'Base64SecretBundleContentDetails'
    else:
        return 'SecretBundleContentDetails'


def remove_last_slash(path):
    """ Remove the last slash in the given path [if any] """
    if path.endswith('/'):
        path = path[:-1]
    return path


def _query_include_self(X, include_self):
    """Return the query based on include_self param"""
    if include_self:
        query = X._fit_X
    else:
        query = None
    return query


def rebuild():
    """This method is called, everytime an issue is updated.
        """


@staticmethod
def factory_by_name(class_name, args=(), kwargs={}):
    """from user specified device class name, return the proper device
        class.

        :param class_name: string (has to match the name of device class)
        :return: the class

        """
    return globals()[class_name](*args, **kwargs)


def absolute_url(relative=0):
    """Return the absolute URL of the object.

        This a canonical URL based on the object's physical
        containment path.  It is affected by the virtual host
        configuration, if any, and can be used by external
        agents, such as a browser, to address the object.

        If the relative argument is provided, with a true value, then
        the value of virtual_url_path() is returned.

        Some Products incorrectly use '/'+absolute_url(1) as an
        absolute-path reference.  This breaks in certain virtual
        hosting situations, and should be changed to use
        absolute_url_path() instead.
        """


def say_hello():
    """This function takes no parameter and just print "Hello, world!"
       onto the screen."""
    print('Hello, world!')


def read_blast_results(filepath):
    """
    Read blast results and return counts of blast search hits
    """
    hits = {}
    with open(filepath) as infile:
        line = infile.readline()
        while line:
            hit = line.strip().split(',')[1]
            if hit in hits:
                hits[hit] += 1
            else:
                hits[hit] = 1
            line = infile.readline()
    return dict(sorted(hits.items(), key=lambda x: x[1])[::-1])


def get_all_users():
    """Returns iterable of all users sorted by email."""


def cHypot():
    """
    Return the kernel code for hypot, which computes the sqrt(x*x + y*y) without intermediate overflow.
    """
    R = """
    KERNEL void cHypot(GLOBAL_MEM float2 *x,
                                    GLOBAL_MEM const float2 *y)
    {
    const unsigned int gid =  get_global_id(0);
    float2 tmp_x;
    float2 tmp_y;
    tmp_x = x[gid];
    tmp_y = y[gid];
    tmp_x.x = hypot( tmp_x.x, tmp_x.y); // sqrt( tmp_x.x*tmp_x.x + tmp_x.y*tmp_x.y);
    tmp_y.x = hypot( tmp_y.x, tmp_y.y); // sqrt( tmp_y.x*tmp_y.x + tmp_y.y*tmp_y.y);

    x[gid].x = hypot(tmp_x.x, tmp_y.x);
    x[gid].y = 0.0;

    };
    """
    return R


def game_type():
    """User can choose playing against computer or another user.
    """
    pass


@staticmethod
def p_a2ml_keyword(p):
    """a2ml_keyword : STRING"""


def ensure_session_key(request):
    """
    Given a request return a session key that will be used. There may already
    be a session key associated, but if there is not, we force the session to
    create itself and persist between requests for the client behind the given
    request.
    """
    key = request.session.session_key
    if key is None:
        request.session.save()
        request.session.modified = True
        key = request.session.session_key
    return key


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

        :param CameraUploadsPolicyChangedType val:
        :rtype: EventType
        """
    return cls('camera_uploads_policy_changed', val)


@staticmethod
def get_subtype(object_dictionary):
    """
        Given the hash representation of a subtype of this class,
        use the info in the hash to return the class of the subtype.
        """
    type = object_dictionary['actionType']
    if type == 'OSS':
        return 'StreamingServiceAction'
    if type == 'ONS':
        return 'NotificationServiceAction'
    if type == 'FAAS':
        return 'FaaSAction'
    else:
        return 'Action'


def check_length(min_length: int, max_length: int, mode: str='and', *args
    ) ->bool:
    """
    check items length is between min_length and max_length
    :param min_length: minimum length
    :param max_length: maximum length
    :param mode: check mode, 'and': all items need clear length check, 'or': more than one item need clear length check
    :param args: items
    :return: status, [correct] or [incorrect]
    """
    if mode == 'and':
        for item in args:
            if not min_length <= len(item) <= max_length:
                return False
        return True
    else:
        for item in args:
            if min_length <= len(item) <= max_length:
                return True
        return False


def accuracy(output, target, topk=(1,)):
    """Computes precision@k for the specified values of k."""
    maxk = max(topk)
    batch_size = target.size(0)
    _, pred = output.topk(maxk, 1, True, True)
    pred = pred.t()
    correct = pred.eq(target.view(1, -1).expand_as(pred))
    res = []
    for k in topk:
        correct_k = correct[:k].view(-1).float().sum(0)
        res.append(correct_k.mul_(100.0 / batch_size))
    return res


def get_backend(mutex_id):
    u"""Возвращает backend, который используется для хранения информации о
    семафорах.

    :param mutex_id: идентификатор семафора, для которого определяется backend

    """
    return None


def toPyModel(model_ptr):
    """
	toPyModel(model_ptr) -> svm_model

	Convert a ctypes POINTER(svm_model) to a Python svm_model
	"""
    if bool(model_ptr) == False:
        raise ValueError('Null pointer')
    m = model_ptr.contents
    m.__createfrom__ = 'C'
    return m


def load_Numeric(finder, module):
    """the Numeric module optionally loads the dotblas module; ignore the error
       if this modules does not exist."""
    module.IgnoreName('dotblas')


def setId(id):
    """Set workflow version id for this object.

        This is used to mark all versions of an object with the
        same id.
        """


def get_function_handle(method, var):
    """
    Return a function handle to a given calculation method.

    Parameters
    ----------
    method : str
        Identifier of the calculation method to return a handle to.
    var : dict
        Local variables needed in the calculation method.

    Returns
    -------
    f_handle : function
        Handle to calculation `method` defined in this globals scope.

    """
    return globals()['wrap_calculate_using_' + method](var)


def find_meta_property(obj, name):
    """
    Return a named (`name`) `QMetaProperty` of a `QObject` instance `obj`.
    If a property by taht name does not exist raise an AttributeError.

    """
    meta = obj.metaObject()
    index = meta.indexOfProperty(name)
    if index == -1:
        raise AttributeError('%s does no have a property named %r.' % (meta
            .className(), name))
    return meta.property(index)


def convert_three_to_python(three, python):
    """Converts a Three flag into a Python flag, and raises customer warnings
    in the process, if needed.
    """
    if not python:
        if three is False:
            return '2'
        elif three is True:
            return '3'
    else:
        return python


def delete_faces(CollectionId=None, FaceIds=None):
    """
    Deletes faces from a collection. You specify a collection ID and an array of face IDs to remove from the collection.
    This operation requires permissions to perform the rekognition:DeleteFaces action.
    See also: AWS API Documentation

    Examples
    This operation deletes one or more faces from a Rekognition collection.
    Expected Output:

    :example: response = client.delete_faces(
        CollectionId='string',
        FaceIds=[
            'string',
        ]
    )

    :type CollectionId: string
    :param CollectionId: [REQUIRED]
            Collection from which to remove the specific faces.

    :type FaceIds: list
    :param FaceIds: [REQUIRED]
            An array of face IDs to delete.
            (string) --

    :rtype: dict
    :return: {
        'DeletedFaces': [
            'string',
        ]
    }

    :returns:
    (string) --

    """
    pass


def specmix(x, wv, aspl, bspl, **kwargs):
    """
    Return the mixture of aspl and bspl specified by the parameters in x.

    Parameters
    ==========
    x : tuple
        A tuple containing the model parameters as (a, b, B0, c, m)
    wv : array-like
        The wavelength of the data
    aspl, bspl : UnivariateSpline
        Spline objects that produce the acid (aspl) or base (aspl)
        molal absorption given a wavelength.
    """
    a, b, B0, c, m = x
    return a * aspl(m * wv + c) + b * bspl(m * wv + c) + B0


def p_track_mode(t):
    """track_mode : AUDIO
                  | MODE1
                  | MODE1_RAW
                  | MODE2
                  | MODE2_FORM1
                  | MODE2_FORM2
                  | MODE2_FORM_MIX
                  | MODE2_RAW"""
    t[0] = t[1]


def convert_waypoint_float(waypoint):
    """
    Convert waypoint values to float
    """
    waypoint['x'] = float(waypoint['x'])
    waypoint['y'] = float(waypoint['y'])
    waypoint['z'] = float(waypoint['z'])
    waypoint['yaw'] = float(waypoint['yaw'])


def __execute(model, iteration_number):
    """
    Execute a simulation model

    :param model: a configured diffusion model
    :param iteration_number: number of iterations
    :return: computed trends
    """
    iterations = model.iteration_bunch(iteration_number, False)
    trends = model.build_trends(iterations)[0]
    del iterations
    del model
    return trends


def extract_prefixed_keys(dictionary, prefix):
    """Returns a dictionary with all keys from :obj:`dictionary` that are prefixed
  with :obj:`prefix`.
  """
    sub_dict = {}
    for key, value in dictionary.items():
        if key.startswith(prefix):
            original_key = key[len(prefix):]
            sub_dict[original_key] = value
    return sub_dict


@staticmethod
def retrieve_members(contfile, files):
    """To be overridden."""


@staticmethod
def _call_with_frames_removed(f, *args, **kwds):
    """remove_importlib_frames in import.c will always remove sequences
        of importlib frames that end with a call to this function

        Use it instead of a normal call in places where including the importlib
        frames introduces unwanted noise into the traceback (e.g. when executing
        module code)
        """
    return f(*args, **kwds)


def nvlist_to_dict(nvlist):
    """Convert a CORBA namevalue list into a dictionary."""
    result = {}
    for item in nvlist:
        result[item.name] = item.value.value()
    return result


def duplicate_line():
    """Duplicate the current line

    """
    pass


def update_counts(s, counts):
    """Adds one to the counts of each appearance of characters in s,
        for characters in counts"""
    for char in s:
        if char in counts:
            counts[char] += 1


def _check_exon_order(data_frame, row_number, row_index, prev_row_index,
    exon_pos):
    """Check that exons are ordered by rank in the transcript."""
    if exon_pos != 0:
        assert data_frame.loc[row_index, 'ExonRank'] > data_frame.loc[
            prev_row_index, 'ExonRank'
            ], "Exons aren't sorted by rank, error with row number " + str(
            row_number) + ', index ' + str(row_index) + '.'


def stroke_curvature(it):
    """
    Compute the 2D curvature at the stroke vertex pointed by the iterator 'it'.
    K = 1 / R
    where R is the radius of the circle going through the current vertex and its neighbors
    """
    for _ in it:
        if it.is_begin or it.is_end:
            yield 0.0
            continue
        else:
            it.decrement()
            prev, current, succ = it.object.point.copy(), next(it).point.copy(
                ), next(it).point.copy()
            it.decrement()
        ab = current - prev
        bc = succ - current
        ac = prev - succ
        a, b, c = ab.length, bc.length, ac.length
        try:
            area = 0.5 * ab.cross(ac)
            K = 4 * area / (a * b * c)
        except ZeroDivisionError:
            K = 0.0
        yield abs(K)


def iter_sequence_infinite(seq):
    """Iterate indefinitely over a Sequence.

    # Arguments
        seq: Sequence object

    # Returns
        Generator yielding batches.
    """
    while True:
        for item in seq:
            yield item


def _load_insert_element_if_necessary(load_df, at):
    """
    Insert an event at the specified point that conserve data consistency
    for "area" and "load" values
    """
    if len(load_df[load_df.time == at]) == 0:
        prev_el = load_df[load_df.time <= at].tail(1)
        new_el = prev_el.copy()
        next_el = load_df[load_df.time >= at].head(1)
        new_el.time = at
        new_el.area = float(new_el.load) * float(next_el.time - at)
        load_df.loc[prev_el.index, 'area'] = float(prev_el.load) * float(at -
            prev_el.time)
        load_df.loc[len(load_df)] = [float(new_el.time), float(new_el.load),
            float(new_el.area)]
        load_df = load_df.sort_values(by=['time'])
    return load_df


def indent_block(text, indention='    '):
    """This function indents a text block with a default of four spaces."""
    temp = ''
    while text and text[-1] == '\n':
        temp += text[-1]
        text = text[:-1]
    lines = text.split('\n')
    return '\n'.join(map(lambda s: indention + s, lines)) + temp


def stream():
    """
        Returns an input stream for reading asset contents.  Raises an
        exception if the asset is a directory or does not exist.
        """


@classmethod
def convert_name_to_id(cls, name: str) ->str:
    """
        Convert result name to configuration name.

        The name given in CCCC results is different than the name given in CCCC
        configuration. This will map the name in the configuration file to the
        name given in the results.
        """
    name_id = ''
    if name == 'IF4':
        name_id = 'IF4'
    elif name == 'fan_out_concrete':
        name_id = 'FOc'
    elif name == 'IF4_visible':
        name_id = 'IF4v'
    elif name == 'coupling_between_objects':
        name_id = 'CBO'
    elif name == 'fan_in_visible':
        name_id = 'FIv'
    elif name == 'weighted_methods_per_class_unity':
        name_id = 'WMC1'
    elif name == 'fan_out':
        name_id = 'FO'
    elif name == 'weighted_methods_per_class_visibility':
        name_id = 'WMCv'
    elif name == 'fan_out_visible':
        name_id = 'FOv'
    elif name == 'IF4_concrete':
        name_id = 'IF4c'
    elif name == 'depth_of_inheritance_tree':
        name_id = 'DIT'
    elif name == 'number_of_children':
        name_id = 'NOC'
    elif name == 'fan_in_concrete':
        name_id = 'FIc'
    elif name == 'fan_in':
        name_id = 'FI'
    elif name == 'lines_of_comment':
        name_id = 'COM'
    elif name == 'lines_of_code_per_line_of_comment':
        name_id = 'L_C'
    elif name == 'McCabes_cyclomatic_complexity':
        name_id = 'MVGper'
    elif name == 'lines_of_code':
        name_id = 'LOCp'
    elif name == 'McCabes_cyclomatic_complexity_per_line_of_comment':
        name_id = 'M_C'
    return name_id


def df_column_dtypes(df, dtype: str=None, target: str=None, max_cardinality:
    int=10):
    """Return the columns grouped by their dtypes or for a specific dtype"""
    numeric_cols = []
    cat_cols = []
    for col in df.columns:
        if col == target:
            continue
        if df[col].dtype in (int, float) and df[col].nunique(
            ) > max_cardinality:
            numeric_cols.append(col)
        else:
            cat_cols.append(col)
    dtypes = dict(numeric=numeric_cols, categorical=cat_cols)
    return dtypes[dtype] if dtype else dtypes


def add_keys(apps, schema_editor):
    """
    We can't import the Post model directly as it may be a newer
    version than this migration expects. We use the historical version.
    """
    Page = apps.get_model('pages', 'Page')
    ContentType = apps.get_model('contenttypes', 'ContentType')
    key = ''
    try:
        key = 'home'
        Page.objects.get(english_title=key)
    except Exception:
        Page.objects.create(title='صفحه اصلی', english_title=key,
            is_show_in_home=True)
    try:
        key = 'library'
        Page.objects.get(english_title=key)
    except Exception:
        Page.objects.create(title='کتابخانه', english_title=key,
            is_show_in_home=False)
    try:
        key = 'category'
        Page.objects.get(english_title=key)
    except Exception:
        Page.objects.create(title='دسته بندی', english_title=key,
            is_show_in_home=False)
    try:
        key = 'contact_us'
        Page.objects.get(english_title=key)
    except Exception:
        Page.objects.create(title='تماس با ما', english_title=key,
            is_show_in_home=False)
    try:
        key = 'about_us'
        Page.objects.get(english_title=key)
    except Exception:
        Page.objects.create(title='درباره ما', english_title=key,
            is_show_in_home=False)
    try:
        key = 'my_products'
        Page.objects.get(english_title=key)
    except Exception:
        Page.objects.create(title='محصولات من', english_title=key,
            is_show_in_home=False)
    try:
        key = 'download_manager'
        Page.objects.get(english_title=key)
    except Exception:
        Page.objects.create(title='دانلود منیجر', english_title=key,
            is_show_in_home=False)
    try:
        key = 'file_manager'
        Page.objects.get(english_title=key)
    except Exception:
        Page.objects.create(title='مدیریت فایل', english_title=key,
            is_show_in_home=False)
    try:
        key = 'user_invitation'
        Page.objects.get(english_title=key)
    except Exception:
        Page.objects.create(title='دعوت از دوستان', english_title=key,
            is_show_in_home=False)
    new_ct = ContentType.objects.get_for_model(Page)
    Page.objects.filter(polymorphic_ctype__isnull=True).update(
        polymorphic_ctype=new_ct)


def find_function_info(func, spec, args):
    """Return function meta-data in a tuple.

    (name, type)"""
    module = getattr(func, '__module__', None)
    name = getattr(func, '__name__', None)
    self = getattr(func, '__self__', None)
    cname = None
    if self:
        cname = self.__name__
    elif len(spec.args) and spec.args[0] == 'self':
        cname = args[0].__class__.__name__
    elif len(spec.args) and spec.args[0] == 'cls':
        cname = args[0].__name__
    if name:
        qname = []
        if module and module != '__main__':
            qname.append(module)
            qname.append('.')
        if cname:
            qname.append(cname)
            qname.append('.')
        qname.append(name)
        name = ''.join(qname)
    return name, None


def _past_month(m):
    """Subtract 1 from month."""
    if m == 1:
        return 12
    else:
        return m - 1


def word_wrap(string, width=80, ind1=0, ind2=0, prefix=''):
    """ word wrapping function.
        string: the string to wrap
        width: the column number to wrap at
        prefix: prefix each line with this string (goes before any indentation)
        ind1: number of characters to indent the first line
        ind2: number of characters to indent the rest of the lines
    """
    string = prefix + ind1 * ' ' + string
    newstring = ''
    while len(string) > width:
        marker = width - 1
        while not string[marker].isspace():
            marker = marker - 1
        newline = string[0:marker] + '\n'
        newstring = newstring + newline
        string = prefix + ind2 * ' ' + string[marker + 1:]
    return newstring + string


def decorator_autogen_code(original_func, decorator, new_func=None):
    """
  auto generates code to create decorated functions with NEW NAMES

  """
    if new_func is None:
        new_func = '%s_verbose' % original_func
    print(
        """

#
# decorator_autogen_code("{original_func}", "{decorator}", '{new_func}' )
#
@{decorator}
def {new_func}(*args, **kwargs):
   return {func}(*args, **kwargs)

  """
        .format(decorator=decorator, func=original_func, new_func=new_func,
        original_func=original_func))


def isValidAssocExtn(extname):
    """
    Determine if the extension name given as input could
    represent a valid association file.

    Parameters
    ----------
    extname : string

    Returns
    -------
    isValid  : boolean value

    """
    validExtnNames = ['asn', 'asc']
    for validName in validExtnNames:
        if extname == validName:
            return True
    return False


def is_tool(name):
    """Check whether `name` is on PATH and marked as executable."""
    from shutil import which
    return which(name) is not None


@classmethod
def _cli_desc(cls):
    """
        Get layer description

        Returns
        -------
        'str'
            Layer description
        """
    return (cls.desc if cls.desc is not None else
        "Apply Layer '{}' to model".format(cls.name))


def fix_image_ch(img):
    """Fix image channel so that it locates last in shape."""
    if img.shape[0] <= 3:
        return img.transpose(1, 2, 0)
    return img


def get_table_name_from_table_id(table_id):
    """ Extracts dataset name from table_id

    :param table_id: str
    :return: str
    """
    return table_id.split('__')[-1]


def _default_key_normalizer(key_class, request_context):
    """
    Create a pool key out of a request context dictionary.

    According to RFC 3986, both the scheme and host are case-insensitive.
    Therefore, this function normalizes both before constructing the pool
    key for an HTTPS request. If you wish to change this behaviour, provide
    alternate callables to ``key_fn_by_scheme``.

    :param key_class:
        The class to use when constructing the key. This should be a namedtuple
        with the ``scheme`` and ``host`` keys at a minimum.
    :type  key_class: namedtuple
    :param request_context:
        A dictionary-like object that contain the context for a request.
    :type  request_context: dict

    :return: A namedtuple that can be used as a connection pool key.
    :rtype:  PoolKey
    """
    context = request_context.copy()
    context['scheme'] = context['scheme'].lower()
    context['host'] = context['host'].lower()
    for key in ('headers', '_proxy_headers', '_socks_options'):
        if key in context and context[key] is not None:
            context[key] = frozenset(context[key].items())
    socket_opts = context.get('socket_options')
    if socket_opts is not None:
        context['socket_options'] = tuple(socket_opts)
    for key in list(context.keys()):
        context['key_' + key] = context.pop(key)
    for field in key_class._fields:
        if field not in context:
            context[field] = None
    return key_class(**context)


def sortable(obj):
    """Returns True if *obj* is sortable else returns False."""
    try:
        sorted([obj, obj])
        return True
    except TypeError:
        return False


def active(datetime):
    """checks if the cron is active"""


def successor_of(element, iterable, pairwise=pairwise):
    """Returns the successor of `element` in `iterable`"""
    for l, r in pairwise(iterable):
        if l == element:
            return r
    raise IndexError


@classmethod
def fromkeys(cls, iterable, value=None):
    """OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
        and values equal to v (which defaults to None).

        """
    d = cls()
    for key in iterable:
        d[key] = value
    return d


def get_single_text(field, text, **kwargs):
    """Returns the first token from an analyzer's output.
    """
    for t in field.process_text(text, mode='query', **kwargs):
        return t


def get_root(region_parent_zip, region_id):
    """
    Return the penultimate `parent_id` for any `region_id`.

    The penultimate parent is one layer below the root (0).
    The set of penultimate parents are the distinct regions contained in the segmentation.
    They correspond to putative functional regions.

    :param tuple region_parent_zip: a list of 2-tuples of `region_ids` and `parent_ids`
    :param int region_id: the `region_id` whose root parent_id is sought
    :return int parent_id: the corresponding penultimate `parent_id` (one step below the root - value of `0`)
    """
    if region_id == 0:
        return 0
    region_parent_dict = dict(region_parent_zip)
    while region_parent_dict[region_id] != 0:
        region_id = region_parent_dict[region_id]
    parent_id = region_id
    return parent_id


def get_tag_marker(identifier, markername, markervalue):
    """
        get_tag_marker()
        ____________________________________________________________________

        Return the formatted tag for node <identifier> and
        the <substring> associated to this node.

        Use this function if the node is a marker.
        ____________________________________________________________________

        PARAMETERS :
        ▪ identifier        : (int) the node's identifier.
        ▪ markername        : (str) the node's substring, reduced to its markername
        ▪ markervalue       : (str) the node's substring, reduced to its markervalue

        RETURNED VALUE : (str)the formatted tag
    """
    return '(#{0}) marker="{1}" (marker value={2})'.format(identifier,
        markername, markervalue)


def _total_secs(td):
    """
    python 2.6 compatible timedelta total seconds calculation
    backport from
    https://docs.python.org/2.7/library/datetime.html#datetime.timedelta.total_seconds
    """
    if hasattr(td, 'total_seconds'):
        return td.total_seconds()
    else:
        return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6
            ) / 10.0 ** 6


def local_rfcformat(dt):
    """Return the RFC822-formatted representation of a timezone-aware datetime
    with the UTC offset.
    """
    weekday = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'][dt.weekday()]
    month = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
        'Oct', 'Nov', 'Dec'][dt.month - 1]
    tz_offset = dt.strftime('%z')
    return '%s, %02d %s %04d %02d:%02d:%02d %s' % (weekday, dt.day, month,
        dt.year, dt.hour, dt.minute, dt.second, tz_offset)


def populate_context(context, exc, status=None):
    """
    Populates the given context dictionary with djexcept's handy default
    values. The dictionary is altered in-place, but values that are
    already present won't be overwritten.

    The following values are added to the context:
        * exc: the exception object
        * exc_name: the name of the exception type
          (e.g. PermissionDenied or ValueError)
        * exc_module: the module name of the exception's type
          (e.g. django.core.exceptions or builtins)
        * exc_modname: both concatenated, separated by a period
          (e.g. django.core.exceptions.PermissionDenied or
          builtins.ValueError)
        * status: the HTTP status code used (only added if not None)
    """
    context.setdefault('exc', exc)
    context.setdefault('exc_name', exc.__class__.__name__)
    context.setdefault('exc_module', exc.__class__.__module__)
    context.setdefault('exc_modname', '{}.{}'.format(exc.__class__.
        __module__, exc.__class__.__name__))
    if status is not None:
        context.setdefault('status', status)


def get_natoms_element(formula):
    """
    Converts 'Be24W2' to {'Be': 24, 'W' : 2}, also BeW to {'Be' : 1, 'W' : 1}
    """
    import re
    elem_count_dict = {}
    elements = re.findall('[A-Z][^A-Z]*', formula)
    for i, elm in enumerate(elements):
        elem_count = re.findall('\\d+|\\D+', elm)
        if len(elem_count) == 1:
            elem_count_dict[elem_count[0]] = 1
        else:
            elem_count_dict[elem_count[0]] = float(elem_count[1])
    return elem_count_dict


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


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


def client_color_to_rgb(value: int):
    """Converts a color number from Tibia's client data to a RGB value.

    Parameters
    ----------
    value: :class:`int`
        A numeric value representing a color.

    Returns
    -------
    int:
        The hexadecimal color represented."""
    if value < 0 or value > 215:
        return 0
    return (value // 36 * 51 << 16) + (value // 6 % 6 * 51 << 8) + (value %
        6 * 51 & 255)


def page_url(user_id, photo_id):
    """flickr picture page url"""
    return 'https://www.flickr.com/photos/{}/{}/'.format(user_id, photo_id)


def exists(xs, f):
    """
    Return an expression that means
    "there exists a variable in *xs* such that *f* true."

    This is identical to ``f.smoothing(xs)``.
    """
    return f.smoothing(xs)


def set_nested_attr(obj, key, value):
    """Set a nested attribute in dictionary, creating sub dictionaries as necessary.

    Arguments:
        obj (dict): The top-level dictionary
        key (str): The dot-separated key
        value: The value to set
    """
    parts = key.split('.')
    for part in parts[:-1]:
        obj.setdefault(part, {})
        obj = obj[part]
    obj[parts[-1]] = value


def kolmogorov_smirnov_2(frame):
    """Computes the Kolmogorov-Smirnov test of the found distributions

    Args:
        frame: DataFrame with Foud and Expected distributions.

    Returns:
        The Suprem, which is the greatest absolute difference between the
            Found end th expected proportions
    """
    ks_frame = frame.sort_index()[['Found', 'Expected']].cumsum()
    return (ks_frame.Found - ks_frame.Expected).abs().max()


def pack_libraries():
    """Pack all used Blender library files into the current .blend

    """
    pass


def _should_allow_unhandled(class_reference, key_name):
    """Check if a property is allowed to be unhandled."""
    if not hasattr(class_reference, '__deserialize_allow_unhandled_map__'):
        return False
    return class_reference.__deserialize_allow_unhandled_map__.get(key_name,
        False)


def gethomedir(username):
    """Return the home directory of username."""
    import pwd
    return pwd.getpwnam(username)[5]


def reset_tar_mtime(tarinfo):
    """Reset the mtime on the the tarball for reproducibility.

    :param tarinfo: the tarball var
    :returns: tarinfo: the modified tar ball
    """
    tarinfo.mtime = 0
    return tarinfo


@staticmethod
def _imgnormcompress(img):
    """
        Compress normalized image. Values:
        > 1 -> 1
        < 0 -> 0
        """
    mask_pass = (img <= 1) * (img >= 0)
    mask_high = img > 1
    return mask_pass * img + mask_high


@staticmethod
def handle_session(session, exc=None):
    """
        rolls back the session if appropriate.

        :param Session session: The session in use.
        :param Exception exc: The exception raised,
            If an exception was raised, else None
        """
    if exc:
        session.rollback()


@classmethod
def from_coo(cls, x):
    """
        Get a :obj:`DOK` array from a :obj:`COO` array.

        Parameters
        ----------
        x : COO
            The array to convert.

        Returns
        -------
        DOK
            The equivalent :obj:`DOK` array.

        Examples
        --------
        >>> from sparse import COO
        >>> s = COO.from_numpy(np.eye(4))
        >>> s2 = DOK.from_coo(s)
        >>> s2
        <DOK: shape=(4, 4), dtype=float64, nnz=4, fill_value=0.0>
        """
    ar = cls(x.shape, dtype=x.dtype, fill_value=x.fill_value)
    for c, d in zip(x.coords.T, x.data):
        ar.data[tuple(c)] = d
    return ar


@staticmethod
def restore_state(filename):
    """Restore state of the background buffers from a file"""
    from six.moves import cPickle
    return cPickle.load(filename)


def fq_path(ob):
    """
    Return the fully qualified path of ``ob``, expected to be a function or
    method
    """
    name = getattr(ob, '__qualname__', None) or getattr(ob, '__name__', None
        ) or repr(ob)
    module = getattr(ob, '__module__', None) or ''
    return '{}.{}'.format(module, name)


def display_init_scene_folder(root):
    """display function for initializing the scene folder"""
    print('Created scenes directory at %s' % root)


def optimize_db(cursor):
    """Set options to make sqlite more efficient on a high memory machine"""
    cursor.execute('PRAGMA cache_size = -%i' % (0.1 * 10 ** 7))
    cursor.execute('PRAGMA temp_store = 2')


def new_model():
    """
    Return a new empty model or None.

    Called in response to >File >New from the GUI.  Creates a new empty
    model.  Also triggered if GUI is started without a model.
    """
    return None


@staticmethod
def update_author_min_max_date(min_date, max_date, target_author,
    author_field='author_uuid'):
    """
        Get the query to update demography_min_date and demography_max_date of a given author

        :param min_date: new demography_min_date
        :param max_date: new demography_max_date
        :param target_author: target author to be updated
        :param author_field: author field

        :return: the query to be executed to update demography data of an author
        """
    es_query = (
        """
        {
          "script": {
            "source":
            "ctx._source.demography_min_date = params.min_date;ctx._source.demography_max_date = params.max_date;",
            "lang": "painless",
            "params": {
                "min_date": "%s",
                "max_date": "%s"
            }
          },
          "query": {
            "term": {
              "%s": "%s"
            }
          }
        }
        """
         % (min_date, max_date, author_field, target_author))
    return es_query


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

    The ".dev0" means dirty.

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


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


@staticmethod
def pre_process_text_block(block):
    """Apply pre processing to text blocks.

        Currently just strips whitespace from the beginning
        and end of the block.
        """
    block['content'] = block['content'].strip()


def _select_algs(alg_type, algs, possible_algs, none_value=None):
    """Select a set of allowed algorithms"""
    if algs == ():
        return possible_algs
    elif algs:
        result = []
        for alg_str in algs:
            alg = alg_str.encode('ascii')
            if alg not in possible_algs:
                raise ValueError('%s is not a valid %s algorithm' % (
                    alg_str, alg_type))
            result.append(alg)
        return result
    elif none_value:
        return [none_value]
    else:
        raise ValueError('No %s algorithms selected' % alg_type)


def set_debug_print_state(debug_enable):
    """Enable/disable debug prints"""
    global _debug
    _debug = debug_enable


def _is_descriptor(obj):
    """Returns True if obj is a descriptor, False otherwise."""
    return hasattr(obj, '__get__') or hasattr(obj, '__set__') or hasattr(obj,
        '__delete__')


def python_to_euc(uni_char, as_bytes=False):
    """
    Return EUC character from a Python Unicode character.

    Converts a one character Python unicode string (e.g. u'\\u4e00') to the
    corresponding EUC hex ('d2bb').
    """
    euc = repr(uni_char.encode('gb2312'))[1:-1].replace('\\x', '').strip("'")
    if as_bytes:
        euc = euc.encode('utf-8')
        assert isinstance(euc, bytes)
    return euc


def input_code():
    """
        Ask the wormhole to perform interactive entry of the code, with
        completion on the nameplate and/or words.

        This does not actually interact with the user, but instead returns a
        'code-entry helper' object.  The application is responsible for doing
        the IO: the helper is used to get completion lists and to submit the
        finished code.  See ``input_with_completion`` for a wrapper function
        that uses ``readline`` to do CLI-style input completion.

        Any Deferreds returned by ``get_code()`` will be fired when the final
        code is submitted to the helper.  Only one of
        generate_code/set_code/input_code may be used.

        :return: a code-entry helper instance
        :rtype: IHelper
        """


def count_by(iterable, iteratee):
    """
    Think of it like a harry potter sorting hat, tells you final number of students in every group.
    Similar to group_by, instead of returning a list with every grouped_key, returns count of grouped elements only.

    params: array, iteratee
        iterable-> list, set, generator
        iteratee-> a function or a lambda for grouping the elements

    Examples
    >>> _.count_by([1, 2, 3, 4, 5], lambda x: 'even' if x % 2 == 0 else 'odd')
    >>> {"odd": 3, "even": 2}
    """
    from collections import defaultdict
    d = defaultdict(lambda : 0)
    for item in iterable:
        key = iteratee(item)
        d[iteratee(item)] += 1
    return dict(d)


def normalize_directory(directory):
    """ Normalize a directory path.

    Normalizing a directory path consists of turning it into a relative
    directory path, even if it initially was a relative directory path.

        /foo/bar/qaz -> foo/bar/qaz
        foo/bar/qaz  -> foo/bar/qaz

    A normalized directory path can be combined with the (path of the)
    root directory.
    """
    return directory.relative_to(directory.root)


@classmethod
def from_queryset(cls, other, **kwargs):
    """根据其他QuerySet对象的数据生成实例"""
    query = other.query.clone()
    if other._sticky_filter:
        query.filter_is_sticky = True
    clone = cls(model=other.model, query=query, using=other._db, hints=
        other._hints)
    clone._for_write = other._for_write
    clone._prefetch_related_lookups = other._prefetch_related_lookups[:]
    clone._known_related_objects = other._known_related_objects
    clone._iterable_class = other._iterable_class
    clone._fields = other._fields
    clone.__dict__.update(kwargs)
    return clone


def _is_float(value):
    """Return True if value is a floating point number, False otherwise."""
    try:
        float(value)
        return True
    except ValueError:
        return False


@staticmethod
def _parameter_name_to_minuit_name(parameter):
    """
        Translate the name of the parameter to the format accepted by Minuit

        :param parameter: the parameter name, of the form source.component.shape.parname
        :return: a minuit-friendly name for the parameter, such as source_component_shape_parname
        """
    return parameter.replace('.', '_')


def parse_ffl_number(ffl_number, parse_values=True):
    """
    This take an FFL number a dictionary representation of the appropriate fields
    :param ffl_number: String with the FFL number, this can be in the format of X-XX-XXX-XX-XX-XXXXX or just the string
    :param parse_values: Parse the values as an int or string, int is useful for working in databases
    :return: dict of parsed FFL number
    """
    ffl_number = ffl_number.replace('-', '')
    if len(ffl_number) != 15:
        raise ValueError('Invalid ffl Length: %s for %s' % (len(ffl_number),
            ffl_number))
    if parse_values:
        render = int
    else:
        render = str
    return {'FFLRegion': render(ffl_number[0]), 'FFLDistrict': render(
        ffl_number[1:3]), 'FFLCounty': render(ffl_number[3:6]), 'FFLType':
        render(ffl_number[6:8]), 'FFLExpiration': ffl_number[8:10],
        'FFLSequence': render(ffl_number[10:]), 'FFLNumber': ffl_number}


def check_gindexer_compatibility(gindexer, resolution, store_whole_genome):
    """Sanity check for gindexer.

    This function tests if the gindexer is compatible with
    other properties of the dataset, including the resolution and
    the store_whole_genome argument

    A ValueError is thrown if the gindexer is not valid.
    """
    if resolution is not None and resolution > 1 and store_whole_genome:
        if gindexer is not None and gindexer.binsize % resolution > 0:
            raise ValueError(
                'binsize must be an integer-multipe of resolution. Got binsize={} and resolution={}'
                .format(gindexer.binsize, resolution))
        for iv_ in (gindexer or []):
            if iv_.start % resolution > 0:
                raise ValueError(
                    'Please ensure that all interval starts line up with the resolution-sized bins. This is necessary to prevent rounding issues. Interval ({}:{}-{}) not compatible with resolution {}. '
                    .format(iv_.chrom, iv_.start, iv_.end, resolution) +
                    'Consider using "janggu-trim <input_roi> <trun_output> -divisible_by {resolution}"'
                    .format(resolution=resolution))
    if not store_whole_genome and gindexer is None:
        raise ValueError('Either specify roi or store_whole_genome=True')


def year():
    """Return the calendar year of the object"""


def _plot_timedep_vels(vels, labels, title=None):
    """Plot trial time-dependent velocities"""
    traces = list()
    for vel, label in zip(vels, labels):
        trace = dict(y=vel, text=label, name=label, hoverinfo='x+y+text')
        traces.append(trace)
    layout = dict(title=title, xaxis=dict(title='% of trial', automargin=
        True), yaxis=dict(title='Velocity (m/s)'))
    return dict(data=traces, layout=layout)


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

        :param PendingSecondaryEmailAddedType val:
        :rtype: EventType
        """
    return cls('pending_secondary_email_added', val)


def snap(frame: int=0):
    """Frame where selected strips will be snapped

    :param frame: Frame, Frame where selected strips will be snapped
    :type frame: int
    """
    pass


def readimg(filename, rows, cols):
    """
    Attempts to read the .img file filename (with or without '.img')
    assuming it was read with rows rows and cols cols.
    """
    import numpy as np
    dt = np.dtype(np.uint16)
    dt = dt.newbyteorder('>')
    filename = filename if filename.endswith('.img') else filename + '.img'
    with open(filename, 'rb') as f:
        ret = np.reshape(np.fromfile(f, dtype=dt), (rows, cols))
    return np.array(ret, dtype=np.float64)


def describe_key_pairs(DryRun=None, KeyNames=None, Filters=None):
    """
    Describes one or more of your key pairs.
    For more information about key pairs, see Key Pairs in the Amazon Elastic Compute Cloud User Guide .
    See also: AWS API Documentation

    Examples
    This example displays the fingerprint for the specified key.
    Expected Output:

    :example: response = client.describe_key_pairs(
        DryRun=True|False,
        KeyNames=[
            'string',
        ],
        Filters=[
            {
                'Name': 'string',
                'Values': [
                    'string',
                ]
            },
        ]
    )

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

    :type KeyNames: list
    :param KeyNames: One or more key pair names.
            Default: Describes all your key pairs.
            (string) --

    :type Filters: list
    :param Filters: One or more filters.
            fingerprint - The fingerprint of the key pair.
            key-name - The name of the key pair.
            (dict) --A filter name and value pair that is used to return a more specific list of results. Filters can be used to match a set of resources by various criteria, such as tags, attributes, or IDs.
            Name (string) --The name of the filter. Filter names are case-sensitive.
            Values (list) --One or more filter values. Filter values are case-sensitive.
            (string) --

    :rtype: dict
    :return: {
        'KeyPairs': [
            {
                'KeyName': 'string',
                'KeyFingerprint': 'string'
            },
        ]
    }

    """
    pass


@classmethod
def from_bytes(cls, data, nVersion):
    """Instantiate from data and nVersion"""
    if not 0 <= nVersion <= 255:
        raise ValueError(
            'nVersion must be in range 0 to 255 inclusive; got %d' % nVersion)
    self = bytes.__new__(cls, data)
    self.nVersion = nVersion
    return self


def _linear_interpolation(x, X, Y):
    """Given two data points [X,Y], linearly interpolate those at x.
    """
    return (Y[1] * (x - X[0]) + Y[0] * (X[1] - x)) / (X[1] - X[0])


@staticmethod
def draw_path(ctx, center_x, center_y, width, height=None):
    """Draws the path of the shape on the given Cairo context, without
        stroking or filling it.

        This method must be overridden in derived classes implementing custom shapes
        and declared as a static method using C{staticmethod(...)}.

        @param ctx: the context to draw on
        @param center_x: the X coordinate of the center of the object
        @param center_y: the Y coordinate of the center of the object
        @param width: the width of the object
        @param height: the height of the object. If C{None}, equals to the width.
        """
    raise NotImplementedError('abstract class')


def isunauthenticated(func):
    """Checks if the function does not require authentication.

    Mark such functions with the `@unauthenticated` decorator.

    :returns: bool
    """
    return getattr(func, 'unauthenticated', False)


def get_row(l, m):
    """Construct dataframe row from `l` (Learner.named_modules() module) and `m` (model_type)"""
    lyr_name = l[0]
    lyr_obj = l[1]
    ln_split = str(lyr_name).split('.', 4)
    ln_n_splits = len(ln_split)
    lyr_str = str(lyr_obj)
    tch_cls_str = str(type(lyr_obj))
    tch_cls_substr = tch_cls_str[tch_cls_str.find('<class') + 8:tch_cls_str
        .find('>') - 1]
    tch_cls = tch_cls_substr.split('.')[-1]
    div = tch_cls if lyr_name == '0' or lyr_name == '1' else ''
    mod = tch_cls if ln_n_splits == 2 else ''
    blk = tch_cls if ln_n_splits == 3 and not lyr_name.startswith('1') else ''
    lyr = lyr_str[:90]
    if m == 'vgg' or m == 'alexnet':
        if ln_n_splits > 2:
            ln_split[2] = ''
        blk = ''
    elif m == 'squeezenet':
        blk = tch_cls if ln_n_splits == 3 and tch_cls == 'Fire' else ''
        if blk == 'Fire':
            lyr = ''
    elif m == 'resnet':
        if blk == 'BasicBlock' or blk == 'Bottleneck':
            lyr = ''
        else:
            if ln_n_splits > 4:
                lyr = f'. . {lyr_str[:86]}'
            if ln_n_splits == 4 and ln_split[3] == 'downsample':
                lyr = f'Container{tch_cls}'
    elif m == 'densenet':
        lyr_name = lyr_name.replace('denseblock', '').replace('denselayer', '')
        ln_split = str(lyr_name).split('.', 5)
        if len(ln_split) > 1 and ln_split[0] != '1':
            del ln_split[1]
        ln_n_splits = len(ln_split)
        mod = tch_cls if lyr_name.startswith('0'
            ) and ln_n_splits == 2 or lyr_name.startswith('1'
            ) and ln_n_splits == 2 else ''
        blk = tch_cls if ln_n_splits == 3 and tch_cls == '_DenseLayer' else ''
        if (mod == '_DenseBlock' or mod == '_Transition' or blk ==
            '_DenseLayer'):
            lyr = ''
        else:
            if lyr_name == '0' or lyr_name == '1':
                div = tch_cls
            if lyr_name == '0.0':
                div = f'. . {tch_cls}'
    elif m == 'xresnet':
        blk = tch_cls if ln_n_splits == 3 and tch_cls == 'ResBlock' else ''
        if mod == 'ConvLayer' or blk == 'ResBlock':
            lyr = ''
        elif ln_n_splits < 4:
            lyr = lyr_str[:90]
        elif ln_n_splits == 4 and tch_cls == 'Sequential':
            lyr = f'Container{tch_cls}'
        elif ln_n_splits == 4 and tch_cls == 'ReLU':
            lyr = lyr_str[:90]
        elif ln_n_splits == 5 and tch_cls == 'ConvLayer':
            lyr = f'. . Container{tch_cls}'
        else:
            lyr = f'. . . . {lyr_str[:32]}'
    else:
        raise Exception('Model type not recognised')
    return {'Module_name': lyr_name, 'Model': tch_cls if lyr_name == '' else
        '', 'Division': div, 'Container_child': mod, 'Container_block': blk,
        'Layer_description': lyr, 'Torch_class': tch_cls_substr,
        'Output_dimensions': '', 'Parameters': '', 'Trainable': '',
        'Currently': '', 'div_id': ln_split[0] if ln_n_splits > 0 else '',
        'chd_id': ln_split[1] if ln_n_splits > 1 else '', 'blk_id':
        ln_split[2] if ln_n_splits > 2 else '', 'lyr_id': ln_split[3] if
        ln_n_splits > 3 else '', 'tch_cls': tch_cls, 'out_dim': '',
        'current': '', 'lyr_blk': '', 'lyr_chd': '', 'blk_chd': '',
        'lyr_obj': lyr_obj}


def safe_getattr_tuple(type_, key):
    """Get attribute from type, defaulting to empty tuple."""
    try:
        return tuple(getattr(type_, key, None) or [])
    except TypeError:
        return ()


def assure_list(s):
    """Given not a list, would place it into a list. If None - empty list is returned

    Parameters
    ----------
    s: list or anything
    """
    if isinstance(s, list):
        return s
    elif s is None:
        return []
    else:
        return [s]


def _formatter_class(name, value):
    """Format the "klass" variable and value on class methods.
    """
    __mname = value.__module__
    if __mname != '__main__':
        return "%s = <type '%s.%s'>" % (name, __mname, value.__name__)
    else:
        return "%s = <type '%s'>" % (name, value.__name__)


def replace_line_magic(source, magic, template='{line}'):
    """
    Given a cell's source, replace line magics using a formatting
    template, where {line} is the string that follows the magic.
    """
    filtered = []
    for line in source.splitlines():
        if line.strip().startswith(magic):
            substitution = template.format(line=line.replace(magic, ''))
            filtered.append(substitution)
        else:
            filtered.append(line)
    return '\n'.join(filtered)


def _get_headers_from_args(method=None, url=None, body=None, headers=None,
    retries=None, redirect=None, assert_same_host=True, timeout=None,
    pool_timeout=None, release_conn=None, chunked=False, body_pos=None, **
    response_kw):
    """
    extract headers from arguments
    """
    return headers


def PolsAnnuity(t):
    """Number of policies: Annuity"""
    return 0


@classmethod
def set_repr_mode(cls, mode):
    """
        Set __repr__() mode.

        There are two modes:

            REPR_REAL - show real repr() on all CachingProxy instances
            REPR_FAKE - show the repr() of wrapped object

        By default, REPR_REAL is used so each cached object will
        be easily identifieable as such.
        """
    cls.repr_mode = True


def trade_update_position(current_position, symbol, trade):
    """
    产生Trade更新对应Postion
    """
    base_currency = symbol.split('/')[0].lower()
    quote_currency = symbol.split('/')[1].lower()
    current_position[base_currency].trade_update('base', trade)
    current_position[quote_currency].trade_update('quote', trade)
    current_position[base_currency].trade_update_cost('base', trade,
        current_position[quote_currency])
    current_position[quote_currency].trade_update_cost('quote', trade,
        current_position[base_currency])


def _try_f2i(x):
    """If possible, convert float to int without rounding.
    Used for log base: if not used, base for log scale can be "10.0" (and then
    printed as such  by pgfplots).
    """
    return int(x) if int(x) == x else x


@classmethod
def number_of_files(cls):
    """Number of files required for load method"""
    return 1


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


def bone_siblings(obj, bone):
    """ Returns a list of the siblings of the given bone.
        This requires that the bones has a parent.

    """
    parent = obj.data.bones[bone].parent
    if parent is None:
        return []
    bones = []
    for b in parent.children:
        if b.name != bone:
            bones += [b.name]
    return bones


def navigate():
    """Interactively navigate around the scene (uses the mode (walk/fly) preference)

    """
    pass


def atse_delSchemata(schema_id, schema_template, name, RESPONSE=None):
    """ delete a schemata """


@classmethod
def notification_payload(cls, method, params=None):
    """JSON v2  notification payload.  There must be no id."""
    payload = {'jsonrpc': '2.0', 'method': method}
    if params:
        payload['params'] = params
    return payload


@staticmethod
def header_length():
    """ Provides the mask needed to decode the header_length from Word 0 """
    return 126976, 12


def indicator_atr(df, lookback=20):
    """Creates average true range

    Args:
        df (pd.DataFrame): OHLCV intraday dataframe, only needs high, low, close
        lookback (:obj:int, optional): rolling window.  Default is 20

    Returns:
        pd.DataFrame: columns with true_range and atr

    Example:
    """
    df = df[['high', 'low', 'close']].copy()
    df['highlow'] = abs(df['high'] - df['low'])
    df['highclose'] = abs(df['high'] - df['close'].shift(1))
    df['lowclose'] = abs(df['low'] - df['close'].shift(1))
    df['true_range'] = df[['highlow', 'highclose', 'lowclose']].max(axis=1)
    df['atr'] = df['true_range'].rolling(lookback).mean()
    return df[['atr', 'true_range']]


def filter_simple_date(value):
    """Filter a `datetime.datetime` into a 'YYYY-MM-DD' string."""
    return value.strftime('%Y-%m-%d')


def format_fields(fields):
    """
    :param fields: list of numbers and operations as strings
    :return a list of formatted fields, with numbers cast into integers
    """
    leading_sign = ''
    formatted_fields = []
    for field in fields:
        try:
            result = int(leading_sign + field)
        except ValueError:
            leading_sign = ''
            if len(field) == 1:
                result = field
            elif len(field) == 2:
                if field == '**':
                    result = field
                elif field[1] in '+-':
                    result, leading_sign = field
                else:
                    raise Exception('Invalid operation')
            elif len(field) == 3:
                if field[:2] == '**':
                    if field[2] in '+-':
                        result, leading_sign = field[:2], field[2]
            else:
                raise Exception('Unsupported operation')
        formatted_fields.append(result)
    return formatted_fields


@staticmethod
def _check_activity(activity, _length, _type):
    """
        Verifies that the activity is valid.

        Args:
            activity (iterable): Array of activity
            _length (int): Count of all points
            _type (string): 'points' or 'triangles'
        """
    if len(activity) != _length:
        raise ValueError(
            'Length of activity must be equal to the length of {}.'.format(
            _type))


def reverse_hex(h: str):
    """Reverses a hex-serialized bytestring"""
    return bytes.fromhex(h)[::-1].hex()


def _get_idxs_for_all_rois(GTCodes, element_infos):
    """Get indices of ROIs within the element_infos dataframe.

    (Internal)

    """
    roi_labels = list(GTCodes.loc[GTCodes.loc[:, ('is_roi')] == 1, 'group'])
    idxs_for_all_rois = []
    for idx, elinfo in element_infos.iterrows():
        if elinfo.group in roi_labels:
            idxs_for_all_rois.append(idx)
    return idxs_for_all_rois


def plural(num, singStr, plStr):
    """Return singStr or plStr depending if num == 1 or not.
    A minor convenience for formatting messages (in lieu of ?: notation)
    """
    if num == 1:
        return singStr
    return plStr


def index(lista, co):
    """.index with on absolute values"""
    for i in range(len(lista)):
        if abs(lista[i]) == co:
            return i
    else:
        raise IndexError


def overlap(intv1, intv2):
    """Overlaping of two intervals"""
    return max(0, min(intv1[1], intv2[1]) - max(intv1[0], intv2[0]))


def track_field(field):
    """
    Returns whether the given field should be tracked by Actionslog.

    Untracked fields are many-to-many relations and relations to the Actionslog LogAction model.

    :param field: The field to check.
    :type field: Field
    :return: Whether the given field should be tracked.
    :rtype: bool
    """
    from actionslog.models import LogAction
    if field.many_to_many:
        return False
    if getattr(field, 'rel', None) is not None and field.rel.to == LogAction:
        return False
    return True


def _iteritems(d):
    """Like d.iteritems, but accepts any collections.Mapping."""
    return d.iteritems() if hasattr(d, 'iteritems') else d.items()


def resource_isdir(resource_name):
    """Is the named resource a directory?  (like ``os.path.isdir()``)"""


def _atomise_link(link, rel=None):
    """Return a link in a suitable format for atom"""
    if type(link) is dict:
        if 'type' not in link:
            link['type'] = 'text/html'
        if rel and 'rel' not in link:
            link['rel'] = rel
        return link
    else:
        result = {'href': link, 'type': 'text/html'}
        if rel:
            result['rel'] = rel
        return result


@staticmethod
def get_dockable_window_class():
    """
        Returns class that should be used to instance an ew dockable DCC window
        :return: class
        """
    try:
        from tpDcc.libs.qt.core import window
        return window.MainWindow
    except Exception:
        pass
    return None


def collection_holdout_set():
    """Mask collection in the active view layer

    """
    pass


def iterate_items(dictish):
    """ Return a consistent (key, value) iterable on dict-like objects,
    including lists of tuple pairs.

    Example:

        >>> list(iterate_items({'a': 1}))
        [('a', 1)]
        >>> list(iterate_items([('a', 1), ('b', 2)]))
        [('a', 1), ('b', 2)]
    """
    if hasattr(dictish, 'iteritems'):
        return dictish.iteritems()
    if hasattr(dictish, 'items'):
        return dictish.items()
    return dictish


def provider_parser(subparser):
    """Configure provider parser for Namecheap"""
    subparser.add_argument('--auth-token', help=
        'specify api token for authentication')
    subparser.add_argument('--auth-username', help=
        'specify username for authentication')
    subparser.add_argument('--auth-client-ip', help=
        'Client IP address to send to Namecheap API calls', default='127.0.0.1'
        )
    subparser.add_argument('--auth-sandbox', help=
        'Whether to use the sandbox server', action='store_true')


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


def swapaxes(input, axis1, axis2):
    """Interchange the two given axes of a tensor.

    Parameters
    ----------
    input : Tensor
        The input tensor.
    axis1, axis2 : int
        The two axes.

    Returns
    -------
    Tensor
        The transposed tensor.
    """
    pass


@staticmethod
def _get_image_url(experiment):
    """
        Gets the url of the docker image for the given experiment

        :param experiment: The experiment whose docker image url is returned
        :type experiment: Dict
        :return: The url of the docker image for the given experiment
        """
    return experiment['container']['settings']['image']['url']


def reshape_monthly_to_annually(dataset):
    """ Reshape monthly binned dataset to annual bins.

    Reshape a monthly binned dataset's 3D value array with shape
    (num_months, num_lats, num_lons) to a 4D array with shape
    (num_years, 12, num_lats, num_lons). This causes the data to be binned
    annually while retaining its original shape.

    It is assumed that the number of months in the dataset is evenly
    divisible by 12. If it is not you will receive error due to
    an invalid shape.

    Example change of a dataset's shape:
    (24, 90, 180) -> (2, 12, 90, 180)

    :param dataset: Dataset object with full-year format
    :type dataset: :class:`dataset.Dataset`

    :returns: Dataset values array with shape (num_year, 12, num_lat, num_lon)
    """
    values = dataset.values[:]
    data_shape = values.shape
    num_total_month = data_shape[0]
    num_year = num_total_month // 12
    if num_total_month % 12 != 0:
        raise ValueError(
            'Number of months in dataset ({}) does not divide evenly into {} year(s).'
            .format(num_total_month, num_year))
    num_month = 12
    year_month_shape = num_year, num_month
    lat_lon_shape = data_shape[1:]
    new_shape = tuple(year_month_shape + lat_lon_shape)
    values.shape = new_shape
    return values


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

        :param BinderReorderPageDetails val:
        :rtype: EventDetails
        """
    return cls('binder_reorder_page_details', val)


def _temp_dict_file_name():
    """Name of the expected python dictionary as a json file from run_external_python().

    .. versionadded:: 9.1
    """
    return '__shared_dictionary__'


@classmethod
def parse(cls, element):
    """Parse xml element.

        :param element: an :class:`~xml.etree.ElementTree.Element` instance
        :rtype: dict
        """
    values = {}
    for child in element:
        node = cls.get_node(child)
        subs = cls.parse(child)
        value = subs or node['value']
        if node['tag'] not in values:
            values[node['tag']] = value
        else:
            if not isinstance(values[node['tag']], list):
                values[node['tag']] = [values.pop(node['tag'])]
            values[node['tag']].append(value)
    return values


def slash_join(base: str, path: str):
    """
    Join a and b with a single slash, regardless of whether they already
    contain a trailing/leading slash or neither.
    :param base: base_url
    :param path: path
    """
    if not path:
        return base
    path = path if path.endswith('/') else '{}/'.format(path)
    if base.endswith('/'):
        if path.startswith('/'):
            return base[:-1] + path
        return base + path
    if path.startswith('/'):
        return base + path
    return base + '/' + path


def is_private_name(name_string):
    """
    Check if this string is written in a private/protected reference python convention
    Args:
        name_string (str):

    Returns (Bool): True if variable begins with "_", False otherwise

    Examples:
        >>> is_private_name("_some_var_name")
        True
        >>> is_private_name("some_var_name")
        False
    """
    return name_string.startswith('_')


def validate_post_request(post_field, allowed_fields):
    """
    Validators returning None if everything is OK - otherwise suitable HTTP
    status and message is set.
    """
    error_msg = None
    dict_diff = list(set(post_field) - set(allowed_fields))
    if dict_diff:
        error_msg = 'There are fields not allowed in your request.'
    for field in allowed_fields:
        if field not in post_field.keys():
            error_msg = "There is no '{}' field in your request.".format(field)
            break
    return error_msg


def catalog_search_path():
    """
    List directories that will be searched for catalog YAML files.

    This is a convenience wrapper around functions used by intake to determine
    its search path.

    Returns
    -------
    directories: tuple
    """
    from intake.catalog.default import user_data_dir, global_data_dir
    return user_data_dir(), global_data_dir()


@classmethod
def on_start_configuration(cls):
    """
    Callback function that is triggered, when the configuration of all undetected controllers starts
    """
    print('EVENT:' + 'Start configuration of unknown controller types')


def glLineWidth(width: float):
    """Specify the width of rasterized lines.

    :param width: Specifies the width of rasterized lines. The initial value is 1.
    :type width: float
    """
    pass


@classmethod
def from_stream(cls, stream, marker_code, offset):
    """
        Return an |_SofMarker| instance for the SOFn marker at *offset* in
        stream.
        """
    segment_length = stream.read_short(offset)
    px_height = stream.read_short(offset, 3)
    px_width = stream.read_short(offset, 5)
    return cls(marker_code, offset, segment_length, px_width, px_height)


def f2norm(params, en=1, mu=1, f2=1, weights=1):
    """
    Objective function for matching mu(E) data to tabulated f''(E)
    """
    p = params.valuesdict()
    model = (p['offset'] + p['slope'] * en + f2) * p['scale']
    return weights * (model - mu)


def str_line(lin):
    """
    Returns a string in the form 'marker' + 'linestyle' from a
    matplotlib.lines.line2D object

    Parameters
    ----------

    lin : matplotlib.lines.line2D object

    Returns
    ----------
    strlin: str
        string in the form 'marker' + 'linestyle'
    """
    strlin = ''
    if lin.get_marker() is not 'None':
        strlin = strlin + lin.get_marker()
    if lin.get_linestyle() is not 'None':
        strlin = strlin + lin.get_linestyle()
    return strlin


def printhelp():
    """If executed in command line, provide a meaning full description
        about this scaffolding plugin and variables that can be defined."""


def _crop(im, target_x, target_y):
    """
    Crops the image to the given specifications.

    :param im: Instance of the image.
    :type im: PIL Image
    :param target_x: New x-axis.
    :type target_x: int
    :param target_y: New y-axis
    :type target_y: int
    :return: Cropped image.
    :rtype: PIL.Image
    """
    source_x, source_y = im.size
    diff_x = int(source_x - min(source_x, target_x))
    diff_y = int(source_y - min(source_y, target_y))
    if diff_x or diff_y:
        halfdiff_x, halfdiff_y = diff_x // 2, diff_y // 2
        box = [halfdiff_x, halfdiff_y, min(source_x, int(target_x) +
            halfdiff_x), min(source_y, int(target_y) + halfdiff_y)]
        im = im.crop(box)
    return im


def put_destination(destinationName=None, targetArn=None, roleArn=None):
    """
    Creates or updates a destination. A destination encapsulates a physical resource (such as a Kinesis stream) and enables you to subscribe to a real-time stream of log events of a different account, ingested using  PutLogEvents . Currently, the only supported physical resource is a Amazon Kinesis stream belonging to the same account as the destination.
    A destination controls what is written to its Amazon Kinesis stream through an access policy. By default, PutDestination does not set any access policy with the destination, which means a cross-account user cannot call  PutSubscriptionFilter against this destination. To enable this, the destination owner must call  PutDestinationPolicy after PutDestination .
    See also: AWS API Documentation

    :example: response = client.put_destination(
        destinationName='string',
        targetArn='string',
        roleArn='string'
    )

    :type destinationName: string
    :param destinationName: [REQUIRED]
            A name for the destination.

    :type targetArn: string
    :param targetArn: [REQUIRED]
            The ARN of an Amazon Kinesis stream to deliver matching log events to.

    :type roleArn: string
    :param roleArn: [REQUIRED]
            The ARN of an IAM role that grants CloudWatch Logs permissions to call Amazon Kinesis PutRecord on the destination stream.

    :rtype: dict
    :return: {
        'destination': {
            'destinationName': 'string',
            'targetArn': 'string',
            'roleArn': 'string',
            'accessPolicy': 'string',
            'arn': 'string',
            'creationTime': 123
        }
    }

    """
    pass


def shadow_offset(fontid: int, x: float, y: float):
    """Set the offset for shadow text.

    :param fontid: The id of the typeface as returned by blf.load(), for default font use 0.
    :type fontid: int
    :param x: Vertical shadow offset value in pixels.
    :type x: float
    :param y: Horizontal shadow offset value in pixels.
    :type y: float
    """
    pass


def do_help():
    """
    returns help string of script
    """
    return __doc__


def diagonal_basis_commutes(pauli_a, pauli_b):
    """
    Test if `pauli_a` and `pauli_b` share a diagonal basis

    Example:

        Check if [A, B] with the constraint that A & B must share a one-qubit
        diagonalizing basis. If the inputs were [sZ(0), sZ(0) * sZ(1)] then this
        function would return True.  If the inputs were [sX(5), sZ(4)] this
        function would return True.  If the inputs were [sX(0), sY(0) * sZ(2)]
        this function would return False.

    :param pauli_a: Pauli term to check commutation against `pauli_b`
    :param pauli_b: Pauli term to check commutation against `pauli_a`
    :return: Boolean of commutation result
    :rtype: Bool
    """
    overlapping_active_qubits = set(pauli_a.get_qubits()) & set(pauli_b.
        get_qubits())
    for qubit_index in overlapping_active_qubits:
        if pauli_a[qubit_index] != 'I' and pauli_b[qubit_index
            ] != 'I' and pauli_a[qubit_index] != pauli_b[qubit_index]:
            return False
    return True


def imgVRange(h, va, fontSize):
    """return bottom,top offsets relative to baseline(0)"""
    if va == 'baseline':
        iyo = 0
    elif va in ('text-top', 'top'):
        iyo = fontSize - h
    elif va == 'middle':
        iyo = fontSize - (1.2 * fontSize + h) * 0.5
    elif va in ('text-bottom', 'bottom'):
        iyo = fontSize - 1.2 * fontSize
    elif va == 'super':
        iyo = 0.5 * fontSize
    elif va == 'sub':
        iyo = -0.5 * fontSize
    elif hasattr(va, 'normalizedValue'):
        iyo = va.normalizedValue(fontSize)
    else:
        iyo = va
    return iyo, iyo + h


def vertex_color_smooth():
    """Smooth colors across vertices

    """
    pass


def _singularize(string):
    """Hacky singularization function."""
    if string.endswith('ies'):
        return string[:-3] + 'y'
    if string.endswith('s'):
        return string[:-1]
    return string


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


def datatypes_for_parameters():
    """
        Returns a sequence of datatypes.

        XXX: This only works for ordered params; make this work
        for named parameters. Probably want to treat the two the same,
        with ordered parameters using indexes as their name.
        """


def get_filter_in(filters):
    """Recuperar filtros de una lista"""
    filter_in = {}
    for filter_index, value in list(filters.items()):
        if isinstance(value, list):
            filter_in.update({filter_index: value})
            del filters[filter_index]
    return filter_in


@classmethod
def and_(cls, constraints):
    """ Factory for a group AND """
    return cls._factory(constraints, 'AND')


def deserialize_date(string):
    """Deserializes string to date.

    :param string: str.
    :type string: str
    :return: date.
    :rtype: date
    """
    try:
        from dateutil.parser import parse
        return parse(string).date()
    except ImportError:
        return string


@classmethod
def from_code(cls, environment, code, globals, uptodate=None):
    """Creates a template object from compiled code and the globals.  This
        is used by the loaders and environment to create a template object.
        """
    namespace = {'environment': environment, '__file__': code.co_filename}
    exec(code, namespace)
    rv = cls._from_namespace(environment, namespace, globals)
    rv._uptodate = uptodate
    return rv


def reverse(vol, csum):
    """Yields a set of paths which reference a given checksum_path name."""


def convert_timedelta_str(dur):
    """Barebones support for storing a timedelta as an ISO8601 duration."""
    micro = '.{:06d}'.format(dur.microseconds) if dur.microseconds else ''
    return 'P{:d}DT{:d}{}S'.format(dur.days, dur.seconds, micro)


def is_numeric(s):
    """
    Determine if a ``pandas.Series`` or ``numpy.ndarray`` is numeric
    from its dtype.
    """
    return s.dtype.kind in 'iufc'


def decode(bstr):
    """
  Decodes an ASCII encoded binary MAC address tring into a number.
  """
    bstr = bstr.replace(b':', b'')
    if len(bstr) != 12:
        raise ValueError('not a valid MAC address: {!r}'.format(bstr))
    try:
        return int(bstr, 16)
    except ValueError:
        raise ValueError('not a valid MAC address: {!r}'.format(bstr))


def caffe2_installed():
    """
    Checks that *caffe* is available.
    """
    try:
        import caffe2
        return True
    except ImportError:
        return False


def check_not_empty(collection, message):
    """
    Tests if a collection is not empty.

    :param collection: (Collection), the collection tested to see if it is not empty.
    :param message: (str), the error message.
    """
    if not collection:
        raise AssertionError(message)


def _build_assignment_lookup(annos):
    """
    Builds a lookup as a dictionary of formIds to groupId lists
    """
    _assignments = {}
    if annos is not None:
        for anno in annos:
            _form_id = None
            _group_id = None
            kvs = anno.getMapValue()
            for kv in kvs:
                if kv.name == 'formId':
                    _form_id = kv.value
                elif kv.name == 'groupId':
                    _group_id = kv.value
            _assignments.setdefault(_form_id, set()).add(int(_group_id))
    return _assignments


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

        @see: ShapeDrawer.intersection_point"""
    height = height or width
    delta_x, delta_y = center_x - source_x, center_y - source_y
    if delta_x == 0 and delta_y == 0:
        return center_x, center_y
    if delta_y > 0 and delta_x <= delta_y and delta_x >= -delta_y:
        ry = center_y - height / 2
        ratio = height / 2 / delta_y
        return center_x - ratio * delta_x, ry
    if delta_y < 0 and delta_x <= -delta_y and delta_x >= delta_y:
        ry = center_y + height / 2
        ratio = height / 2 / -delta_y
        return center_x - ratio * delta_x, ry
    if delta_x > 0 and delta_y <= delta_x and delta_y >= -delta_x:
        rx = center_x - width / 2
        ratio = width / 2 / delta_x
        return rx, center_y - ratio * delta_y
    if delta_x < 0 and delta_y <= -delta_x and delta_y >= delta_x:
        rx = center_x + width / 2
        ratio = width / 2 / -delta_x
        return rx, center_y - ratio * delta_y
    if delta_x == 0:
        if delta_y > 0:
            return center_x, center_y - height / 2
        return center_x, center_y + height / 2
    if delta_y == 0:
        if delta_x > 0:
            return center_x - width / 2, center_y
        return center_x + width / 2, center_y


def length():
    """Return unicode string with number of children to display in
        tree or empty string"""


def deferred_update():
    """refresh portlet data on KSS events (and only then)

        this is similar to update() but it is only called from a KSS action
        and thus can be used to do long computing/retrieval only on loading
        the portlet via KSS but not in the initial page load.
        """


def view_zoom(factor: float=0.0):
    """Zoom in/out the image

    :param factor: Factor, Zoom factor, values higher than 1.0 zoom in, lower values zoom out
    :type factor: float
    """
    pass


def get_resource_filename(manager, resource_name):
    """Return a true filesystem path for `resource_name`

        `manager` must be an ``IResourceManager``"""


def _normalize(dns_name):
    """
    The Amazon Route53 API silently accepts 'foo.com' as a dns record, but
    internally that becomes 'foo.com.'. In order to match records we need to do
    the same.
    """
    return dns_name.rstrip('.') + '.'


@classmethod
def remove_role(cls, options=None):
    """Remove a user role.

        Usage:
            hammer user-group remove-role [OPTIONS]

        Options:
            --id ID
            --name NAME                   Name to search by
            --role ROLE_NAME              User role name
            --role-id ROLE_ID
        """
    cls.command_sub = 'remove-role'
    return cls.execute(cls._construct_command(options), output_format='csv')


def looks_like_issubclass(obj, classname):
    """ Return True if the object has a class or superclass with the given class
    name.

    Ignores old-style classes.
    """
    t = obj
    if t.__name__ == classname:
        return True
    for klass in t.__mro__:
        if klass.__name__ == classname:
            return True
    return False


def distance_calc(s1, s2):
    """
    Calculate Levenshtein distance between two words.

    :param s1: first word
    :type s1 : str
    :param s2: second word
    :type s2 : str
    :return: distance between two word

    References :
    1- https://stackoverflow.com/questions/2460177/edit-distance-in-python
    2- https://en.wikipedia.org/wiki/Levenshtein_distance
    """
    if len(s1) > len(s2):
        s1, s2 = s2, s1
    distances = range(len(s1) + 1)
    for i2, c2 in enumerate(s2):
        distances_ = [i2 + 1]
        for i1, c1 in enumerate(s1):
            if c1 == c2:
                distances_.append(distances[i1])
            else:
                distances_.append(1 + min((distances[i1], distances[i1 + 1],
                    distances_[-1])))
        distances = distances_
    return distances[-1]


def _npx_nonzero(a):
    """
    Return the indices of the elements that are non-zero.

    Returns a ndarray with ndim is 2. Each row contains the indices
    of the non-zero elements. The values in `a` are always tested and returned in
    row-major, C-style order.

    The result of this is always a 2-D array, with a row for
    each non-zero element.

    Parameters
    ----------
    a : array_like
        Input array.

    Returns
    -------
    array : ndarray
        Indices of elements that are non-zero.

    Notes
    -----
    This function differs from the original numpy.nonzero in the following aspects:
        - Does not support python numeric.
        - The return value is same as numpy.transpose(numpy.nonzero(a)).

    Examples
    --------
    >>> x = np.array([[3, 0, 0], [0, 4, 0], [5, 6, 0]])
    >>> x
    array([[3, 0, 0],
           [0, 4, 0],
           [5, 6, 0]])
    >>> npx.nonzero(x)
    array([[0, 0],
           [1, 1],
           [2, 0],
           [2, 1]], dtype=int64)

    >>> np.transpose(npx.nonzero(x))
    array([[0, 1, 2, 2],
           [0, 1, 0, 1]], dtype=int64)
    """
    pass


@staticmethod
def is_regression(modelobj):
    """
        determined whether users modelobj is regression or classification based on
        presence of predict_proba

        :param modelobj: sklearn model object
        :return: sklearn predict method, str classification type
        :rtype: sklearn predict, str
        """
    if hasattr(modelobj, 'predict_proba'):
        predict_engine = getattr(modelobj, 'predict_proba')
        model_type = 'classification'
    else:
        predict_engine = getattr(modelobj, 'predict')
        model_type = 'regression'
    return predict_engine, model_type


def clearcaches(clear_persisted_data=False):
    """Clear any caches associated with this instance."""


def decode(packet):
    """
    https://raw.githubusercontent.com/telldus/telldus/master/telldus-core/service/ProtocolOregon.cpp

    >>> decode(dict(data=0x201F242450443BDD, model=6701))["data"]["temp"]
    24.2
    >>> decode(dict(data=0x201F242450443BDD, model=6701))["data"]["humidity"]
    45.0
    """
    if packet['model'] != 6701:
        raise NotImplementedError('The Oregon model %i is not implemented.' %
            packet['model'])
    data = packet['data']
    value = int(data)
    value >>= 8
    checksum1 = value & 255
    value >>= 8
    checksum = (value >> 4 & 15) + (value & 15)
    hum1 = value & 15
    value >>= 8
    checksum += (value >> 4 & 15) + (value & 15)
    neg = value & 1 << 3
    hum2 = value >> 4 & 15
    value >>= 8
    checksum += (value >> 4 & 15) + (value & 15)
    temp2 = value & 15
    temp1 = value >> 4 & 15
    value >>= 8
    checksum += (value >> 4 & 15) + (value & 15)
    temp3 = value >> 4 & 15
    value >>= 8
    checksum += (value >> 4 & 15) + (value & 15)
    address = value & 255
    value >>= 8
    checksum += (value >> 4 & 15) + (value & 15)
    checksum += 1 + 10 + 2 + 13 - 10
    if checksum != checksum1:
        raise ValueError(
            'The checksum in the Oregon packet does not match the caluclated one!'
            )
    temperature = (temp1 * 100 + temp2 * 10 + temp3) / 10.0
    if neg:
        temperature = -temperature
    humidity = hum1 * 10.0 + hum2
    return dict(packet, sensorId=address, data=dict(temp=temperature,
        humidity=humidity))


def lint_repeats(tool_xml, lint_ctx):
    """Lint repeat blocks in tool inputs."""
    repeats = tool_xml.findall('./inputs//repeat')
    for repeat in repeats:
        if 'name' not in repeat.attrib:
            lint_ctx.error('Repeat does not specify name attribute.')
        if 'title' not in repeat.attrib:
            lint_ctx.error('Repeat does not specify title attribute.')


def op_to_dunder_binary(op: str) ->str:
    """Return the dunder method name corresponding to binary op."""
    if op == '+':
        return '__add__'
    elif op == '-':
        return '__sub__'
    elif op == '*':
        return '__mul__'
    elif op == '//':
        return '__idiv__'
    elif op == '%':
        return '__mod__'
    elif op == '/':
        return '__div__'
    elif op == '**':
        return '__pow__'
    elif op == '&':
        return '__and__'
    elif op == '^':
        return '__xor__'
    elif op == '|':
        return '__or__'
    elif op == '==':
        return '__eq__'
    elif op == '!=':
        return '__ne__'
    elif op == '<':
        return '__lt__'
    elif op == '<=':
        return '__le__'
    elif op == '>':
        return '__gt__'
    elif op == '>=':
        return '__ge__'
    else:
        return op


def import_statsd():
    """
    Import only the statd by wolph not the mozilla statsd
    TODO: Move to mozilla statds which is more widely used
    """
    try:
        import django_statsd
        is_wolphs_statsd = hasattr(django_statsd, 'start') and hasattr(
            django_statsd, 'stop')
        if not is_wolphs_statsd:
            django_statsd = None
    except ImportError:
        django_statsd = None
    return django_statsd


def parse_content_type(value):
    """
    Parse out the content type from a content type header.

    >>> parse_content_type('application/json; charset=utf8')
    'application/json'

    """
    if not value:
        return ''
    return value.split(';')[0].strip()


def viaCombusta(obj):
    """ Returns if an object is in the Via Combusta. """
    return 195 < obj.lon < 225


def getTimesOfExperiment(expList, expId):
    """getTimesOfExperiment returns a list of the start and end time of the experiment given expId.

    Input:

        expList - the list of MadrigalExperiment objects

        expId - the experiment id

    Returns:

        a list of:
            (startyear,
            startmonth,
            startday,
            starthour,
            startmin,
            startsec,
            endyear,
            endmonth,
            endday,
            endhour,
            endmin,
            endsec)
    """
    retList = None
    for exp in expList:
        if exp.id == expId:
            retList = (exp.startyear, exp.startmonth, exp.startday, exp.
                starthour, exp.startmin, exp.startsec, exp.endyear, exp.
                endmonth, exp.endday, exp.endhour, exp.endmin, exp.endsec)
    return retList


def percentile(array, *args, **kwargs):
    """
    Computes the qth percentile of the data along the specified axis.

    See Also
    --------
    Array.percentile
    """
    return array.percentile(*args, **kwargs)


def seek(wfile, position, end=None):
    """
    Seeks `position` in `wfile`, and returns the number of frames to read until `end`.
    """
    end_frame = wfile.getnframes()
    if end != None:
        end_frame = min(end * wfile.getframerate(), end_frame)
    position_frame = position * wfile.getframerate()
    wfile.setpos(int(round(position_frame)))
    return int(round(end_frame - position_frame))


def p_style(p):
    """
    math_object : STYLE block
                    | STYLE symbol
    """
    p[2].style = p[1]
    p[0] = [p[2]]


def evaluate_media_query(query_list, device_media_type):
    """Return the boolean evaluation of `query_list` for the given
    `device_media_type`.

    :attr query_list: a cssutilts.stlysheets.MediaList
    :attr device_media_type: a media type string (for now)

    """
    return 'all' in query_list or device_media_type in query_list


@staticmethod
def check_compatibility(a, b):
    """
        Simple comparison of cubes. if X,Y,Z dims are the same, and
        voxel sizes as well, then they are compatible. (Duck typed)

        See also the function is_compatible().

        :params Cube a: the first cube to be compared with the second (b).
        :params Cube b: the second cube to be compared with the first (a).

        """
    eps = 1e-05
    if a.dimx != b.dimx:
        return False
    elif a.dimy != b.dimy:
        return False
    elif a.dimz != b.dimz:
        return False
    elif a.pixel_size - b.pixel_size > eps:
        return False
    elif a.slice_distance != b.slice_distance:
        return False
    else:
        return True


def _format_visibility(data):
    """Return a formatted visibility string

    :param data:
        The server's visibility (is_public) status value: True, False
    :rtype:
        A string formatted to public/private
    """
    if data:
        return 'public'
    else:
        return 'private'


def categorical_excess_cardinality_flagger_and_reducer(df, useful_cols,
    cardinality_fraction_threshold=0.1,
    cardinality_max_categories_threshold=50, **kwargs):
    """
    Function inspects categorical features in the input dataframe where there is excess cardinality (too many unique     values), and returns a list of features which exceed these thresholds, as well as Series detailing the cardinality     (in absolute terms as well as as a fraction of the total number of samples).

    Parameters
    ----------
    df : pandas.DataFrame
        The input dataframe
    useful_cols : pandas.DataFrame
        Look-up dataframe, which contains information about the dtypes of desired features, and how to deal with
        missing values for each feature
    cardinality_fraction_threshold : int or None
        Cardinality fraction is the ratio of unique values for a given feature to the total number of samples in the dataset
        - If None, no threshold applied
        - If int, this is the threshold beyond which a feature is deemed to have excessive cardinality
    cardinality_max_categories_threshold : int or None
        Cardinality max categories is the absolute number of unique values for a given feature
        - If None, no threshold applied
        - If int, this is the threshold beyond which a feature is deemed to have excessive cardinality

    Returns
    -------
    df_cardinality : pandas.Series
        Cardinality (number of unique elements) of the categorical features in the input dataset
    df_cardinality_fraction : pandas.Series
        Cardinality fractions of the categorical features in the input dataset
    excess_cardinality : list
        List of features which exceed one or more of the thresholds

    """
    categorical_features = list(useful_cols.loc[useful_cols.dtype ==
        'nominal', 'feature'])
    categorical_data = df[categorical_features]
    m_samples = categorical_data.shape[0]
    df_cardinality = categorical_data.nunique()
    df_cardinality_fraction = df_cardinality / m_samples
    excess_cardinality_fraction = set(df_cardinality_fraction[
        df_cardinality_fraction > cardinality_fraction_threshold].index)
    print(
        f'Following features exceed cardiality fraction threshold of {cardinality_fraction_threshold}: {excess_cardinality_fraction}'
        )
    excess_cardinality_absolute = set(df_cardinality[df_cardinality >
        cardinality_max_categories_threshold].index)
    print(
        f'Following features exceed cardiality absolute number threshold of {cardinality_max_categories_threshold}: {excess_cardinality_absolute}'
        )
    excess_cardinality = list(set.union(excess_cardinality_fraction,
        excess_cardinality_absolute))
    if kwargs['reducer'] == True:
        n_max_categories = kwargs['reducer_max_categories']
        for feature in excess_cardinality:
            value_counts = df[feature].value_counts()
            small_categories = list(value_counts[n_max_categories:].index)
            df.loc[df[feature].isin(small_categories), feature
                ] = 'SMALL_CATEGORY'
        print(
            f'Features {excess_cardinality} exceeded thresholds and have each been reduced down to a maximum {n_max_categories} categories per feature'
            )
    return df_cardinality, df_cardinality_fraction, excess_cardinality


@classmethod
def list(cls, context, limit=None, marker=None, sort_key=None, sort_dir=
    None, filters=None):
    """Return a list of Node objects.

        :param cls: the :class:`Node`
        :param context: Security context.
        :param limit: maximum number of resources to return in a single result.
        :param marker: pagination marker for large data sets.
        :param sort_key: column to sort results by.
        :param sort_dir: direction to sort. "asc" or "desc".
        :param filters: Filters to apply.
        :returns: a list of :class:`Node` object.

        """
    db_nodes = cls.dbapi.get_node_list(filters=filters, limit=limit, marker
        =marker, sort_key=sort_key, sort_dir=sort_dir)
    return cls._from_db_object_list(context, db_nodes)


def pop_trigger(data):
    """Pops trigger and trigger args from a given dict."""
    trigger_name = data.pop('trigger')
    trigger_args = {}
    if trigger_name == 'date':
        trigger_arg_names = 'run_date', 'timezone'
    elif trigger_name == 'interval':
        trigger_arg_names = ('weeks', 'days', 'hours', 'minutes', 'seconds',
            'start_date', 'end_date', 'timezone')
    elif trigger_name == 'cron':
        trigger_arg_names = ('year', 'month', 'day', 'week', 'day_of_week',
            'hour', 'minute', 'second', 'start_date', 'end_date', 'timezone')
    else:
        raise Exception('Trigger %s is not supported.' % trigger_name)
    for arg_name in trigger_arg_names:
        if arg_name in data:
            trigger_args[arg_name] = data.pop(arg_name)
    return trigger_name, trigger_args


@classmethod
def remove_attribute(cls, name):
    """Remove an attribute from the class.
        """
    return delattr(cls, name)


@classmethod
def decode(cls, value):
    """
        decode the bytes from redis back into a float

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


def update_checksums():
    """Calculate and update all checksums
        """


def module_to_class(module):
    """
    transform fooBar to FooBar
    """
    return module[0].upper() + module[1:]


def not_zero(x):
    """Return None if value is zero"""
    if x == 0:
        return
    return x


@classmethod
def _reload_testing_flag(cls, testing):
    """
        When testing is set to True, all authenticate decorators in services returns uid as "testuid1"
        :param testing:
        :return:
        """
    cls.testing = testing


def duplicate_move(ACTION_OT_duplicate=None, TRANSFORM_OT_transform=None):
    """Make a copy of all selected keyframes and move them

    :param ACTION_OT_duplicate: Duplicate Keyframes, Make a copy of all selected keyframes
    :param TRANSFORM_OT_transform: Transform, Transform selected items by mode type
    """
    pass


@classmethod
def download_facebook_data(cls, request, ppm_id):
    """
        Downloads the Facebook dataset for the passed user
        :param request: The original Django request object
        :param ppm_id: The PPM ID of the requesting user
        :return: The requested dataset
        """
    response = cls.get(request, f'/sources/api/facebook/{ppm_id}/download',
        raw=True)
    if response:
        return response.content
    return None


def jaccard_index(nodes_a, nodes_b):
    """Jaccard index of a bipartite graph."""
    return len(nodes_a & nodes_b) / len(nodes_a | nodes_b)


def track_field(field):
    """
    Returns whether the given field should be tracked by Auditlog.

    Untracked fields are many-to-many relations and relations to the Auditlog LogEntry model.

    :param field: The field to check.
    :type field: Field
    :return: Whether the given field should be tracked.
    :rtype: bool
    """
    from auditlog.models import LogEntry
    if field.many_to_many:
        return False
    if getattr(field, 'remote_field', None
        ) is not None and field.remote_field.model == LogEntry:
        return False
    elif getattr(field, 'rel', None) is not None and field.rel.to == LogEntry:
        return False
    return True


def _matches_expected_response_header(request_headers, response_headers):
    """
    Returns true if the Content-Type value of the response header matches the
    Accept value of the request header, false otherwise

    :param request_headers: the headers for a cosmos request
    :type request_headers: dict[str, str]
    :param response_headers: the headers for a cosmos response
    :type response_headers: dict[str, str]
    :return: true if the Content-Type value of the response header matches the
    Accept value of the request header, false otherwise
    :rtype: bool
    """
    return request_headers.get('Accept') in response_headers.get('Content-Type'
        )


@staticmethod
def previousChild(hotmap, index):
    """ Return the previous sibling of the node indicated by index. """
    previousChildIndex = max(0, index - 1)
    return hotmap[previousChildIndex][1]