def provides_facts():
    """
    Doesn't really provide any facts.
    """
    return {}


def butterworth_type_filter(frequency, highcut_frequency, order=2):
    """
    Butterworth low pass filter

    Parameters
    ----------

    highcut_frequency: float
        high-cut frequency for the low pass filter
    fs: float
        sampling rate, 1./ dt, (default = 1MHz)
    period:
        period of the signal (e.g. 25Hz base frequency, 0.04s)
    order: int
        The order of the butterworth filter

    Returns
    -------

    frequency, h: ndarray, ndarray
        Filter values (`h`) at frequencies (`frequency`) are provided.
    """
    h = 1.0 / (1 + 1.0j * (frequency / highcut_frequency)) ** order
    highcut_frequency = 300 * 1000.0
    h *= 1.0 / (1 + 1.0j * (frequency / highcut_frequency)) ** 1
    return h


def ask_question(question, accept_confirmation=False):
    """Method to ask the user a yes/no question

    Args:
        question(str): A question to ask the user
        accept_confirmation(bool): Optional flag, if True will automatically accept question

    Returns:
        bool: True if yes, False if no
    """
    if accept_confirmation:
        return True
    valid_response = {'yes': True, 'y': True, 'no': False, 'n': False}
    while True:
        print('{} [y/n]: '.format(question), end='')
        choice = input().lower().strip()
        if choice in valid_response:
            return valid_response[choice]
        else:
            print("Please respond with 'yes' or 'no' (or 'y' or 'n').\n")


def FIBOTR(df, price='Close'):
    """
    Fibonacci Time Retracements
    """


def expandhosts(hosts, config):
    """
    load config and expand host names
    """
    res = []
    for host in hosts:
        if host in config:
            expandedhosts = config[host].get('host', host)
        else:
            expandedhosts = [host]
        res += expandedhosts
    return res


def __subclasscheck__(cls, subclass):
    """``issubclass(subclass, cls)``"""
    if cls is subclass:
        return True
    try:
        template = subclass.template
    except AttributeError:
        return False
    else:
        if template == cls.template:
            if cls.specialisations is None:
                return True
            else:
                return cls._subclasscheck_specialisation(subclass)
        return False


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 hhv(series, n):
    """
    求series在n个周期内的最高值

        注意: n为0的情况下, 或当n为有效值但当前的series序列元素个数不足n个, 函数返回 NaN 序列

    Args:
        series (pandas.Series): 数据序列

        n (int): 周期

    Returns:
        pandas.Series: 最高值序列

    Example::

        from tqsdk import TqApi, TqSim, tafunc

        api = TqApi(TqSim())
        klines = api.get_kline_serial("CFFEX.IF1908", 24 * 60 * 60)
        hhv = tafunc.hhv(klines.high, 4)  # 求4个周期最高价的最大值, 即4周期高点(包含当前k线)
        print(list(hhv))
    """
    hhv_data = series.rolling(n).max()
    return hhv_data


def split_unescape(s, delim, escape='\\', unescape=True):
    """
    >>> split_unescape('foo|bar', '|')
    ['foo', 'bar']
    >>> split_unescape(r'foo\\|bar', '|')
    ['foo|bar']
    >>> split_unescape(r'foo\\|bar', '|', unescape=True)
    [r'foo|', 'bar']
    >>> split_unescape(r'foo\\|bar', '|', unescape=False)
    [r'foo\\', 'bar']
    >>> split_unescape(r'foo', '|', unescape=True)
    [r'foo']
    """
    ret = []
    current = []
    itr = iter(s)
    for ch in itr:
        if ch == escape:
            try:
                if not unescape:
                    current.append(escape)
                current.append(next(itr))
            except StopIteration:
                if unescape:
                    current.append(escape)
        elif ch == delim:
            ret.append(''.join(current))
            current = []
        else:
            current.append(ch)
    ret.append(''.join(current))
    return ret


def merge_dicts(*dicts):
    """Given any number of dicts, merges them into a new one."""
    result = {}
    for d in dicts:
        result.update(d)
    return result


@classmethod
def register_model(cls, model):
    """
        Register data model.

        :param model: Data model
        :type model: class
        """
    cls.models.add(model)


@staticmethod
def _call_hooks(obj, hooks):
    """ Calls a series of callbacks """
    if not hooks:
        return obj
    for hook in hooks:
        ret = hook(obj)
        if ret is not None:
            obj = ret
    return obj


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


@staticmethod
def from_primitive(primitive):
    """Setup the current PDU using an A-release (response) primitive.

        Parameters
        ----------
        primitive : pdu_primitives.A_RELEASE
            The primitive to use to set the current PDU field values.
        """
    pass


def update_mailq(data1, data2):
    """ Update mailq dict """
    for key, value in data2.items():
        if key not in data1:
            data1[key] = []
        for item in value:
            data1[key].append(item)
    return data1


def convert2boolean(arg):
    """convert2boolean is used for environmental variables that must be
    returned as boolean"""
    if not isinstance(arg, bool):
        return arg.lower() in ('yes', 'true', 't', '1', 'y')
    return arg


def geometric_to_geopotential(z, r0):
    """ Converts from given geometric altitude to geopotential one.

    Parameters
    ----------
    z: ~astropy.units.Quantity
        Geometric altitude.
    r0: ~astropy.units.Quantity
        Planet/Natural satellite radius.

    Returns
    -------
    h: ~astropy.units.Quantity
        Geopotential altitude.
    """
    h = r0 * z / (r0 + z)
    return h


@classmethod
def assemble(cls, user_id, methods, system, project_id, domain_id,
    expires_at, audit_ids, trust_id, federated_group_ids,
    identity_provider_id, protocol_id, access_token_id, app_cred_id):
    """Assemble the payload of a token.

        :param user_id: identifier of the user in the token request
        :param methods: list of authentication methods used
        :param system: a string including system scope information
        :param project_id: ID of the project to scope to
        :param domain_id: ID of the domain to scope to
        :param expires_at: datetime of the token's expiration
        :param audit_ids: list of the token's audit IDs
        :param trust_id: ID of the trust in effect
        :param federated_group_ids: list of group IDs from SAML assertion
        :param identity_provider_id: ID of the user's identity provider
        :param protocol_id: federated protocol used for authentication
        :param access_token_id: ID of the secret in OAuth1 authentication
        :param app_cred_id: ID of the application credential in effect
        :returns: the payload of a token

        """
    raise NotImplementedError()


@classmethod
def search(cls, string, *args, **kwargs):
    """
        A wrapper for ``re.regex.search``: Searches for a match in the argument string.
        Takes optional parameters like ``re.regex.search``.
        :param string: the string in which to search
        :return: an instance of this class, if a match was found; ``None`` otherwise

        :see: https://docs.python.org/3.6/library/re.html#re.regex.search
        """
    return cls._delegate(cls._pattern.search, string, *args, **kwargs)


@classmethod
def check_runtime_prereq(cls):
    """Checks for install prerequisites.

        This method will be run at Django start and should check if everything this engine needs is installed
        and ready to go. You can check for installed django apps via settings.INSTALLED_APPS etc.
        """


def knife_project(cut_through: bool=False):
    """Use other objects outlines & boundaries to project knife cuts

    :param cut_through: Cut through, Cut through all faces, not just visible ones
    :type cut_through: bool
    """
    pass


def set_logger_factory(factory):
    """Set a factory object for creating loggers.  This object must
    publish a method or class named 'get_logger' that takes a string
    parameter naming the logger instance to retrieve.  Logger objects
    returned by this factory must, at a minimum, expose the methods
    'isEnabledFor' and 'debug'.
    """
    global _logger_factory
    _logger_factory = factory


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


def store_local_storage(file):
    """ Stores the file locally with the desired storage information """
    pass


@staticmethod
def check_req_keys_in_dict(sd_key, req_keys, sd_instance):
    """
        Check that required keys are in a test dictionary

        Args:
            :sd_key: special key from the schemadict
            :req_keys: List of keys required in the test dictionary
            :testdict: Test dictionary

        Raises:
            :KeyError: If a required key is not found in the test dictionary
        """
    testdict_keys = list(sd_instance.testdict.keys())
    for req_key in req_keys:
        if req_key not in testdict_keys:
            raise KeyError(f'{sd_key!r}: required key {req_key!r} not found')


def infer(datum):
    """
    Returns the inferred data type
    """
    if datum is None or datum == '':
        return None
    try:
        int(datum)
        return 'integer'
    except (ValueError, TypeError):
        pass
    try:
        float(datum)
        return 'number'
    except (ValueError, TypeError):
        pass
    return 'string'


def handle_line(line, builder):
    """
    Read one line of the tab-separated nadya.jp input, and yield 0 or 1
    ConceptNet edges that can be extracted from it.
    """
    parts = line.rstrip('\n').split('\t')
    (cnet4_id, lang, frame_text, relname, start_text, end_text, freq, vote,
        email, creator, voter) = parts
    if cnet4_id == 'cnet4_id':
        return
    cnet4_id = int(cnet4_id)
    freq = int(freq)
    vote = int(vote)
    if vote > 0:
        parts_dict = {'lang': lang, 'polarity': freq, 'cnet4_id': cnet4_id,
            'relname': relname, 'frame_text': frame_text, 'startText':
            start_text, 'endText': end_text, 'creator': voter, 'votes': [],
            'activity': 'nadya.jp', 'goodness': 3}
        yield from builder.handle_assertion(parts_dict)


def need_redirect(resp):
    """ check whether redirect is necessary. """
    if resp.status == 301 or resp.status == 302:
        url = resp.getheader('Location')
        return url


def lock_output_type(lock: bool=True) ->None:
    """
    This method will restrict type entropy by always returning a List[Header] instead of Union[Header, List[Header]]
    """
    global OUTPUT_LOCK_TYPE
    OUTPUT_LOCK_TYPE = lock


def _check_elements_equal(lst):
    """
    Returns true if all of the elements in the list are equal.
    """
    assert isinstance(lst, list), 'Input value must be a list.'
    return not lst or lst.count(lst[0]) == len(lst)


def strip_sdist_extras(ignore, filelist):
    """Strip generated files that are only present in source distributions.

    We also strip files that are ignored for other reasons, like
    command line arguments, setup.cfg rules or MANIFEST.in rules.
    """
    return ignore.filter(filelist)


def x_offset_gff(GFFParseobj, x_offset):
    """Takes in a gff object (a gff file parsed as a pandas dataframe),
    and an x_offset value and shifts the start, stop, center, lmost, and rmost.

    Returns a GFFParse object with the shifted values in GFFParse.features.
    """
    for columnname in ['start', 'stop', 'center', 'lmost', 'rmost']:
        GFFParseobj.features[columnname] = GFFParseobj.features[columnname
            ] + x_offset
    return GFFParseobj


