def remove_cookie_by_name(cookiejar, name, domain=None, path=None):
    """Unsets a cookie by name, by default over all domains and paths.

    Wraps CookieJar.clear(), is O(n).
    """
    clearables = []
    for cookie in cookiejar:
        if cookie.name != name:
            continue
        if domain is not None and domain != cookie.domain:
            continue
        if path is not None and path != cookie.path:
            continue
        clearables.append((cookie.domain, cookie.path, cookie.name))
    for domain, path, name in clearables:
        cookiejar.clear(domain, path, name)


@classmethod
def register_create_as(cls, repl, orig):
    """Register that we can create objects of class `repl` in the same way as objects         of class `orig`.

        :param repl: object we want to create
        :param orig: object construction we can use instead
        """
    cls.create_as[repl].append(orig)


def _in_estimate(index, props, estimate):
    """
    Check is index is in estimate with props
    """
    if index in estimate:
        for p in props:
            if p in estimate[index]:
                return True
    return False


def notafunction(*args, **kwargs):
    """Default function for some parts of bot"""
    pass


def year(datetimes):
    """Return the year of given dates."""
    return datetimes.astype('datetime64[Y]', copy=False)


def show_hierarchy():
    """Open all object entries and close all others

    """
    pass


@staticmethod
def __filter_nodes(node_weights, return_positive_weights=True):
    """
        Filters out nodes with positive or negative weights and
        takes the absolute.

        :param node_weights: dict
        :param return_positive_weights: bool, if True returns nodes with
                                              positive weights,
                                              if False negative weights
        :return:
        """
    new_node_weights = {}
    for n, nv in node_weights.items():
        if nv > 0 and return_positive_weights:
            new_node_weights[n] = nv
        elif nv < 0 and not return_positive_weights:
            new_node_weights[n] = -nv
    return new_node_weights


def _validate_checkers_data(checkers_data):
    """Check if precommit-checkers.yml contains valid options only."""
    for each_option in checkers_data:
        if each_option not in ('config', 'project-checkers', 'file-checkers'):
            raise ValueError(
                'precommit-checkers.yml contains invalid option "{}"'.
                format(each_option))


def gather(hub, raw):
    """
    Collect the keys that need to be found and pass them to the
    os specific loaded plugin
    """
    ret = {}
    for imp in raw:
        ret[imp] = {}
        for sec in hub.config.CONFIG_SECTIONS:
            if sec not in raw[imp]:
                continue
            for key in raw[imp][sec]:
                osvar = raw[imp][sec][key].get('os', None)
                if osvar is not None:
                    val = hub.config.os.system.collect(osvar)
                    if val is not None:
                        ret[imp][key] = val
    return ret


def img_str_to_src_format(img_str):
    """
    将img的base64编码的字符串，增加数据，变为前端可以直接展示的src型字符串

    :param img_str:
    :return:
    """
    return 'data:image/jpeg;base64,' + img_str


@staticmethod
def loads(value):
    """Just pass through the value."""
    return value


def chunks(lst, size):
    """Yield successive sized chunks from lst."""
    for i in range(0, len(lst), size):
        yield lst[i:i + size]


def dict_splicer(plot_dict, Ld, Lx):
    """Dictionary constructor for plotting

	This function is a base-level function used by most other plotting functions to construct a list of dictionaries,
	each containing the passed arguments to the underlying plotting calls for each different dataset.

	Parameters
	----------
	plot_dict : dict
		Contains the parameters to be passed to the underlying plotting function.
	Ld : int
		Number of plots to be made.
	Lx : list
		Contains the lenght of the data array of each plot to be made.

	Returns
	-------
	dict_list : list
		List of dictionaries, one for each plot to be made.
	"""
    from numbers import Number
    dict_list = []
    dict_keys = plot_dict.keys()
    for i in range(Ld):
        temp_dict = {}
        for k in dict_keys:
            try:
                temp = (i for i in plot_dict[k])
            except TypeError:
                temp_dict[k] = plot_dict[k]
            else:
                if type(plot_dict[k]) is str or len(plot_dict[k]) == Lx[i]:
                    temp_dict[k] = plot_dict[k]
                elif (k in 'color' or 'color' in k) and (type(plot_dict[k]) is
                    str or isinstance(plot_dict[k][0], Number)):
                    temp_dict[k] = plot_dict[k]
                else:
                    temp_dict[k] = plot_dict[k][i]
        dict_list.append(temp_dict)
    return dict_list


def Graetz_heat(V, D, x, rho=None, Cp=None, k=None, alpha=None):
    """Calculates Graetz number or `Gz` for a specified velocity
    `V`, diameter `D`, axial distance `x`, and specified properties for the
    given fluid.

    .. math::
        Gz = \\frac{VD^2\\cdot C_p \\rho}{x\\cdot k} = \\frac{VD^2}{x \\alpha}

    Inputs either of any of the following sets:

    * V, D, x, density `rho`, heat capacity `Cp`, and thermal conductivity `k`
    * V, D, x, and thermal diffusivity `alpha`

    Parameters
    ----------
    V : float
        Velocity, [m/s]
    D : float
        Diameter [m]
    x : float
        Axial distance [m]
    rho : float, optional
        Density, [kg/m^3]
    Cp : float, optional
        Heat capacity, [J/kg/K]
    k : float, optional
        Thermal conductivity, [W/m/K]
    alpha : float, optional
        Thermal diffusivity, [m^2/s]

    Returns
    -------
    Gz : float
        Graetz number []

    Notes
    -----
    .. math::
        Gz = \\frac{\\text{Time for radial heat diffusion in a fluid by conduction}}
        {\\text{Time taken by fluid to reach distance x}}

    .. math::
        Gz = \\frac{D}{x}RePr

    An error is raised if none of the required input sets are provided.

    Examples
    --------
    >>> Graetz_heat(1.5, 0.25, 5, 800., 2200., 0.6)
    55000.0
    >>> Graetz_heat(1.5, 0.25, 5, alpha=1E-7)
    187500.0

    References
    ----------
    .. [1] Bergman, Theodore L., Adrienne S. Lavine, Frank P. Incropera, and
       David P. DeWitt. Introduction to Heat Transfer. 6E. Hoboken, NJ:
       Wiley, 2011.
    """
    if rho and Cp and k:
        alpha = k / (rho * Cp)
    elif not alpha:
        raise Exception(
            'Either heat capacity and thermal conductivity and        density, or thermal diffusivity is needed'
            )
    return V * D ** 2 / (x * alpha)


def are_equivalent_timestamps(first, second, delta=0):
    """ Check if two timestamps are equivalent

    Parameters
    ----------
    first : int
        First timestamp
    second : int
        Second timestamp
    delta : int, optional
        Allowed difference between the two timestamps

    Returns
    -------
    bool
        True if timestamps are equivalent, False otherwise
    """
    return abs(int(float(first)) - int(float(second))) in range(0, delta + 1)


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

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


def resolve_variables(variables, context, provider):
    """Given a list of variables, resolve all of them.

    Args:
        variables (list of :class:`stacker.variables.Variable`): list of
            variables
        context (:class:`stacker.context.Context`): stacker context
        provider (:class:`stacker.provider.base.BaseProvider`): subclass of the
            base provider

    """
    for variable in variables:
        variable.resolve(context, provider)


def np_vec_to_cut_vec(np_vec, decimals=4):
    """Converts a 3x1 numpy array to its representation in the CUT domain.

	:param np_vec: numpy array or None
	:param decimals: number of decimal places to round each element
	in np_vec to. - integer - default = 4

	:return: Empty string if np_vec is None or len(np_vec) != 3. Otherwise,
	the string '< x1, x2, x3 >' where x1, x2, x3 are the elements of np_vec
	rounded to decimals decimal places.
	"""
    if np_vec is None or len(np_vec) != 3:
        return ''
    else:
        return '< %.*f, %.*f, %.*f >' % (decimals, np_vec[0] + 0, decimals,
            np_vec[1] + 0, decimals, np_vec[2] + 0)


def t_CDI(t):
    """CDI/2336|CDI/2352"""
    return t


@classmethod
def register_resources(klass, registry, resource_class):
    """ meta model subscriber on resource registration.

        We watch for new resource types being registered and if they
        support aws config, automatically register the jsondiff filter.
        """
    if resource_class.resource_type.config_type is None:
        return
    resource_class.filter_registry.register('json-diff', klass)


def _do_get_latest_training_dataset_version(training_dataset_name,
    featurestore_metadata):
    """
    Utility method to get the latest version of a particular training dataset

    Args:
        :training_dataset_name: the training dataset to get the latest version of
        :featurestore_metadata: metadata of the featurestore

    Returns:
        the latest version of the training dataset in the feature store
    """
    training_datasets = featurestore_metadata.training_datasets
    matches = list(filter(lambda td: td.name == training_dataset_name,
        training_datasets.values()))
    versions = list(map(lambda td: int(td.version), matches))
    if len(versions) > 0:
        return max(versions)
    else:
        return 0


def text_to_int(text, default_base='hex'):
    """ Convert text to int, raising exeception on invalid input
    """
    if text.startswith('0x'):
        value = int(text[2:], 16)
    elif text.startswith('$'):
        value = int(text[1:], 16)
    elif text.startswith('#'):
        value = int(text[1:], 10)
    elif text.startswith('%'):
        value = int(text[1:], 2)
    elif default_base == 'dec':
        value = int(text)
    else:
        value = int(text, 16)
    return value


@staticmethod
def load_topics_descr(path):
    """
        Loads a topic description file (for each topic word distribution)
        """
    with open(path, 'r') as file:
        topics_descript = file.readlines()
    return str(topics_descript[0])


def add_pull_parser(sub_parser):
    """
    Adds a sub-parser for the "pull" sub-command to the parser provided.

    :param sub_parser: the parser to add to
    :type sub_parser: <class 'argparse.ArgumentParser'>
    """
    pull_parser = sub_parser.add_parser('pull', help='Pull file from remote')
    pull_parser.add_argument('remote', help='remote to pull')
    pull_parser.add_argument('-k', '--key', help=
        'key of file to pull (from .surround/config.yaml)')


def is_sf_database(db, model=None):
    """The alias is a Salesforce database."""
    from django.db import connections
    if db is None:
        return hasattr(model, '_salesforce_object')
    engine = connections[db].settings_dict['ENGINE']
    return engine == 'salesforce.backend' or connections[db
        ].vendor == 'salesforce'


def parse_symbol_type(symbol):
    """ parse_symbol_type

    It parse the symbol to Rockwell Spec
    :param symbol: the symbol associated to a tag
    :return: A tuple containing information about the tag
    """
    pass
    return None


def p_if_else_elseif(p):
    """
    statement : if_block_begin
              | elseif_block_begin
              | else_statement
    """
    p[0] = p[1]


