@classmethod
def _dasd_conversion(cls, val, **kwargs):
    """
        converts 0/1/2 for dasd reg key
        """
    if val is not None:
        if val == '0' or val == 0 or val == '':
            return 'Administrators'
        elif val == '1' or val == 1:
            return 'Administrators and Power Users'
        elif val == '2' or val == 2:
            return 'Administrators and Interactive Users'
        else:
            return 'Not Defined'
    else:
        return 'Not Defined'


def _gutter(idx, offset, max_val):
    """
    When deleting rows and columns are deleted we rely on overwriting.
    This may not be the case for a large offset on small set of cells:
    range(cells_to_delete) > range(cell_to_be_moved)
    """
    gutter = range(max(max_val + 1 - offset, idx), min(idx + offset,
        max_val) + 1)
    return gutter


def fpGT(a, b):
    """
    Checks if floating point `a` is greater than floating point `b`.
    """
    return a > b


def readcomments(filename, comment='#'):
    """
    Reads in filename and extracts only data that contains the comments
    parameter.

    Reference
    ---------
    https://stackoverflow.com/a/39724905/8765762
    """
    comments_all = []
    with open(filename, 'r') as cmt_file:
        for line in cmt_file:
            if line[0] == comment:
                comments_all.append(line[1:])
    return comments_all


@staticmethod
def _showsetns(val):
    """Get list of settings to show or hide"""
    hatchsetns = ('linewidth', 'linestyle', 'patternspacing', 'backcolor',
        'backtransparency', 'backhide')
    if val == 'solid' or val.find('dense') >= 0:
        return (), hatchsetns
    else:
        return hatchsetns, ()


def runner_from_runnable(runnable, known_runners):
    """
    Gets a Runner instance from a Runnable
    """
    runner = known_runners.get(runnable.kind, None)
    if runner is not None:
        return runner(runnable)
    raise ValueError('Unsupported kind of runnable: %s' % runnable.kind)


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 shift_ip(x, d=1):
    """
    Optimized inplace shift
    """
    assert x.flags.contiguous, 'x must be contiguous'
    if d >= 0:
        x[:d - 1:-1] = x[-d - 1::-1]
    else:
        x[d - 1::-1] = x[:-d - 1:-1]
    return x


def getsong():
    """
    @api {post} /music/collect/getsong 获取收藏的单曲
    @apiVersion 1.0.0
    @apiGroup Collect
    @apiDescription 获取收藏的单曲

    @apiParam (Headers) {string} token 令牌
    @apiParam (Headers) {String} device_token 设备令牌
    @apiParam (Headers) {String} content_type 内容类型
    @apiParam (Headers) {String} timestamp 时间戳

    @apiSuccess (Success) {Object} itemid 单曲编号
    @apiSuccess (Success) {Object} translatename 翻译名称

    @apiSuccessExample {json} Success-Response:
    [
        {
            "itemid": 8955124,
            "translatename": "原上草 (《楚乔传》电视剧楚乔人物曲)"
        }
    ]

    """


def beforeDaemonize():
    """
        Hook to be called immediately before daemonization. No reactor methods
        may be called until L{afterDaemonize} is called.

        @return: L{None}.
        """


def takeTime(elem):
    """
    function: 提取time字段
    :param elem:
    :return:
    """
    return elem['time']


def eyedropper_id():
    """Sample a data-block from the 3D View to store in a property

    """
    pass


def update_parser(parser, optlist=None, arglist=None):
    """Add given options and arguments to parser.
    """
    for shortopt, longopt, kwargs in optlist:
        parser.add_argument(shortopt, longopt, **kwargs)
    for argname, kwargs in arglist:
        parser.add_argument(argname, **kwargs)


def loop_multi_select(ring: bool=False):
    """Select a loop of connected edges by connection type

    :param ring: Ring
    :type ring: bool
    """
    pass


def get_features(api: str='gl', profile: str='core', version: str='3.3',
    extensions=None):
    """Generate a subset of the registry"""
    raise NotImplementedError()


def _file_iter_range(fp, offset, bytes, maxread=1024 * 1024):
    """ Yield chunks from a range in a file. No chunk is bigger than maxread."""
    fp.seek(offset)
    while bytes > 0:
        part = fp.read(min(bytes, maxread))
        if not part:
            break
        bytes -= len(part)
        yield part


def histogram(values, mode=0, bin_function=None):
    """Return a list of (value, count) pairs, summarizing the input values.
    Sorted by increasing value, or if mode=1, by decreasing count.
    If bin_function is given, map it over values first."""
    if bin_function:
        values = map(bin_function, values)
    bins = {}
    for val in values:
        bins[val] = bins.get(val, 0) + 1
    if mode:
        return sorted(list(bins.items()), key=lambda x: (x[1], x[0]),
            reverse=True)
    return sorted(bins.items())


def get_block_extension(rawdata=None, **kwargs):
    """Returns the label of the upcoming extension."""
    try:
        data = rawdata.peek(2)
        if len(data) < 2:
            return
        return int.from_bytes(data[1:2], byteorder='little')
    except AttributeError:
        pass


def unescape(string, chars=''):
    """Remove backslash in front of any character in `string` that is in `chars`"""
    if '\\' in string:
        for c in chars:
            string = string.replace('\\' + c, c)
    return string


def primes(imax):
    """
    Returns prime numbers up to imax.

    Parameters
    ----------
    imax: int
        The number of primes to return. This should be less or equal to 10000.

    Returns
    -------
    result: list
        The list of prime numbers.
    """
    p = list(range(10000))
    result = []
    k = 0
    n = 2
    if imax > 10000:
        raise ValueError('imax should be <= 10000')
    while len(result) < imax:
        i = 0
        while i < k and n % p[i] != 0:
            i = i + 1
        if i == k:
            p[k] = n
            k = k + 1
            result.append(n)
            if k > 10000:
                break
        n = n + 1
    return result


def get_current_version(config):
    """Return the current version of the config.

    :return: current config version or 0 if not defined
    """
    return config.get('CONFIG_VERSION', {}).get('CURRENT', 0)


def mapfivo(ol, *args, **kwargs):
    """
        #mapfivo          f,i,v,o四元决定                     fivo-4-tuple-engine
        #map_func         diff_func(index,value,*diff_args)
    """
    args = list(args)
    lngth = args.__len__()
    if lngth == 0:
        diff_funcs_arr = kwargs['map_funcs']
        diff_args_arr = kwargs['map_func_args_array']
    elif lngth == 1:
        if 'map_func_args_array' in kwargs:
            diff_funcs_arr = args[0]
            diff_args_arr = kwargs['map_func_args_array']
        else:
            diff_funcs_arr = kwargs['map_funcs']
            diff_args_arr = args[0]
    else:
        diff_funcs_arr = args[0]
        diff_args_arr = args[1]
    lngth = ol.__len__()
    rslt = []
    for i in range(0, lngth):
        index = i
        value = ol[i]
        func = diff_funcs_arr[i]
        args = diff_args_arr[i]
        ele = func(index, value, *args)
        rslt.append(ele)
    return rslt


def Contributors():
    """ Deprecated alias for 'listContributors'.

        o 'initial caps' names are reserved for strings.
        """


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 dump_classifier_loop(extractor):
    """
    Ask the user if he wants to save the classifier, and in that case where.
    If the file already exists keeps asking until it gets an answer
    """
    while True:
        answer = input(
            '\nDo you want to save the classifier generated? (y/n): ')
        if answer not in ['y', 'n', 'yes', 'no']:
            print('Invalid answer\n')
        else:
            break
    if answer in ['y', 'yes']:
        while True:
            output_filepath = input('\nChoose the filename of the output: ')
            try:
                extractor.save(output_filepath)
                break
            except ValueError:
                print('Error: file already exists, try another one.\n')
            except FileNotFoundError:
                print("Error: couldn't open the file, try another one.\n")


def _try_resize_dim_0_inplace(array, new_shape_0):
    """Try to resize 0-axis of array in-place or return a view otherwise."""
    if new_shape_0 >= array.shape[0]:
        return array
    try:
        array.resize((new_shape_0,) + array.shape[1:])
        return array
    except ValueError:
        return array[:new_shape_0]


def mmseqs_phamerate_command(parameters, wd):
    """
    Builds MMseqs2 phameration command (base command + user args)
    :param parameters: dictionary of MMseqs2 parameters
    :param wd: the temporary working directory for phameration
    :return: command
    """
    command = f'mmseqs cluster {wd}/sequenceDB {wd}/clusterDB {wd}'
    for parameter in parameters.keys():
        command += f' {parameter} {parameters[parameter]}'
    return command


def iterable(x):
    """Tell whether an object is iterable or not."""
    try:
        iter(x)
    except TypeError:
        return False
    else:
        return True


def chunk_bounds(nsamples, chunk_size, overlap=0):
    """Returns chunks of the form:
    [ overlap/2 | chunk_size-overlap | overlap/2 ]
    s_start   keep_start           keep_end     s_end
    Except for the first and last chunks which do not have a left/right overlap

    """
    s_start = 0
    s_end = chunk_size
    keep_start = s_start
    keep_end = s_end - overlap // 2
    yield s_start, s_end, keep_start, keep_end
    while s_end - overlap + chunk_size < nsamples:
        s_start = s_end - overlap
        s_end = s_start + chunk_size
        keep_start = keep_end
        keep_end = s_end - overlap // 2
        if s_start < s_end:
            yield s_start, s_end, keep_start, keep_end
    s_start = s_end - overlap
    s_end = nsamples
    keep_start = keep_end
    keep_end = s_end
    if s_start < s_end:
        yield s_start, s_end, keep_start, keep_end


def _is_permission(possible_permissions):
    """Is ``possible_permissions`` a permission?"""
    return isinstance(possible_permissions, int)


def findValueTokens(resultName, query=None, maxDepth=None, filter=None,
    targetQuery=None, targetFilter=None, transitiveQueriesFactory=None):
    """find token results for searchTerms.
        - resultName is the index name wanted for results.
        - if query is None (or evaluates to boolean False), returns the
          underlying btree data structure; which is an iterable result but
          can also be used with BTree operations
        Otherwise, same arguments as findRelationshipChains.
        """


def strip_quotes(string):
    """
    Strips embedded starting and ending quotes, if any.
    Starting and ending quote characters have to be the same.
    """
    if string[0] == string[-1] and string[0] in ('"', "'"):
        return string[1:-1]
    return string


@classmethod
def from_dict(cls, config):
    """Return a Module from the config dictionary"""
    return cls(**config)


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