def parse_varint(tx):
    """ Parses a given transaction for extracting an encoded varint element.

    :param tx: Transaction where the element will be extracted.
    :type tx: TX
    :return: The b-bytes representation of the given value (a) in hex format.
    :rtype: hex str
    """
    data = tx.hex[tx.offset:]
    assert len(data) > 0
    size = int(data[:2], 16)
    assert size <= 255
    if size <= 252:
        storage_length = 1
    elif size == 253:
        storage_length = 3
    elif size == 254:
        storage_length = 5
    elif size == 255:
        storage_length = 9
    else:
        raise Exception('Wrong input data size')
    varint = data[:storage_length * 2]
    tx.offset += storage_length * 2
    return varint


@staticmethod
def __get_number_label(dict_pixel_label):
    """Get sum of label in image

        @return dict_label:  with key is label, value: coordinates of sprite
        @return list_label: sum of label in image
        """
    dict_label = {}
    for key, value in dict_pixel_label.items():
        if value not in dict_label:
            dict_label[value] = [key]
        elif key not in dict_label[value]:
            dict_label[value].append(key)
    return dict_label


def tag_slice_iter_from_slices_of_tag_dict(slices_of_tag):
    """
    Get an iterator of (tag, (bt, tt)) pairs
    :param slices_of_tag: a {tag: [(bt, tt),...], ...} dict listing slices annotated by tags
    :return: a tag, (bt, tt) iterator
    """
    for tag, slices in slices_of_tag.items():
        for sl in slices:
            yield tag, sl


def write(data):
    """
        Write some data to the physical connection, in sequence, in a
        non-blocking fashion.

        If possible, make sure that it is all written.  No data will
        ever be lost, although (obviously) the connection may be closed
        before it all gets through.
        """


@classmethod
def serialize(cls, value):
    """Return a string representing the formatted value"""
    raise NotImplementedError


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

    The ".dev0" means dirty.

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


def add_dicts(*args):
    """
    Combine dicts. If there are duplicate keys, raise an error.
    """
    new = {}
    for arg in args:
        for key in arg:
            if key in new:
                raise ValueError('Duplicate key: %r' % key)
            new[key] = arg[key]
    return new


def namespace_path_join(base, name):
    """Extend the current namespace path with an additional name

    Take a namespace path (i.e., package.module.class) and extends it
    with an additional name (i.e., package.module.class.subclass).
    This is similar to how os.path.join works.

    :param base: (String) The base namespace path.
    :param name: (String) The new name to append to the base path.
    :returns: (String) A new namespace path resulting from combination of
              base and name.
    """
    return '%s.%s' % (base, name)


def _add_doc(func, doc):
    """Add documentation to a function."""
    func.__doc__ = doc


def fixe_titre_ecran(cls, titre):
    """Fixe le titre de l'écran"""
    cls.ecran.title(titre)


def colname_gen(df, col_name='unnamed_col'):
    """ Returns a column name that isn't in the specified DataFrame
    Parameters:
    df - DataFrame
        DataFrame to analyze
    col_name - string, default 'unnamed_col'
        Column name to use as the base value for the generated column name
    """
    if col_name not in df.keys():
        yield col_name
    id_number = 0
    while True:
        col_name = col_name + str(id_number)
        if col_name in df.keys():
            id_number += 1
        else:
            return col_name


@staticmethod
def defaultSymbol():
    """
        Returns the default symbol path for this node.

        :returns: symbol path (or resource).
        """
    return ':/symbols/multilayer_switch.svg'


def calculateTimeError(localTime, referenceTime):
    """
    Calculate Time Error (TE) of two timebases assuming they are identically, uniformly sampled.

    Assume localTime and referenceTime are numpy arrays.

    "Definitions and terminology for synchronization networks", ITU-T G.810 (08/96), Section 4.5.13, pp7
    """
    assert localTime.size == referenceTime.size
    return localTime - referenceTime


def bin_append(a, b, length=None):
    """
    Appends number a to the left of b
    bin_append(0b1, 0b10) = 0b110
    """
    length = length or b.bit_length()
    return a << length | b


def collect_parameters(oauth_parameters, status, url_parameters):
    """Combines oauth, url and status parameters"""
    temp = oauth_parameters.copy()
    if status is not None:
        temp['status'] = status
    for k, v in url_parameters.iteritems():
        temp[k] = v
    return temp


def extract_basis_value_from_sos_file_path(file_path):
    """ does what it says, returns an int """
    return int(file_path.split('_B')[1].split('.json')[0])


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

        :param str val:
        :rtype: UserSelectorArg
        """
    return cls('team_member_id', val)


@classmethod
def _colspec(cls, dataset_width):
    """Generates the column specification for the LaTeX `tabular` environment
        based on the dataset width.

        The first column is justified to the left, all further columns are aligned
        to the right.

        .. note:: This is only a heuristic and most probably has to be fine-tuned
        post export. Column alignment should depend on the data type, e.g., textual
        content should usually be aligned to the left while numeric content almost
        always should be aligned to the right.

        :param dataset_width: width of the dataset
        """
    spec = 'l'
    for _ in range(1, dataset_width):
        spec += 'r'
    return spec


def get_roi_center(roi_reference, roi_size):
    """
    Returns the coordiantes of ROI center.

    :param roi_reference: (y, x) coordinates of ROI upper-left vertex.
    :param roi_size: (y. x) size of ROI.
    :return roi_center: (y, x) coordinates of ROI center pixel.
    """
    return roi_reference[0] + roi_size[0] // 2, roi_reference[1] + roi_size[1
        ] // 2


def gencrossentropy(px, py, pxpy, alpha=1, logbase=2, measure='T'):
    """
    Generalized cross-entropy measures.

    Parameters
    ----------
    px : array_like
        Discrete probability distribution of random variable X
    py : array_like
        Discrete probability distribution of random variable Y
    pxpy : 2d array_like, optional
        Joint probability distribution of X and Y.  If pxpy is None, X and Y
        are assumed to be independent.
    logbase : int or np.e, optional
        Default is 2 (bits)
    measure : str, optional
        The measure is the type of generalized cross-entropy desired. 'T' is
        the cross-entropy version of the Tsallis measure.  'CR' is Cressie-Read
        measure.
    """


def get_service_type(f):
    """
    Retrieves service type from function
    """
    return getattr(f, 'service_type', None)


@classmethod
def get_BZ_integration_grid_X(cls, calc, **kwargs):
    """Return a number of points in the Brillouin zone along reciprocal lattice vector X."""
    array = cls._get_BZ_integration_grid(calc, **kwargs)
    if array is not None:
        return array[0]
    return None


@conf
def fc_flags(conf):
    """
	Defines common fortran configuration flags and file extensions
	"""
    v = conf.env
    v.FC_SRC_F = []
    v.FC_TGT_F = ['-c', '-o']
    v.FCINCPATH_ST = '-I%s'
    v.FCDEFINES_ST = '-D%s'
    if not v.LINK_FC:
        v.LINK_FC = v.FC
    v.FCLNK_SRC_F = []
    v.FCLNK_TGT_F = ['-o']
    v.FCFLAGS_fcshlib = ['-fpic']
    v.LINKFLAGS_fcshlib = ['-shared']
    v.fcshlib_PATTERN = 'lib%s.so'
    v.fcstlib_PATTERN = 'lib%s.a'
    v.FCLIB_ST = '-l%s'
    v.FCLIBPATH_ST = '-L%s'
    v.FCSTLIB_ST = '-l%s'
    v.FCSTLIBPATH_ST = '-L%s'
    v.FCSTLIB_MARKER = '-Wl,-Bstatic'
    v.FCSHLIB_MARKER = '-Wl,-Bdynamic'
    v.SONAME_ST = '-Wl,-h,%s'


def load_linestyle(i):
    """
    Provide linestyle via index.
    @param i: index
    """
    linestyles = ['-', ':', '-.', '--']
    return linestyles[i % len(linestyles)]


@classmethod
def static_files_path(cls):
    """

		can be none or non-existens path

		:return:
		"""
    return None


def check(name, type, country, geometry, **args):
    """Should return True if this area is NEW, False if we should match against
    an ONS code, or an Area to be used as an override instead."""
    return False


def slice_as_int(s: slice, l: int) ->int:
    """Converts slices of length 1 to the integer index they’ll access."""
    out = list(range(*s.indices(l)))
    assert len(out) == 1
    return out[0]


def fmodifier_paste(only_active: bool=True, replace: bool=False):
    """Add copied F-Modifiers to the selected F-Curves

    :param only_active: Only Active, Only paste F-Modifiers on active F-Curve
    :type only_active: bool
    :param replace: Replace Existing, Replace existing F-Modifiers, instead of just appending to the end of the existing list
    :type replace: bool
    """
    pass


@staticmethod
def out_back(progress):
    """.. image:: images/anim_out_back.png
        """
    p = progress - 1.0
    return p * p * ((1.70158 + 1) * p + 1.70158) + 1.0


def to_str(seq):
    """Decode bytestring if necessary.

    :param seq: Input bytestring, string, or other sequence.
    :return: String.
    """
    if isinstance(seq, bytes):
        value = seq.decode('utf-8')
    elif isinstance(seq, str):
        value = seq
    else:
        value = str(seq)
    return value


def _relative_view(telstate, name):
    """Create a telstate view by appending `name` to all existing namespaces."""
    prefix = telstate.prefixes[-1]
    view = telstate.view(prefix + name, exclusive=True)
    for prefix in reversed(telstate.prefixes[:-1]):
        view = view.view(prefix + name)
    return view


def append_all(file, content, binary=False, encoding=None, errors=None):
    """Append the content to a file.

    :param file: path to file or file descriptor
    :type file: :term:`path-like object` or int
    :param content: file content
    :type content: bytes or str
    :param bool binary: if ``True`` the content must be ``bytes`` else ``str``
    :param str encoding: name of the encoding (ignored if ``binary=True``)
    :param str errors: error handler (ignored if ``binary=True``)
    :return: number of bytes or characters written
    :rtype: int
    :raises OSError: on I/O failure

    .. versionchanged:: 0.6.0
       Add parameter ``errors``
    """
    mode, encoding, errors = ('ab', None, None) if binary else ('at',
        encoding, errors)
    with open(file, mode=mode, encoding=encoding, errors=errors) as fh:
        return fh.write(content)


def muzeropad(runs, out):
    """
    muzeropad(runs,out)
        runs is a string containing the run number
    utility of the suite tab, not a method
    future:
    1) determine how many leading zeros for padding
       read a file from data dir
       check number of digits before '.'
       count number of digits in run
       zero pad
    now:
    0) zeroth version pads a fixed number of zeros to 4 digits
    out in mugui is _output_, Textarea for printing messages
    """
    zeros = '0000'
    if len(runs) < len(zeros):
        return zeros[:len(zeros) - len(runs)] + runs
    elif len(runs) == len(zeros):
        return runs
    else:
        with out:
            print('Too long run number!')
        return []


def parse_remainder(args):
    """Parse the remainder of the command line arguments"""
    if len(args) == 0:
        return {}
    if not args[0].startswith(('-', '--')):
        raise ValueError('Only optional arguments allowed')
    kwargs = {}
    curr_arg = args[0]
    curr_val = None
    for arg in args[1:]:
        if arg.startswith(('-', '--')):
            if not curr_val:
                kwargs[curr_arg] = True
            else:
                kwargs[curr_arg] = curr_val
            curr_arg = arg
            curr_val = None
        elif not curr_val:
            cur_val = arg
        elif isinstance(cur_val, list):
            cur_val.append(arg)
        else:
            cur_val = [cur_val]
            cur_val.append(arg)
    return kwargs


def _f_reaction_rev(sid, prefix='R_'):
    """Add reaction prefix to id.

    Warnings
    --------
    This method is intended for internal use only.

    """
    return prefix + sid


def __flatten(ls):
    """
    Aux function to flatten lists and remove None from result (k, v) sequences
    :param ls: original list
    :return: flattened list
    """
    for e in ls:
        if type(e) is list:
            for i in e:
                yield i
        elif type(e) is tuple:
            yield e


def _get_element_attrs(element, attrs):
    """Get the value of an attribute from an element

    Args:
        element (lxml.html.HtmlElement): dom element to be parsed
        attrs (list): Attributes to check

    Returns:
        dict: keys being the name of the attribute

    """
    result = {}
    for attr in attrs:
        result[attr] = element.get(attr)
    return result


def __setitem__(key, val):
    """Set item to storage.
        """


def keyListSort(keyList):
    """
    Sort list of keys by their names ignoring the case
    """
    keyList.sort(key=lambda x: x.GetName().lower())


def config(args):
    """execute subcommand config"""
    if args.default:
        from liesl.cli.lsl_api import init_lsl_api_cfg
        init_lsl_api_cfg(args.scope)
        return
    from liesl.cli.lsl_api import Ini
    ini = Ini(args.scope)
    ini.refresh()
    if args.sessionid:
        print(args.sessionid)
        try:
            ini.ini['lab']['SessionID'] = args.sessionid
        except KeyError:
            ini.ini['lab'] = {}
            ini.ini['lab']['SessionID'] = args.sessionid
        ini.write()
    if args.knownpeers:
        print(args.knownpeers)
        try:
            ini.ini['lab']['KnownPeers'] = '{' + args.knownpeers + '}'
        except KeyError:
            ini.ini['lab'] = {}
            ini.ini['lab']['KnownPeers'] = '{' + args.knownpeers + '}'
        ini.write()
    from liesl.cli.lsl_api import print_config
    print_config(args.scope)


def omit(*names):
    """Omit fields with given names
        """


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

    The ".dev0" means dirty.

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


def get_likers(item_type, item_id):
    """List all userids liking <item_type> <item_id>"""


def SetDataMenuBar(G2frame, menu=None):
    """Set the menu for the data frame.

    Note that data frame items do not have menus, for these (menu=None)
    display the standard main menu for the data tree window.
    """
    if menu is None:
        G2frame.SetMenuBar(G2frame.GSASIIMenu)
    else:
        G2frame.SetMenuBar(menu)


def header(string, flank=True):
    """

    Generate a Header String

    :param string: a string.
    :type string: ``str``
    :param flank: if True, flank the header with line breaks.
    :type flank: ``bool``
    :return:
    """
    sep_line = '-' * len(string)
    if flank:
        print('\n')
    print('\n{0}\n{1}\n{2}\n'.format(sep_line, string, sep_line))
    if flank:
        print('\n')


def tryname(text):
    """Try to make a loosely POSIX-style name."""
    stripped = str(text).strip()
    if not stripped:
        raise ValueError('Cannot make an option name from an empty string.')
    if not stripped[:1].isalnum():
        return stripped
    name = '-'.join(stripped.split())
    return f'-{name}' if len(name) == 1 else f'--{name}'


def set_warning_message(message):
    """Sets a warning. This will be reported by pingers.

    :param str|unicode message:

    :rtype: bool
    """
    return False


def addError(errors, experimenter, error):
    """Associates the error with the correct experimenter"""
    if experimenter not in errors.keys():
        errors[experimenter] = [error]
    else:
        errors[experimenter].append(error)


@classmethod
def base_queryset(cls):
    """
        Returns a queryset of objects of this type to use as a base
        for calling get_or_create() on.

        You can use the `select_related` attribute on your class to
        specify a list of foreign key field names, which the method
        will attempt to select additional related-object data for
        when the query is executed.

        If your needs are more complex than this, you can override
        this method on your custom class.
        """
    queryset = cls.objects.all()
    if cls.select_related is not None:
        queryset = queryset.select_related(*cls.select_related)
    return queryset


def scroll_backward(event, half=False):
    """
    Scroll window up.
    """
    w = event.app.layout.current_window
    b = event.app.current_buffer
    if w and w.render_info:
        info = w.render_info
        scroll_height = info.window_height
        if half:
            scroll_height //= 2
        y = max(0, b.document.cursor_position_row - 1)
        height = 0
        while y > 0:
            line_height = info.get_height_for_line(y)
            if height + line_height < scroll_height:
                height += line_height
                y -= 1
            else:
                break
        b.cursor_position = b.document.translate_row_col_to_index(y, 0)


def _nint(x):
    """Integer casting used in :func:`from_lt`."""
    if x >= 0:
        y = x + 0.5
    else:
        y = x - 0.5
    return int(y)


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

        :param SharedContentCopyDetails val:
        :rtype: EventDetails
        """
    return cls('shared_content_copy_details', val)