def dfs_edges(G, source, condition=None):
    """Traverse a graph (DFS) with an optional condition to filter out nodes
        """
    if isinstance(source, list):
        nodes = source
    else:
        nodes = [source]
    visited = set()
    for start in nodes:
        if start in visited:
            continue
        visited.add(start)
        stack = [(start, G.out_edges(start).__iter__())]
        while stack:
            parent, children = stack[-1]
            try:
                e = next(children)
                if e.dst not in visited:
                    visited.add(e.dst)
                    if condition is None or condition(e.src, e.dst, e.data):
                        yield e
                        stack.append((e.dst, G.out_edges(e.dst).__iter__()))
            except StopIteration:
                stack.pop()


def importByName(fullName):
    """Import a class by name"""
    name = fullName.split('.')
    moduleName = name[:-1]
    className = name[-1]
    module = __import__('.'.join(moduleName), {}, {}, moduleName)
    return getattr(module, className)


def is_string_in_file(string, filepath):
    """
    Check if a string is in a file

    Args:
        :string: string to search for
        :filepath: path of file

    Returns:
        :is_found: True if found, False otherwise
    """
    if string in open(filepath).read():
        return True
    return False


@classmethod
def decode(cls, *a, **kw):
    """Apply base58 decode, verify checksum, return payload.
        """
    decoded = cls.decode_base(*a, **kw)
    assert cls.verify_checksum(decoded)
    payload = decoded[:-4]
    payload = payload[1:]
    return payload


def add_tags(ResourceId=None, Tags=None):
    """
    Adds tags to an Amazon EMR resource. Tags make it easier to associate clusters in various ways, such as grouping clusters to track your Amazon EMR resource allocation costs. For more information, see Tagging Amazon EMR Resources .
    See also: AWS API Documentation

    :example: response = client.add_tags(
        ResourceId='string',
        Tags=[
            {
                'Key': 'string',
                'Value': 'string'
            },
        ]
    )

    :type ResourceId: string
    :param ResourceId: [REQUIRED]
            The Amazon EMR resource identifier to which tags will be added. This value must be a cluster identifier.

    :type Tags: list
    :param Tags: [REQUIRED]
            A list of tags to associate with a cluster and propagate to EC2 instances. Tags are user-defined key/value pairs that consist of a required key string with a maximum of 128 characters, and an optional value string with a maximum of 256 characters.
            (dict) --A key/value pair containing user-defined metadata that you can associate with an Amazon EMR resource. Tags make it easier to associate clusters in various ways, such as grouping clusters to track your Amazon EMR resource allocation costs. For more information, see Tagging Amazon EMR Resources .
            Key (string) --A user-defined key, which is the minimum required information for a valid tag. For more information, see Tagging Amazon EMR Resources .
            Value (string) --A user-defined value, which is optional in a tag. For more information, see Tagging Amazon EMR Resources .

    :rtype: dict
    :return: {}

    """
    pass


@classmethod
def add_url(cls, url, parent_id=0, callback_url=None):
    """ Add new transfer from URI"""
    data = {'url': url, 'save_parent_id': parent_id}
    if callback_url:
        data['callback_url'] = callback_url
    d = cls.client.request('/transfers/add', method='POST', data=data)
    return cls(d['transfer'])


@classmethod
def from_center(cls, center=None, width=None):
    """
        SpectralRegion class method that enables the definition of a `SpectralRegion`
        from the center and width rather than lower and upper bounds.

        Parameters
        ----------

        center : Scalar `~astropy.units.Quantity` with pixel or any valid ``spectral_axis`` unit
           The center of the spectral region.

        width : Scalar `~astropy.units.Quantity` with pixel or any valid ``spectral_axis`` unit
           The width of the spectral region.
        """
    if width.value <= 0:
        raise ValueError('SpectralRegion width must be positive.')
    return cls(center - width, center + width)