def convert_kwargs_to_query_params_for_get_request(request_url, kwargs_dict):
    """
    Function to take in a set of kwargs and convert them to query parameters and append them to the request url
    :param request_url:
    :param kwargs_dict:
    :return:
    """
    separator = '?'
    for key in kwargs_dict:
        request_url += '{}{}={}'.format(separator, key, kwargs_dict[key])
        if separator == '?':
            separator = '&'
    return request_url


def fmt(docstr):
    """Format a docstring for use as documentation in sample config."""
    docstr = docstr.replace('\n', ' ')
    docstr = docstr.strip()
    return docstr


def channels_click(extend: bool=False):
    """Handle clicks to select NLA channels

    :param extend: Extend Select
    :type extend: bool
    """
    pass


def normalizeCode(codestring):
    """
    Function to normalize the given code.

    @param codestring code to be normalized
    @type str
    @return normalized code
    @rtype str
    """
    codestring = codestring.replace('\r\n', '\n').replace('\r', '\n')
    if codestring and codestring[-1] != '\n':
        codestring = codestring + '\n'
    return codestring


def words(fpth):
    """
    ww = words(os.path.join(app_root, 'ig/helper.py'))
    for k, v in (ww.most_common(3)):
        print(k, v)

    :param fpth:
    :type fpth:
    :return:
    :rtype:
    """
    from collections import Counter
    words__ = Counter()
    with open(fpth) as fp:
        for line in fp:
            words__.update(line.strip().split(' '))
    return words__


@staticmethod
def _prepare_configs(configs, requires_filters, temporal_timeouts):
    """
        Overrides the filters specified in the decorator with the given ones

        :param configs: Field → (Requirement, key, allow_none) dictionary
        :param requires_filters: Content of the 'requires.filter' component
                                 property (field → string)
        :param temporal_timeouts: Content of the 'temporal.timeouts' component
                                  property (field → float)
        :return: The new configuration dictionary
        """
    if not isinstance(requires_filters, dict):
        requires_filters = {}
    if not isinstance(temporal_timeouts, dict):
        temporal_timeouts = {}
    if not requires_filters and not temporal_timeouts:
        return configs
    new_configs = {}
    for field, config in configs.items():
        requirement, timeout = config
        explicit_filter = requires_filters.get(field)
        explicit_timeout = temporal_timeouts.get(field)
        try:
            explicit_timeout = int(explicit_timeout)
            if explicit_timeout <= 0:
                explicit_timeout = timeout
        except (ValueError, TypeError):
            explicit_timeout = timeout
        if not explicit_filter and not explicit_timeout:
            new_configs[field] = config
        else:
            try:
                requirement_copy = requirement.copy()
                if explicit_filter:
                    requirement_copy.set_filter(explicit_filter)
                new_configs[field] = requirement_copy, explicit_timeout
            except (TypeError, ValueError):
                new_configs[field] = config
    return new_configs


def fixSlices(slices):
    """A convenience function used by :meth:`selectByValue`,
    :meth:`clearSelection` and :meth:`getIndices`, to sanitise their
    ``restrict`` parameter.
    """
    if slices is None:
        slices = [None, None, None]
    if len(slices) != 3:
        raise ValueError('Three slice objects are required')
    for i, s in enumerate(slices):
        if s is None:
            slices[i] = slice(None)
    return tuple(slices)


def get_voxet_from_cube(dict_vxyz, dict_vidx):
    """
    -i- dict_vxyz : dict, cube xyz
    -i- dict_vidx : dict, cube line numbers
    -o- dictVoxet : dict, ready for write to .vo file
    """
    dictVoxet = {'AXIS_UNIT': ('ft', 'ft', 'ft'), 'AXIS_MIN': (0, 0, 0),
        'AXIS_MAX': (1, 1, 1), 'AXIS_NAME': ('depth', 'XLINE_NO', 'ILINE_NO')}
    ox = dict_vxyz['AXIS_ORX']
    oy = dict_vxyz['AXIS_ORY']
    oz = dict_vidx['DP_FRST']
    dictVoxet['AXIS_O'] = ox, oy, oz
    ux = uy = 0
    uz = dict_vidx['DP_LAST']
    dictVoxet['AXIS_U'] = ux, uy, uz
    vx = dict_vxyz['AXIS_XLX'] - ox
    vy = dict_vxyz['AXIS_XLY'] - oy
    vz = 0
    dictVoxet['AXIS_V'] = vx, vy, vz
    wx = dict_vxyz['AXIS_ILX'] - ox
    wy = dict_vxyz['AXIS_ILY'] - oy
    wz = 0
    dictVoxet['AXIS_W'] = wx, wy, wz
    NDP = dict_vidx['DP_AMNT']
    NXL = dict_vidx['XL_AMNT']
    NIL = dict_vidx['IL_AMNT']
    dictVoxet['AXIS_N'] = NDP, NXL, NIL
    dpno1 = dict_vidx['DP_FRST']
    xlno1 = dict_vidx['XL_FRST']
    ilno1 = dict_vidx['IL_FRST']
    dictVoxet['AXIS_LABEL_MIN'] = dpno1, xlno1, ilno1
    dpno2 = dict_vidx['DP_LAST']
    xlno2 = dict_vidx['XL_LAST']
    ilno2 = dict_vidx['IL_LAST']
    dictVoxet['AXIS_LABEL_MAX'] = dpno2, xlno2, ilno2
    return dictVoxet


def is_Tuple_ellipsis(tpl):
    """Python version independent function to check if a typing.Tuple object
    contains an ellipsis."""
    try:
        return tpl.__tuple_use_ellipsis__
    except AttributeError:
        try:
            if tpl.__args__ is None:
                return False
            if tpl.__args__[-1] is Ellipsis:
                return True
        except AttributeError:
            pass
        return False


def view_center_pick():
    """Center the view to the Z-depth position under the mouse cursor

    """
    pass


def implementedBy(class_):
    """Test whether the interface is implemented by instances of the class

        Return true of the class asserts that its instances implement the
        interface, including asserting that they implement an extended
        interface.
        """


def whitespace_tokenize(text):
    """Runs basic whitespace cleaning and splitting on a piece of text."""
    text = text.strip()
    if not text:
        return []
    tokens = text.split()
    return tokens


def identity(x):
    """
    Helper function which returns its argument unchanged.
    That is, `identity(x)` returns `x` for any input `x`.
    """
    return x


@staticmethod
def get_vector_from_axis(axis_index):
    """
        Returns vector from the given axis type
        :param axis_index: int
        :return: list<int, int, int>
        """
    vectors = [[1, 0, 0], [0, 1, 0], [0, 0, 1], [-1, 0, 0], [0, -1, 0], [0,
        0, -1], [0, 0, 0]]
    return vectors[axis_index]


def default_unmarshaller(instance, state):
    """
    Restore the state of an object.

    If the ``__setstate__()`` method exists on the instance, it is called with the state object
    as the argument. Otherwise, the instance's ``__dict__`` is replaced with ``state``.

    :param instance: an uninitialized instance
    :param state: the state object, as returned by :func:`default_marshaller`

    """
    if hasattr(instance, '__setstate__'):
        instance.__setstate__(state)
    else:
        try:
            instance.__dict__.update(state)
        except AttributeError:
            raise TypeError(
                '{!r} has no __dict__ attribute and does not implement __setstate__()'
                .format(instance.__class__.__name__))


def current_account_overview(client):
    """
    client: the client created from the user_login() function.
            returns dict (json) of the current user's account overview.
    """
    response = client.get('http://www.reddit.com/api/me.json')
    acc_info = response.json()['data']
    if not acc_info:
        raise Exception('No data found, Please user user_login() to log in')
    return acc_info


def get_document(Name=None, DocumentVersion=None):
    """
    Gets the contents of the specified SSM document.
    See also: AWS API Documentation

    :example: response = client.get_document(
        Name='string',
        DocumentVersion='string'
    )

    :type Name: string
    :param Name: [REQUIRED]
            The name of the SSM document.

    :type DocumentVersion: string
    :param DocumentVersion: The document version for which you want information.

    :rtype: dict
    :return: {
        'Name': 'string',
        'DocumentVersion': 'string',
        'Content': 'string',
        'DocumentType': 'Command'|'Policy'|'Automation'
    }

    """
    pass


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

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

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


def parse_patterns(patterns_spec, ignore_patterns_spec, separator=';'):
    """
    Parses pattern argument specs and returns a two-tuple of
    (patterns, ignore_patterns).
    """
    patterns = patterns_spec.split(separator)
    ignore_patterns = ignore_patterns_spec.split(separator)
    if ignore_patterns == ['']:
        ignore_patterns = []
    return patterns, ignore_patterns


@staticmethod
def destroy_all_models_in_dict(target_dict):
    """ Method runs the prepare destruction method of models
            which are assumed in list or tuple as values within a dict
        """
    if target_dict:
        for model_list in target_dict.values():
            if isinstance(model_list, (list, tuple)):
                for model in model_list:
                    model.prepare_destruction()
                    if model._parent:
                        model._parent = None
            else:
                raise Exception('wrong data in clipboard')


def parseNamespace(uri):
    """
    Utility function for parsing the namespace from an RDF type -- note, this
    will work on some SBOL object URIs, but not universally.  It is primarily
    for use with RDF types.
    """
    rlimit = uri.rfind('#') + 1
    if rlimit:
        return uri[:rlimit]
    rlimit = uri.rfind('/') + 1
    if rlimit:
        return uri[:rlimit]
    return ''


@staticmethod
def to_halotools(cosmo, redshift, mdef, concentration_key=None, **kwargs):
    """
        Return a {func_name} HOD model in the format of :mod:`halotools`.

        See :func:`halotools.empirical_models.{name}_model_dictionary`.

        Parameters
        ----------
        cosmo :
            the nbodykit or astropy Cosmology object to use in the model
        redshift : float
            the desired redshift of the model
        mdef : str, optional
            string specifying mass definition, used for computing default
            halo radii and concentration; should be 'vir' or 'XXXc' or
            'XXXm' where 'XXX' is an int specifying the overdensity
        concentration_key : str
            the name of the column that will specify concentration; if not
            provided, the analytic formula from
            `Dutton and Maccio 2014 <https://arxiv.org/abs/1402.7073>`_
            is used.
        **kwargs :
            additional keywords passed to the model components; see the
            Halotools documentation for further details

        Returns
        -------
        :class:`~halotools.empirical_models.HodModelFactory`
            the halotools object implementing the HOD model
        """
    raise NotImplementedError


def get_encode(base_swf):
    """
    4バイト目の Flash のバージョンを読み取り判定
    Flash ver.6 以降は、UTF-8
    See https://secure.m2osw.com/swf_tag_file_header
    4バイト目が必要なだけので、base_swf は header でも swf 本体でも良い
    """
    if base_swf[3] < '\x06':
        return 'cp932'
    else:
        return 'utf-8'