def shorten_lines(lines, maxlen):
    """Generate a list of shared prefixes and a map of long string -> encoded string."""
    prefixes = []
    mapping = {}
    for line in sorted(lines, key=lambda line: -len(line)):
        if len(line) <= maxlen:
            break
        for i, prefix in enumerate(prefixes):
            if line.startswith(prefix):
                break
        else:
            i = len(prefixes)
            prefixcode = '\x00%i\x00' % i
            prefix = line[:-(maxlen - len(prefixcode))]
            prefixes.append(prefix)
        mapping[line] = '\x00%i\x00%s' % (i, line[len(prefix):])
    return prefixes, mapping


def _update_pulled_fields(instance, imported_instance, fields):
    """ Update instance fields based on imported from backend data.

        Save changes to DB only one or more fields were changed.
    """
    modified = False
    for field in fields:
        pulled_value = getattr(imported_instance, field)
        if getattr(instance, field) != pulled_value:
            setattr(instance, field, pulled_value)
            modified = True
    if modified:
        instance.save()


def delete():
    """Erase selected strips from the sequencer

    """
    pass


def get_metadata_lines(name):
    """Yield named metadata resource as list of non-blank non-comment lines

       Leading and trailing whitespace is stripped from each line, and lines
       with ``#`` as the first non-blank character are omitted."""


@property
def all_supported_mime_types(cls):
    """
        Return all mime types supported by all implementations of `Serializer`.

        :return: A frozen set of mime types.
        """
    return cls._all_supported_mime_types


def bulletin_link():
    """Example: http://bulletin.sc.edu/preview_course.php?catoid=70&coid=85439"""
    raise BaseException('NOPE NOPE NOPE')


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

    The ".dev0" means dirty.

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


def parse_errors(path):
    """Parse the file path for errors."""
    dct = {'errors': [], 'warnings': [], 'fatal': []}
    fl = path.read_text().split('\n')
    append = False
    temp = ''
    for l in fl:
        if l.startswith('! '):
            dct['fatal'] += [l]
        if l.startswith('./.workspace/test.tex:'):
            temp = l
            append = True
        if append:
            temp += l
        if l.startswith('l.'):
            temp += l
            append = False
            dct['errors'] += [temp]
    for key in ['errors', 'warnings', 'fatal']:
        if dct[key]:
            return dct
    return {}


def coerce_put_post(request):
    """Django doesn't particularly understand REST. In case we send data over PUT,
    Django won't actually look at the data and load it. We need to twist its arm here.

    The try/except abomination here is due to a bug in mod_python. This should fix it.

    From django-piston/piston/utils.py

    """
    if request.method == 'PUT':
        if hasattr(request, '_post'):
            del request._post
            del request._files
        try:
            request.method = 'POST'
            request._load_post_and_files()
            request.method = 'PUT'
        except AttributeError:
            request.META['REQUEST_METHOD'] = 'POST'
            request._load_post_and_files()
            request.META['REQUEST_METHOD'] = 'PUT'
        request.PUT = request.POST


@classmethod
def line_solution_rate(cls, row, size=None):
    """How many cells in a given line are known to be solved"""
    raise NotImplementedError()


@staticmethod
def _update_listing_client_kwargs(client_kwargs, max_request_entries):
    """
        Updates client kwargs for listing functions.

        Args:
            client_kwargs (dict): Client arguments.
            max_request_entries (int): If specified, maximum entries returned
                by request.

        Returns:
            dict: Updated client_kwargs
        """
    client_kwargs = client_kwargs.copy()
    if max_request_entries:
        client_kwargs['num_results'] = max_request_entries
    return client_kwargs


def synchronize_download(client, source, destination):
    """ Synchronize local files with a remote directory.

    Long description.
    """
    raise NotImplementedError


def reverseByteOrder(data):
    """DEPRECATED: See https://github.com/adafruit/Adafruit_Python_GPIO/issues/48"""
    raise RuntimeError(
        'reverseByteOrder is deprecated! See: https://github.com/adafruit/Adafruit_Python_GPIO/issues/48'
        )


def store(obj, id=None):
    """Store an object in the database with given id

        If id is not specified, unique one will be generated
        """


def add_vectors(v1, v2):
    """
    Calculate the scalar product of two vectors
    """
    return v1[0] + v2[0], v1[1] + v2[1]


def list_non_recursive_find_keys_via_value(l, v):
    """
        from xdict.utils import *
        from xdict.jprint import pobj
        l = ['a',['b',['x','b']],'b']
        list_find_keys_via_value_non_recursive(l,'b')
    """
    rslt = []
    for i in range(0, l.__len__()):
        if l[i] == v:
            rslt.append(i)
    return rslt


@classmethod
def fromflat(cls, flat):
    """
        Create an instance of this from new logits values

        :param flat: ([float]) the categorical logits input
        :return: (ProbabilityDistribution) the instance from the given categorical input
        """
    return cls(flat)


def default_error_callback(e):
    """The default callback for handling exceptions caught in the client and server stubs:
    just raise the exception."""
    raise e


def amount_in_current_base(source):
    """
    Get amount in current base from input or output source
    """
    return source.amount * 10 ** source.base