def set_web_presentation_properties(web_format, web_scale, web_crop):
    """Sets format, scaling and cropping information to create the
        web image.

        - ``web_format`` (str): either ``JPEG``, ``GIF`` or ``PNG``,

        - ``web_scale`` (str): WidthXHeight or nn.n%.

        - ``web_crop`` (str): X1xY1-X2xY2, crop-box or empty for no
          cropping.

        Raises ``ValueError`` if ``web_scale`` cannot be parsed.  If
        changing the settings succeed, it will update the web version
        of the image.
        """


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

        :param list of [str] val:
        :rtype: UsersSelectorArg
        """
    return cls('external_ids', val)


def driver_delete_invalid():
    """Delete all visible drivers considered invalid

    """
    pass


def console_has_colours(stream):
    """
    Detects if the specified stream has colourising capability.

    :param stream: stream to check (typically sys.stdout)
    """
    if not hasattr(stream, 'isatty'):
        return False
    if not stream.isatty():
        return False
    try:
        import curses
        curses.setupterm()
        return curses.tigetnum('colors') > 2
    except:
        return False


def islistempty(listvar):
    """
    Checks wether a list has only empty values.
    Empty values are empty strings ("") or None.

    :param list listvar:
    :return: True if empty, False otherwise
    :rtype: bool
    """
    has_empty = True
    empty = '', None
    for item in listvar:
        if item not in empty:
            has_empty = False
    return has_empty


def chunk_workload(workload, size):
    """
    Splits workload into multiple chunks,
    to iteratively add large amount of data into redis
    Currently split happens only by number of elements
    """
    chunk = []
    for item in workload:
        chunk.append(item)
        if len(chunk) >= size:
            yield chunk
            chunk = []
    if chunk:
        yield chunk


def dump(chart, fileobj):
    """Dump a Chart to a file (or other object with a write() method)."""
    chart.dump(fileobj)


def compute_image_shape(width: int, height: int, fmt: str) ->tuple:
    """Compute numpy array shape for a given image.

    The output image shape is 2-dim for grayscale, and 3-dim for color images:

    * ``shape = (height, width)`` for FITS images with one grayscale channel
    * ``shape = (height, width, 3)`` for JPG images with three RGB channels
    * ``shape = (height, width, 4)`` for PNG images with four RGBA channels

    Parameters
    ----------
    width, height : int
        Width and height of the image
    fmt : {'fits', 'jpg', 'png'}
        Image format

    Returns
    -------
    shape : tuple
        Numpy array shape
    """
    if fmt == 'fits':
        return height, width
    elif fmt == 'jpg':
        return height, width, 3
    elif fmt == 'png':
        return height, width, 4
    else:
        raise ValueError(f'Invalid format: {fmt}')


def take_nth(n, coll):
    """
    Returns a generator of every ``n``th item in ``coll``.
    """
    if n <= 0:
        for e in coll:
            while True:
                yield e
    for i, e in enumerate(coll):
        if i % n == 0:
            yield e


def polygen(*args):
    """Create a polynomial value."""
    value = 0
    for bit in args:
        value |= 1 << bit - 1
    return value


def session_draw_bis(sessions_id, weblog, weblog_columns_dict):
    """
    Draw the graph of sessions with sessions_id given in entry
    """
    from graph_tool.all import Graph
    from graph_tool.all import graph_draw
    session = weblog[weblog.session_id == sessions_id]
    session = session.rename(index=str, columns={weblog_columns_dict[
        'requested_page_column']: 'requested_page', weblog_columns_dict[
        'referrer_page_column']: 'referrer_page'})
    s_pages = session['requested_page']
    s_pages_ref = session['referrer_page']
    s_pages = s_pages.append(s_pages_ref)
    s_pages.drop_duplicates(inplace=True)
    g = Graph()
    v = {}
    for page in s_pages.values:
        v[page] = g.add_vertex()
    session.apply(lambda x: g.add_edge(v[x.referrer_page], v[x.
        requested_page]), axis=1)
    graph_draw(g, output='../graph_dump/_session' + str(sessions_id) + '.png')
    return


def make_time_series_noise(dates, mean=0.0, std=1.0):
    """ Generate a time series of noise
    """
    pass


def set_fullname(fullname):
    """Change member fullname.
        """


def IndentationLevel(Line, TabSize=4):
    """
	return the indentation level of specified line.
	"""
    LineX = Line.expandtabs(TabSize)
    if LineX.isspace():
        return 0
    else:
        return int((len(LineX) - len(LineX.lstrip())) / TabSize)


def bubble_speak(dialog_box):
    """Golden Sun style synth-speech for dialog boxes.

    Args:
        dialog_box: The dialog box to read.

    """
    pass


def quadratic_extrap(ys, xs):
    """
    Quadratically extrapolate from three x,y pairs to x = 0.

    ys: y values from x,y pairs. Note that these can be arrays of values.
    xs: x values from x,y pairs. These should be scalars.

    Returns extrapolated y at x=0.
    """
    y1, y2, y3 = ys
    x1, x2, x3 = xs
    return x2 * x3 / ((x1 - x2) * (x1 - x3)) * y1 + x1 * x3 / ((x2 - x1) *
        (x2 - x3)) * y2 + x1 * x2 / ((x3 - x1) * (x3 - x2)) * y3


def zset_score_pairs(response, **options):
    """
    If ``withscores`` is specified in the options, return the response as
    a list of (value, score) pairs
    """
    if not response or not options['withscores']:
        return response
    score_cast_func = options.get('score_cast_func', float)
    it = iter(response)
    return list(zip(it, map(score_cast_func, it)))


def _send_release_rp(event):
    """Standard logging handler for sending an A-RELEASE-RP PDU."""
    pass


def _get_win_folder_from_registry(csidl_name):
    """This is a fallback technique at best. I'm not sure if using the
    registry for this guarantees us the correct answer for all CSIDL_*
    names.
    """
    import _winreg
    shell_folder_name = {'CSIDL_APPDATA': 'AppData', 'CSIDL_COMMON_APPDATA':
        'Common AppData', 'CSIDL_LOCAL_APPDATA': 'Local AppData'}[csidl_name]
    key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER,
        'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders'
        )
    dir, type = _winreg.QueryValueEx(key, shell_folder_name)
    return dir


def supplements(parms, countrate=None):
    u"""Supplementary parameters:
        [11] n₁ = n*F₁     Particle number of species 1
        [12] n₂ = n*(1-F₁) Particle number of species 2
    """
    n = parms[0]
    F1 = parms[3]
    Info = list()
    Info.append([u'n₁', n * F1])
    Info.append([u'n₂', n * (1.0 - F1)])
    if countrate is not None:
        cpp = countrate / n
        Info.append(['cpp [kHz]', cpp])
    return Info


def __repr__(A):
    """For `print` and `pprint`"""
    return A.to_str()


def create_index(DirectoryArn=None, OrderedIndexedAttributeList=None,
    IsUnique=None, ParentReference=None, LinkName=None):
    """
    Creates an index object. See Indexing for more information.
    See also: AWS API Documentation

    :example: response = client.create_index(
        DirectoryArn='string',
        OrderedIndexedAttributeList=[
            {
                'SchemaArn': 'string',
                'FacetName': 'string',
                'Name': 'string'
            },
        ],
        IsUnique=True|False,
        ParentReference={
            'Selector': 'string'
        },
        LinkName='string'
    )

    :type DirectoryArn: string
    :param DirectoryArn: [REQUIRED]
            The ARN of the directory where the index should be created.

    :type OrderedIndexedAttributeList: list
    :param OrderedIndexedAttributeList: [REQUIRED]
            Specifies the attributes that should be indexed on. Currently only a single attribute is supported.
            (dict) --A unique identifier for an attribute.
            SchemaArn (string) -- [REQUIRED]The Amazon Resource Name (ARN) of the schema that contains the facet and attribute.
            FacetName (string) -- [REQUIRED]The name of the facet that the attribute exists within.
            Name (string) -- [REQUIRED]The name of the attribute.

    :type IsUnique: boolean
    :param IsUnique: [REQUIRED]
            Indicates whether the attribute that is being indexed has unique values or not.

    :type ParentReference: dict
    :param ParentReference: A reference to the parent object that contains the index object.
            Selector (string) --A path selector supports easy selection of an object by the parent/child links leading to it from the directory root. Use the link names from each parent/child link to construct the path. Path selectors start with a slash (/) and link names are separated by slashes. For more information about paths, see Accessing Objects . You can identify an object in one of the following ways:
            $ObjectIdentifier - An object identifier is an opaque string provided by Amazon Cloud Directory. When creating objects, the system will provide you with the identifier of the created object. An object s identifier is immutable and no two objects will ever share the same object identifier
            /some/path - Identifies the object based on path
            #SomeBatchReference - Identifies the object in a batch call

    :type LinkName: string
    :param LinkName: The name of the link between the parent object and the index object.

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

    """
    pass


@classmethod
def validate(cls, output_destination):
    """Validate destination of report.

        :param output_destination: Destination of report
        """
    pass


@classmethod
def fit(cls, data, **guesses):
    """ Fit a distribution to sample using scipy's maximum
        likelihood estimation methods.

        Parameters
        ----------
        data : array-like
            A sample whose distribution parameters will be estimated.
        guesses : named arguments of floats
            Inital guess values for certain parameters of the
            distribution. See the class docstring for more information
            on the parameters.

        Returns
        -------
        params : namedtuple
            A namedtuple containing all of the paramaters of the
            distribution.

        """
    return cls.param_template(*cls._fit(data, **guesses))


@staticmethod
def is_actionable(media_file):
    """Perform check to determine if action should be taken.

        :param media_file: the file to inspect to determine
                           if action is necessary
        :returns: a flag indicating to act or not to act
        :rtype: boolean
        """
    return True


def get_ADC_value(bus, addr, channel):
    """
    This method selects a channel and initiates conversion
    The ADC operates at 240 SPS (12 bits) with 1x gain
        One shot conversions are used, meaning a wait period is needed
        in order to acquire new data. This is done via a constant poll
        of the ready bit.
    Upon completion, a ratiomeric value is returned to the caller.

    Usage - ADC_start(bus, SensorCluster.ADC_addr, channel_to_read)

    """
    if channel == 1:
        INIT = 128
    elif channel == 2:
        INIT = 160
    elif channel == 3:
        INIT = 192
    elif channel == 4:
        INIT = 224
    bus.write_byte(addr, INIT)
    data = bus.read_i2c_block_data(addr, 0, 3)
    status = (data[2] & 128) >> 7
    while status == 1:
        data = bus.read_i2c_block_data(addr, 0, 3)
        status = (data[2] & 128) >> 7
    sign = data[0] & 8
    val = (data[0] & 7) << 8 | data[1]
    if sign == 1:
        val = (val ^ 1023) + 1
    return float(val) / float(2047)


def make_little_d(x, order, mode):
    """
    Make the LP equation d' vector (Da = d')
    """
    if mode == 'f':
        return x[order:].reshape(len(x) - order, 1)
    elif mode == 'b':
        L = len(x) - order
        return x[:L].reshape(L, 1)
    else:
        raise ValueError("mode must be 'f' or 'b'")


def __get_cycle(graph, ordering, parent_lookup):
    """Gets the main cycle of the dfs tree."""
    root_node = ordering[0]
    for i in range(2, len(ordering)):
        current_node = ordering[i]
        if graph.adjacent(current_node, root_node):
            path = []
            while current_node != root_node:
                path.append(current_node)
                current_node = parent_lookup[current_node]
            path.append(root_node)
            path.reverse()
            return path


@staticmethod
def _fill_form(form):
    """
        Fill all inputs with provided Jinja2 templates.
        If no field had click key, submit last element.
        """
    clicked = False
    last_element = None
    for field in form:
        if field['text']:
            field['element'].clear()
            field['element'].send_keys(field['text'])
        if field['click']:
            field['element'].click()
            clicked = True
        last_element = field['element']
    if last_element:
        if not clicked:
            last_element.submit()


def is_directory(entry):
    """Returns true if the given entry is a directory"""
    return entry['nlink'] > 1


def contains_all(set1, set2, warn):
    """
    Checks if all elements from set2 are in set1.

    :param set1:  a set of values
    :param set2:  a set of values
    :param warn: the error message that should be thrown
     when the sets are not containd
    :return: returns true if all values of set2 are in set1
    """
    for elem in set2:
        if elem not in set1:
            raise ValueError(warn)
    return True


def nested_dict_add(dictionary, value, *keys):
    """Nested adding in a dictionary.

    Parameters
    ----------
        dictionary : dict
            The dictionary that is going to be parsed.

        value : object
            The value that is going to be added.

        keys : list(hashable)
            A list of keys.
    Returns
    -------
    None.

    """
    address = dictionary
    for k in keys[:-1]:
        if k not in address:
            address[k] = dict()
        address = address[k]
    address[keys[-1]] = value


def write_token_file(filename, oauth_token, oauth_token_secret):
    """
    Write a token file to hold the oauth token and oauth token secret.
    """
    oauth_file = open(filename, 'w')
    print(oauth_token, file=oauth_file)
    print(oauth_token_secret, file=oauth_file)
    oauth_file.close()


def get_mime_type(page):
    """
    Extracts the Content-Type header from the headers returned by page.
    """
    try:
        doc_type = str(page.headers['content-type'])
        return doc_type
    except KeyError:
        return ''


@classmethod
def get_by(cls, prop, value, offset=0, size=1):
    """Get an object using a query on a specific property

        prop must be one of the properties defined in the Document.
        If value is a list type a terms query is used.
        """
    query_type = isinstance(value, (list, tuple)) and 'terms' or 'term'
    body = {'query': {query_type: {prop.get_query_name(): value}}, 'size':
        size, 'from': offset}
    hits = cls.search(body)
    return hits['hits']['hits']


@staticmethod
def strip_ws_name(range_str):
    """Splits out the worksheet reference, if any, from a range reference."""
    if '!' in range_str:
        sheet, range_str = range_str.rsplit('!', 1)
        return sheet + '!', range_str
    return '', range_str


@property
def name(cls):
    """The name property is a function of the class - its __name__."""
    return cls.__name__


@classmethod
def from_str_or_key(cls, value, drop=[], append=[], tag=None):
    """Return a new Key from *value*.

        Parameters
        ----------
        value : str or Key
            Value to use to generate a new Key.
        drop : list of str, optional
            Existing dimensions of *value* to drop. See :meth:`drop`.
        append : list of str, optional.
            New dimensions to append to the returned Key. See :meth:`append`.
        tag : str, optional
            Tag for returned Key. If *value* has a tag, the two are joined
            using a '+' character. See :meth:`add_tag`.

        Returns
        -------
        :class:`Key`
        """
    if isinstance(value, cls):
        base = value
    else:
        name, *dims = value.split(':')
        _tag = dims[1] if len(dims) == 2 else None
        dims = dims[0].split('-') if len(dims) else []
        base = cls(name, dims, _tag)
    return base.drop(*(base.dims if drop is True else drop)).append(*append
        ).add_tag(tag)


def review_data(game_id: int, level, reactions=None, add_to_library=False,
    text='', post_twitter=False, post_facebook=False) ->dict:
    """creates the data for review operations

        :param game_id: the int id of the game
        :type game_id: int
        :param level: 1 = skip, 3 = meh, 4 = Recommended, 5 = Exceptional
        :type level: int
        :param reactions: List of the reactions to add, defaults to None
        :type reactions: List[int], optional
        :param add_to_library: whether the game whouls be added to the authenticated users library, defaults to False
        :type add_to_library: bool, optional
        :param text: the review text, uses html formats like <br>, defaults to ""
        :type text: str, optional
        :param post_twitter: whether to post on twitter, defaults to False
        :type post_twitter: bool, optional
        :param post_facebook: whether to post on facebook, defaults to False
        :type post_facebook: bool, optional
        :return: The data that has been made
        :rtype: dict
        """
    data = {'game': game_id, 'rating': 5, 'post_facebook': post_facebook,
        'post_twitter': post_twitter, 'add_to_library': add_to_library}
    if len(text) > 0:
        data['text'] = text
    if isinstance(reactions, list):
        data['reactions'] = reactions
    return data


def image(*args, **kwargs):
    """
    We parse the content of the text to get the information about the image.
    """
    text = kwargs.get('text', None)
    name = kwargs.get('name', None)
    view = kwargs.get('view', None)
    class_ = kwargs.get('class', 'article-image')
    style = kwargs.get('style', 'width:80%')
    path_str = view.path_str
    img_url = '/static/assets/{}/{}'.format(view.path_str, name)
    img = (
        """

{}

"""
        .format(img_url, class_, style, text))
    return img


def wenss_fit(c, x):
    """ sqrt(c0*c0 + c1^2/x^2)"""
    import numpy as N
    y = N.sqrt(c[0] * c[0] + c[1] * c[1] / (x * x))
    return y


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

        :param DeviceApprovalsChangeUnlinkActionDetails val:
        :rtype: EventDetails
        """
    return cls('device_approvals_change_unlink_action_details', val)


def changelog_entries(lines):
    """Return a list of changelog entries.

    :param lines: lines of a changelog file.
    :returns: list of entries.  Each entry is a tuple of lines.
    """
    entries = []
    for line in lines:
        if line[0] not in (' ', '\t', '\n'):
            entries.append([line])
        else:
            try:
                entry = entries[-1]
            except IndexError:
                entries.append([])
                entry = entries[-1]
            entry.append(line)
    return list(map(tuple, entries))


def is_datasource(tool_xml):
    """Returns true if the tool is a datasource tool"""
    return tool_xml.getroot().attrib.get('tool_type', '') == 'data_source'


def evalint(s):
    """Evaluate string to an integer."""
    return int(eval(s, {}, {}))


def _est_unregularized_naive(mod, pnum, partitions, fit_kwds=None):
    """estimates the unregularized fitted parameters.

    Parameters
    ----------
    mod : statsmodels model class instance
        The model for the current partition.
    pnum : scalar
        Index of current partition
    partitions : scalar
        Total number of partitions
    fit_kwds : dict-like or None
        Keyword arguments to be given to fit

    Returns
    -------
    An array of the parameters for the fit
    """
    if fit_kwds is None:
        raise ValueError('_est_unregularized_naive currently ' +
            'requires that fit_kwds not be None.')
    return mod.fit(**fit_kwds).params