@staticmethod
def process_result_package(package):
    """Process result package.
        :return: MultiprocessingSpider.packages.ResultPackage or its subclass or None.
        """
    return package


def getprotocaps():
    """Returns the list of protocol-level capabilities of client

        Returns a list of capabilities as declared by the client for
        the current request (or connection for stateful protocol handlers)."""


def filter_output(output, filtered):
    """ Filters out characters from output """
    for char in filtered:
        output = output.replace(char, '')
    return output


def select_more():
    """Select keyframes beside already selected ones

    """
    pass


def _make_extension_entry(name, description, url, enabled, core,
    latest_version, installed_version, status, installed=None):
    """Create an extension entry that can be sent to the client"""
    ret = dict(name=name, description=description, url=url, enabled=enabled,
        core=core, latest_version=latest_version, installed_version=
        installed_version, status=status)
    if installed is not None:
        ret['installed'] = installed
    return ret


def apply_scale():
    """Apply scaling of selected strips to their referenced Actions

    """
    pass


def __str__():
    """Convert a DateTime to a string."""


def solar_geometric_mean_longitude(julian_century):
    """Returns the Solar Geometric Mean with Julian Century, julian_century."""
    solar_geometric_mean_longitude = (280.46646 + julian_century * (
        36000.76983 + julian_century * 0.0003032)) % 360
    return solar_geometric_mean_longitude


def retransmit_timeout(group_state: 'GroupState'):
    """
    retransmit timer associated with group GroupState object has expired
    """
    group_state.group_state_logger.debug(
        'NonQuerier CheckingMembership: retransmit_timeout')
    return


def clamp(val, minVal, maxVal):
    """
    Clamp a value between minVal and maxVal

    :param val: Incoming value
    :param minVal: bottom of range
    :param maxVal: top of range
    :return: clamped value
    """
    return max(minVal, min(val, maxVal))


def node_topic(node):
    """
    Inverse of topic_node
    @return str: undo topic_node() operation
    """
    return node[1:]


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


def _any_array_len(any_array):
    """Return the length of an any_array."""
    array_type = any_array.WhichOneof('type')
    the_array = getattr(any_array, array_type).data
    return len(the_array)


@staticmethod
def do_quit(line):
    """
        A way to quit the application. Try entering just 'q' followed by enter. As long as it can be
        unambiguously matched, it will autocomplete to quit end exit the example.
        :param line:
        """
    exit(0)


def render_image(**kwargs):
    """
    Unstrict template block for rendering an image:
    <img alt="{alt_text}" title="{title}" src="{url}">
    """
    html = ''
    url = kwargs.get('url', None)
    if url:
        html = '<img'
        alt_text = kwargs.get('alt_text', None)
        if alt_text:
            html += ' alt="{}"'.format(alt_text)
        title = kwargs.get('title', None)
        if title:
            html += ' title="{}"'.format(title)
        html += ' src="{}">'.format(url)
    return html


def get_models_by_app(app_name):
    """
    Returns model module after import of the app_name

    """
    return None


def remove_articles(text):
    """Takes a string and removes any articles in it."""
    text = text.lower()
    articles = ['and', 'a', '&', 'issue', 'the']
    new_text = ''
    for word in text.split(' '):
        if word not in articles:
            new_text += word + ' '
    new_text = new_text[:-1]
    new_text = new_text.replace(':', '')
    new_text = new_text.replace(',', '')
    new_text = new_text.replace('-', ' ')
    return new_text


def is_flush(five_card_hand):
    """Return true if the hand is a flush."""
    for suit, suit_count in five_card_hand.suit_counts.items():
        if suit_count == 5:
            return True
    return False


@classmethod
def class_unique_id(cls):
    """
         具体ump类关键字唯一名称，类方法：return 'price_edge'
         主要针对外部user设置自定义ump使用, 需要user自己保证class_unique_id的唯一性，内部不做检测
         具体使用见ABuUmpManager中extend_ump_block方法
        """
    return 'price_edge'


def first(iterable, default=None, key=None):
    """Return first element of *iterable* that evaluates to ``True``, else
    return ``None`` or optional *default*. Similar to :func:`one`.
    >>> first([0, False, None, [], (), 42])
    42
    >>> first([0, False, None, [], ()]) is None
    True
    >>> first([0, False, None, [], ()], default='ohai')
    'ohai'
    >>> import re
    >>> m = first(re.match(regex, 'abc') for regex in ['b.*', 'a(.*)'])
    >>> m.group(1)
    'bc'

    The optional *key* argument specifies a one-argument predicate function
    like that used for *filter()*.  The *key* argument, if supplied, should be
    in keyword form. For example, finding the first even number in an iterable:
    >>> first([1, 1, 3, 4, 5], key=lambda x: x % 2 == 0)
    4

    Contributed by Hynek Schlawack, author of `the original standalone module`_.
    .. _the original standalone module: https://github.com/hynek/first
    """
    return next(filter(key, iterable), default)


def _self_referential_fk(model):
    """
    Return whether this model has a self ref FK, and the name for the field
    """
    for f in model._meta.concrete_fields:
        if f.related_model:
            if issubclass(model, f.related_model):
                return f.attname
    return None


def agrupar_lectures_per_data(lectures):
    """Retorna un diccionari de llistes en què les
       claus són les dates inicial i final de les lectures
    """
    lect = {}
    for i in lectures:
        key = i['fecha_desde'], i['fecha_actual']
        if key not in lect:
            lect[key] = []
        lect[key].append(i)
    return lect


@staticmethod
def _get_fileholders(file_map):
    """ Return fileholder for header and image

        For single-file niftis, the fileholder for the header and the image
        will be the same
        """
    return file_map['image'], file_map['image']


def vertices_to_label(selected_vert_indices, all_vert_coords, header=
    '#!ascii label'):
    """
    Write a string in FreeSurfer label format from the vertices.

    Write a string in FreeSurfer label format from the vertices. This can be used to create a label from a list of vertices, e.g., for displaying the vertices in Freeview or other tools supporting FreeSurfers label file format.
    """
    res = [header]
    res.append('%d' % len(selected_vert_indices))
    for idx in selected_vert_indices:
        res.append('%d %f %f %f 0.0000000000' % (idx, all_vert_coords[idx][
            0], all_vert_coords[idx][1], all_vert_coords[idx][2]))
    return '\n'.join(res)


def isctrl(c):
    """Return True if byte corresponds to device control character.

    (See also: http://www.w3schools.com/tags/ref_ascii.asp)
    """
    return ord(c) < 32 or ord(c) == 127


def setCss(css):
    """
    Function generating a script to set a given CSS style sheet.

    @param css style sheet
    @type str
    @return script to set the style sheet
    @rtype str
    """
    source = """
(function() {{
    var css = document.createElement('style');
    css.setAttribute('type', 'text/css');
    css.appendChild(document.createTextNode('{0}'));
    document.getElementsByTagName('head')[0].appendChild(css);
    }})()"""
    style = css.replace("'", "\\'").replace('\n', '\\n')
    return source.format(style)


def knapsack01(obj, weights, capacity):
    """ 0/1 knapsack solver, maximizes profit. weights and capacity integer """
    assert len(obj) == len(weights)
    n = len(obj)
    if n == 0:
        return 0, []
    c = [([0] * (capacity + 1)) for i in range(n)]
    added = [([False] * (capacity + 1)) for i in range(n)]
    for i in range(n):
        for j in range(capacity + 1):
            if weights[i] > j:
                c[i][j] = c[i - 1][j]
            else:
                c_add = obj[i] + c[i - 1][j - weights[i]]
                if c_add > c[i - 1][j]:
                    c[i][j] = c_add
                    added[i][j] = True
                else:
                    c[i][j] = c[i - 1][j]
    i = n - 1
    j = capacity
    solution = []
    while i >= 0 and j >= 0:
        if added[i][j]:
            solution.append(i)
            j -= weights[i]
        i -= 1
    return c[n - 1][capacity], solution


def get_3grams(string):
    """ Return the set of different tri-grams in a string
    """
    string = '  ' + string + '  '
    return list(zip(string, string[1:], string[2:]))


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


def extract_client(request):
    """
    Return session id from the request
    """
    _id = request.requestHeaders.getRawHeaders('Bloc-Session-ID', None)
    return _id[0] if _id is not None else None


def geojson_driver_args(distribution):
    """
    Construct driver args for a GeoJSON distribution.
    """
    url = distribution.get('downloadURL') or distribution.get('accessURL')
    if not url:
        raise KeyError(f'A download URL was not found for {str(distribution)}')
    return {'urlpath': url}


def auto_newline(buffer):
    """
    Insert \\n at the cursor position. Also add necessary padding.
    """
    insert_text = buffer.insert_text
    if buffer.document.current_line_after_cursor:
        insert_text('\n')
    else:
        current_line = buffer.document.current_line_before_cursor.rstrip()
        insert_text('\n')
        unindent = current_line.rstrip().endswith(' pass')
        current_line2 = current_line[4:] if unindent else current_line
        for c in current_line2:
            if c.isspace():
                insert_text(c)
            else:
                break
        if current_line[-1:] == ':':
            for x in range(4):
                insert_text(' ')


def equilibrium_quotient(concs, stoich):
    """ Calculates the equilibrium quotient of an equilbrium

    Parameters
    ----------
    concs: array_like
        per substance concentration
    stoich: iterable of integers
        per substance stoichiometric coefficient

    Examples
    --------
    >>> '%.12g' % equilibrium_quotient([1.0, 1e-7, 1e-7], [-1, 1, 1])
    '1e-14'

    """
    import numpy as np
    if not hasattr(concs, 'ndim') or concs.ndim == 1:
        tot = 1
    else:
        tot = np.ones(concs.shape[0])
        concs = concs.T
    for nr, conc in zip(stoich, concs):
        tot *= conc ** nr
    return tot


def do_print(*args, **kwargs):
    """
    A mockable print()
    """
    return print(*args, **kwargs)