def callable_validator(instance, attribute, value):
    """Validate that an attribute value is callable.

    :raises TypeError: if ``value`` is not callable
    """
    if not callable(value):
        raise TypeError('"{name}" value "{value}" must be callable'.format(
            name=attribute.name, value=value))


def Property(func):
    """ http://adam.gomaa.us/blog/the-python-property-builtin/ """
    return property(**func())


def __iter__():
    """Return an iterator for the keys of the mapping object.
        """


def add_mask(name: str='Mask'):
    """Add a mask node to the current node editor

    :param name: Name, Data-block name to assign
    :type name: str
    """
    pass


def parse_errfile(errfile):
    """
    Parse dream statistics from a particular fit.

    Returns overall chisq, list of chisq for individual models and
    a parameter dictionary with attributes for number, name, mean, median,
    p68 for 68% credible interval and p95 for 95% credible interval.

    The parameter dictionary is keyed by parameter name.

    Usually there is only one errfile in a directory, which can be
    retrieved using::

        import glob
        errfile = glob.glob(path+'/*.err')[0]
    """
    from .dream.stats import parse_var
    pars = []
    chisq = []
    overall = None
    with open(errfile) as fid:
        for line in fid:
            if line.startswith('[overall'):
                overall = float(line.split()[1][6:-1])
                continue
            if line.startswith('[chisq'):
                chisq.append(float(line.split()[0][7:-1]))
                continue
            p = parse_var(line)
            if p is not None:
                pars.append(p)
    if overall is None:
        overall = chisq[0]
    pardict = dict((p.name, p) for p in pars)
    return overall, chisq, pardict


@classmethod
def sretrieve(cls, val):
    """Return enumeration equivalent value in string if it is a valid enumeration code."""
    return cls.tostring(cls.retrieve(val))


def explode_port(port, base_port=10000):
    """
    Create a high port number > 10000 for use with UDP tunnels
    :param port: port number to add to the base port
    :param base_port: Port number above 10000
    :return: Int port number
    """
    port_error = 'port must be and integer from 0 to 99 or 666'
    if not isinstance(port, int):
        raise AttributeError(port_error)
    if port == 666:
        return base_port + port
    elif not 0 <= port < 100:
        raise AttributeError(port_error)
    return base_port + port


def get_shape_columns(shape):
    """Return the number of columns for the shape."""
    try:
        return shape[1]
    except (IndexError, TypeError):
        return 0


def f1(x):
    """
    Name: First constraint for the Wikipedia Rosenbrock function.
    """
    return (x[0] - 1.0) ** 3 - x[1] + 1.0


def _unflatten_dims(dims):
    """ ['a','b,c','d'] ==> ['a','b','c','d']
    """
    flatdims = []
    for d in dims:
        flatdims.extend(d.split(','))
    return flatdims


def _call_or_raise(exc, func, *args, **kw):
    """
    Call func(*args, **kw) and catch any exceptions, raising exc instead.

    This exists to avoid a bunch of boilerplate try/except blocks in
    parse_absolute_time()
    """
    try:
        return func(*args, **kw)
    except:
        raise exc


@staticmethod
def str2none(value):
    """ Ensures string to bool conversion """
    if value == '':
        return None
    return value


def aggregate_video_cluster_metrics(responses, metrics, info=None):
    """Aggregates the video cluster metrics with one step responses.

  Args:
    responses: a dictionary of names, observed responses.
    metrics: A dictionary mapping from metric_name to its value in float.
    info: Additional info for computing metrics (ignored here)

  Returns:
    A dictionary storing metrics after aggregation.
  """
    del info
    is_clicked = False
    metrics['impression'] += 1
    for response in responses:
        if not response['click']:
            continue
        is_clicked = True
        metrics['click'] += 1
        metrics['quality'] += response['quality']
        cluster_id = response['cluster_id']
        metrics['cluster_watch_count_cluster_%d' % cluster_id] += 1
    if not is_clicked:
        metrics['cluster_watch_count_no_click'] += 1
    return metrics


@staticmethod
def get_subtype(object_dictionary):
    """
        Given the hash representation of a subtype of this class,
        use the info in the hash to return the class of the subtype.
        """
    type = object_dictionary['type']
    if type == 'Structured':
        return 'StructuredSearchDetails'
    if type == 'FreeText':
        return 'FreeTextSearchDetails'
    else:
        return 'SearchDetails'


def get_ts_tick_labels_monthly(df):
    """
    get_ts_tick_labels_monthly

    Function for producing cleanly-formatted tick labels for DataFrames
    with a time-series index, one per week

    INPUTS:
        df - DataFrame with datetime Index from which to extract
             tick labels for plotting

    OUTPUTS:
        tick_labs - array of tick labels (one per month, minimally complex)

    """
    tick_labs = df.index.strftime('').values
    is_first_week_of_month = df.index.day <= 7
    is_first_week_of_year = df.index.dayofyear <= 7
    tick_labs[is_first_week_of_month] = df.index[is_first_week_of_month
        ].strftime('%b')
    tick_labs[is_first_week_of_year] = df.index[is_first_week_of_year
        ].strftime('%b\n%Y')
    return tick_labs


def merge_partial_elements(element_list):
    """
    merges model elements which collectively all define the model component,
    mostly for multidimensional subscripts

    Parameters
    ----------
    element_list

    Returns
    -------
    """
    outs = dict()
    for element in element_list:
        if element['py_expr'] != 'None':
            name = element['py_name']
            if name not in outs:
                eqn = element['expr'] if 'expr' in element else element['eqn']
                outs[name] = {'py_name': element['py_name'], 'real_name':
                    element['real_name'], 'doc': element['doc'], 'py_expr':
                    [element['py_expr']], 'unit': element['unit'], 'subs':
                    [element['subs']], 'lims': element['lims'], 'eqn': eqn,
                    'kind': element['kind'], 'arguments': element['arguments']}
            else:
                outs[name]['doc'] = outs[name]['doc'] or element['doc']
                outs[name]['unit'] = outs[name]['unit'] or element['unit']
                outs[name]['lims'] = outs[name]['lims'] or element['lims']
                outs[name]['eqn'] = outs[name]['eqn'] or element['eqn']
                outs[name]['py_expr'] += [element['py_expr']]
                outs[name]['subs'] += [element['subs']]
                outs[name]['arguments'] = element['arguments']
    return list(outs.values())


def _convert_to_token_dependent_format(dependencies):
    """Converts the entered value to a dependency format acceptable for the token() class.

    Args:
        dependencies (list(rule) or dict): These are rules in a list.

    Returns:
        list: Returns a list with a boolean in position 0 and dependencies in position 1.
    """
    if isinstance(dependencies, dict) and 'rules' in dependencies.keys():
        converted_input = dependencies
        if 'ignore_rules' not in dependencies.keys():
            converted_input['ignore_rules'] = []
        return [True, converted_input]
    elif isinstance(dependencies, list):
        converted_input = {'rules': dependencies, 'ignore_rules': []}
        return [True, converted_input]
    else:
        return [False, {'rules': [], 'ignore_rules': []}]


def invalidate():
    """Causes the next access to reread the dirstate.

        This is different from localrepo.invalidatedirstate() because it always
        rereads the dirstate. Use localrepo.invalidatedirstate() if you want to
        check whether the dirstate has changed before rereading it."""


@classmethod
def _get_version(cls):
    """Return VCS program version."""
    return cls._popen(['--version'], merge_err=False).split()[2]


@classmethod
def iter_pegasus_to_nice(cls, plist):
    """Return an iterator converting a sequence of 4-term Pegasus
        coordinates to 5-term nice coordinates.

        Note that this method does not depend on the size of the Pegasus
        lattice.
        """
    for p in plist:
        yield cls.pegasus_to_nice(p)


def new():
    """Return a new hashid value."""


def RemoveProperty(cls, attr: str):
    """Removes a dynamically defined property.

    :param cls: The class containing the property (must be a positional argument).
    :param attr: Property name (must be passed as a keyword).
    :type attr: str
    """
    pass


def check_type(name, val, expected_type):
    """
    returns and converts if necessary
    :param name: the name of the value
    :param val: the value to check
    :param expected_type: the expected type
    """
    if isinstance(expected_type, list):
        if val not in expected_type:
            raise ValueError('{} is not a member of expected list {}, got {}'
                .format(name, expected_type, val))
    elif not isinstance(val, expected_type):
        raise ValueError("{} should be a '{}' but is of type '{}'.".format(
            name, expected_type.__name__, type(val).__name__))


@classmethod
def from_dict(cls, dict_obj):
    """ Creates a yalchemy ForeignKey from a dictionary.

        The dictionary has the following specification::

            {
                # The name of the column
                'column': str(required),

                # The name of the remote table
                'remote_table': str(required),

                # The name of the remote column
                'remote_column': str(required),
            }

        .. note:: The ``column`` and ``remote_column`` arguments can
            be list of strings in the case of creating foreign keys on
            combinations of columns.
        """
    return cls(**dict_obj)


def _sort_arrows(steps):
    """
        Sort arrows in order of priority
        """
    for step in steps.values():
        step.Meta.arrows.sort(key=lambda arrow: arrow.priority)


@classmethod
def _canonicalize_url(cls, url):
    """ If using caterogies, return the category-less URL

        eg:
          - category URL: https://example.com/project/dev/foobar/
          - category-less URL: https://example.com/projects/foobar/

        API endpoints are reachable only for category-less URLs.
        """
    m = cls.REGEX_CATEGORY_PROJECT_URL.match(url)
    if m:
        return '{base_url}/projects/{project_name}'.format(**m.groupdict())
    else:
        return url


def lambd_NH3_Na_CB89(T, P):
    """n-c: ammonia sodium [CB89]."""
    lambd = 0.0175
    valid = T == 298.15
    return lambd, valid


@staticmethod
def build_command(commands, name, driver='local', description=None):
    """Builds a command to be added to the pool of available commands."""
    return {'driver': driver, 'name': name, 'commands': commands,
        'description': description}


@classmethod
def fillna_panel(cls, panel):
    """
        Fills NaNs in the panel as follows:

        - nan volume becomes 0
        - close is forward-filled
        - open, high, low are forward-filled with the prior close

        Before:
                     open  high   low close volume
        2018-02-06  50.10 51.00 49.90 50.56  45100
        2018-02-07    NaN   NaN   NaN   NaN    NaN
        2018-02-08  48.89 48.99 46.58 47.20  90500

        After:
                     open  high   low close volume
        2018-02-06  50.10 51.00 49.90 50.56  45100
        2018-02-07  50.56 50.56 50.56 50.56      0
        2018-02-08  48.89 48.99 46.58 47.20  90500
        """
    panel = panel.swapaxes('items', 'minor')
    panel.volume.fillna(0, inplace=True)
    panel.close.fillna(method='ffill', inplace=True)
    panel.open = panel.open.fillna(panel.close.shift())
    panel.high = panel.high.fillna(panel.close.shift())
    panel.low = panel.low.fillna(panel.close.shift())
    panel = panel.swapaxes('items', 'minor')
    return panel