def append_action(_, rundle, payload):
    """
    Simplest action case -- append rundle name to list

    Input:
        rundle -- rundle name
        payload -- list we will append rundle name to
    """
    payload.append(rundle)


def renamed(node):
    """Obtain copy metadata for a node.

        Returns ``False`` if no copy metadata is stored or a 2-tuple of
        (path, node) from which this revision was copied.
        """


def _set_default_configs(user_settings, default):
    """Set the default value to user settings if user not specified
    the value.
    """
    for key in default:
        if key not in user_settings:
            user_settings[key] = default[key]
    return user_settings


def _parse_vasp_name(xml_tree):
    """Extract the system name from an XML ElementTree representing a
    vasprun.xml file.
    """
    xml_general = xml_tree.find('./parameters/separator[@name="general"]')
    return xml_general.find('./i[@name="SYSTEM"]').text


def estimate_f_coefficients(my_car, passengers=0):
    """
    f0, f1, f2 coefficients of resistance are estimated

    :param my_car:
    :param passengers:
    :type passengers: int
    :return:
    """
    d = {}
    d['cabriolet'] = 0.28
    d['sedan'] = 0.27
    d['hatchback'] = 0.3
    d['stationwagon'] = 0.28
    d['suv/crossover'] = 0.35
    d['mpv'] = 0.3
    d['coupé'] = 0.27
    d['pick-up'] = 0.4
    rolling_res_coef = 0.009
    theor_aero_coeff = d[my_car.type_of_car]
    operating_mass = my_car.veh_mass + 100 + 75 * passengers
    f0 = (operating_mass + 100) * rolling_res_coef * 9.81
    f2 = 0.5 * 1.2 * (0.84 * my_car.car_width * my_car.car_height *
        theor_aero_coeff) / pow(3.6, 2)
    f1 = -71.735 * f2 + 2.7609
    return f0, f1, f2


def extract_attr(param, field):
    """
    Extract a particular field from a parameter object

    Parameters
    ----------
    param : parameter object
       Various parameter objects defined by Google messages.
    field : string
       Parameter field.

    Returns
    -------
    string or None
        Field value or None if parameter or field doesn't exist.

    """
    tmpval = getattr(param, field, None)
    if tmpval is not None:
        return tmpval
    else:
        return None


def argsort(input, dim, descending):
    """Return the indices that would sort the input along the given dim.

    Parameters
    ----------
    input : Tensor
        The input tensor.
    dim : int
        The dim to sort along.
    descending : bool
        Controls the sorting order (False: ascending, True: descending)

    Returns
    -------
    Tensor
        A framework-specific tensor.
    """


def _move_to_next(fid, byte=8):
    """Move to next byte boundary."""
    now = fid.tell()
    if now % byte != 0:
        now = now - now % byte + byte
        fid.seek(now, 0)


@staticmethod
def sanitize_command(cmd: str) ->list:
    """
        Sanitizes the command into an array of arguments
        :param cmd: the command string
        :return: a list of tokens for the launcher
        """
    within_quote = False
    within_double_quote = False
    tokens = []
    accumulator = ''
    for c in cmd:
        if c == '"' and not within_quote:
            if within_double_quote:
                if len(accumulator) > 0:
                    tokens.append(accumulator)
                    accumulator = ''
                within_double_quote = False
            elif len(accumulator) == 0:
                within_double_quote = True
            else:
                accumulator += c
        elif c == "'" and not within_double_quote:
            if within_quote:
                if len(accumulator) > 0:
                    tokens.append(accumulator)
                    accumulator = ''
                within_quote = False
            elif len(accumulator) == 0:
                within_quote = True
            else:
                accumulator += c
        elif (c == ' ' or c == '\t' or c == '\n'
            ) and not within_double_quote and not within_quote:
            if len(accumulator) > 0:
                tokens.append(accumulator)
                accumulator = ''
        else:
            accumulator += c
    if len(accumulator) > 0:
        tokens.append(accumulator)
    return tokens


def get_blueprints(app):
    """Returns blueprints dict."""
    return app.blueprints


def clear(library, session):
    """Clears a device.

    Corresponds to viClear function of the VISA library.

    :param library: the visa library wrapped by ctypes.
    :param session: Unique logical identifier to a session.
    :return: return value of the library call.
    :rtype: :class:`pyvisa.constants.StatusCode`
    """
    return library.viClear(session)


def py_to_psqls(item):
    """ Convert the provided python object into a postgres-dumpfile-compatible
    string """
    if item == None:
        return 'NULL'
    return str(item)


def get_bag_retriever(environ, bag):
    """
    When loading :py:class:`bag <tiddlyweb.model.bag.Bag>` or
    :py:class:`tiddlers <tiddlyweb.model.tiddler.Tiddler>` within it
    from the :py:class:`store <tiddlyweb.store.Store>`, this method is
    used to inspect ``config['special_bag_detectors']`` to determine
    if there is a special handler. If there is, the handler is returned
    and used for retrieval, otherwise ``None`` is returned and the store
    is used as normal.
    """
    try:
        config = environ['tiddlyweb.config']
    except KeyError:
        from tiddlyweb.config import config
    testers = config.get('special_bag_detectors', [])
    for bag_tester in testers:
        retriever = bag_tester(environ, bag)
        if retriever:
            return retriever
    return None


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

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

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


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


def raw_str(s, enc, end=u'\x00'):
    """Returns a string representing @s as an @end (by default \\x00)
    terminated @enc encoded string.

    @s: the unicode str to serialize
    @enc: the encoding to apply to @s and @end before serialization.
    @end: the ending string/character to append to the string _before encoding_
        and serialization (by default '\\x00')
    """
    return (s + end).encode(enc)


def p_switch_case_list(p):
    """switch_case_list : LBRACE case_list RBRACE
                        | LBRACE SEMI case_list RBRACE"""
    if len(p) == 4:
        p[0] = p[2]
    else:
        p[0] = p[3]


def can_preview(file):
    """Check if file can be previewed."""
    return file.has_extensions('.pdf', '.pdfa')


def strip_block_comments(text):
    """Strips text of block comments"""
    import re
    block_comment_re = re.compile(
        '//.*?$|/\\*.*?\\*/|\\\'(?:\\\\.|[^\\\\\\\'])*\\\'|"(?:\\\\.|[^\\\\"])*"'
        , re.DOTALL | re.MULTILINE)
    return re.sub(block_comment_re, '', text)


def _HPERM_OP(a):
    """Clever bit manipulation."""
    t = (a << 18 ^ a) & 3435921408
    return a ^ t ^ t >> 18 & 16383


def Bin2Hex(numstr):
    """Converts the given binary numstr (string) to a hex string. Returns the
    string.
    """
    result = ''
    while len(numstr):
        bstr = numstr[:8]
        numstr = numstr[8:]
        tmpval = 0
        for x in bstr:
            tmpval *= 2
            tmpval += int(x)
        result += '%x' % tmpval
    return result


def assign_charge(mol, force_recalc=False):
    """Assign charges in physiological condition"""
    mol.require('Aromatic')
    for i, nbrs in mol.neighbors_iter():
        atom = mol.atom(i)
        nbrcnt = len(nbrs)
        if atom.symbol == 'N':
            if not atom.pi:
                mol.atom(i).charge_phys = 1
            elif nbrcnt == 1 and atom.pi == 2:
                ni = list(nbrs.keys())[0]
                conj = False
                sp2n = None
                for nni, nnb in mol.neighbors(ni).items():
                    if mol.atom(nni
                        ).symbol == 'N' and nnb.order == 2 and not mol.atom(nni
                        ).aromatic:
                        mol.atom(nni).charge_conj = 1
                        conj = True
                    elif mol.atom(nni).symbol == 'N' and nni != i:
                        sp2n = nni
                if conj:
                    mol.atom(i).charge_phys = 1
                    if sp2n is not None:
                        mol.atom(sp2n).charge_conj = 1
        elif atom.symbol == 'O' and nbrcnt == 1 and atom.pi == 2:
            ni = list(nbrs.keys())[0]
            conj = False
            if mol.atom(ni).symbol == 'N':
                mol.atom(i).n_oxide = True
                mol.atom(ni).n_oxide = True
            for nni, nnb in mol.neighbors(ni).items():
                if mol.atom(nni).symbol in ('O', 'S'
                    ) and nnb.order == 2 and not mol.atom(ni).n_oxide:
                    mol.atom(nni).charge_conj = -1
                    conj = True
            if conj:
                mol.atom(i).charge_phys = -1
        elif atom.symbol == 'S' and nbrcnt == 1:
            ni = list(nbrs.keys())[0]
            if mol.atom(ni).aromatic:
                mol.atom(i).charge_phys = -1
    mol.charge_assigned = True
    mol.descriptors.add('Phys_charge')


def total_seconds(td):
    """Alternative to datetime.timedelta.total_seconds
    total_seconds() only available since Python 2.7
    https://docs.python.org/2/library/datetime.html#datetime.timedelta.total_seconds
    """
    return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6
        ) / 10 ** 6


@staticmethod
def _search_patterns(content, patterns):
    """ Returns the regex of the first pattern that matches specified content, None if nothing matches """
    for pattern in patterns:
        if pattern.search(content):
            return pattern.pattern
    return None


def _iget(key, lookup_dict):
    """
    Case-insensitive search for `key` within keys of `lookup_dict`.
    """
    for k, v in lookup_dict.items():
        if k.lower() == key.lower():
            return v
    return None


def BoolProperty(name: str='', description: str='', default=False, options:
    set={'ANIMATABLE'}, tags: set={}, subtype: str='NONE', update=None, get
    =None, set=None):
    """Returns a new boolean property definition.

    :param name: Name used in the user interface.
    :type name: str
    :param description: Text used for the tooltip and api documentation.
    :type description: str
    :param options: Enumerator in [‘HIDDEN’, ‘SKIP_SAVE’, ‘ANIMATABLE’, ‘LIBRARY_EDITABLE’, ‘PROPORTIONAL’,’TEXTEDIT_UPDATE’].
    :type options: set
    :param tags: Enumerator of tags that are defined by parent class.
    :type tags: set
    :param subtype: Enumerator in [‘PIXEL’, ‘UNSIGNED’, ‘PERCENTAGE’, ‘FACTOR’, ‘ANGLE’, ‘TIME’, ‘DISTANCE’, ‘NONE’].
    :type subtype: str
    :param update: Function to be called when this value is modified, This function must take 2 values (self, context) and return None. Warning there are no safety checks to avoid infinite recursion.
    :param get: Function to be called when this value is ‘read’, This function must take 1 value (self) and return the value of the property.
    :param set: Function to be called when this value is ‘written’, This function must take 2 values (self, value) and return None.
    """
    pass