@classmethod
def as_decorator(cls, func=None, **kwargs):
    """
        A decorator for validating the units of arguments to functions.

        This decorator was adapted from Astropy's
        `~astropy.units.quantity_input`,
        but adds range checking and the possibilities to strip
        the units before feeding into the decorated function.
        It also allows to apply a new unit to the returned value
        (`~astropy.units.quantity_input` only does this in conjuction
        with type annotations).

        A `~astropy.units.UnitsError` will be raised if the unit
        attribute of the argument is not equivalent to the unit
        specified to the decorator or in the annotation. If the
        argument has no unit attribute, i.e. it is not a Quantity
        object, a `ValueError` will be raised.

        Where an equivalency is specified in the decorator, the
        function will be executed with that equivalency in force.

        Parameters
        ----------
        func : function
            The function to decorate.
        **kwargs : any number of key word arguments
            The function argument names and ranges that are to be checked
            for the decorated function. Must have the form
            `param=(min, max, unit)`, e.g.::

                @ranged_quantity_input(a=(0, 1, u.m), b=(0, None, u.s))
                def func(a, b):
                    return a ** 2, 1 / b

            will check that input `a` has unit of meters (or equivalent)
            and is in the range between zero and one meters; and that
            `b` is at least zero seconds.
        equivalencies : list of functions
            Equivalencies functions to apply (see `Astropy docs
            <http://docs.astropy.org/en/stable/units/equivalencies.html>`__).
        strip_input_units : bool, optional
            Whether to strip units from parameters. Only applied
            to parameters that are "registered" in the decorator,
            see examples. (default: False)
        output_unit : `~astropy.units.Unit` or tuple of `~astropy.units.Unit`, optional
            Add units to the return value(s) of the decorated function.
            Note that internally the given units are *multiplied* with
            the return values, which means you should only use this
            if you have stripped the units from the input (or otherwise
            made sure that the return values are unit-less).
        allow_none : bool, optional
            Allow to use `None` as default value; see examples.

        Returns
        -------
        ranged_quantity_input : function decorator
            Function decorator to check units and value ranges.

        Notes
        -----

        The checking of arguments inside variable arguments to a
        function is not supported (i.e. \\*arg or \\**kwargs).

        Examples
        --------

        In the most basic form, `~pycraf.utils.ranged_quantity_input`
        behaves like `~astropy.units.quantity_input`, but adds
        range checking::

            >>> import astropy.units as u
            >>> from pycraf.utils import ranged_quantity_input

            >>> @ranged_quantity_input(a=(0, 1, u.m))
            ... def func(a):
            ...     return a ** 2

            >>> func(0.5 * u.m)  # doctest: +FLOAT_CMP
            <Quantity 0.25 m2>

            >>> func(2 * u.m)
            Traceback (most recent call last):
            ...
            ValueError: Argument 'a' to function 'func' out of range
            (allowed 0 to 1 m).

        It is possible to disable range checking, for the lower, upper,
        or both bounds, e.g.::

            >>> @ranged_quantity_input(a=(0, None, u.m))
            ... def func(a):
            ...     return a ** 2

            >>> func(2 * u.m)  # doctest: +FLOAT_CMP
            <Quantity 4.0 m2>

        Often one wants to add units support to third-party functions,
        which expect simple types::

            >>> # this is defined somewhere else
            >>> def _func(a):
            ...     assert isinstance(a, float), 'No Way!'
            ...     return a ** 2

            >>> _func(0.5 * u.m)
            Traceback (most recent call last):
            ...
            AssertionError: No Way!

        We can do the following to the rescue::

            >>> @ranged_quantity_input(a=(0, 1, u.m), strip_input_units=True)
            ... def func(a):
            ...     return _func(a)

            >>> # which is the same as
            >>> # func = ranged_quantity_input(
            >>> #    a=(0, 1, u.m), strip_input_units=True
            >>> #    )(_func)

            >>> func(0.5 * u.m)  # doctest: +FLOAT_CMP
            0.25

        However, by doing this there are still no units for the output.
        We can fix this with the `output_unit` option::

            >>> @ranged_quantity_input(
            ...     a=(0, 1, u.m),
            ...     strip_input_units=True,
            ...     output_unit=u.m ** 2
            ...     )
            ... def func(a):
            ...     return _func(a)

            >>> func(0.5 * u.m)  # doctest: +FLOAT_CMP
            <Quantity 0.25 m2>

        If you have several return values (tuple), just provide a tuple
        of output units.

        The decorator also works flawlessly with default values::

            >>> @ranged_quantity_input(a=(0, 1, u.m))
            ... def func(a=0.5 * u.m):
            ...     return a ** 2

            >>> func()  # doctest: +FLOAT_CMP
            <Quantity 0.25 m2>

        However, sometimes one wants to use `None` as default, which will
        fail, because `None` has no unit::

            >>> @ranged_quantity_input(a=(0, 1, u.m))
            ... def func(a=None):
            ...     return a ** 2

            >>> func()
            Traceback (most recent call last):
            ...
            TypeError: Argument 'a' to function 'func' has no 'unit'
            attribute. You may want to pass in an astropy Quantity instead.

        One can use the `allow_none` option, to deal with such cases::

            >>> @ranged_quantity_input(a=(0, 1, u.m), allow_none=True)
            ... def func(a=None):
            ...     if a is None:
            ...         a = 0.5
            ...     return a ** 2

            >>> func()  # doctest: +FLOAT_CMP
            0.25

        and of course, the unit check still works,  if a something other
        than `None` is provided::

            >>> func(1 * u.s)
            Traceback (most recent call last):
            ...
            astropy.units.core.UnitsError: Argument 'a' to function
            'func' must be in units convertible to 'm'.

        """
    self = cls(**kwargs)
    if func is not None and not kwargs:
        return self(func)
    else:
        return self


def BSR_Row_WriteVect(A, i, x):
    """Overwrite the nonzeros in row i of BSR matrix A with the vector x.

    length(x) and nnz(A[i,:]) must be equivalent

    Parameters
    ----------
    A : bsr_matrix
        Matrix assumed to be in BSR format
    i : int
        Row number
    x : array
        Array of values to overwrite nonzeros in row i of A

    Returns
    -------
    A : bsr_matrix
        The nonzeros in row i of A have been
        overwritten with entries from x.  x must be same
        length as nonzeros of row i.  This is guaranteed
        when this routine is used with vectors derived form
        Get_BSR_Row

    Examples
    --------
    >>> from numpy import array
    >>> from scipy.sparse import bsr_matrix
    >>> from pyamg.util.BSR_utils import BSR_Row_WriteVect
    >>> indptr  = array([0,2,3,6])
    >>> indices = array([0,2,2,0,1,2])
    >>> data    = array([1,2,3,4,5,6]).repeat(4).reshape(6,2,2)
    >>> B = bsr_matrix( (data,indices,indptr), shape=(6,6) )
    >>> BSR_Row_WriteVect(B,5,array([11,22,33,44,55,66]))

    """
    blocksize = A.blocksize[0]
    BlockIndx = int(i / blocksize)
    rowstart = A.indptr[BlockIndx]
    rowend = A.indptr[BlockIndx + 1]
    localRowIndx = i % blocksize
    x = x.__array__().reshape((max(x.shape),))
    indys = A.data[rowstart:rowend, (localRowIndx), :].nonzero()
    A.data[rowstart:rowend, (localRowIndx), :][indys[0], indys[1]] = x


def offset_value(hsv, offset):
    """
    Offsets the value (brightness/darkness) in range 0-1 by the given offset amount
    :param hsv: list(float, float, float), list or tuple representing the hue saturation and value color
    :param offset: float, offset value to offset the color
    :return: list(float, float, float), offset hue saturation value color
    """
    hsv[2] += offset
    if hsv[2] > 1:
        hsv[2] = 1
    elif hsv[2] < 0:
        hsv[2] = 0
    return hsv


def coerce_types(T1, T2):
    """Coerce types T1 and T2 to a common type.

    Coercion is performed according to this table, where "N/A" means
    that a TypeError exception is raised.

    +----------+-----------+-----------+-----------+----------+
    |          | int       | Fraction  | Decimal   | float    |
    +----------+-----------+-----------+-----------+----------+
    | int      | int       | Fraction  | Decimal   | float    |
    | Fraction | Fraction  | Fraction  | N/A       | float    |
    | Decimal  | Decimal   | N/A       | Decimal   | float    |
    | float    | float     | float     | float     | float    |
    +----------+-----------+-----------+-----------+----------+

    Subclasses trump their parent class; two subclasses of the same
    base class will be coerced to the second of the two.

    """
    if T1 is T2:
        return T1
    if T1 is int:
        return T2
    if T2 is int:
        return T1
    if issubclass(T2, T1):
        return T2
    if issubclass(T1, T2):
        return T1
    if issubclass(T2, float):
        return T2
    if issubclass(T1, float):
        return T1
    if T1.__base__ is T2.__base__:
        return T2
    raise TypeError('cannot coerce types %r and %r' % (T1, T2))


def locscale_grad(y, loc, scale, dlldy, *args):
    """derivative of log-likelihood with respect to location and scale

    Parameters
    ----------
    y : array_like
        data points of random variable at which loglike is evaluated
    loc : float
        location parameter of distribution
    scale : float
        scale parameter of distribution
    dlldy : function
        derivative of loglikelihood fuction wrt. random variable x
    args : array_like
        shape parameters of log-likelihood function

    Returns
    -------
    dlldloc : ndarray
        derivative of loglikelihood wrt location evaluated at the
        points given in y
    dlldscale : ndarray
        derivative of loglikelihood wrt scale evaluated at the
        points given in y

    """
    yst = (y - loc) / scale
    dlldloc = -dlldy(yst, *args) / scale
    dlldscale = -1.0 / scale - dlldy(yst, *args) * (y - loc) / scale ** 2
    return dlldloc, dlldscale


@staticmethod
def _fit_one_forecaster_compute(task, **func_kwargs):
    """
        A function that is used to fit a model. This function can be passed
        as a callable to any of the compute backends that support `ComputeJobType.ForecasterUnion`
        job types.

        param task: Tuple of forecaster_name and its corresponding estimator.
        type task: tuple.
        param func_args: Keyword fit parameters passed on to the forecaster fit methods.
                        These arguments should have the form,
                        ```<Forecaster name>[<Parameter name>]=<Parameter value>```
        type func_args: dict.

        :return: Tuple containing the estimator name and its fitted Model
        :rtype: tuple
        """
    if task is None:
        raise Exception('task argument is invalid or not a tuple')
    if func_kwargs is None:
        raise Exception('func_args argument is invalid')
    _X = func_kwargs.pop('X')
    _y = func_kwargs.pop('y')
    _fit_param_dict = func_kwargs.pop('forecaster_fit_params')
    _forecaster_name = task[0]
    _forecaster = task[1]
    return _forecaster_name, _forecaster.fit(_X, _y, **_fit_param_dict[
        _forecaster_name])


def _a_decode_false(stream, offset, count, mapping):
    """
    'a0F',3,1 -> 3,False
    """
    assert count == 0
    return offset, False