def parseLogPrefix(tb):
    """
    Takes a traceback returned by 'extract_tb' and returns the package, module,
    and line number
    """
    path = tb.split('/')
    module = path[-1].replace('.py', '')
    package = path[-2]
    return module, package


@staticmethod
def get_subtype(object_dictionary):
    """
        Given the hash representation of a subtype of this class,
        use the info in the hash to return the class of the subtype.
        """
    type = object_dictionary['type']
    if type == 'service_determined':
        return 'AttachServiceDeterminedVolumeDetails'
    if type == 'emulated':
        return 'AttachEmulatedVolumeDetails'
    if type == 'iscsi':
        return 'AttachIScsiVolumeDetails'
    if type == 'paravirtualized':
        return 'AttachParavirtualizedVolumeDetails'
    else:
        return 'AttachVolumeDetails'


@classmethod
def description_contains(cls, description_query: str):
    """Build a filter for networks whose descriptions contain the query."""
    return cls.description.contains(description_query)


def is_leaf(node):
    """
        | Is leaf-node or not(have children)

        :param  lxml.etree._Element node:
            lxml-etree-element
        :return bool:
            if leaf, return True
    """
    eles = node.getchildren()
    cond = eles.__len__() == 0
    return cond


def attach(item, action):
    """Attaches a parse action to an item."""
    return item.copy().addParseAction(action)


def handleRemoved(ob):
    """ Remove object from queue
        """


@staticmethod
def executemany(operation, **kwargs):
    """Prepare a database operation (query or command) and then execute it
        against all parameter sequences
        or mappings found in the sequence seq_of_parameters . """
    pass


def Omega(T):
    """
        Compute regularization term.

        Parameters
        ----------
        T: array, shape = len(a) x len(b)
            Input array.

        Returns
        -------
        value: float
            Regularization term.
        """
    raise NotImplementedError


def logical_xor(image1, image2):
    """Logical XOR between two images.

    .. code-block:: python

        out = ((bool(image1) != bool(image2)) % MAX)

    :rtype: :py:class:`~PIL.Image.Image`
    """
    image1.load()
    image2.load()
    return image1._new(image1.im.chop_xor(image2.im))


def avg(array):
    """
    Makes the average of an array without Nones.
    Args:
        array (list): a list of floats and Nones

    Returns:
        float: the average of the list without the Nones.
    """
    array_wo_nones = list(filter(None, array))
    return sum(array_wo_nones, 0.0) / len(array_wo_nones) if len(array_wo_nones
        ) > 0 else 0.0


@staticmethod
def _list_element_starts_with(items, needle):
    """True of any of the list elements starts with needle"""
    for item in items:
        if item.startswith(needle):
            return True
    return False


@staticmethod
def error(message):
    """Log an error level log message."""
    print('ERROR: ' + message)


def count_and_log(message, i, total, log_every_n):
    """Print a message to reflect the progress of processing once a while.

    Parameters
    ----------
    message : str
        Message to print.
    i : int
        Current index.
    total : int
        Total count.
    log_every_n : None or int
        Molecule related computation can take a long time for a large dataset and we want
        to learn the progress of processing. This can be done by printing a message whenever
        a batch of ``log_every_n`` molecules have been processed. If None, no messages will
        be printed.
    """
    if log_every_n is not None and (i + 1) % log_every_n == 0:
        print('{} {:d}/{:d}'.format(message, i + 1, total))


def export_cli(f):
    """a decorator that marks a function as exported for CLI

    intended to be used by plugins
    the HandlerRegistry will export the function under its own name
    """
    setattr(f, 'exported_cli', True)
    return f


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

        :param TeamMergeRequestSentShownToPrimaryTeamType val:
        :rtype: EventType
        """
    return cls('team_merge_request_sent_shown_to_primary_team', val)


def read_file(filename):
    """
    Returns the contents of a file as a string
    :param filename: the name of the file
    :return:
    """
    out = str()
    the_file = None
    try:
        the_file = open(filename)
        for line in the_file:
            out += line
        return out
    finally:
        if the_file:
            the_file.close()


def field_names():
    """ Returns a list of field names provided by this property
        """


def _ones_complement_sum_carry_16(a, b):
    """Compute ones complement sum and carry at 16 bits.

    :type a: int
    :type b: int

    :return: Sum of a and b, ones complement, carry at 16 bits.
    """
    pre_sum = a + b
    return (pre_sum & 65535) + (pre_sum >> 16)


def _set_full_id(ctx):
    """Sets full document identifier.

    """
    ctx.ext.full_id = '{}-{}'.format(ctx.meta.id, ctx.meta.version)


@classmethod
def supports_replay_gain(cls):
    """returns True if this class supports ReplayGain"""
    return True


def nxbdump(nxbfile):
    """
    Scan save files (.nxb) from Nexus Race and output the bitstream.

    References:
    * http://www.nexusmarine.se/support/info-and-reg-nexus-software/software-download/
    * http://www.chicagomarineelectronics.com/NX2_FDX.htm
    """
    content = open(nxbfile, 'rb').read()
    assert type(content) == bytes
    lastidx = 0
    while True:
        idx = content[lastidx:].find(b'\x81')
        if idx == -1:
            break
        yield 0.0, content[lastidx:lastidx + idx + 1]
        lastidx = lastidx + idx + 1


def expand_1d_to_2d_array(array_1d, length, axis=0):
    """
    General utility routine to 'extend a 1D array into a 2D array
    by duplicating the data along a given 'axis' (default is 0)
    of size 'length'.

    **Examples**

    >>> a = np.array([1,2,3,4])
    >>> expand_1d_to_2d_array(a, 4, axis=0)
    [[1 2 3 4]
     [1 2 3 4]
     [1 2 3 4]
     [1 2 3 4]]

    >>> a = np.array([1,2,3,4])
    >>> expand_1d_to_2d_array(a, 4, axis=1)
    [[1 1 1 1]
     [2 2 2 2]
     [3 3 3 3]
     [4 4 4 4]]

    :param array_1d:
    :param length:
    :param axis:
    :return:
    """
    import numpy as np
    if axis == 0:
        array_2d = np.repeat(array_1d[(np.newaxis), :], length, 0)
    else:
        array_2d = np.repeat(array_1d[:, (np.newaxis)], length, 1)
    return array_2d


@classmethod
def _load_mx_exceptions(cls):
    """ Import mxODBC exception classes into the module namespace,
        as if they had been imported normally. This is done here
        to avoid requiring all SQLAlchemy users to install mxODBC.
        """
    global InterfaceError, ProgrammingError
    from mx.ODBC import InterfaceError
    from mx.ODBC import ProgrammingError


def setup():
    """Setup printer for use.

        This method should do any logic required for the correct functioning of
        the printer, like checking if it uses 2 or 3 decimal places for product
        prices and quantity, and using this properties when necessary.
        """


@classmethod
def data_continued(cls, block_chunk):
    """Return true if block data is continued in next block"""
    if cls.header_type(block_chunk) is 'data':
        is_cont = (block_chunk[0] & cls.data_continued_mask) >> 6
        return is_cont == cls.data_continued_flag
    return False


@classmethod
def show_colorising_days(cls, dataframe_items, rep_date):
    """Show colorising avaliable days in dataframe."""
    if 'day' in dataframe_items:
        avail_days = dataframe_items.day
        avail_days = sorted(set(avail_days))
        print('Имеющиеся отчеты:\n\t', cls.colorise_avaliable_date(rep_date
            ['year'], rep_date['month'], avail_days))


def readline(size=None):
    """Read one entire line from the file. See Python documentation for
        :class:`io.IOBase` for details.
        """


def _get_trading_day_start_time(trading_day):
    """给定交易日, 获得交易日起始时间"""
    begin_mark = 631123200000000000
    start_time = trading_day - 21600000000000
    week_day = (start_time - begin_mark) // 86400000000000 % 7
    if week_day >= 5:
        start_time -= 86400000000000 * (week_day - 4)
    return start_time


def reply(v):
    """
	formats the value as a redis reply
	"""
    return '$%s\r\n%s\r\n' % (len(v), v)


def _result_iter(cursor, arraysize):
    """
    An iterator that uses fetchmany to keep memory usage down
    """
    count = 0
    while True:
        results = cursor.fetchmany(arraysize)
        count += len(results)
        if not results:
            print('no rows to process')
            break
        print('%s rows processed' % count)
        for result in results:
            yield result


def determine_keep_history(cursor, keep_history=None):
    """Determine whether the RelStorage databases is set to keep history.
    """
    if keep_history is None:
        cursor.execute(
            "select 1 from pg_catalog.pg_class where relname = 'current_object'"
            )
        keep_history = bool(list(cursor))
    return keep_history


@staticmethod
def check_args(parser, namespace):
    """Postprocess the argparse values.

        Should raise C{argparse.ArgumentError} on failure.

        This is only called for addons that are enabled, but before
        they are instantiated.
        """


def shim_metric_definition(vdrp_measurement_doc):
    """Convert JSON structure in validate DRP into the JSON expected
    by SQuaSH for metric definition.
    """
    metric = vdrp_measurement_doc['metric']
    metric_json = {'metric': metric['name'], 'description': metric[
        'description'], 'reference': metric['reference'], 'specs': metric[
        'specifications'], 'operator': metric['operator_str'], 'parameters':
        metric['parameters'], 'unit': vdrp_measurement_doc['unit']}
    return metric_json


@classmethod
def unguard(cls):
    """
        Disable the mass assigment restrictions.
        """
    cls.__unguarded__ = True


def test_readinto():
    """Checks the micropython firmware to see if sys.stdin.readinto exists."""
    import sys
    try:
        _ = sys.stdin.readinto
        return True
    except:
        return False


def is_gzip(path):
    """Test if a file is gzipped by reading its first two bytes and compare
    to the gzip marker bytes.
    """
    with open(path, 'rb') as f:
        marker_bytes = f.read(2)
    return marker_bytes[0] == 31 and marker_bytes[1] == 139


def what_we_want():
    """Returns what we want for open data."""
    return 'We want the data raw, and we want the data now.'


def std_scalar(comment, valueType='integer', option=0, **kwargs):
    """Description for standard scalar column."""
    return dict(comment=comment, valueType=valueType, dataManagerType=
        'StandardStMan', dataManagerGroup='StandardStMan', option=option,
        maxlen=0, **kwargs)


def join_tracks():
    """Join selected tracks

    """
    pass


def readme(filename='README.md'):
    """
    Returns a simple `README.md` template.

    From https://www.makeareadme.com
    """
    with open(filename, 'w') as f:
        f.write(
            """# Foobar