def main():
    """No health check for python client"""
    return 0


def idfn(df, id_global_assignment):
    """ID measures: Number of false negatives matches after global min-cost matching."""
    del df
    rids, cids = id_global_assignment['rids'], id_global_assignment['cids']
    return id_global_assignment['fnmatrix'][rids, cids].sum()


def freestyle_lineset_paste():
    """Paste the buffer content to the active line set

    """
    pass


def getstorage(tree):
    """Retrieve an interface to storage for a particular tree.

        If ``tree`` is the empty bytestring, storage for the root manifest will
        be returned. Otherwise storage for a tree manifest is returned.

        TODO formalize interface for returned object.
        """


def get_p2p_scatter_over_mad(model):
    """Get ratio of variability of folded and unfolded models."""
    return model['scatter_over_mad']


def subImage(Img, FracBox):
    """return a subImage from Image based on coordinates in dimensionless units"""
    width, height = Img.size
    left = round(width * FracBox[0])
    right = round(width * FracBox[2])
    bottom = round(height * FracBox[1])
    top = round(height * FracBox[3])
    return Img.crop((left, bottom, right, top))


def getCubes():
    """Returns a list of ICube in the catalog."""


@staticmethod
def __find_by_target_id(target_id, target_list):
    """find target by id
        """
    for target in target_list:
        if target_id == target['target_id']:
            return target
    raise KeyError('target_id: %s not found', target_id)


def create_activity(name=None):
    """
    Creates an activity.
    See also: AWS API Documentation

    :example: response = client.create_activity(
        name='string'
    )

    :type name: string
    :param name: [REQUIRED]
            The name of the activity to create. This name must be unique for your AWS account and region.

    :rtype: dict
    :return: {
        'activityArn': 'string',
        'creationDate': datetime(2015, 1, 1)
    }

    """
    pass


def getFeedLinks():
    """
    Function generating a script to extract all RSS and Atom feed links.

    @return script to extract all RSS and Atom feed links
    @rtype str
    """
    source = """
(function() {
    var out = [];
    var links = document.getElementsByTagName('link');
    for (var i = 0; i < links.length; ++i) {
        var e = links[i];
        if ((e.rel == 'alternate') &&
            ((e.type == 'application/atom+xml') ||
             (e.type == 'application/rss+xml')
            )
           ) {
            out.push({
                url: e.getAttribute('href'),
                title: e.getAttribute('title')
            });
        }
    }
    return out;
})()"""
    return source


def change_spacing(delta: int=1):
    """Change font spacing

    :param delta: Delta, Amount to decrease or increase character spacing with
    :type delta: int
    """
    pass


@classmethod
def use(cls, connection):
    """ Register a new data warehouse connection for use by all
        table operations.
        """
    cls.__connection = connection
    cls.__version = None


def decode(message):
    """Decode message without key."""
    pass


@classmethod
def from_idtag(cls, tag):
    """Year tags have the lower-case letter y + the four digit year,
           eg. y2008.
        """
    y = int(tag[1:5])
    return cls(year=y)


def _task_print_debug(task, line):
    """Default task debug printing function."""
    print(line)


def glFrustum(left, right, bottom, top, zNear, zFar):
    """Multiply the current matrix by a perspective matrix

    :param right: Specify the coordinates for the left and right vertical clipping planes.
    :param bottom: Specify the coordinates for the bottom and top horizontal clipping planes.
    :param zFar: Specify the distances to the near and far depth clipping planes. Both distances must be positive.
    """
    pass


def initialize(context):
    """Initializer called when used as a Zope 2 product."""


def look_up(name, obj):
    """
    Looks up a qualified name.
    """
    result = obj
    for part in name.split('.'):
        result = getattr(result, part)
    return result


def region_flip():
    """Toggle the region’s alignment (left/right or top/bottom)

    """
    pass


def _allow_join(statement):
    """
    Tests if a join should be suggested

    We need this to avoid bad suggestions when entering e.g.
        select * from tbl1 a join tbl2 b <cursor>
    So check that the preceding token is a JOIN keyword

    :param statement: an sqlparse.sql.Statement
    :return: boolean
    """
    if not statement or not statement.tokens:
        return False
    last_tok = statement.token_prev(len(statement.tokens))[1]
    return last_tok.value.lower().endswith('join') and last_tok.value.lower(
        ) not in ('cross join', 'natural join')


def find_in_enum_members(item, enum_members: list):
    """Matches a string in the provided list of member strings.
	The item must be not fully matched.
	Rules:
	- If the member string starts with underscore, it is cut out before the matching continues.
	- The item is matched if a member string starts with the item (item is a prefix of the member)."""
    found = None
    for x in enum_members:
        if x.startswith(item):
            found = x
            break
        if x.startswith('_'):
            if x.strip('_').startswith(item):
                found = x
                break
    return found


def write(parameters: dict, cmdline_file: str):
    """
    Create a cmdline file with the provided parameters
    Overwrite it if it exists

    :param parameters: A dictionary of key/value pairs
    :param cmdline_file: The **boot partition's** cmdline file
    """
    data = ''
    for key in parameters:
        if len(data) != 0:
            data += ' '
        data += '{}={}'.format(key, parameters[key])
    with open(cmdline_file, 'w') as fpt:
        fpt.write(data)


@staticmethod
def get_job_metadata():
    """Collect metadata for extractor-job"""
    return {}


def atof(conv, string, func=float):
    """Parses a string as a float according to the locale settings."""
    ts = conv['thousands_sep']
    if ts:
        string = string.replace(ts, '')
    dd = conv['decimal_point']
    if dd:
        string = string.replace(dd, '.')
    return func(string)


def cli_err_msg(cmd, err):
    """ get cli exception message"""
    if not err:
        return 'Error: Fail to get cli exception message.'
    msg = list()
    err_list = str(err).split('\r\n')
    for err in err_list:
        err = err.strip('.,\r\n\t ')
        if not err:
            continue
        if cmd and cmd == err:
            continue
        if " at '^' position" in err:
            err = err.replace(" at '^' position", '').strip()
        err = err.strip('.,\r\n\t ')
        if err == '^':
            continue
        if len(err) > 2 and err[0] in ['<', '['] and err[-1] in ['>', ']']:
            continue
        err.strip('.,\r\n\t ')
        if err:
            msg.append(err)
    if cmd:
        msg.insert(0, 'Command: %s' % cmd)
    return ', '.join(msg).capitalize() + '.'


def _value_grouped(df, index_grouped, col):
    """Return index_grouped as list of value list"""
    value = []
    for item in index_grouped:
        value_val = df.iloc[item, col].to_list()
        value.append(value_val)
    return value


def _invalidWin32App(pywinerr):
    """
    Determine if a pywintypes.error is telling us that the given process is
    'not a valid win32 application', i.e. not a PE format executable.

    @param pywinerr: a pywintypes.error instance raised by CreateProcess

    @return: a boolean
    """
    return pywinerr.args[0] == 193


def meta_remove():
    """Separate out the strips held by the selected meta-strips

    """
    pass


@staticmethod
def _get_decimal_places(c):
    """returns the the number of decimal places in the string"""
    try:
        s = str(c)
        return len(s) - s.index('.') - 1
    except ValueError:
        return 0


def logamp_structure(logamp_a, logamp_b, axis=-1):
    """Structure function for log-amplitude fluctuations.

    See Daigle, equation 17.
    """
    return ((logamp_a - logamp_b) ** 2.0).mean(axis=axis)


def get_version():
    """
	Returns the current dj-paypal version
	"""
    from . import __version__
    return __version__


def tile_set(tile: int=(0, 0)):
    """Set UV image tile coordinates

    :param tile: Tile, Tile coordinate
    :type tile: int
    """
    pass