@classmethod
def _get_index_type(cls, index):
    """Assigns an integer code to the type of the index.

        The index type determines how differently typed values are sorted. This ordering is based
        on https://firebase.google.com/docs/database/rest/retrieve-data#section-rest-ordered-data
        """
    if index is None:
        return cls._type_none
    if isinstance(index, bool) and not index:
        return cls._type_bool_false
    if isinstance(index, bool) and index:
        return cls._type_bool_true
    if isinstance(index, (int, float)):
        return cls._type_numeric
    if isinstance(index, str):
        return cls._type_string
    return cls._type_object


def layer_add():
    """Add new Grease Pencil layer for the active Grease Pencil data-block

    """
    pass


@classmethod
def _node_to_dict(cls, node, json, json_fields):
    """ Helper method for ``get_tree``.
        """
    if json:
        pk_name = node.get_pk_name()
        result = {'id': getattr(node, pk_name), 'label': node.__repr__()}
        if json_fields:
            result.update(json_fields(node))
    else:
        result = {'node': node}
    return result


def listify(obj, ignore=(list, tuple, type(None))):
    """ Wraps all non-list or tuple objects in a list; provides a simple way
    to accept flexible arguments. """
    return obj if isinstance(obj, ignore) else [obj]


def encode_segment_name(tli, log, seg):
    """
    Build the xlog segment name based on timeline, log ID and segment ID

    :param int tli: timeline number
    :param int log: log number
    :param int seg: segment number
    :return str: segment file name
    """
    return '%08X%08X%08X' % (tli, log, seg)


def center(widget, width, height):
    """
    Center the given widget.
    """
    screen_width = widget.winfo_screenwidth()
    screen_height = widget.winfo_screenheight()
    x_offset = int(screen_width / 2 - width / 2)
    y_offset = int(screen_height / 2 - height / 2)
    widget.geometry('{}x{}+{}+{}'.format(width, height, x_offset, y_offset))


@classmethod
def supports_to_pcm(cls):
    """returns True if all necessary components are available
        to support the .to_pcm() method"""
    try:
        from audiotools.decoders import MPCDecoder
        return True
    except ImportError:
        return False


def quote(value):
    """ Quote value if needed """
    if ' ' in value:
        return '"' + value + '"'
    return value


@classmethod
def estimateInitialPeltValue(cls, first_val, first_event_time_s,
    start_time_s, half_life_ms):
    """There will typically be a delay between the time when a task starts,
        and the first trace event that logs PELT signals for that task. During
        this time the signal will change from its initial value. This method
        takes the time at which a task starts running and the timestamp and
        value of the first PELT trace event related to that task. It returns an
        estimate for the value the PELT signal had the task started.

        Example:
        ::

            +---------------------+      Task is RUNNING
            |              E      |

          --+--------------+------+--------- Time --->
            ^              ^
          task_start     first PELT event logged for the task

        This method estimates the value of the PELT signal at task_start,
        assuming the task was running in the interval of time between
        task_start and the first PELT event logged of the task.

        :param first_val: value of the very first event realted to the
            task that shows PELT info
        :type first_val: int

        :param first_event_time_s: instant of time in seconds when the first
            PELT event related to the task was generated
        :type first_event_time_s: float

        :param start_time_s: instant of time in seconds when the task starts
            running for the first time
        :type start_time_s: float

        :param half_life_ms: the [ms] interval required by a signal to
                             increased/decreased by half of its range
        :type  half_life_ms: int

        :returns: int - Estimated value of PELT signal when the task starts
        """
    geom_y = pow(0.5, 1.0 / half_life_ms)
    geom_u = float(cls._signal_max) * (1.0 - geom_y)
    time_since_start = first_event_time_s - start_time_s
    if time_since_start < 0:
        raise ValueError(
            'First sched_load_avg_* event happens before the task starts')
    updates_since_start = int(time_since_start / (cls._sample_us / 1000000.0))
    pelt_val = first_val
    for i in range(updates_since_start):
        pelt_val = (pelt_val - geom_u) / geom_y
    return pelt_val


@classmethod
def get_computation_wallclock_time(cls, calc, **kwargs):
    """Return the computation wallclock time in seconds."""
    parameters = calc.outputs.output_parameters
    if 'wall_time_seconds' not in parameters.attrs():
        return None
    return parameters.get_attr('wall_time_seconds')


@staticmethod
def _print_2_columns(col1, col2):
    """print using a 2-columns format """
    column1_len = 24
    column2_start = 28
    left = col1.ljust(column1_len)
    right = col2.replace('\n', '\n' + column2_start * ' ')
    return '  %s  %s' % (left, right)


def timings(samples):
    """Converts samples to sample times per observation."""
    groups = samples.groupby(axis=1, level=0)
    return groups.apply(lambda group: group.iloc[:, (1)] - group.iloc[:, (0)])


def p_statement_list(p):
    """statement_list : statement statement_list
                      | empty"""
    if p[1] is None:
        return []
    if len(p) < 3 or p[2] is None:
        p[0] = [p[1]]
    else:
        p[0] = [p[1]] + p[2]


def apply(**data):
    """ Applies the data to the object
        """


def _contrib_sign_ste(data=None, out=None, name=None, **kwargs):
    """Straight-through-estimator of `sign()`.

    In forward pass, returns element-wise sign of the input (same as `sign()`).

    In backward pass, returns gradients of ``1`` everywhere (instead of ``0`` everywhere as in ``sign()``):
    :math:`\\frac{d}{dx}{sign\\_ste(x)} = 1` vs. :math:`\\frac{d}{dx}{sign(x)} = 0`.
    This is useful for quantized training.

    Reference: Estimating or Propagating Gradients Through Stochastic Neurons for Conditional Computation.

    Example::
      x = sign_ste([-2, 0, 3])
      x.backward()
      x = [-1.,  0., 1.]
      x.grad() = [1.,  1., 1.]

    The storage type of ``sign_ste`` output depends upon the input storage type:
      - round_ste(default) = default
      - round_ste(row_sparse) = row_sparse
      - round_ste(csr) = csr

    Defined in src/operator/contrib/stes_op.cc:L80

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

    out : NDArray, optional
        The output NDArray to hold the result.

    Returns
    -------
    out : NDArray or list of NDArrays
        The output of this function.
    """
    return 0,


@classmethod
def set_fitler(cls, tag):
    """set log filter tag"""
    cls._Fitler_Tag = '[%s]' % tag.upper()


def validate_output_transform(x, y, y_pred):
    """A transform to format the output of the supervised evaluator before calculating the metric

    Args:
        x (:obj:`torch.Tensor`): the input to the model
        y (:obj:`torch.Tensor`): the output of the model
        y_pred (:obj:`torch.Tensor`): the ground truth labels

    Returns:
        (:obj:`torch.Tensor`, :obj:`torch.Tensor`): model predictions and ground truths reformatted
    """
    output = y_pred
    labels = y
    B, V, C = output.shape
    B_labels, V_labels, C_labels = labels.shape
    output = output.view(B * V, C)
    labels = labels.view(B_labels * V_labels, C_labels)
    return output, labels


def get_site_url(site):
    """Get a ``site`` URL

    :param str site: the site to get URL for
    :return: a valid site URL
    :raise ValueError: when site is empty, or isn't well formatted

    The ``site`` argument is checked: its scheme must be ``http`` or ``https``,
    or a :exc:`ValueError` is raised.

    If the ``site`` does not have a scheme, ``http`` is used. If it doesn't
    have a TLD, ``.com`` is used.
    """
    site = site.strip() if site else ''
    if not site:
        raise ValueError('What site do you want to check?')
    if site[:7] != 'http://' and site[:8] != 'https://':
        if '://' in site:
            protocol = site.split('://')[0] + '://'
            raise ValueError('Try it again without the %s' % protocol)
        site = 'http://' + site
    if '.' not in site:
        site += '.com'
    return site


def find_index(fn: callable, items: list):
    """Returns the index of the first element in the array that satisfies the provided testing function. Otherwise, it returns -1, indicating that no element passed the test."""
    for i, item in enumerate(items):
        if fn(item):
            return i
    return -1


def previewrange_set():
    """Automatically set Preview Range based on range of keyframes

    """
    pass


def asciify(data):
    """
    Limit the byte data string to only ascii characters and convert it to a string.
    Non-representable characters are dropped.
    :param data: byte data string to convert to ascii
    :return: string
    """
    return ''.join(map(chr, filter(lambda x: x < 128, data)))


@classmethod
def from_strategy(cls, strategy):
    """
        Initialize wealth from strategy.

        Parameters
        ----------
        - strategy : TradeStrategy
        - verbose : bool
        """
    return cls(bars=cls._get_bars(strategy), wealth=cls._get_wealth(strategy))


def get_utility(interface, name='', context=None):
    """Get the utility that provides interface

        Returns the nearest utility to the context that implements the
        specified interface.  If one is not found, raises
        ComponentLookupError.
        """


def sensitivity(real, predicted):
    """ Sensitivity = `|True Positives| / (|True Positives| + |False Negatives|)`

    Parameters
    ----------
    real : dict
        A dictionary mapping quasispecies to frequencies.

    predicted : dict
        The calculated dictionary mapping quasispecies to frequencies.

    Returns
    -------
    sensitivity : float
        The sensitivity.
    """
    truepos = set(predicted.keys()) & set(real.keys())
    return len(truepos) / float(len(real))


def to_utf8(value):
    """ Safe encodng of value to utf-8 taking care of unicode values
    """
    if isinstance(value, str):
        value = value.encode('utf8')
    return value


def decrypt(num_keys, keylist, wordlist, word_to_idx, words):
    """Encrypt words using OTP word indexes."""
    if len(words) > num_keys:
        raise ValueError('Number of input words exceeds key length')
    result = []
    for i in range(0, len(words)):
        c = words[i]
        c_i = word_to_idx[c]
        k = keylist[i]
        m_i = (c_i - k) % len(wordlist)
        result.append({'message': wordlist[m_i], 'ciphertext': wordlist[c_i]})
    return result


def not_keyword(func):
    """Decorator to disable exposing functions or methods as keywords.

    Examples::

        @not_keyword
        def not_exposed_as_keyword():
            # ...

        def exposed_as_keyword():
            # ...

    Alternatively the automatic keyword discovery can be disabled with
    the :func:`library` decorator or by setting the ``ROBOT_AUTO_KEYWORDS``
    attribute to a false value.

    New in Robot Framework 3.2.
    """
    func.robot_not_keyword = True
    return func