Foobar is a Python library for dealing with word pluralization.

## Installation

Use the package manager [pip](https://pip.pypa.io/en/stable/) to install foobar.

```bash
pip install foobar
```

## Usage

```python
import foobar

foobar.pluralize('word') # returns 'words'
foobar.pluralize('goose') # returns 'geese'
foobar.singularize('phenomena') # returns 'phenomenon'
```

## Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

## License
[MIT](https://choosealicense.com/licenses/mit/)"""
            )


def createHeaders(X_APIKEY, Content_Type='application/json'):
    """
    Create headers for API calls within this package

    REQUIRED ARGUMENTS
    :param X_APIKEY: String - Authentication key for the API

    OPTIONAL ARGUMENTS
    :param Content_Type: String - Default to "application/json"

    :return: JSON Headers for API call
    """
    headers = {'Content-Type': Content_Type, 'X-APIKEY': X_APIKEY}
    return headers


@staticmethod
def _find_between(s, first, last):
    """Finds the substring between two strings."""
    try:
        start = s.index(first) + len(first)
        end = s.index(last, start)
        return s[start:end]
    except ValueError:
        return ''


def AddToCRC(b, crc):
    """ computes crc iteratively by returning updated crc input"""
    if b < 0:
        b += 256
    for i in range(8):
        odd = (b ^ crc) & 1 == 1
        crc >>= 1
        b >>= 1
        if odd:
            crc ^= 140
    return crc


@classmethod
def from_hash(cls, witness_hash):
    """Creates and address object from a hash string"""
    return cls(witness_hash=witness_hash)


def addActionProvider(provider_name):
    """ Register an IActionProvider to the set queried by this tool.

        o 'provider_name' is appended to the set of names already registered
          with the tool.

        o Raise ComponentLookupError if no utility of that name is registered
          for IActionProvider.

        o Deprecated: In the future, expect to use 'getUtilitiesFor' instead
          (presuming either that ordering either doesn't matter or that
          ordering is supported by the utility registry).

        o Permission:  Manage portal
        """


def get_page_tags(page):
    """
    Retrieves all the tags for a Page instance.

    :param page: a Page instance

    :return: list or queryset of attached tags
    :type: List
    """
    from .models import PageTags
    try:
        return page.pagetags.tags.all()
    except PageTags.DoesNotExist:
        return []


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

        :param SessionLogInfo val:
        :rtype: AccessMethodLogInfo
        """
    return cls('end_user', val)


def divergence(rl, score, threshold):
    """ Returns all repeats in ``rl`` with a divergence below a certain
        threshold.

    Returns all repeats in ``rl`` with a divergence below a certain threshold.

    Args:
        rl (RepeatList): An instance of the RepeatList class.
        score (str): The type of score defines the divergence that is used for
                    filtering
        threshold (float): All repeats with a divergence of type `score` above
                            this threshold are filtered out.
    """
    res = []
    for i_repeat in rl.repeats:
        if i_repeat.divergence(score) <= threshold:
            res.append(i_repeat)
    return res


def add_client_session(engine, session_id, client_id, sid, base_url, workspace
    ):
    """Add client session."""
    logger = engine.logger
    clients = engine.store.clients
    registered_sessions = engine.store.registered_sessions
    if client_id in clients:
        clients[client_id].append(sid)
        client_connected = True
    else:
        clients[client_id] = [sid]
        client_connected = False
    logger.info('Adding client session %s', sid)
    registered_sessions[sid] = {'client': client_id, 'session': session_id,
        'base_url': base_url, 'workspace': workspace}
    return client_connected


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

        :param AccountLockOrUnlockedDetails val:
        :rtype: EventDetails
        """
    return cls('account_lock_or_unlocked_details', val)


def list_certificate_issuer_admins(client, vault_base_url, issuer_name):
    """ List admins for a specified certificate issuer. """
    return client.get_certificate_issuer(vault_base_url, issuer_name
        ).organization_details.admin_details


def _canonical_first_vertex(polygon):
    """
        Return the index of the vertex with smallest y-coordinate.
        If two vertices have the same y-coordinate, then the one with least x-coordinate is returned.
        """
    best = 0
    best_pt = polygon.vertex(best)
    for v in range(1, polygon.num_edges()):
        pt = polygon.vertex(v)
        if pt[1] < best_pt[1]:
            best = v
            best_pt = pt
    if best == 0:
        if pt[1] == best_pt[1]:
            return v
    return best


def t_php_DOC_COMMENT(t):
    """/\\*\\*(.|\\n)*?\\*/"""
    t.lexer.lineno += t.value.count('\n')
    return t


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 decode_cipher(cipher_spec, key_size):
    """Decode a dm-crypt style cipher specification string

       The assumed format being cipher[:keycount]-chainmode-ivmode[:ivopts] as
       documented under linux/Documentation/device-mapper/dm-crypt.txt in the
       kernel source tree.
    """
    cipher_alg, cipher_mode, ivgen_alg = cipher_spec.split('-')
    cipher_alg = cipher_alg + '-' + str(key_size)
    return {'cipher_alg': cipher_alg, 'cipher_mode': cipher_mode,
        'ivgen_alg': ivgen_alg}


def __contains__(name):
    """Return true if we contain the named subclass"""


def apply_intersect(query, docids):
    """ Run the query implied by query, and return query results
        intersected with the ``docids`` set that is supplied.  If
        ``docids`` is None, return the bare query results. """


def reset_bits(value: int, pos: int) ->int:
    """ Resets bits higher than the given pos. """
    reset_bits_mask = ~(255 << pos)
    value &= reset_bits_mask
    return value


def _check_biomart_response(response):
    """
    Return True if the response doesn't look like an query ERROR or 404 page.

    >>> _check_biomart_response('')
    False
    >>> _check_biomart_response('<html>')
    False
    >>> _check_biomart_response('Query ERROR: caught BioMart::Exception')
    False
    >>> _check_biomart_response('ENSG00000107643	ENST00000432379	48306655')
    True
    """
    response = response.strip()
    if response.startswith('<html') or response.startswith('Query ERROR:'
        ) or not response:
        return False
    return True


@classmethod
def from_lincs_dataset(cls, lincs_dataset, name):
    """Constructor from base Dataset class

        Parameters
        ----------
        name : ``str``
            Type of dataset. Must be one of ``'train'``, ``'validation'``, or ``'test'``.
        """
    return cls(lincs_dataset._data, lincs_dataset.gene_meta, lincs_dataset.
        n_genes, name)


def make_delete_skeleton(_table_name, _key_fields):
    """NOT IMPLEMENTED: Make a skeleton for an SQL DELETE statement object.

    :param _table_name:
    :param _key_fields:
    :return:
    """
    raise Exception("make_delete_skeleton isn't implemented")
    """
    TODO: Implement this:
    _destination_identifier = ParameterIdentifier(_identifier=_table_name)

    _column_identifiers = make_column_identifiers(_key_fields)
    return VerbDelete()
    """


def boolean(value):
    """
    Parse the string ``"true"`` or ``"false"`` as a boolean (case insensitive).

    Also accepts ``"1"`` and ``"0"`` as ``True``/``False`` (respectively).

    If the input is from the request JSON body, the type is already a native python boolean,
    and will be passed through without further parsing.

    :raises ValueError: if the boolean value is invalid
    """
    if isinstance(value, bool):
        return value
    if value is None:
        raise ValueError('boolean type must be non-null')
    elif not value:
        return False
    value = str(value).lower()
    if value in ('true', '1', 'on'):
        return True
    if value in ('false', '0'):
        return False
    raise ValueError('Invalid literal for boolean(): {0}'.format(value))


def setStatus(status, reason=None):
    """Sets the HTTP status code of the response

        The status parameter must be either an integer (preferred), a value
        that can be converted to an integer using the int() function,
        or one of the standard status messages listed in the status_codes
        dict of the zope.publisher.http module (including "OK", "NotFound",
        and so on).  If the parameter is some other value, the status will
        be set to 500.

        The reason parameter is a short message to be sent with the status
        code to the client.  If reason is not provided, a standard
        reason will be supplied, falling back to "Unknown" for unregistered
        status codes.
        """


@staticmethod
def in_out_quad(progress):
    """.. image:: images/anim_in_out_quad.png
        """
    p = progress * 2
    if p < 1:
        return 0.5 * p * p
    p -= 1.0
    return -0.5 * (p * (p - 2.0) - 1.0)


def CheckSpin(isym, SGData):
    """ Check for exceptions in spin rules
    """
    if SGData['SGPtGrp'] in ['222', 'mm2', '2mm', 'm2m']:
        if SGData['SGSpin'][1] * SGData['SGSpin'][2] * SGData['SGSpin'][3] < 0:
            SGData['SGSpin'][(isym + 1) % 3 + 1] *= -1
        if SGData['SpGrp'][0] == 'F' and isym > 2:
            SGData['SGSpin'][(isym + 1) % 3 + 3] == 1
    elif SGData['SGPtGrp'] == 'mmm':
        if SGData['SpGrp'][0] == 'F' and isym > 2:
            SGData['SGSpin'][(isym + 1) % 3 + 3] == 1


@classmethod
def exception(cls, name, message, *args):
    """
        Convenience function to log a message at the ERROR level with additonal exception information.

        :param name:    The name of the logger instance in the VSG namespace (VSG.<name>)
        :param message: A message format string.
        :param args:    The arguments that are are merged into msg using the string formatting operator.
        :..note:        This method should only be called from an exception handler.
        """
    cls.getLogger(name).exception(message, *args)


def _join_translated(translated_parts, os_sep_class):
    """Join translated glob pattern parts.

    This is different from a simple join, as care need to be taken
    to allow ** to match ZERO or more directories.
    """
    res = ''
    for part in translated_parts[:-1]:
        if part == '.*':
            res += part
        else:
            res += part + os_sep_class
    if translated_parts[-1] == '.*':
        res += '.+'
        res += '({os_sep_class}?.*)?'.format(os_sep_class=os_sep_class)
    else:
        res += translated_parts[-1]
    return res


def _unpack_obs_player(role, strategy, payoff, **_):
    """Unpack an observation player"""
    return role, strategy, payoff


def p_isset_variables(p):
    """isset_variables : isset_variables COMMA variable
                       | variable"""
    if len(p) == 4:
        p[0] = p[1] + [p[3]]
    else:
        p[0] = [p[1]]


def rate_of_return(period_ret):
    """
    转换回报率为"每期"回报率：如果收益以稳定的速度增长, 则相当于每期的回报率
    """
    period = int(period_ret.name.replace('period_', ''))
    return period_ret.add(1).pow(1.0 / period).sub(1)


def download_dbox_file(path, outdir, filename):
    """Given a link including dropbox.com,
    initialize a dropbox file download.

    need two arguments:
      * file id from the share link
      * file name (may be different from the original file name)
    """
    import requests
    headers = {'user-agent': 'Wget/1.16 (linux-gnu)'}
    r = requests.get(path, stream=True, headers=headers)
    with open(outdir + filename, 'wb') as f:
        for chunk in r.iter_content(chunk_size=1024):
            if chunk:
                f.write(chunk)


def _get_relevant_commits(repo, commit_shas, branch):
    """
    Gets all commits on the repo with the given shas

    :param Repo repo:
    :param list[unicode] commit_shas:
    :param unicode branch:
    :return: list[Commit]
    """
    remaining_shas = set(commit_shas)
    commits = list()
    for commit in repo.iter_commits(branch):
        if commit.hexsha in remaining_shas:
            commits.append(commit)
            remaining_shas.remove(commit.hexsha)
    return commits


@classmethod
def error(cls, msg):
    """
        Log provided message with level ERROR.
        """
    return cls(msg, level='error')


def clean_question_mark(content):
    """Removes question mark strings, turning them to nulls.

    Parameters
    ----------
    content: :class:`str`
        A string to clean.

    Returns
    -------
    :class:`str`
        The string, or None if it was a question mark.
    """
    if not content:
        return None
    if '?' in content:
        return None
    return content.strip()


def default_func(entity, attribute, value):
    """
    Look in the entity for an attribute with the provided value.
    First real object attributes are checked, then, if available,
    extended fields. If neither of these are present, return ``False``.
    """
    try:
        return getattr(entity, attribute) == value
    except AttributeError:
        try:
            return entity.fields[attribute] == value
        except (AttributeError, KeyError):
            return False


def PolsOther(t):
    """Number of policies: Other benefits"""
    return 0


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

    Example::

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

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

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


def get_hostname():
    """
    Get system's hostname for worker process name.
    """
    import socket
    hostname = socket.gethostname()
    del socket
    return hostname


def wf_error_message(message):
    """
    It returns the error message for the specified action node, or an empty string
    if no action node has not exited with ERROR state.

    The error message can be useful for debugging and notification purposes.
    """


def collect_quadrature_rules(integrals, default_scheme, default_degree):
    """Collect quadrature rules found in list of integrals."""
    rules = set()
    for integral in integrals:
        md = integral.metadata() or {}
        scheme = md.get('quadrature_rule', default_scheme)
        degree = md.get('quadrature_degree', default_degree)
        rule = scheme, degree
        rules.add(rule)
    return rules


def scaledUnitString(num, infix=' ', suffix='B', div=1000):
    """
    Returns a human-readable file size string.
    thanks to Fred Cirera
    http://stackoverflow.com/questions/1094841/reusable-library-to-get-human-readable-version-of-file-size
    :param num: number in bytes
    :param suffix: 'B' for bytes by default.
    :param div: divisor of num, 1000 by default.
    :return: the file size string
    """
    for unit in ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']:
        if abs(num) < div:
            return '{:3.1f}{}{}{}'.format(num, infix, unit, suffix)
        num /= div
    return '{:.1f}{}{}{}'.format(num, infix, unit, suffix)


@classmethod
def add_transfered_item(cls, store, branch, transfer_order_item):
    """
        Adds a transfered_item, populates the ProductHistory table using a
        *transfered_order_item* created during a |transfer|.

        :param store: a store
        :param branch: the source branch
        :param transfer_order_item: the item transfered from source branch
        """
    cls(branch=branch, sellable=transfer_order_item.sellable,
        quantity_transfered=transfer_order_item.quantity, received_date=
        transfer_order_item.transfer_order.receival_date, store=store)


@classmethod
def get(cls, project_id, prediction_explanations_id):
    """
        Retrieve a specific prediction explanations.

        Parameters
        ----------
        project_id : str
            id of the project the explanations belong to
        prediction_explanations_id : str
            id of the prediction explanations

        Returns
        -------
        prediction_explanations : PredictionExplanations
            The queried instance.
        """
    path = '{}{}/'.format(cls._path_template.format(project_id),
        prediction_explanations_id)
    return cls.from_location(path)


def unordered_domain_values(var, assignment, csp):
    """The default value order."""
    return csp.choices(var)


def _cliffs_delta(x, y):
    """
    Calculates Cliff's delta.
    """
    delta = 0
    for x_val in x:
        result = 0
        for y_val in y:
            if y_val > x_val:
                result -= 1
            elif x_val > y_val:
                result += 1
        delta += result / len(y)
    if abs(delta) < 1e-15:
        delta = 0
    else:
        delta = delta / len(x)
    return delta


def n_sum(n: int):
    """Calculates sum of first `n` numbers, e.g. 1+2+3+...n"""
    return n * (n + 1) / 2


def DT2dt(date):
    """Convert Zope's DateTime to Pythons's datetime
    """
    return date.asdatetime()


def get_host_port(spec, default_port):
    """parse 'hostname:22' into a host and port, with the port optional"""
    args = (spec.split(':', 1) + [default_port])[:2]
    args[1] = int(args[1])
    return args[0], args[1]


def ensure_one(found):
    """
    确保列表中仅有一个项，并返回这个项，否则抛出 `ValueError` 异常

    通常可用在查找聊天对象时，确保查找结果的唯一性，并直接获取唯一项

    :param found: 列表
    :return: 唯一项
    """
    if not isinstance(found, list):
        raise TypeError('expected list, {} found'.format(type(found)))
    elif not found:
        raise ValueError('not found')
    elif len(found) > 1:
        raise ValueError('more than one found')
    else:
        return found[0]


def add_sets(*args):
    """
    Add sets. The arguments need not be sets. Returns a set of unique
    values. If the arguments include unhashable types, raises a TypeError.
    """
    out = set()
    for arg in args:
        for thing in arg:
            out.add(thing)
    return out


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

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


def generate_presigned_url(ClientMethod=None, Params=None, ExpiresIn=None,
    HttpMethod=None):
    """
    Generate a presigned url given a client, its method, and arguments

    :type ClientMethod: string
    :param ClientMethod: The client method to presign for

    :type Params: dict
    :param Params: The parameters normally passed to
            ClientMethod.

    :type ExpiresIn: int
    :param ExpiresIn: The number of seconds the presigned url is valid
            for. By default it expires in an hour (3600 seconds)

    :type HttpMethod: string
    :param HttpMethod: The http method to use on the generated url. By
            default, the http method is whatever is used in the method's model.

    """
    pass


def __getattr__(cls, key):
    """Get configuration with key."""
    return cls.config.get(key, {})


def Huq_Loth(x, rhol, rhog):
    """Calculates void fraction in two-phase flow according to the model of
    [1]_, also given in [2]_, [3]_, and [4]_.

    .. math::
        \\alpha = 1 - \\frac{2(1-x)^2}{1 - 2x + \\left[1 + 4x(1-x)\\left(\\frac
        {\\rho_l}{\\rho_g}-1\\right)\\right]^{0.5}}

    Parameters
    ----------
    x : float
        Quality at the specific tube interval []
    rhol : float
        Density of the liquid [kg/m^3]
    rhog : float
        Density of the gas [kg/m^3]

    Returns
    -------
    alpha : float
        Void fraction (area of gas / total area of channel), [-]

    Notes
    -----
    [1]_ has been reviewed, and matches the expressions given in the reviews
    [2]_, [3]_, and [4]_; the form of the expression is rearranged somewhat
    differently.

    Examples
    --------
    >>> Huq_Loth(.4, 800, 2.5)
    0.9593868838476147

    References
    ----------
    .. [1] Huq, Reazul, and John L. Loth. "Analytical Two-Phase Flow Void
       Prediction Method." Journal of Thermophysics and Heat Transfer 6, no. 1
       (January 1, 1992): 139-44. doi:10.2514/3.329.
    .. [2] Xu, Yu, and Xiande Fang. "Correlations of Void Fraction for Two-
       Phase Refrigerant Flow in Pipes." Applied Thermal Engineering 64, no.
       1-2 (March 2014): 242–51. doi:10.1016/j.applthermaleng.2013.12.032.
    .. [3] Dalkilic, A. S., S. Laohalertdecha, and S. Wongwises. "Effect of
       Void Fraction Models on the Two-Phase Friction Factor of R134a during
       Condensation in Vertical Downward Flow in a Smooth Tube." International
       Communications in Heat and Mass Transfer 35, no. 8 (October 2008):
       921-27. doi:10.1016/j.icheatmasstransfer.2008.04.001.
    .. [4] Woldesemayat, Melkamu A., and Afshin J. Ghajar. "Comparison of Void
       Fraction Correlations for Different Flow Patterns in Horizontal and
       Upward Inclined Pipes." International Journal of Multiphase Flow 33,
       no. 4 (April 2007): 347-370. doi:10.1016/j.ijmultiphaseflow.2006.09.004.
    """
    B = 2 * x * (1 - x)
    D = (1 + 2 * B * (rhol / rhog - 1)) ** 0.5
    return 1 - 2 * (1 - x) ** 2 / (1 - 2 * x + D)


def get_user_role(identifier=None):
    """Return a list of roles that ``identifier`` has. If ``identifier``
        is None, return a list of roles for currently authenticated
        user.
        """


def normalize(title):
    """
    Normalizes a page title to the database format.  E.g. spaces are converted
    to underscores and the first character in the title is converted to
    upper-case.

    :Parameters:
        title : str
            A page title
    :Returns:
        The normalized title.
    :Example:
        >>> from mw.lib import title
        >>>
        >>> title.normalize("foo bar")
        'Foo_bar'

    """
    if title is None:
        return title
    elif len(title) > 0:
        return (title[0].upper() + title[1:]).replace(' ', '_')
    else:
        return ''


def get_image(repository, name):
    """Get the full image name by integrating repository and image name.

    :param repository: The name of repository
    :param name: The short image name
    :returns: str: Full image name, format: repo/name.

    """
    return '{repo}/{name}'.format(repo=repository, name=name)


@classmethod
def getConfigSections(cls):
    """Only needs to be overriden if has additional ini sections."""
    return ['base_xenforoforum', cls.getConfigSection()]


@classmethod
def get_by_uuid(cls, context, uuid):
    """Find a port based on UUID and return a :class:`Port` object.

        :param cls: the :class:`Port`
        :param context: Security context
        :param uuid: the UUID of a port.
        :returns: a :class:`Port` object.
        :raises: PortNotFound

        """
    db_port = cls.dbapi.get_port_by_uuid(uuid)
    port = cls._from_db_object(context, cls(), db_port)
    return port


def KK_RC9(w, Rs, R_values, t_values):
    """
    Kramers-Kronig Function: -RC-

    Kristian B. Knudsen (kknu@berkeley.edu / kristianbknudsen@gmail.com)
    """
    return Rs + R_values[0] / (1 + w * 1.0j * t_values[0]) + R_values[1] / (
        1 + w * 1.0j * t_values[1]) + R_values[2] / (1 + w * 1.0j * t_values[2]
        ) + R_values[3] / (1 + w * 1.0j * t_values[3]) + R_values[4] / (1 +
        w * 1.0j * t_values[4]) + R_values[5] / (1 + w * 1.0j * t_values[5]
        ) + R_values[6] / (1 + w * 1.0j * t_values[6]) + R_values[7] / (1 +
        w * 1.0j * t_values[7]) + R_values[8] / (1 + w * 1.0j * t_values[8])


def get_duration(name, instance):
    """
    Getter for Duration Property field.

    Handles correctly the conversion of of negative running duration (for more refer to the Toggl API doc).
    """
    if instance.is_running:
        return instance.start.int_timestamp * -1
    return int((instance.stop - instance.start).in_seconds())


def drange(v0, v1, d):
    """Returns a discrete range."""
    assert v0 < v1, str((v0, v1, d))
    return range(int(v0) // d, int(v1 + d) // d)


def dropname(ss, li):
    """drop names from a list of strings,
    names to drop are in space delimeted list
    does not change original list
    """
    newli = li[:]
    for item in ss.split():
        newli.remove(item)
    return newli


def slice_tracks(tracks, max_tracklist_length):
    """Return a (tracks, length) tuple, where tracks is the list of tracks with length
    less than or equal to max_tracklist_length and length is the length of tracks.
    """
    length = 0.0
    for i, track in enumerate(tracks):
        if length + track['length'] <= max_tracklist_length:
            length += track['length']
        else:
            break
    return tracks[:i + 1], length


def selectBit(val: int, bitNo: int):
    """
    Get bit from int
    """
    return val >> bitNo & 1


def real_project_name(project_name):
    """
    Used to let yacms run from its project template directory, in which
    case "{{ project_name }}" won't have been replaced by a real project name.
    """
    if project_name == '{{ project_name }}':
        return 'project_name'
    return project_name


def defvalkey(js, key, default=None, take_none=True):
    """
    Returns js[key] if set, otherwise default. Note js[key] can be None.
    :param js:
    :param key:
    :param default:
    :param take_none:
    :return:
    """
    if js is None:
        return default
    if key not in js:
        return default
    if js[key] is None and not take_none:
        return default
    return js[key]


def mass_weighted_number(dat, total_sampled_mass, component_mass):
    """Compute the total number of systems in the synthetic catalog
    based on the total sampled mass of the simulated system and
    the total mass of a given galactic component

    Parameters
    ----------
    dat : DataFrame
        DataFrame containing the fixed population created from cosmic-pop
    total_sampled_mass : float
        total amount of mass sampled to generate the fixed population
        including single stars
    component_mass : float
        mass of the Galactic component we are simulating

    Returns
    -------
    nSystems : int
        number of systems in a Milky Way population for the selected
        Galactic population and fixed population
    """
    nSystems = int(len(dat.mass_1) * component_mass / total_sampled_mass)
    return nSystems


def _is_sunder(name):
    """Returns True if a _sunder_ name, False otherwise."""
    return name[0] == name[-1] == '_' and name[1:2] != '_' and name[-2:-1
        ] != '_' and len(name) > 2


@staticmethod
def _create_cluster_request_template(cluster_name, cluster_description='',
    initial_nodes=3, disk_size_gb=100, machine_type='n1-standard-1',
    disable_hpa=False, disable_lb=False, disable_k8s_dashboard=False):
    """ Returns a request body template for create cluster option """
    request_body = {'cluster': {'name': cluster_name, 'description':
        cluster_description, 'initialNodeCount': initial_nodes,
        'nodeConfig': {'diskSizeGb': disk_size_gb, 'machineType':
        machine_type}, 'addonsConfig': {'horizontalPodAutoscaling': {
        'disabled': disable_hpa}, 'httpLoadBalancing': {'disabled':
        disable_lb}, 'kubernetesDashboard': {'disabled':
        disable_k8s_dashboard}}}}
    return request_body


def get_only(field):
    """
    `get_only` is a sugar for `property`.

    ``` py
    value = get_only('_value')

    # equals:

    @property
    def value(self):
        return getattr(self, '_value')
    ```
    """
    return property(lambda self: getattr(self, field))


def deprecated_validate_name(name):
    """Checks that name matches AWS requirements."""
    import re
    assert len(name) < 30
    assert re.match('[-+=._:\\/@a-zA-Z0-9]+', name)


def DIPPR_EQ102_derivative_by_T(T, a, b, c, d):
    """T-Derivative of DPPR Equation #102."""
    return a * b * T ** b / (T * (c / T + d / T ** 2 + 1)) + a * T ** b * (
        c / T ** 2 + 2 * d / T ** 3) / (c / T + d / T ** 2 + 1) ** 2


def MoninObukhov_length2(u_star, w, T, specific_humidity=None):
    """Calculate the Monin Obukhov length

    Not validated!!!

    parameters
    ----------
    u_star :
        Refencence velocity at hub height
    w : array_like
        Vertical wind fluctuations
    T : array_like
        Temperature in celcius
    """
    K = 0.4
    g = 9.82
    if specific_humidity is not None:
        potential_temperature = (w * (T + 273.15)).mean() + 0.61 * (T + 273.15
            ).mean() * (w * specific_humidity).mean()
    else:
        potential_temperature = (w * (T + 273.15)).mean()
    return -u_star ** 3 * (T.mean() + 273.15) / (K * g * potential_temperature)


def check_pool_create(conn, poolname, logger):
    """Check the result of create storage pool.  """
    pool_names = conn.listStoragePools()
    logger.info('poolnames is: %s ' % pool_names)
    if poolname in pool_names:
        return True
    else:
        logger.info('check_pool_create %s storage pool is UNSUCCESSFUL!!' %
            poolname)
        return False


def hash_file(upload_context):
    """
    Function run by HashFileCommand to calculate a file hash.
    :param upload_context: PathData: contains path to a local file to hash
    :return HashData: result of hash (alg + value)
    """
    path_data = upload_context.params
    hash_data = path_data.get_hash()
    return hash_data


def _load_grid_filename(degree: int, size: int):
    """Construct Lebedev file name for given degree and size.

    Parameters
    ----------
    degree : int
    size : int

    Returns
    -------
    str, file name for given type of Lebedev grid
    """
    return f'lebedev_{degree}_{size}.npz'


def split_tool_tag(tag: str) ->(str, str):
    """Split tool tag into tool name and tool version"""
    tag_split = tag.split(':', maxsplit=2)
    return tag_split[0], tag_split[1] if len(tag_split) > 1 else 'latest'


def deriv_B_r_midplane_func(*, γ, deriv_B_φ, η_H, η_P, v_r):
    """
    Compute B_r' at the midplane
    """
    return γ - 1 / 4 - (deriv_B_φ * η_H + v_r) / η_P


def concat(a, b):
    """Same as a + b, for a and b sequences."""
    if not hasattr(a, '__getitem__'):
        msg = "'%s' object can't be concatenated" % type(a).__name__
        raise TypeError(msg)
    return a + b


def scroll_backward(event, half=False):
    """
    Scroll window up.
    """
    w = event.app.layout.current_window
    b = event.app.current_buffer
    if w and w.render_info:
        info = w.render_info
        scroll_height = info.window_height
        if half:
            scroll_height //= 2
        y = max(0, b.document.cursor_position_row - 1)
        height = 0
        while y > 0:
            line_height = info.get_height_for_line(y)
            if height + line_height < scroll_height:
                height += line_height
                y -= 1
            else:
                break
        b.cursor_position = b.document.translate_row_col_to_index(y, 0)


def num2strg(num):
    """
    Attempt to emulate Excel's default conversion from number to string.
    """
    s = str(num)
    if s.endswith('.0'):
        s = s[:-2]
    return s


@classmethod
def arrow_cr(cls, arrow1, arrow2):
    """Right to Left arrow composition

        This expression means the same as: maybe cast the string as an
        int, then maybe add 1 but read right to left.

        >>> from fp.monads.maybe import Maybe
        >>> from fp import p
        >>> maybe_int = p(Maybe.catch, int)
        >>> string_to_plus = Maybe.arrow_cr(lambda x: Maybe(x+1), maybe_int)
        >>> string_to_plus("1")
        Just(2)
        """
    return cls.arrow_cl(arrow2, arrow1)


@classmethod
def add_hook(cls, hook_type, hook_func):
    """Add a new hook of specified type.

        :param cls: class that registers hooks
        :param hook_type: hook type, e.g., '__pre_parse_args__'
        :param hook_func: hook function
        """
    if hook_type not in cls._hooks_map:
        cls._hooks_map[hook_type] = []
    cls._hooks_map[hook_type].append(hook_func)


@staticmethod
def _fix_trace(trace: list, func: str, var: str):
    """
        The main goal here is to get rid of repetitive paths (not exactlly
        similar) but they "certinally" give the same solution.
        * There are still many more paths that must be detected and removed!
        path is 1-D list
        Rules:
            1- No repetition in two adjacent conected var
            2- if func == cv:
                crop the left side of the cv
            3- if var == cv:
                crop the right side of the cv
            4- once everything is cleand, remove redundent paths

        """
    npath = []
    ocv = None
    for b in range(0, len(trace) - 2, 2):
        l = trace[b]
        cv = trace[b + 1]
        r = trace[b + 2]
        if cv == func:
            if not npath:
                npath.append(r)
            else:
                break
        elif cv == var:
            if not npath:
                npath.append(l)
            else:
                npath[-1] = l
            break
        elif cv == ocv:
            npath[-1] = r
        elif cv != ocv:
            if npath and npath[-1] == l:
                npath += [cv, r]
            else:
                npath += [l, cv, r]
        ocv = cv
    if len(npath) == 2:
        npath.pop()
    return npath


def compare_sets(set1, set2):
    """Compute the intersection and differences between two sets.

    :param set1: The first input set.
    :type set1: set
    :param set2: The second input set.
    :type set2: set
    :returns:
        tuple (set_intersection, set1_diff, set2_diff)
        WHERE
        set_intersection(set) is the set of shared values.
        set1_diff(set) is the set of values unique to the first set.
        set2_diff(set) is the set of values unique to the second set.
    :rtype: tuple
    """
    set_intersection = set1 & set2
    set1_diff = set1 - set2
    set2_diff = set2 - set1
    return set_intersection, set1_diff, set2_diff


def region_context_menu():
    """Display region context menu

    """
    pass


def format_legend_label(legend_label):
    """Return a properly formated legend label

    Args:
        legend_label (str): list of legend labels (strings)

    Returns:
        the input axis object
    """
    if legend_label is not None:
        return legend_label
    else:
        return None