def bitstring_to_bytes(bitstring: str, byteorder: str='big') ->bytes:
    """
    Converts a bitstring to bytes.

    Parameters:
        bitstring (str): Bitstring to convert.
        byteorder (str): Desired byte order ('big' or 'little').

    Returns:
        bytes: Bytes representation.
    """
    return int(bitstring, 2).to_bytes(len(bitstring) // 8, byteorder=byteorder)


def _insert_jinja_configuration(c):
    """Insert the configuration for the sphinx-jinja extension.

    The "default" Jinja context includes all variables in the conf.py
    configuration namespace.
    """
    c['jinja_contexts'] = {'default': c}
    return c


def get_value(tl, key, **kwargs):
    """
        tl = [('k1','v11'),('k1','v12'),('k31','v3'),('k32','v3'),('k4','v41'),('k4','v42'),('k1','v13')]
        get_value(tl,'k1')
        get_value(tl,'k1',whiches=1)
        get_value(tl,'k1',whiches=[1,2])

    """
    single = False
    if 'mode' in kwargs:
        mode = kwargs['mode']
    else:
        mode = 'key'
    if 'whiches' in kwargs:
        whiches = kwargs['whiches']
    else:
        whiches = 'all'
    if isinstance(whiches, list):
        pass
    elif isinstance(whiches, int):
        single = True
        whiches = [whiches]
    else:
        pass
    length = tl.__len__()
    rslt = []
    cursor = 0
    for i in range(0, length):
        t = tl[i]
        k = t[0]
        v = t[1]
        if k == key:
            if whiches == 'all':
                cond = True
            else:
                cond = cursor in whiches
            if cond:
                if single == False:
                    rslt.append(v)
                else:
                    return v
            else:
                pass
            cursor = cursor + 1
        else:
            pass
    if single == True:
        raise KeyError(key)
    else:
        return rslt


def getbundle(source, **kwargs):
    """Obtain remote repository data as a bundle.

        This command is how the bulk of repository data is transferred from
        the peer to the local repository

        Returns a generator of bundle data.
        """


def remove_cookie_by_name(cookiejar, name, domain=None, path=None):
    """Unsets a cookie by name, by default over all domains and paths.

    Wraps CookieJar.clear(), is O(n).
    """
    clearables = []
    for cookie in cookiejar:
        if cookie.name != name:
            continue
        if domain is not None and domain != cookie.domain:
            continue
        if path is not None and path != cookie.path:
            continue
        clearables.append((cookie.domain, cookie.path, cookie.name))
    for domain, path, name in clearables:
        cookiejar.clear(domain, path, name)


def _genotype(data):
    """Simple decision about genotype."""
    if data['ratio'] > 0.9:
        return '1/1'
    return '1/0'


@staticmethod
def parse_line(line):
    """
        Parse line inputs.

        **Parameters**

            line: *str*
                A string that holds coulomb information.

        **Returns**

            None
        """
    raise Exception('Error - Function has not been done yet.')


def SizeBenefitSurg(t):
    """Surgery benefit per policy"""
    return 0


def can_paginate(operation_name=None):
    """
    Check if an operation can be paginated.

    :type operation_name: string
    :param operation_name: The operation name. This is the same name
            as the method name on the client. For example, if the
            method name is create_foo, and you'd normally invoke the
            operation as client.create_foo(**kwargs), if the
            create_foo operation can be paginated, you can use the
            call client.get_paginator('create_foo').

    """
    pass


def annotated_frames_object(scribbles_data, object_id):
    """ Computes which frames have a scribble for a certain object.

    # Arguments
        scribbles_data (dict): Scribble in the default format.
        object_id (int): Id of the object of interest.

    # Returns
        dict: Number of the frames that contain at least one scribble.
    """
    frames_list = []
    scribbles = scribbles_data['scribbles']
    for ii, scribble_frame in enumerate(scribbles):
        for scribble in scribble_frame:
            if scribble['object_id'] == object_id:
                frames_list.append(ii)
                break
    return frames_list


@staticmethod
def _unmarshal_parts(pkg_reader, package, part_factory):
    """
        Return a dictionary of |Part| instances unmarshalled from
        *pkg_reader*, keyed by partname. Side-effect is that each part in
        *pkg_reader* is constructed using *part_factory*.
        """
    parts = {}
    for partname, content_type, reltype, blob in pkg_reader.iter_sparts():
        parts[partname] = part_factory(partname, content_type, reltype,
            blob, package)
    return parts


def _align32b(i):
    """Return int `i` aligned to the 32-bit boundary"""
    r = i % 4
    return i if not r else i + 4 - r


def solve_linear(a, b, c):
    """
    Solve a*x + b*y = c.
    Solution (x0 + b*n, y0 + a*n).
    Return None or (x0, y0).
    """
    return None


def byte2int(s, index=0):
    """Get the ASCII int value of a character in a string.

    :param s: a string
    :param index: the position of desired character

    :return: ASCII int value
    """
    return s[index]


def get_bool(val):
    """ given a string value of a boolean configuration option, return
    an actual bool (True or False) """
    truelist = ['1', 'yes', 'True', 'true', 'on']
    falselist = ['0', 'no', 'False', 'false', 'off']
    if val in truelist:
        return True
    elif val in falselist:
        return False
    else:
        raise ValueError('Not a boolean value', val)


@classmethod
def from_requirement(cls, requirement, file_path=None):
    """A requirement in this method's context is a
        pkg_resources.Requirement
        """
    return cls(requirement.project_name, file_path=file_path)


@classmethod
def register(cls, a_type, patcher):
    """Register a patcher for the given type"""
    cls.types[a_type] = patcher


def convertYaml2Json(fyml, fjson):
    """Converts the file from YAML to JSON.

   :param fyml: Name of YAML file
   :type fyml: string
   :param fjson: Name of JSON file
   :type fjson: string

   :Example:

   >>> from westpy import *
   >>> convertYaml2Json("file.yml","file.json")

   .. note:: The file fjon will be created, fyml will not be overwritten.
   """
    import yaml, json
    from westpy import writeJsonFile
    data = yaml.load(open(fyml))
    writeJsonFile(fjson, data)


def get_kwargs_defaults(argspec):
    """Computes a kwargs_defaults dictionary for use by get_args_tuple given an argspec."""
    arg_names = tuple(argspec.args)
    defaults = argspec.defaults or ()
    num_args = len(argspec.args) - len(defaults)
    kwargs_defaults = {}
    for i, default_value in enumerate(defaults):
        kwargs_defaults[arg_names[num_args + i]] = default_value
    if getattr(argspec, 'kwonlydefaults', None):
        kwargs_defaults.update(argspec.kwonlydefaults)
    return kwargs_defaults


@staticmethod
def _is_sympy(value):
    """Returns True if the object is a SymPy object."""
    if hasattr(value, '__module__'):
        if 'sympy' in value.__module__:
            return True
    return False


def solverDict2List(sDict):
    """Returns list of chosen solvers based on values in dict of bools."""
    sList = []
    for key, value in sDict.items():
        if value:
            sList.append(key)
    return sList


@classmethod
def update(cls, oid=None, **kwargs):
    """
            Add or edit depending on presence if 'id' field from oid or kwargs
        """
    oid = oid or kwargs.pop('id', None)
    if oid:
        return cls.edit(oid, **kwargs)
    return cls.add(**kwargs)


def __getFloat(s):
    """Take string 's,' remove any commas and return a float"""
    if s:
        return float(s.replace(',', ''))
    else:
        return None


def assign_friends(manager):
    """First, assign friends."""


@staticmethod
def _on_error_json(error):
    """
        Convert exception to JSON format to use with error handlers

        :param Exception error: Exception to parse
        :return: Dictionary with error type and message
        :rtype: dict
        """
    return {'error': {'type': error.__class__.__name__, 'message': str(error)}}


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

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


def _verify_np_symbol(op_name, func_name, sym):
    """Verify if the sym is a numpy symbol.

    Parameters
    ----------
    op_name : str
        Operator full name registered in backend.
    func_name : str
        Operator name exposed to users. This is usually the name by stripping off
        the prefix of the full operator names registered in backend.
    sym : symbol to be verified
    """
    from .numpy._symbol import _Symbol as np_symbol
    if not isinstance(sym, np_symbol):
        raise TypeError(
            'Operator `{}` registered in backend is known as `{}` in Python. This is a numpy operator which can only accept MXNet numpy ndarrays, while received a legacy ndarray. Please ensure that you have activated numpy semantics by calling `npx.set_np()` in your code. If you still see this error with numpy semantics activated, please call `as_np_ndarray()` upon the legacy ndarray to convert it to an MXNet numpy ndarray, and then feed the converted array to this operator.'
            .format(op_name, func_name))


@classmethod
def set_default_renderer(cls, renderer):
    """ Set the callable that will act as a default renderer for
        instances of the associated class when no ``renderer``
        argument is provided to the class' constructor.  Useful when
        you'd like to use an alternate templating system.

        Calling this method resets the :term:`default renderer`.
        """
    cls.default_renderer = staticmethod(renderer)


@classmethod
def strip_zeros(cls, string):
    """
        Strip leading zeros in any number longer than one digit found
        in a string.

        :param string: str
        :rtype: str

        :Example:

        >>> MatchBlock.strip_zeros('Agent 007')
        'Agent 7'
        """
    numbers = cls._re_digits.findall(string)
    for number in numbers:
        if number.startswith('0') and len(number) > 1:
            string = string.replace(number, number.lstrip('0'))
    return string


def default_field_resolver(source, info, **args):
    """Default field resolver.

    If a resolve function is not given, then a default resolve behavior is used which
    takes the property of the source object of the same name as the field and returns
    it as the result, or if it's a function, returns the result of calling that function
    while passing along args and context.

    For dictionaries, the field names are used as keys, for all other objects they are
    used as attribute names.
    """
    field_name = info.field_name
    value = source.get(field_name) if isinstance(source, dict) else getattr(
        source, field_name, None)
    if callable(value):
        return value(info, **args)
    return value


def arctanh(x):
    """The hyperbolic arctan or the arctanh"""
    raise NotImplementedError


def test_jpeg1(h, f):
    """JPEG data in JFIF format"""
    if b'JFIF' in h[:23]:
        return 'jpeg'


@classmethod
def init_from_wordlist(cls, wordlist):
    """
        Initializes the WordDictionary instance with a list of words,
        independently from their frequencies. Every word in the list gets an
        entry.
        """
    return cls(None, wordlist=wordlist)


def money_format(money):
    """Return the integer value of a monetary amount string.

    Remove euro currency sign from `money` and letters expressing the
    order of magnitude from the passed in string, e.g. "K" for thousands
    and "M" for milions. Cast the string into an integer. Returned values
    are expressed in thousands of euros.

    Parameters
    ----------
    money : str
        String containing monetary amount with a currency sign and
        order of magnitude abbreviation.

    Returns
    -------
    money : int
        Integer value of the monetary amount.

    Examples
    --------
    >>> v = money_format("€500K")
    >>> print(v)
    500

    >>> v = money_format("€70.5M")
    >>> print(v)
    70500
    """
    money = money.replace('€', '')
    if 'M' in money:
        money = money.replace('M', '')
        return int(float(money) * 1000)
    money = money.replace('K', '')
    return int(money)


def remove_resource(stack_definition, resource_name):
    """Remove the named resource from the stack definition.

    Remove the resource from the template and eliminate references to it.
    """
    stack_definition.t.remove_resource(resource_name)
    if stack_definition._resource_defns is not None:
        stack_definition._resource_defns.pop(resource_name, None)
    stack_definition._resource_data.pop(resource_name, None)
    stack_definition._resources.pop(resource_name, None)


def padLen4(aString):
    """
    Calculate how many additional bytes a given string needs to have a length
    of a multiple of 4. A zero-length array is considered a multiple of 4.
    """
    mod = divmod(len(aString), 4)[1]
    return 4 - mod if mod else 0


def filter_near_diagonal(df, distance=24000, drop=True):
    """
    Drops rows from df where its 'distance' column is less than k.

    Dropping occurs in-place.

    Parameters
    ----------
    df : pd.DataFrame
        Must have a 'distance' column.
    distance : int
        Threshold for distance (in bp).
    drop : bool
        Pass True to drop the filtered rows in-place. Pass False to return an
        index subset for the filtered rows instead.
    """
    index_subset = df[df['distance'] < distance].index
    if drop:
        df.drop(index_subset, inplace=True)
    else:
        return index_subset


def secant(f, a, b, n):
    """Approximate solution of f(x)=0 on interval [a,b] by the secant method.

    Parameters
    ----------
    f : function
        The function for which we are trying to approximate a solution f(x)=0.
    a,b : numbers
        The interval in which to search for a solution. The function returns
        None if f(a)*f(b) >= 0 since a solution is not guaranteed.
    n : (positive) integer
        The number of iterations to implement.

    Returns
    -------
    m_N : number
        The x intercept of the secant line on the the Nth interval
            m_n = a_n - f(a_n)*(b_n - a_n)/(f(b_n) - f(a_n))
        The initial interval [a_0,b_0] is given by [a,b]. If f(m_n) == 0
        for some intercept m_n then the function returns this solution.
        If all signs of values f(a_n), f(b_n) and f(m_n) are the same at any
        iterations, the secant method fails and return None.

    Examples
    --------
    >>> f = lambda x: x**2 - x - 1
    >>> secant(f,1,2,5)
    1.6180257510729614
    """
    if f(a) * f(b) >= 0:
        print('Secant method fails.')
        return None
    a_n = a
    b_n = b
    for n in range(1, n + 1):
        m_n = a_n - f(a_n) * (b_n - a_n) / (f(b_n) - f(a_n))
        f_m_n = f(m_n)
        if f(a_n) * f_m_n < 0:
            a_n = a_n
            b_n = m_n
        elif f(b_n) * f_m_n < 0:
            a_n = m_n
            b_n = b_n
        elif f_m_n == 0:
            return m_n
        else:
            return None
    return a_n - f(a_n) * (b_n - a_n) / (f(b_n) - f(a_n))


@classmethod
def allowed_to_disconnect(cls, user, backend_name, association_id=None):
    """Return if it's safe to disconnect the social account for the
        given user"""
    raise NotImplementedError('Implement in subclass')


def attach_tz_if_none(dt, tz):
    """
    Makes a naive timezone aware or returns it if it is already aware.

    Attaches the timezone tz to the datetime dt if dt has no tzinfo. If
    dt already has tzinfo set, return dt.

    :type dt: datetime
    :param dt: A naive or aware datetime object.

    :type tz: pytz timezone
    :param tz: The timezone to add to the datetime

    :rtype: datetime
    :returns: An aware datetime dt with tzinfo set to tz. If dt already had
        tzinfo set, dt is returned unchanged.
    """
    return tz.localize(dt) if dt.tzinfo is None else dt


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

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


def substiSentence(morphs, poses, substi, only):
    """명사와 동사를 찾아 기호로 변환하고, 명사,동사,조사,어미만 붙여 연결한다"""
    noun_list = []
    verb_list = []
    nouns = ''
    verbs = ''
    morph_idx = 0
    noun_idx = 0
    verb_idx = 0
    if substi:
        for pos in poses:
            if pos == 'NNG' or pos == 'NNP':
                noun_list.append(morphs[morph_idx])
                morphs[morph_idx] = 'NOUN' + str(noun_idx)
                noun_idx += 1
            elif pos == 'VV' or pos == 'VA' or pos == 'VX' or pos == 'XR':
                verb_list.append(morphs[morph_idx])
                morphs[morph_idx] = 'VERB' + str(verb_idx)
                verb_idx += 1
            morph_idx += 1
    new_data = ''
    if only:
        pos_idx = 0
        for morph in morphs:
            if poses[pos_idx] == 'NNG' or poses[pos_idx] == 'NNP' or poses[
                pos_idx] == 'VV' or poses[pos_idx] == 'VA' or poses[pos_idx
                ] == 'VX' or poses[pos_idx] == 'XR' or poses[pos_idx
                ].startswith('J') or poses[pos_idx].startswith('E'):
                new_data += ' ' + morph + ' '
            pos_idx += 1
    else:
        for morph in morphs:
            new_data += ' ' + morph + ' '
    for noun_each in noun_list:
        nouns += noun_each + ','
    for verb_each in verb_list:
        verbs += verb_each + ','
    return new_data, nouns, verbs


@classmethod
def bell(cls, n, **kwargs):
    """
        Return the output of :meth:`mvpoly.dict.MVPolyDict.bell`
        converted to other polynomial subclasess.
        """
    from mvpoly.dict import MVPolyDict
    return cls(MVPolyDict.bell(n, **kwargs), **kwargs)


@classmethod
def process(cls, *, context=None, parameter=None):
    """ Evaluate the SUB command. """
    lhs, rhs = context.stack.pop(), context.stack.pop()
    context.stack.append(lhs - rhs)


def remove_admin_access_permissions(apps, schema_editor):
    """Reverse the above additions of permissions."""
    ContentType = apps.get_model('contenttypes.ContentType')
    Permission = apps.get_model('auth.Permission')
    wagtailadmin_content_type = ContentType.objects.get(app_label=
        'wagtailadmin', model='admin')
    Permission.objects.filter(content_type=wagtailadmin_content_type,
        codename='access_admin').delete()


def apply_inds(data, inds):
    """Apply inds computed from speckle_inds

    This is just a shortcut to a 1 line piece
    of code:

    data.ravel()[indices] = filtered bla

    """
    data_flat = data.ravel()
    return data_flat[inds]


@staticmethod
def get_jenkins_plugin_name():
    """Gets the name of the Jenkins plugin associated with this PyJen plugin

        This static method is used by the PyJen plugin API to associate this
        class with a specific Jenkins plugin, as it is encoded in the config.xml

        :rtype: :class:`str`
        """
    return 'com.tikal.jenkins.plugins.multijob.MultiJobProject'


@classmethod
def derive_url_pattern(cls, crud_path: str, action: str):
    """Derive the url pattern."""
    return f'{cls.get_crud_path_pattern(crud_path, action)}/'


def extract_text_from_element(elem):
    """ As an element is valid and contains text, extract it and return """
    if elem and hasattr(elem, 'text') and elem.text:
        text = elem.text
    else:
        text = None
    return text


@classmethod
def name(cls):
    """
        Returns the name of the pass
        """
    return cls._name


def strip_nmea(frame):
    """
    Extracts NMEA header from T3-Micro or NMEA encoded KISS frames.
    """
    if len(frame) > 0:
        if frame[0] == 240:
            return frame[1:].rstrip()
    return frame


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


def hex_to_byte(hex_str):
    """
    Convert a string hex byte values into a byte string. The Hex Byte values may
    or may not be space separated.
    :param hex_str: hex string msg with UUID.
    :return: byte string msg with UUID.
    """
    bytes_str = []
    hex_str = ''.join(hex_str.split(' '))
    for i in range(0, len(hex_str), 2):
        bytes_str.append(chr(int(hex_str[i:i + 2], 16)))
    return ''.join(bytes_str)


def _has_extension(filename, extensions):
    """
    Checks if the given filename has one of the given extensions
    """
    for ext in extensions:
        if filename.endswith('.' + ext):
            return True
    return False


def wait_for_client_connections(num_clients=int):
    """Do not return until we have connections to at least NUM_CLIENTS
        storage servers.
        """


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

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

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


def end_period_contribution_component(amount, rate, years, periods):
    """
    Calculates the periodic contribution component of a financial application.

    The contribution is made at the end of each compouding period.

    Parameters
    ----------
    amount : float
        The contribution component amount, to be considered at the end of each compounding period.
    rate : float
        The annualized compouding interest rate.
    years : int
        The number of years of the application.
    periods : int
        The number of compounding periods per years.

    Returns
    -------
    out : float
        The value of the contribution components after the given years.
    """
    return amount * ((1 + rate / periods) ** (years * periods) - 1) / (rate /
        periods)


def broadcast_greater(lhs=None, rhs=None, name=None, attr=None, out=None,
    **kwargs):
    """Returns the result of element-wise **greater than** (>) comparison operation with broadcasting.

    Example::

       x = [[ 1.,  1.,  1.],
            [ 1.,  1.,  1.]]

       y = [[ 0.],
            [ 1.]]

       broadcast_greater(x, y) = [[ 1.,  1.,  1.],
                                  [ 0.,  0.,  0.]]

    Defined in src/operator/tensor/elemwise_binary_broadcast_op_logic.cc:L82

    Parameters
    ----------
    lhs : Symbol
        First input to the function
    rhs : Symbol
        Second input to the function

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

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


@staticmethod
def metadata_id(item):
    """Extracts the identifier from a Build item."""
    return str(item['url'])


def make_season(year):
    """
        :param year string of year (e.g. 2012, 2013)
        :return season valid string of season used by the API.             (e.g. 2015-16, 2012-13)
    """
    next_yr = str(year + 1)[-2:]
    return '{0}-{1}'.format(year, next_yr)


def centre_colormap_values(vmin, vmax):
    """Calculate vmin and vmax to set the colormap midpoint to zero.

    Parameters
    ----------
    vmin, vmax : scalar
        The range of data to display.

    Returns
    -------
    cvmin, cvmax : scalar
        The values to obtain a centre colormap.

    """
    absmax = max(abs(vmin), abs(vmax))
    return -absmax, absmax


def _call_bool_filter(context, value):
    """Pass a value through the 'bool' filter.

    :param context: Jinja2 Context object.
    :param value: Value to pass through bool filter.
    :returns: A boolean.
    """
    return context.environment.call_filter('bool', value, context=context)


@classmethod
def get_instance(cls):
    """Get the singleton instance of this manager."""
    if cls._instance is None:
        cls._instance = cls()
    return cls._instance


def pytest_report_collectionfinish(config, startdir, items):
    """
    .. versionadded:: 3.2

    return a string or list of strings to be displayed after collection has finished successfully.

    This strings will be displayed after the standard "collected X items" message.

    :param _pytest.config.Config config: pytest config object
    :param startdir: py.path object with the starting dir
    :param items: list of pytest items that are going to be executed; this list should not be modified.
    """


@classmethod
def get_count_by_uuids_and_user(cls, context, uuids, user_id):
    """Get the count of InstanceMapping objects by UUIDs and user_id.

        The count is used to represent the count of server group members
        belonging to a particular user, for the purpose of counting quota
        usage. Instances that are queued_for_deleted=True are not included in
        the count (deleted and SOFT_DELETED instances).

        :param uuids: List of instance UUIDs on which to filter
        :param user_id: The user_id on which to filter
        :returns: An integer for the count
        """
    return cls._get_count_by_uuids_and_user_in_db(context, uuids, user_id)


def bucket_policy_document(bucket):
    """Return the policy document to access an S3 bucket

    Parameters
    ----------
    bucket: string
        An Amazon S3 bucket name

    Returns
    -------
    s3_policy_doc: dict
        A dictionary containing the AWS policy document
    """
    s3_policy_doc = {'Version': '2012-10-17', 'Statement': [{'Effect':
        'Allow', 'Action': ['s3:ListBucket'], 'Resource': [
        'arn:aws:s3:::{0:s}'.format(bucket)]}, {'Effect': 'Allow', 'Action':
        ['s3:PutObject', 's3:GetObject'], 'Resource': [
        'arn:aws:s3:::{0:s}/*'.format(bucket)]}]}
    return s3_policy_doc


@classmethod
def restore_history(cls, ids, datetime):
    """Restore record ids from history at the date time"""
    cls._restore_history(ids, datetime)


def _guess_max_lengths(info):
    """Compute the maximum length for keys and lines."""
    max_key_len = 0
    max_line_len = 0
    for sec in info:
        for k in info[sec]:
            l_k = len(k)
            l_data = len(info[sec])
            line_len = l_k + 2 + l_data
            if line_len > 80:
                continue
            if line_len > max_line_len:
                max_line_len = line_len
            if l_k > max_key_len:
                max_key_len = l_k
    return max_key_len, max_line_len


def render():
    """Render link's HTML"""


def get_commit_url(repo_url):
    """Determine URL to view commits for repo."""
    if 'github.com' in repo_url:
        return repo_url[:-4] if repo_url.endswith('.git') else repo_url
    if 'git.openstack.org' in repo_url:
        uri = '/'.join(repo_url.split('/')[-2:])
        return 'https://github.com/{0}'.format(uri)
    return repo_url


@classmethod
def unpack_new(cls, raw, offset=0, buf_len=None, prev=None):
    """
    Unpacks a new instance of this class from a buffer

    returns (new_offset, object)
    """
    raise RuntimeError('Unimplemented on class %s' % (cls.__name__,))


@classmethod
def _check_param(cls, name=None, value=None, params=None, optional=True,
    max_length=None, type=None, gte=None, lte=None, sub_max_length=None,
    sub_type=None):
    """
        This checks the value for different type, max length, etc.  If all of the checks pass, then the value is placed
        in the params bucket
        :param name: The name of the parameter
        :param value: The value of param
        :param params: The dictionary where the param should go if all of the checks pass
        :param optional: True (default) if the value is optional
        :param max_length: The maximum length of the param
        :param type: The type of the param
        :param gte: Greater than or equal to this number
        :param lte: LEss than or equal to this number
        :param sub_max_length: The sub maximum length (for iterables)
        :param sub_type: The sub type (for iterables)
        :return: Nothing
        """
    assert params is None or isinstance(params, dict)
    if value is None:
        if not optional:
            assert value is not None
    else:
        if type is not None:
            assert isinstance(value, type)
        if max_length is not None:
            assert len(value) <= max_length
        if isinstance(value, list):
            for sub_value in value:
                if sub_type is not None:
                    assert isinstance(sub_value, sub_type)
                if sub_max_length is not None:
                    assert len(sub_value) <= sub_max_length
        if isinstance(value, dict):
            for key in value:
                sub_value = value[key]
                if sub_type is not None:
                    assert isinstance(sub_value, sub_type)
                if sub_max_length is not None:
                    assert len(sub_value) <= sub_max_length
        if isinstance(value, int):
            if gte is not None:
                assert value >= gte
            if lte is not None:
                assert value <= lte
        if name is not None and params is not None:
            params[name] = value


def remap(listoflists, criterion):
    """
Remaps values in a given column of a 2D list (listoflists).  This requires
a criterion as a function of 'x' so that the result of the following is
returned ... map(lambda x: 'criterion',listoflists).

Usage:   remap(listoflists,criterion)    criterion=string
Returns: remapped version of listoflists
"""
    function = 'map(lambda x: ' + criterion + ',listoflists)'
    lines = eval(function)
    return lines


def update_animation_flags():
    """Update animation flags

    """
    pass


def draw_countries(basemap, linewidth=1, style='dashed'):
    """
    Draw the country borders using the given basemap.

    Parameters:

    * basemap : mpl_toolkits.basemap.Basemap
        The basemap used for plotting (see :func:`~fatiando.vis.mpl.basemap`)
    * linewidth : float
        The width of the lines
    * style : str
        The style of the lines. Can be: 'solid', 'dashed', 'dashdot' or
        'dotted'

    """
    lines = basemap.drawcountries(linewidth=linewidth)
    lines.set_linestyles(style)


def is_galaxy_engine(**kwds):
    """Return True iff the engine configured is :class:`GalaxyEngine`."""
    engine_type_str = kwds.get('engine', 'galaxy')
    return engine_type_str in ['galaxy', 'docker_galaxy', 'external_galaxy']


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 readFastq(file):
    """
    Read textual input from the file object `file`, which is assumed
    to be in line-oriented FASTQ format (not full multi-line FASTQ).
    Yields the sequence of (name, sequence, label, quality) tuples.
    """
    grp = []
    for l in file:
        l = l.strip()
        grp.append(l)
        if len(grp) == 4:
            yield tuple(grp)
            grp = []
    if grp == 4:
        yield tuple(grp)


@staticmethod
def __vertex_json_id(vertex):
    """ A proxy property based access to vertices in current edge

        When edge is serialized to JSON object, no explicit object for its vertices are created, but rather they are referenced
        by special vertex json_ids.
        """
    if hasattr(vertex, 'json_id'):
        return vertex.json_id
    return hash(vertex)


def scroll_page_up(event):
    """
    Scroll page up. (Prefer the cursor at the bottom of the page, after scrolling.)
    """
    w = event.app.layout.current_window
    b = event.app.current_buffer
    if w and w.render_info:
        line_index = max(0, min(w.render_info.first_visible_line(), b.
            document.cursor_position_row - 1))
        b.cursor_position = b.document.translate_row_col_to_index(line_index, 0
            )
        b.cursor_position += b.document.get_start_of_line_position(
            after_whitespace=True)
        w.vertical_scroll = 0


def get_stack(topology, node, data=True):
    """Return the stack of a node, if any

    Parameters
    ----------
    topology : Topology
        The topology
    node : any hashable type
        The ID of the node
    data : bool, optional
        If true, returns a tuple of the stack name and its attributes,
        otherwise just the stack name

    Returns
    -------
    stack : tuple (name, properties) or name only
        If data = True, a tuple of two values, where the first value is the
        name of the stack and the second value is the dictionary of its
        properties.
        If data = False returns only the stack name
        If no stack is deployed, return None
    """
    if 'stack' not in topology.node[node]:
        return None
    name, props = topology.node[node]['stack']
    return (name, props) if data else name


def list_replace(subject_list, replacement, string):
    """
    To replace a list of items by a single replacement
    :param subject_list: list
    :param replacement: string
    :param string: string
    :return: string
    """
    for s in subject_list:
        string = string.replace(s, replacement)
    return string


def value2str(value):
    """
    format a parameter value to string to be inserted into a workflow

    Parameters
    ----------
    value: bool, int, float, list

    Returns
    -------
    str
        the string representation of the value
    """
    if isinstance(value, bool):
        strval = str(value).lower()
    elif isinstance(value, list):
        strval = ','.join(map(str, value))
    elif value is None:
        strval = value
    else:
        strval = str(value)
    return strval


@classmethod
def set_standard_vars(cls, executor, context, variant, build_type, install,
    build_path, install_path=None):
    """Sets a standard set of environment variables for the build system to
        use
        """
    vars = cls.get_standard_vars(context=context, variant=variant,
        build_type=build_type, install=install, build_path=build_path,
        install_path=install_path)
    for var, value in vars.items():
        executor.env[var] = value


def complete_count(async_results):
    """
    TODO: Would it be better to rely on the job registry instead of job.result?

    --- Example:
    from rq import job
    from rq.registry import FinishedJobRegistry
    registry = FinishedJobRegistry('default', connection=redis_conn)
    job_ids = registry.get_job_ids()
    job_obj = job.Job.fetch("job-id-here", connection=redis_conn)

    """
    count = 0
    for job in async_results:
        if job.result is not None:
            count += 1
    return count


def tup_to_vs(tup):
    """tuple to version string"""
    return '.'.join(tup)


@classmethod
def get_schema(cls):
    """Defines a Schema that the input parameters shall comply to

        :return: A jsonschema format (mandatory default setting)
        :rtype: dict
        """
    return {}


def is_script(path):
    """
    Check if a given file starts with the magic sequence '#!'.
    """
    with open(path, 'rb') as f:
        return f.read(2) == b'#!'


def _match_sort_key(m):
    """sort key which treats empty timestamp as most recent"""
    return m['timestamp'] is None, m['timestamp'] or ''


@staticmethod
def to_embedded(res_id=None, name=None, system=None):
    """
        Constructs an embeded object of `UnityResourceInfo`.

        :param res_id: identifier of the resource.
        :param name: name of the resource.
        :param system: system on which the resource exists.
        :return:
        """
    return {'resId': res_id, 'name': name, 'system': system}


def num_to_str(num):
    """
    Convert an int or float to a nice string.
    E.g.,
        21 -> '21'
        2.500 -> '2.5'
        3. -> '3'
    """
    return '{0:0.02f}'.format(num).rstrip('0').rstrip('.')


@staticmethod
def get_file_content(file_name):
    """
        Open a file in binary mode and close it afterwards.
        :param str file_name:
        :return: file content
        """
    with open(file_name, 'rb') as f:
        fc = f.read()
    return fc


def get_qual_name(func: object) ->str:
    """Reverse resolve full dotted name of a Python function.

    Courtesy of http://stackoverflow.com/a/13653312/315168
    """
    return func.__module__ + '.' + func.__name__


def make_command_summary_string(command_summaries):
    """Construct subcommand summaries

    :param command_summaries: Commands and their summaries
    :type command_summaries: list of (str, str)
    :returns: The subcommand summaries
    :rtype: str
    """
    doc = ''
    for command, summary in command_summaries:
        doc += '\n\t{:15}\t{}'.format(command, summary.strip())
    return doc


def get_developer(repo_info):
    """Get trending developer name"""
    try:
        developer = ' '.join(repo_info.find('h2').find('a').text.split())
        return developer
    except AttributeError:
        return


def open_and_call(callback):
    """Call a function with an open connection and cursor.

        If the function returns, commits the transaction and returns the
        result returned by the function.
        If the function raises an exception, aborts the transaction
        then propagates the exception.
        """


def _serial_nash_func(game, spec):
    """Serializable function for nash finding"""
    func, mix, req = spec
    return req, func(game, mix)


def hex2dec(string_num):
    """
    Convert HEX to DEC.
    """
    return str(int(string_num.upper(), 16))


@classmethod
def from_config(cls, config, name, section_key='metrics_collectors'):
    """
        metrics_collectors:
        local_logging:
        class: ores.metrics_collectors.Logging
        """
    return cls()


def sync_bytes():
    """
    Sync Bytes for start of Oric tape header
    """
    return bytearray(b'\x16\x16\x16\x16$')


@staticmethod
def determine_selected(available, selected, schemas):
    """Determine selected schema from available schemas."""
    for schema_a, schema_b in schemas.items():
        available.append(schema_a)
        if schema_b:
            selected = schema_a
    return available, selected


def DebugOnAll():
    """Turn on debugging for all modules
    No arguments
    Returns: void
    Throws:  nothing

    Turns on debugging flag for all modules
    """
    global _modulesToDebug, _debugAllModules
    _debugAllModules = 1


@classmethod
def _get_mvar(cls, df, column, windows):
    """ get moving variance

        :param df: data
        :param column: column to calculate
        :param windows: collection of window of moving variance
        :return: None
        """
    window = cls.get_only_one_positive_int(windows)
    column_name = '{}_{}_mvar'.format(column, window)
    df[column_name] = df[column].rolling(min_periods=1, window=window,
        center=False).var()


@classmethod
def get_by_user(cls, user_id, desc=True, offset=0, limit=10, session=None):
    """Get the related object of a user.

        :param string/int user_id: The ID (if int) or UUID (if string) of the
            user.
        :param bool desc: Whether to sort DESC. Default is ``True``.
        :param integer offset: The offset of the objects. If limit is 10 and
            offset is 5, the function will attempt to get the 6th to 15th
            most recent objects.
        :param integer limit: The max number of objects to get.
        :param Session session: The optional SQL session.
        :returns list<UserRelationMixin>: The list of objects matching the
            requirement.
        """
    column = 'user_id' if isinstance(user_id, int) else 'user_uuid'
    return cls.get_multi(column, user_id, cls.sort_key, desc=desc, offset=
        offset, limit=limit, session=session)


def stringLine(line, length):
    """simple case: line with just strings and spacings which can be ignored"""
    strings = []
    for x in line:
        if isinstance(x, str):
            strings.append(x)
    text = ' '.join(strings)
    result = [text, float(length)]
    nextlinemark = 'nextLine', 0
    if line and line[-1] == nextlinemark:
        result.append(nextlinemark)
    return result