@staticmethod
def _get_points_to_use(data, points_per_side):
    """Get a number of points from the spectrum to use for a fit.

        Slices the list of all data points to have a list of
        points from each side of the spectrum to use for polynomial fitting.

        Parameters
        ----------
        data: :class:`list`
            List from which points should be used on each side.

        points_per_side: :class:'int'
            How many points from each end of the list should be used.

        Returns
        -------
        points_to_use: :class:`list`
            List only containing the correct number of points from each side
            and not the points in between.
        """
    left_part = data[:points_per_side + 1]
    right_part = data[len(data) - points_per_side - 1:]
    points_to_use = left_part
    points_to_use.extend(right_part)
    return points_to_use


def get_header(input_file):
    """
    Extract header information from a relion star file.

    Arguments:
    input_file - Input star file

    Return:
    Color string
    """
    with open(input_file, 'r') as read:
        lines = read.readlines()
    header = []
    idx = None
    for idx, line in enumerate(lines):
        line = line.lstrip().rstrip()
        if line.startswith('_rln'):
            name = line.split()[0]
            name = name.replace('_rlnFinalResolution', '_rlnCtfMaxResolution')
            if name == '_rlnMicrographName' or name == '_rlnCtfImage':
                header.append((name, '|U1200'))
            else:
                header.append((name, '<f8'))
        elif line == '' or line == 'data_' or line == 'loop_':
            continue
        else:
            break
    if idx is None:
        raise ValueError
    else:
        return header, idx


@staticmethod
def segment_coupler_scan():
    """Generate a scan-command for LCN segment-couplers.

        Used to detect the local segment (where the physical bus connection is
        located).

        :return:    The PCK command (without address header) as text
        :rtype:    str
        """
    return 'SK'


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

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

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

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


def app_view(request):
    """Return the actual view as indicated by self.app,
        with `self.app_parameters` applied to the `request`."""


def freeze(model):
    """ Set all layers in a model to non-trainable.

    The weights for these layers will not be updated during training.

    This function modifies the given model in-place,
    but it also returns the modified model to allow easy chaining with other functions.
    """
    for layer in model.layers:
        layer.trainable = False
    return model


def _get_contour_values(min_val, max_val, base=0, interval=100):
    """Return a list of values between min and max within an interval."""
    i = base
    out = []
    if min_val < base:
        while i >= min_val:
            i -= interval
    while i <= max_val:
        if i >= min_val:
            out.append(i)
        i += interval
    return out


def is_code_line(line):
    """A code line is a non empty line that don't start with #"""
    return line.strip()[:1] not in {'#', '%', ''}


def check_anagram(str1: str, str2: str) ->bool:
    """
    LeetCode 242: Valid Anagram
    Given two strings str1 and str2 , write a function to determine if str2 is an anagram of str1.
    todo compare speeds
    """
    if len(str1) != len(str2):
        return False
    for c in set(str1):
        if str1.count(c) != str2.count(c):
            return False
    return True


def cat(filename):
    """Return the contents of a file. Replaces the `cat` command.

    This function took about ~148 time units per call, while
    run(['cat']) needed ~4688 time units.
    """
    try:
        with open(filename, 'r', encoding='utf-8') as infile:
            return 'success', infile.read()
    except Exception:
        return 'failure', None


@classmethod
def _validate_dictionary_name(cls, name, version=2):
    """
            Check if the given name is a valid dictionary name.
            Available dictionaries are DELAS, DELAF and DELACF.
            The first two dictionaries have two versions.
        """
    valid = {'DELAS': {(1): 'DELAS_PB', (2): 'DELAS_PB_v2'}, 'DELAF': {(1):
        'DELAF_PB', (2): 'DELAF_PB_v2'}, 'DELACF': {(1): 'DELACF_PB', (2):
        'DELACF_PB'}}
    error_msg = """
                        Valid names are DELAS, DELAF, and DELACF.
                    """
    name = name.upper()
    if name in valid:
        return valid[name][version]
    raise Exception(error_msg)


@classmethod
def create(cls, root, schema):
    """
        Create an object based on the root tag name.
        @param root: An XML root element.
        @type root: L{Element}
        @param schema: A schema object.
        @type schema: L{schema.Schema}
        @return: The created object.
        @rtype: L{SchemaObject}
        """
    fn = cls.tags.get(root.name)
    if fn is not None:
        return fn(schema, root)
    else:
        return None


def analyzer_resolution(analyzer_information, slit_width=None, slit_number=
    None, pass_energy=10):
    """
    Estimates analyzer resolution from slit dimensioons pass energy, and analyzer radius.
    :param analyzer_information:
    :param slit_width:
    :param slit_number:
    :param pass_energy:
    :return:
    """
    if slit_width is None:
        slit_width = analyzer_information['slits'][slit_number]
    return 1000 * pass_energy * (slit_width / (2 * analyzer_information[
        'radius']))


@classmethod
def from_path(cls, path, dirname=None):
    """Construct instance of this type from full path name.

        :param str: (unicode) string representing path
        :param str dirname: optional prefix directory
        """
    if len(path) > 2 and path[0].isalpha() and path[1] == ':':
        path = path[2:]
    path = path.replace('\\', '/').lstrip('/')
    return cls(path.split('/'), dirname)


def on_bmo_save(sender, **kwargs):
    """Alternative method - maintain GL through a signal

    Master-detail BMOs can't use a simple save hook, and
    instead need to set a signal to call this'
    """
    sender.update_gl()


def unique(objects):
    """
    Return a list of unique objects.
    """
    uniques = []
    for obj in objects:
        if obj not in uniques:
            uniques.append(obj)
    return uniques


def align_left(text, length, left_edge='|', right_edge='|', text_length=
    None, left_padding=2):
    """Left align text."""
    if text_length is None:
        text_length = len(text)
    computed_length = text_length + left_padding + len(left_edge) + len(
        right_edge)
    if length - computed_length >= 0:
        padding = left_padding
    else:
        padding = 0
    output = []
    length_so_far = 0
    output.append(left_edge)
    length_so_far += len(left_edge)
    output.append(' ' * padding)
    length_so_far += padding
    output.append(text)
    length_so_far += text_length
    output.append(' ' * (length - length_so_far - len(right_edge)))
    output.append(right_edge)
    return ''.join(output)


def build_algorithm(trainer):
    """ Builds the RL algorithm
        :param trainer: A reinforcement learning trainer instance.
        :type trainer: diplomacy_research.models.training.reinforcement.trainer.ReinforcementTrainer
    """
    if not trainer.queue_dataset or not trainer.model:
        raise RuntimeError(
            'You must build the model and the dataset before building the RL algorithm'
            )
    trainer.algorithm = trainer.algorithm_constructor(trainer.queue_dataset,
        trainer.model, trainer.hparams)


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


@classmethod
def reset(cls) ->None:
    """Used for testing purposes to reset state."""
    cls._goals = frozenset()


def bytes_replace(byte_str, start_idx, stop_idx, replacement):
    """
    Replaces given portion of the byte string with the replacement, returns new array
    :param byte_str:
    :param start_idx:
    :param stop_idx:
    :param replacement:
    :return:
    """
    return byte_str[:start_idx] + replacement + byte_str[stop_idx:]


def _mergeeffects(text, start, stop):
    """Insert start sequence at every occurrence of stop sequence

    >>> s = _mergeeffects(b'cyan', b'[C]', b'|')
    >>> s = _mergeeffects(s + b'yellow', b'[Y]', b'|')
    >>> s = _mergeeffects(b'ma' + s + b'genta', b'[M]', b'|')
    >>> s = _mergeeffects(b'red' + s, b'[R]', b'|')
    >>> s
    '[R]red[M]ma[Y][C]cyan|[R][M][Y]yellow|[R][M]genta|'
    """
    parts = []
    for t in text.split(stop):
        if not t:
            continue
        parts.extend([start, t, stop])
    return b''.join(parts)


def frozen(status):
    """
    Return the frozen version of the given status name.

    @type status: C{unicode}
    @rtype: C{unicode}
    """
    return u'.' + status


def resiliency_upstream(graph, edgelist, event):
    """
    This function computes the resiliency of all upstream sections,
    mainly looking out for generators
    :param edgelist: All upstream sections of the feeder, from persective of a feeder being analyzed
    :return:
    """
    print('Heat your ', edgelist)
    pass


def out_8(library, session, space, offset, data, extended=False):
    """Write in an 8-bit value from the specified memory space and offset.

    Corresponds to viOut8* functions of the VISA library.

    :param library: the visa library wrapped by ctypes.
    :param session: Unique logical identifier to a session.
    :param space: Specifies the address space. (Constants.*SPACE*)
    :param offset: Offset (in bytes) of the address or register from which to read.
    :param data: Data to write to bus.
    :param extended: Use 64 bits offset independent of the platform.
    :return: return value of the library call.
    :rtype: :class:`pyvisa.constants.StatusCode`
    """
    if extended:
        return library.viOut8Ex(session, space, offset, data)
    else:
        return library.viOut8(session, space, offset, data)


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

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

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


def _get_supplied_args(signature_params, args, kwargs):
    """Return names of all args that have been passed in
    either as positional or keyword arguments, and are not None.
    """
    supplied_args = []
    for index in range(len(args)):
        if args[index] is not None:
            supplied_args.append(signature_params[index])
    for keyword in kwargs:
        if kwargs[keyword] is not None:
            supplied_args.append(keyword)
    return supplied_args


def issueRequest(request):
    """Issue a request (duh)."""


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 base36_to_int(s):
    """
    Convertd a base 36 string to an integer
    """
    return int(s, 36)


@classmethod
def build_tag(cls, tag, text='', attrs=None):
    """Build tag full info include the attributes.

        :param tag: tag name.
        :param text: tag text.
        :param attrs: tag attributes. Default：``None``.
        :type attrs: dict or None
        :rtype: str
        """
    return '{}{}{}'.format(cls.tag_start(tag, attrs), text, cls.tag_end(tag))


def least_fixpoint(transitions, bdd):
    """Return ancestor nodes."""
    target = bdd.add_expr('!x0 & x1')
    q = bdd.false
    qold = None
    prime = {'x0': "x0'", 'x1': "x1'"}
    qvars = {"x0'", "x1'"}
    while q != qold:
        qold = q
        next_q = bdd.let(prime, q)
        u = transitions & next_q
        pred = bdd.exist(qvars, u)
        q = q | pred | target
    return q


def _extract_class_dict(cls):
    """Retrieve a copy of the dict of a class without the inherited methods"""
    clsdict = dict(cls.__dict__)
    if len(cls.__bases__) == 1:
        inherited_dict = cls.__bases__[0].__dict__
    else:
        inherited_dict = {}
        for base in reversed(cls.__bases__):
            inherited_dict.update(base.__dict__)
    to_remove = []
    for name, value in clsdict.items():
        try:
            base_value = inherited_dict[name]
            if value is base_value:
                to_remove.append(name)
        except KeyError:
            pass
    for name in to_remove:
        clsdict.pop(name)
    return clsdict


def apply_request_id_middleware(app):
    """Apply a :meth:`consensys_utils.wsgi.RequestIDMiddleware` on a Flask application

    :param app: Flask application
    :type app: :class:`flask.Flask`
    """
    if 'wsgi' in app.config and 'request_id' in app.config['wsgi']:
        from ..wsgi import RequestIDMiddleware
        app.wsgi_app = RequestIDMiddleware(app.wsgi_app, config=app.config[
            'wsgi']['request_id'])


def parse_gerber_value(value, format=(2, 5), zero_suppression='trailing'):
    """ Convert gerber/excellon formatted string to floating-point number

    .. note::
        Format and zero suppression are configurable. Note that the Excellon
        and Gerber formats use opposite terminology with respect to leading
        and trailing zeros. The Gerber format specifies which zeros are
        suppressed, while the Excellon format specifies which zeros are
        included. This function uses the Gerber-file convention, so an
        Excellon file in LZ (leading zeros) mode would use
        `zero_suppression='trailing'`

    Parameters
    ----------
    value : string
        A Gerber/Excellon-formatted string representing a numerical value.

    format :  tuple (int,int)
        Gerber/Excellon precision format expressed as a tuple containing:
        (number of integer-part digits, number of decimal-part digits)

    zero_suppression : string
        Zero-suppression mode. May be 'leading', 'trailing' or 'none'

    Returns
    -------
    value : float
        The specified value as a floating-point number.

    """
    if '.' in value:
        return float(value)
    integer_digits, decimal_digits = format
    MAX_DIGITS = integer_digits + decimal_digits
    if MAX_DIGITS > 13 or integer_digits > 6 or decimal_digits > 7:
        raise ValueError('Parser only supports precision up to 6:7 format')
    value = value.lstrip('+')
    negative = '-' in value
    if negative:
        value = value.lstrip('-')
    missing_digits = MAX_DIGITS - len(value)
    if zero_suppression == 'trailing':
        digits = list(value + '0' * missing_digits)
    elif zero_suppression == 'leading':
        digits = list('0' * missing_digits + value)
    else:
        digits = list(value)
    result = float(''.join(digits[:integer_digits] + ['.'] + digits[
        integer_digits:]))
    return -result if negative else result


def low_daily_frequency(df):
    """
    Checks for weekdays that have less than 600 candles 'G01' OR
    Checks for sundays that have less than 60 candles 'G01'

    :df dataframe consisting of g01 candles
    :return dataframe containing days that have a low frequency of g01 candles
    :rtype dataframe
    """
    df = df.new_year
    df = df.dropna(how='any')
    xmas = (df.index.month == 12) & (df.index.day == 25)
    new_year = (df.index.month == 1) & (df.index.day == 1)
    sunday_condition = (df.index.weekday != 6) & (df['volume'] < 600) & ~(xmas
         | new_year)
    not_sunday_condition = (df.index.weekday == 6) & (df['volume'] < 60) & ~(
        xmas | new_year)
    df = df.loc[sunday_condition | not_sunday_condition]
    return df


def is_localhost(hostname):
    """
    Literally checks that specified hostname means local host.
    This function does not perform DNS lookup.
    Use it in combination with `get_localhost`.

    :param hostname: Domain name or IPv4/IPv6 address.
    :return: True if specified host is a local host.
    """
    return hostname in ('localhost', 'localhost.localdomain', '127.0.0.1',
        '::1')


@classmethod
def deserialize(cls, serializer, s_state, **kwargs):
    """
        Deserializes a WorkflowSpec instance using the provided serializer.

        :type  serializer: :class:`SpiffWorkflow.serializer.serialzer.Serializer`
        :param serializer: The serializer to use.
        :type  s_state: object
        :param s_state: The serialized workflow specification object.
        :type  kwargs: dict
        :param kwargs: Passed to the serializer.
        :rtype:  WorkflowSpec
        :returns: The resulting instance.
        """
    return serializer.deserialize_workflow_spec(s_state, **kwargs)


def p_statement_expr(p):
    """statement : expr SEMICOLON"""
    p[0] = 'statement_expr', p[1]


def cmd_mode(args):
    """Set file transfer mode.  No read access required. Obselete.
        """


def remove_all_records(apps, schema_editor):
    """
    We can't import the Post model directly as it may be a newer
    version than this migration expects. We use the historical version.
    """
    Object = apps.get_model('contactus', 'ContactUs')
    Object.objects.all().delete()


def dbh_xlg(path, contenttype, extension, roottag, nsurl):
    """ Generic XLG Handler - Returns xlg_viewer for all XLG files """
    if (extension == 'xlg' or extension == 'xlp') and nsurl.startswith(
        'http://thermal.cnde.iastate.edu'):
        return 'db_datacollect_v2_viewer'
    else:
        return False


def theta_Cl_PO4_HFM89(T, P):
    """a-a': chloride phosphate [HFM89]."""
    theta = -0.59
    valid = T == 298.15
    return theta, valid


def duplicate_move(MASK_OT_duplicate=None, TRANSFORM_OT_translate=None):
    """Duplicate mask and move

    :param MASK_OT_duplicate: Duplicate Mask, Duplicate selected control points and segments between them
    :param TRANSFORM_OT_translate: Translate, Translate (move) selected items
    """
    pass


def list(feeds, args):
    """List all the feeds in the database"""
    for i, feed in enumerate(feeds):
        if feed.active:
            active_char = '*'
        else:
            active_char = ' '
        print('{}: [{}] {}'.format(i, active_char, feed))


def hex2rgb(color):
    """Converts a hex str to RGB list."""
    rgb_clr = list(tuple(bytes.fromhex('{}'.format(color.strip('#')))))
    return rgb_clr


def vertex_group_fix(dist: float=0.0, strength: float=1.0, accuracy: float=1.0
    ):
    """Modify the position of selected vertices by changing only their respective groups’ weights (this tool may be slow for many vertices)

    :param dist: Distance, The distance to move to
    :type dist: float
    :param strength: Strength, The distance moved can be changed by this multiplier
    :type strength: float
    :param accuracy: Change Sensitivity, Change the amount weights are altered with each iteration: lower values are slower
    :type accuracy: float
    """
    pass


def Date(zone=None):
    """ Return the DCMI Date element (default resource date).

        o Result is a string, formatted 'YYYY-MM-DD H24:MN:SS TZ'.

        o If 'zone' is 'None', return the time in the system default
          timezone.

        o Permission:  View
        """


def id_delete():
    """Delete the ID under cursor

    """
    pass


def gen_time_str(t_info):
    """
    从时间信息生成要访问的日志文件名

    20150101

    """
    year = str(t_info.tm_year)
    if t_info.tm_mon < 10:
        month = '0' + str(t_info.tm_mon)
    else:
        month = str(t_info.tm_mon)
    if t_info.tm_mday < 10:
        day = '0' + str(t_info.tm_mday)
    else:
        day = str(t_info.tm_mday)
    return year + month + day


def nt_quote_arg(arg):
    """Quote a command line argument according to Windows parsing rules"""
    result = []
    needquote = False
    nb = 0
    needquote = ' ' in arg or '\t' in arg
    if needquote:
        result.append('"')
    for c in arg:
        if c == '\\':
            nb += 1
        elif c == '"':
            result.append('\\' * (nb * 2) + '\\"')
            nb = 0
        else:
            if nb:
                result.append('\\' * nb)
                nb = 0
            result.append(c)
    if nb:
        result.append('\\' * nb)
    if needquote:
        result.append('\\' * nb)
        result.append('"')
    return ''.join(result)


def rotate():
    """Rotate the view

    """
    pass


def get_transcript2phylosofs(data, exon2char):
    """
    Return a dictionary from transcript id to its phylosofs representation.
    """
    transcript2phylosofs = {}
    for _, gene in data.groupby('GeneID'):
        for transcript_id, transcript in gene.groupby('TranscriptID'):
            phylosofs = []
            for subexon in transcript.sort_values('SubexonRank')['S_exons']:
                for ortholog in subexon.split('/'):
                    phylosofs.append(exon2char[ortholog])
            transcript2phylosofs[transcript_id] = ''.join(phylosofs)
    return transcript2phylosofs


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


def fixture_to_tables(fixture):
    """ convert fixture into *behave* examples
    :param fixture: a dictionary in the following form::

        {
            "test1name":
            {
                "test1property1": ...,
                "test1property2": ...,
                ...
            },
            "test2name":
            {
                "test2property1": ...,
                "test2property2": ...,
                ...
            }
        }

    :return: a list, with each item represent a table: `(caption, rows)`,
    each item in `rows` is `(col1, col2,...)`
    """
    tables = []
    for title, content in fixture.iteritems():
        rows = []
        keys = sorted(content.keys())
        rows.append(tuple(keys))
        row1 = []
        for col in rows[0]:
            row1.append(content[col])
        rows.append(tuple(row1))
        tables.append((title, tuple(rows)))
    return tables


def get_target_namespace(xsd_tree, namespaces):
    """Returns the target namespace used in the schema

    Args:
        xsd_tree:
        namespaces:

    Returns:

    """
    root_attributes = xsd_tree.getroot().attrib
    target_namespace = root_attributes['targetNamespace'
        ] if 'targetNamespace' in root_attributes else None
    target_namespace_prefix = ''
    if target_namespace is not None:
        for prefix, url in list(namespaces.items()):
            if url == target_namespace:
                target_namespace_prefix = prefix
                break
    return target_namespace, target_namespace_prefix


def train_2d(trainer):
    """Optimize the objective function of 2d variables with a customized trainer."""
    x1, x2 = -5, -2
    s_x1, s_x2 = 0, 0
    res = [(x1, x2)]
    for i in range(20):
        x1, x2, s_x1, s_x2 = trainer(x1, x2, s_x1, s_x2)
        res.append((x1, x2))
    print('epoch %d, x1 %f, x2 %f' % (i + 1, x1, x2))
    return res


def boolify(v):
    """
    return a boolean from a string
    yes, y, true, True, t, 1 -> True
    otherwise -> False
    """
    return v.lower() in ['yes', 'y', 'true', 't', '1']


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


def create_scales_at_adding(image, event):
    """Create scales for edm listing images
       to avoid overlay timeout
       """
    if image.portal_type != 'Image':
        return
    if image.getParentNode().getLayout() != 'edm_folder_listing':
        return
    image.restrictedTraverse('@@images').scale(fieldname='image', scale='large'
        )


def remove_if_exists(input_list, entries_to_remove):
    """
    Utility to remove certain values from a list.

    :param input_list: initial list
    :type input_list: list
    :param entries_to_remove: values to remove
    :type entries_to_remove: list
    :return: list with removed entries
    :rtype: list
    """
    assert isinstance(input_list, list)
    for entry in entries_to_remove:
        if entry in input_list:
            input_list.remove(entry)
    return input_list


def serializeValueWithNone(value):
    """Return NONE_MARKER if value is None, otherwise serialize normally.
        """


@classmethod
def get_version(cls, name):
    """ Checks a string for a possible version of an object (no prefix, no suffix).
            Assumes only up to 4 digit padding

        :param name: str, string that represents a possible name of an object
        :return: (float, int, list(str), None), gets the version number then the string matches
        """
    try:
        date = cls.get_date(name)
        date = date['datetime'].strftime(date['format'])
    except TypeError:
        pass
    return cls.get_version_naive(name, ignore=date or '')


def write_lines(filepath, lines):
    """Write the given lines to the file in filepath

    Parameters
    ----------
    filepath: str

    lines: list of str
    """
    with open(filepath, 'w') as f:
        f.writelines(lines)


def ascii_chr(value):
    """
    Converts byte to ASCII char

    :param value: ASCII code of character
    :return: char
    """
    return bytes([value])


@classmethod
def __init_subclass_with_meta__(cls, **meta_options):
    """This method just terminates the super() chain"""


def conflicting_single_link(scheme, link):
    """
    Find and return an existing link in `scheme` connected to the same
    input channel as `link` if the channel has the 'single' flag.
    If no such channel exists (or sink channel is not 'single')
    return `None`.

    """
    if link.sink_channel.single:
        existing = scheme.find_links(sink_node=link.sink_node, sink_channel
            =link.sink_channel)
        if existing:
            assert len(existing) == 1
            return existing[0]
    return None


@classmethod
def storage_key(cls, pk):
    """Key within the document store for a particular pk."""
    return '{storage_name}/{pk}'.format(storage_name=cls.storage_name, pk=pk)


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

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

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


def quick_pagination(queryset, page, limit, max_limit=1000):
    """
    Функция быстрой паджинации для больших таблиц, не вызывающая count(*).
    """
    try:
        page = int(page)
    except ValueError:
        page = 1
    try:
        limit = int(limit)
        assert limit <= max_limit
    except ValueError:
        limit = 10
    except AssertionError:
        limit = max_limit
    offset = (page - 1) * limit
    queryset = queryset[offset:offset + limit + 1]
    result = queryset
    if len(result) > limit:
        has_next = True
        result = result[:limit]
    else:
        has_next = False
    return result, page, limit, has_next


def is_valid_patch(xs, ys, patch_size, purple_mask, intensity_threshold,
    threshold=0.5):
    """Deprecated, computes whether patch is valid."""
    print(xs, ys)
    return (purple_mask[xs:xs + patch_size, ys:ys + patch_size] >=
        intensity_threshold).mean() > threshold


def groupby(x, key):
    """Like `itertools.groupby` but doesn't need to be sorted, and isn't lazy"""
    res = {}
    for o in x:
        res.setdefault(key(o), []).append(o)
    return res


@classmethod
def begin(cls):
    """
        begin() and commit() let you explicitly specify an SQL transaction.
        Be sure to call commit() after you call begin().
        """
    db = cls.db
    db.b_commit = False


def add_marker_move(CLIP_OT_add_marker=None, TRANSFORM_OT_translate=None):
    """Add new marker and move it on movie

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


def __hyp2f1_coefficients(m, N):
    """ Precomputes the coefficients of 1/f(P) = hyp2f1(1, -m, N-m, z).

    m -- a positive integer.
    N -- a positive integer greater than m.
    """
    f = float(m)
    g = N - m
    c = [0] * (m + 1)
    c[0] = 1.0
    k = 1
    while True:
        c[k] = f / g * c[k - 1]
        f -= 1
        if f == 0:
            break
        k += 1
        g += 1
    return c


def distinguishable_paths(path1, path2):
    """
    Checks if two model paths are distinguishable in a deterministic way, without looking forward
    or backtracking. The arguments are lists containing paths from the base group of the model to
    a couple of leaf elements. Returns `True` if there is a deterministic separation between paths,
    `False` if the paths are ambiguous.
    """
    e1, e2 = path1[-1], path2[-1]
    for k, e in enumerate(path1):
        if e not in path2:
            depth = k - 1
            break
    else:
        depth = 0
    if path1[depth].max_occurs == 0:
        return True
    univocal1 = univocal2 = True
    if path1[depth].model == 'sequence':
        idx1 = path1[depth].index(path1[depth + 1])
        idx2 = path2[depth].index(path2[depth + 1])
        before1 = any(not e.is_emptiable() for e in path1[depth][:idx1])
        after1 = before2 = any(not e.is_emptiable() for e in path1[depth][
            idx1 + 1:idx2])
        after2 = any(not e.is_emptiable() for e in path1[depth][idx2 + 1:])
    else:
        before1 = after1 = before2 = after2 = False
    for k in range(depth + 1, len(path1) - 1):
        univocal1 &= path1[k].is_univocal()
        idx = path1[k].index(path1[k + 1])
        if path1[k].model == 'sequence':
            before1 |= any(not e.is_emptiable() for e in path1[k][:idx])
            after1 |= any(not e.is_emptiable() for e in path1[k][idx + 1:])
        elif any(e.is_emptiable() for e in path1[k] if e is not path1[k][idx]):
            univocal1 = False
    for k in range(depth + 1, len(path2) - 1):
        univocal2 &= path2[k].is_univocal()
        idx = path2[k].index(path2[k + 1])
        if path2[k].model == 'sequence':
            before2 |= any(not e.is_emptiable() for e in path2[k][:idx])
            after2 |= any(not e.is_emptiable() for e in path2[k][idx + 1:])
        elif any(e.is_emptiable() for e in path2[k] if e is not path2[k][idx]):
            univocal2 = False
    if path1[depth].model != 'sequence':
        if before1 and before2:
            return True
        elif before1:
            return univocal1 and e1.is_univocal() or after1 or path1[depth
                ].max_occurs == 1
        elif before2:
            return univocal2 and e2.is_univocal() or after2 or path2[depth
                ].max_occurs == 1
        else:
            return False
    elif path1[depth].max_occurs == 1:
        return before2 or (before1 or univocal1) and (e1.is_univocal() or
            after1)
    else:
        return (before2 or (before1 or univocal1) and (e1.is_univocal() or
            after1)) and (before1 or (before2 or univocal2) and (e2.
            is_univocal() or after2))


def nolog(*allargs):
    """Dummy function, assigned to log when logging is disabled."""
    pass


@classmethod
def is_site_in_topic(cls) ->bool:
    """True if site id is in topic."""
    return True


def _read_line_data(ncol, stripline, line_parser):
    """Read data for :py:func:`.read_some_lines.`.

    Parameters
    ----------
    ncol : integer
        The expected number of columns to read. If this is less than 1
        it is not yet set. Note that we skip data which appear
        inconsistent. A warning will be issued about this.
    stripline : string
        The line to read. Note that we assume that leading and
        trailing spaces have been removed.
    line_parser : callable
        A method we use to parse a single line.

    """
    if line_parser is None:
        return stripline, True, ncol
    try:
        linedata = line_parser(stripline)
    except (ValueError, IndexError):
        return None, False, -1
    newcol = len(linedata)
    if ncol == -1:
        ncol = newcol
    if newcol == ncol:
        return linedata, True, ncol
    return None, False, -1


def HOUR(expression):
    """
    Returns the hour portion of a date as a number between 0 and 23.
    See https://docs.mongodb.com/manual/reference/operator/aggregation/hour/
    for more details
    :param expression: expression or variable of a Date, a Timestamp, or an ObjectID
    :return: Aggregation operator
    """
    return {'$hour': expression}


def end_check(input_string):
    """
    This function check end page
    :param input_string: raw html
    :type input_string:str
    :return: True or False
    """
    if input_string.find('reached the end') != -1:
        return True
    else:
        return False


def psi_MgOH_Cl_OH_HMW84(T, P):
    """c-a-a': magnesium-hydroxide chloride hydroxide [HMW84]."""
    psi = 0
    valid = T == 298.15
    return psi, valid


def rule_1(doc):
    """ Validate :ref:`ags4_rule_1`

    :param raw_str:
    :rtype: tuple
    :return:
        - A list of ags_errors
        - A list of sys_errors
    """
    warnings = []
    errors = []
    try:
        doc.source.decode('ascii')
        return warnings, errors
    except UnicodeDecodeError:
        errors.append('Unicode decode error')
        for lidx, line in enumerate(doc.source.split('\n')):
            for cidx, charlie in enumerate(line):
                if ord(charlie) < 128:
                    pass
                else:
                    warnings.append(dict(line=lidx + 1, column=cidx + 1,
                        illegal=[]))
    return warnings, errors


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


def default(value, default):
    """
    Return `default` is `value` is :data:`None`, otherwise return `value`.
    """
    if value is None:
        return default
    return value


def get_usage_plans(position=None, keyId=None, limit=None):
    """
    Gets all the usage plans of the caller's account.
    See also: AWS API Documentation

    :example: response = client.get_usage_plans(
        position='string',
        keyId='string',
        limit=123
    )

    :type position: string
    :param position: The current pagination position in the paged result set.

    :type keyId: string
    :param keyId: The identifier of the API key associated with the usage plans.

    :type limit: integer
    :param limit: The maximum number of returned results per page.

    :rtype: dict
    :return: {
        'position': 'string',
        'items': [
            {
                'id': 'string',
                'name': 'string',
                'description': 'string',
                'apiStages': [
                    {
                        'apiId': 'string',
                        'stage': 'string'
                    },
                ],
                'throttle': {
                    'burstLimit': 123,
                    'rateLimit': 123.0
                },
                'quota': {
                    'limit': 123,
                    'offset': 123,
                    'period': 'DAY'|'WEEK'|'MONTH'
                },
                'productCode': 'string'
            },
        ]
    }

    """
    pass


def get_query_param(request, key):
    """Get query parameter uniformly for GET and POST requests."""
    value = request.query_params.get(key) or request.data.get(key)
    if value is None:
        raise KeyError()
    return value


def _get_pol_flag(fhc_vars):
    """Check for presence of polarimetric variables"""
    if fhc_vars['DR'] or fhc_vars['KD'] or fhc_vars['LD'] or fhc_vars['RH']:
        pol_flag = True
    else:
        pol_flag = False
    return pol_flag