def to_list(x):
    """This normalizes a list/tensor into a list.

    If a tensor is passed, we return
    a list of size 1 containing the tensor.
    """
    if isinstance(x, list):
        return x
    return [x]


@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 images_separate(length: int=1):
    """On image sequence strips, it returns a strip for each image

    :param length: Length, Length of each frame
    :type length: int
    """
    pass


def addArguments(string, args, joiner='_'):
    """
        args is an array of ArgumentToAdd.
    """
    for arg in args:
        string = string + ('' if arg.val is None or arg.val is False or
            hasattr(arg.val, '__len__') and len(arg.val) == 0 else joiner +
            arg.transform())
    return string


def resolve_name(name):
    """Resolve a name like ``module.object`` to an object and return it.

    Raise `ImportError` if the module or name is not found.
    """
    parts = name.split('.')
    cursor = len(parts) - 1
    module_name = parts[:cursor]
    attr_name = parts[-1]
    while cursor > 0:
        try:
            ret = __import__('.'.join(module_name), fromlist=[attr_name])
            break
        except ImportError:
            if cursor == 0:
                raise
            cursor -= 1
            module_name = parts[:cursor]
            attr_name = parts[cursor]
            ret = ''
    for part in parts[cursor:]:
        try:
            ret = getattr(ret, part)
        except AttributeError:
            raise ImportError(name)
    return ret


def get_pg_tc(links_table_name, links_table_input_field,
    links_table_output_field, closure_table_name,
    closure_table_parent_field, closure_table_child_field):
    """
    Return the transitive closure table template
    """
    from string import Template
    pg_tc = Template(
        """

DROP TRIGGER IF EXISTS autoupdate_tc ON $links_table_name;
DROP FUNCTION IF EXISTS update_tc();

CREATE OR REPLACE FUNCTION update_tc()
  RETURNS trigger AS
$$BODY$$
DECLARE

    new_id INTEGER;
    old_id INTEGER;
    num_rows INTEGER;

BEGIN

  IF tg_op = 'INSERT' THEN

    IF EXISTS (
      SELECT Id FROM $closure_table_name
      WHERE $closure_table_parent_field = new.$links_table_input_field
         AND $closure_table_child_field = new.$links_table_output_field
         AND depth = 0
         )
    THEN
      RETURN null;
    END IF;

    IF new.$links_table_input_field = new.$links_table_output_field
    OR EXISTS (
      SELECT id FROM $closure_table_name
        WHERE $closure_table_parent_field = new.$links_table_output_field
        AND $closure_table_child_field = new.$links_table_input_field
        )
    THEN
      RETURN null;
    END IF;

    INSERT INTO $closure_table_name (
         $closure_table_parent_field,
         $closure_table_child_field,
         depth)
      VALUES (
         new.$links_table_input_field,
         new.$links_table_output_field,
         0);

    new_id := lastval();

    UPDATE $closure_table_name
      SET entry_edge_id = new_id
        , exit_edge_id = new_id
        , direct_edge_id = new_id
      WHERE id = new_id;

    INSERT INTO $closure_table_name (
      entry_edge_id,
      direct_edge_id,
      exit_edge_id,
      $closure_table_parent_field,
      $closure_table_child_field,
      depth)
      SELECT id
         , new_id
         , new_id
         , $closure_table_parent_field
         , new.$links_table_output_field
         , depth + 1
        FROM $closure_table_name
        WHERE $closure_table_child_field = new.$links_table_input_field;

    INSERT INTO $closure_table_name (
      entry_edge_id,
      direct_edge_id,
      exit_edge_id,
      $closure_table_parent_field,
      $closure_table_child_field,
      depth)
      SELECT new_id
        , new_id
        , id
        , new.$links_table_input_field
        , $closure_table_child_field
        , depth + 1
        FROM $closure_table_name
        WHERE $closure_table_parent_field = new.$links_table_output_field;

    INSERT INTO $closure_table_name (
      entry_edge_id,
      direct_edge_id,
      exit_edge_id,
      $closure_table_parent_field,
      $closure_table_child_field,
      depth)
      SELECT A.id
        , new_id
        , B.id
        , A.$closure_table_parent_field
        , B.$closure_table_child_field
        , A.depth + B.depth + 2
     FROM $closure_table_name A
        CROSS JOIN $closure_table_name B
     WHERE A.$closure_table_child_field = new.$links_table_input_field
       AND B.$closure_table_parent_field = new.$links_table_output_field;

  END IF;

  IF tg_op = 'DELETE' THEN

    IF NOT EXISTS(
        SELECT id FROM $closure_table_name
        WHERE $closure_table_parent_field = old.$links_table_input_field
        AND $closure_table_child_field = old.$links_table_output_field AND
        depth = 0 )
    THEN
        RETURN NULL;
    END IF;

    CREATE TABLE PurgeList (Id int);

    INSERT INTO PurgeList
      SELECT id FROM $closure_table_name
          WHERE $closure_table_parent_field = old.$links_table_input_field
        AND $closure_table_child_field = old.$links_table_output_field AND
        depth = 0;

    WHILE (1 = 1)
    loop

      INSERT INTO PurgeList
        SELECT id FROM $closure_table_name
          WHERE depth > 0
          AND ( entry_edge_id IN ( SELECT Id FROM PurgeList )
          OR direct_edge_id IN ( SELECT Id FROM PurgeList )
          OR exit_edge_id IN ( SELECT Id FROM PurgeList ) )
          AND Id NOT IN (SELECT Id FROM PurgeList );

      GET DIAGNOSTICS num_rows = ROW_COUNT;
      if (num_rows = 0) THEN
        EXIT;
      END IF;
    end loop;

    DELETE FROM $closure_table_name WHERE Id IN ( SELECT Id FROM PurgeList);
    DROP TABLE PurgeList;

  END IF;

  RETURN NULL;

END
$$BODY$$
  LANGUAGE plpgsql VOLATILE
  COST 100;

CREATE TRIGGER autoupdate_tc
  AFTER INSERT OR DELETE OR UPDATE
  ON $links_table_name FOR each ROW
  EXECUTE PROCEDURE update_tc();

"""
        )
    return pg_tc.substitute(links_table_name=links_table_name,
        links_table_input_field=links_table_input_field,
        links_table_output_field=links_table_output_field,
        closure_table_name=closure_table_name, closure_table_parent_field=
        closure_table_parent_field, closure_table_child_field=
        closure_table_child_field)


def copyDisplayProperties(displayCtx, src, dest, displayExclude=None,
    optExclude=None, displayArgs=None, optArgs=None):
    """Copies all properties from the ``src`` :class:`.Display` and
    :class:`.DisplayOpts` instances to the ``dest`` instances.

    :arg displayCtx:     The :class:`.DisplayContext`

    :arg displayExclude: Collection of :class:`.Display` properties which
                         should not be copied

    :arg optExclude:     Collection of :class:`.DisplayOpts` properties which
                         should not be copied

    :arg displayArgs:    Values to be used instead of the ``src`` ``Display``
                         values.

    :arg optArgs:        Values to be used instead of the ``src``
                         ``DisplayOpts`` values.
    """
    if displayExclude is None:
        displayExclude = []
    if optExclude is None:
        optExclude = []
    if displayArgs is None:
        displayArgs = {}
    if optArgs is None:
        optArgs = {}
    srcDisplay = displayCtx.getDisplay(src)
    destDisplay = displayCtx.getDisplay(dest)
    for prop in srcDisplay.getAllProperties()[0]:
        if prop in displayExclude:
            continue
        if not srcDisplay.propertyIsEnabled(prop
            ) or not destDisplay.propertyIsEnabled(prop):
            continue
        val = displayArgs.get(prop, getattr(srcDisplay, prop))
        if prop == 'overlayType':
            choices = destDisplay.getProp('overlayType').getChoices(destDisplay
                )
            if val not in choices:
                continue
        setattr(destDisplay, prop, val)
    srcOpts = displayCtx.getOpts(src)
    destOpts = displayCtx.getOpts(dest)
    for prop in srcOpts.getAllProperties()[0]:
        if prop in optExclude:
            continue
        if not hasattr(destOpts, prop):
            continue
        if not srcOpts.propertyIsEnabled(prop
            ) or not destOpts.propertyIsEnabled(prop):
            continue
        val = optArgs.get(prop, getattr(srcOpts, prop))
        setattr(destOpts, prop, val)


def collapseWidget(pageIndex, columnIndex, widgetIndex, collapse, retJson=True
    ):
    """ Collapse or expand specific widget.

        @param pageIndex
        index of page the widget lies on( start from 0 )

        @param columnIndex
        index of column the widget lies on( start from 0 )

        @param widgetIndex
        index of the widget, count from top to bottom( start from 0 )

        @param collapse
        widget collapse status, True means collapse, False means expand

        @retJson
        format return value to json format or not( default True )

        @return
        a dict contains state of process, format like:
        {
            'success': True,
            'msg': 'Change widget collapse state success.'
        }

        """


def revc(seq_string):
    """
    Return the reverse compelement of given nucleotide sequence
    """
    o = 'ACGTUWSMKRYBDHVNZacgtuwsmkrybdhvnz-'
    c = 'TGCAAWSKMYRVHDBNZtgcaawskmyrvhdbnz-'
    if len(set(seq_string) & set(o)) > len(set(seq_string)):
        errmsg = 'invalid character was found in the sequeces'
        raise RuntimeWarning(errmsg)
    return seq_string.translate(str.maketrans(o, c))[::-1]


def _zseries_to_cseries(zs):
    """Covert z-series to a Chebyshev series.

    Covert a z series to the equivalent Chebyshev series. The result is
    never an empty array. The dtype of the return is the same as that of
    the input. No checks are run on the arguments as this routine is for
    internal use.

    Parameters
    ----------
    zs : 1-D ndarray
        Odd length symmetric z-series, ordered from  low to high.

    Returns
    -------
    c : 1-D ndarray
        Chebyshev coefficients, ordered from  low to high.

    """
    n = (zs.size + 1) // 2
    c = zs[n - 1:].copy()
    c[1:n] *= 2
    return c


def allocate_hosted_connection(connectionId=None, ownerAccount=None,
    bandwidth=None, connectionName=None, vlan=None):
    """
    Creates a hosted connection on an interconnect or a link aggregation group (LAG).
    Allocates a VLAN number and a specified amount of bandwidth for use by a hosted connection on the given interconnect or LAG.
    See also: AWS API Documentation

    :example: response = client.allocate_hosted_connection(
        connectionId='string',
        ownerAccount='string',
        bandwidth='string',
        connectionName='string',
        vlan=123
    )

    :type connectionId: string
    :param connectionId: [REQUIRED]
            The ID of the interconnect or LAG on which the connection will be provisioned.
            Example: dxcon-456abc78 or dxlag-abc123
            Default: None

    :type ownerAccount: string
    :param ownerAccount: [REQUIRED]
            The numeric account ID of the customer for whom the connection will be provisioned.
            Example: 123443215678
            Default: None

    :type bandwidth: string
    :param bandwidth: [REQUIRED]
            The bandwidth of the connection.
            Example: 500Mbps
            Default: None
            Values: 50Mbps, 100Mbps, 200Mbps, 300Mbps, 400Mbps, or 500Mbps

    :type connectionName: string
    :param connectionName: [REQUIRED]
            The name of the provisioned connection.
            Example: '500M Connection to AWS '
            Default: None

    :type vlan: integer
    :param vlan: [REQUIRED]
            The dedicated VLAN provisioned to the hosted connection.
            Example: 101
            Default: None

    :rtype: dict
    :return: {
        'ownerAccount': 'string',
        'connectionId': 'string',
        'connectionName': 'string',
        'connectionState': 'ordering'|'requested'|'pending'|'available'|'down'|'deleting'|'deleted'|'rejected',
        'region': 'string',
        'location': 'string',
        'bandwidth': 'string',
        'vlan': 123,
        'partnerName': 'string',
        'loaIssueTime': datetime(2015, 1, 1),
        'lagId': 'string',
        'awsDevice': 'string'
    }

    :returns:
    Ordering : The initial state of a hosted connection provisioned on an interconnect. The connection stays in the ordering state until the owner of the hosted connection confirms or declines the connection order.
    Requested : The initial state of a standard connection. The connection stays in the requested state until the Letter of Authorization (LOA) is sent to the customer.
    Pending : The connection has been approved, and is being initialized.
    Available : The network link is up, and the connection is ready for use.
    Down : The network link is down.
    Deleting : The connection is in the process of being deleted.
    Deleted : The connection has been deleted.
    Rejected : A hosted connection in the 'Ordering' state will enter the 'Rejected' state if it is deleted by the end customer.

    """
    pass


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


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

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

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


def catch(func, handle=lambda e: e, *args, **kwargs):
    """Helper function to enable the list comprehension in xmltolist.

    Whenenver a data field doesn't have an entry, put an empty string.

    cf. http://stackoverflow.com/a/8915613
    """
    try:
        return func(*args, **kwargs)
    except KeyError:
        return ''


def distribute_value(samples, spacing=1.0, range_start=0.0, range_end=1.0):
    """
    Returns a list of values distributed between a start and end range
    :param samples: int, number of values to sample across the value range
    :param spacing: float, incremental scale for each sample distance
    :param range_start: float, minimum value in the sample range
    :param range_end: float, maximum value in the sample range
    :return: list<float>
    """
    value_list = [range_start]
    value_dst = abs(range_end - range_start)
    unit = 1.0
    factor = 1.0
    for i in range(samples - 2):
        unit += factor * spacing
        factor *= spacing
    unit = value_dst / unit
    total_unit = unit
    for i in range(samples - 2):
        mult_factor = total_unit / value_dst
        value_list.append(range_start - (range_start - range_end) * mult_factor
            )
        unit *= spacing
        total_unit += unit
    value_list.append(range_end)
    return value_list


def change_settings(new_settings=None, filename=None):
    """ Changes the value of configuration variables."""
    new_settings = new_settings or {}
    gl = globals()
    if filename:
        with open(filename) as in_file:
            exec(in_file)
        gl.update(locals())
    gl.update(new_settings)


def log_floor(n, b):
    """
    The largest integer k such that b^k <= n.
    """
    p = 1
    k = 0
    while p <= n:
        p *= b
        k += 1
    return k - 1


@classmethod
def from_dict(cls, customer, attributes=None, parent_attr=None,
    properties_class=None):
    """
        Create a new Education initialized by a specified dictionary of attributes

        :param customer: the customer associated to this education object
        :param parent_attr: the parent attribute for compiling the mutation tracker dictionary
        :param attributes: key-value arguments for generating the structure of the Education's attributes
        :param properties_class: reference to the actual Properties class
        :return: a new Education object
        """
    o = cls(customer=customer, parent_attr=parent_attr, properties_class=
        properties_class)
    o.attributes = {} if attributes is None else attributes
    return o


def _get_v1_error_from_json(_json_error, _fail_on_no_results):
    """This function extracts error details (if present) from a Community API v1 response.

    :param _json_error: The API response in JSON format
    :type _json_error: dict
    :param _fail_on_no_results: Defines if an exception should be raised if no results are returned
    :type _fail_on_no_results: bool
    :returns: A Boolean stating if an error was found and a tuple with the error code and error/exception messages
    """
    _error_code, _error_msg, _exc_msg = 0, '', ''
    _error_found = True if _json_error['status'] == 'error' else False
    if _error_found:
        _error_code = _json_error['error']['code']
        _error_msg = _json_error['error']['message']
        _exc_msg = (
            f"The Community API v1 call failed with the error code '{_error_code}' and the following "
             + f'message: {_error_msg}')
    _inner_response = _json_error[list(_json_error.keys())[1]]
    if len(_inner_response[list(_inner_response.keys())[0]]) == 0:
        _error_found = _fail_on_no_results
        _error_code = 404
        _error_msg = f'The Community API v1 call returned no results.'
        _exc_msg = _error_msg
    return _error_found, (_error_code, _error_msg, _exc_msg)


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

        :param str val:
        :rtype: MemberAddResult
        """
    return cls('user_already_paired', val)


def add_frametype_option(parser, **kwargs):
    """Add a `-f/--frametype` option to this given parser
    """
    kwargs.setdefault('help', 'the frame type name')
    return parser.add_argument('-f', '--frametype', **kwargs)


@classmethod
def get_default(cls, entity):
    """Return a bound proxy instance for this mutable attribute.

        :param entity: The entity this attribute is on
        :returns: A bound proxy instance

        """
    return cls.Proxy(entity)


@staticmethod
def formatlist(data, name, fmt, sep):
    """convert iterable to appropriate list format"""
    return list(data)


def modulus(out, young=None, bulk=None, shear=None, poisson=None):
    """Calculate `out` using `given`.

    :param out: Desired elastic modulus.
    :param young: Young's modulus.
    :param bulk: Bulk modulus.
    :param shear: Shear modulus.
    :param poisson: Poisson ration.

    This function determines the desired elastic modulus using the given moduli.
    """
    if out == 'bulk':
        if young and shear:
            return young * shear / (9.0 * shear - 3.0 * young)
        elif young and poisson:
            return young / (3.0 - 6.0 * poisson)
        elif shear and poisson:
            return 2.0 * shear * (1.0 + poisson) / (3.0 - 6.0 * poisson)
    elif out == 'young':
        if bulk and shear:
            return 9.0 * bulk * shear / (3.0 * bulk + shear)
        elif young and poisson:
            return 3.0 * bulk * (1.0 - 2.0 * poisson)
        elif shear and poisson:
            return 2.0 * shear * (1.0 + poisson)
    elif out == 'shear':
        if bulk and young:
            return 3.0 * bulk * young / (9.0 * bulk - young)
        elif bulk and poisson:
            return 3.0 * bulk * (1.0 - 2.0 * poisson) / (2.0 + 2.0 * poisson)
        elif young and poisson:
            return young / (2.0 + 2.0 * poisson)
    elif out == 'poisson':
        if bulk and young:
            return (3.0 * bulk - young) / (6.0 * bulk)
        elif bulk and shear:
            return (3.0 * bulk - 2.0 * shear) / (6.0 * bulk + 2.0 * shear)
        elif young and shear:
            return young / (2.0 * shear) - 1.0
    raise ValueError('Cannot determine {} with the given moduli.'.format(out))


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

        :param PasswordResetAllDetails val:
        :rtype: EventDetails
        """
    return cls('password_reset_all_details', val)


def round(data=None, name=None, attr=None, out=None, **kwargs):
    """Returns element-wise rounded value to the nearest integer of the input.

    Example::

       round([-1.5, 1.5, -1.9, 1.9, 2.1]) = [-2.,  2., -2.,  2.,  2.]

    The storage type of ``round`` output depends upon the input storage type:

      - round(default) = default
      - round(row_sparse) = row_sparse
      - round(csr) = csr

    Defined in src/operator/tensor/elemwise_unary_op_basic.cc:L778

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

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

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


def csv_writer(output_dict, input_dict, file):
    """
    This function write each line of csv file
    :param output_dict: output dictionary
    :param input_dict: input dictionary
    :param file: csv file object
    :return: None
    """
    input_keys = list(input_dict.keys())
    input_keys.sort()
    output_keys = list(output_dict.keys())
    output_keys.sort()
    for inp in input_keys:
        file.write(str(input_dict[inp]) + ',')
    file.write(',,')
    for index, out in enumerate(output_keys):
        file.write(str(output_dict[out]))
        if index < len(output_keys):
            file.write(',')
    file.write('\n')


def _torads(in_file, fmap_range=None, newpath=None):
    """
    Convert a field map to rad/s units

    If fmap_range is None, the range of the fieldmap
    will be automatically calculated.

    Use fmap_range=0.5 to convert from Hz to rad/s
    """
    from math import pi
    import nibabel as nb
    from nipype.utils.filemanip import fname_presuffix
    out_file = fname_presuffix(in_file, suffix='_rad', newpath=newpath)
    fmapnii = nb.load(in_file)
    fmapdata = fmapnii.get_data()
    if fmap_range is None:
        fmap_range = max(abs(fmapdata.min()), fmapdata.max())
    fmapdata = fmapdata * (pi / fmap_range)
    out_img = nb.Nifti1Image(fmapdata, fmapnii.affine, fmapnii.header)
    out_img.set_data_dtype('float32')
    out_img.to_filename(out_file)
    return out_file, fmap_range


def class_register(cls):
    """Class decorator that allows to map LSP method names to class methods."""
    cls.handler_registry = {}
    cls.sender_registry = {}
    for method_name in dir(cls):
        method = getattr(cls, method_name)
        if hasattr(method, '_handle'):
            cls.handler_registry.update({method._handle: method_name})
        if hasattr(method, '_sends'):
            cls.sender_registry.update({method._sends: method_name})
    return cls


def can_merge(git, into):
    """we check if the branch we want to send commits to is up to date or not. if current branch is equal to into branch we check if we want to commit"""
    current_branch = git.get_current_branch()
    if current_branch == into:
        return git.has_commitable_changes()
    for line in git(f'branch --contains {current_branch}').splitlines():
        if line.strip().decode('utf-8') == into:
            return True


def to_native_string(value, encoding):
    """Convert bytes from Lua to "Native" strings, which wsgi likes.

    In Python 3 these are 'str' and not 'bytes'.

    In Python 2 these are 'str' and not 'unicode'"""
    assert isinstance(value, bytes), repr(value)
    return str(value.decode(encoding))


def _check_status(response):
    """
    Check the response code is a 2xx (raise an exception otherwise)
    """
    if response.status_code < 200 or response.status_code >= 300:
        raise ValueError('Expected a 2xx code, got {}'.format(response.
            status_code))


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 _empty_fp_events():
    """Container for forceplate events"""
    return dict(R_strikes=[], R_toeoffs=[], L_strikes=[], L_toeoffs=[],
        valid=set(), R_strikes_plate=[], L_strikes_plate=[], our_fp_info={},
        coded='')


def skip_key(point, key, origin, keys, predicate):
    """Find the next result in ``keys`` for which ``predicate(key)`` is ``False``.

    If none is found, or if ``key`` is already such a result, the
    return value is ``(point, key)``.

    """
    while predicate(key):
        try:
            p, key = next(keys)
        except StopIteration:
            break
        point = origin + p
    return point, key


def _setup_residual_graph(G, weight):
    """Setup residual graph as a copy of G with unique edges weights.

    The node set of the residual graph corresponds to the set V' from
    the Baswana-Sen paper and the edge set corresponds to the set E'
    from the paper.

    This function associates distinct weights to the edges of the
    residual graph (even for unweighted input graphs), as required by
    the algorithm.

    Parameters
    ----------
    G : NetworkX graph
        An undirected simple graph.

    weight : object
        The edge attribute to use as distance.

    Returns
    -------
    NetworkX graph
        The residual graph used for the Baswana-Sen algorithm.
    """
    residual_graph = G.copy()
    for u, v in G.edges():
        if not weight:
            residual_graph[u][v]['weight'] = id(u), id(v)
        else:
            residual_graph[u][v]['weight'] = G[u][v][weight], id(u), id(v)
    return residual_graph


def tuple_or_list_params_2_dict_params(params):
    """
    tuple和list类型的params转dict类型的params
    :param params:
    :return:
    """
    _ = {}
    for item in params:
        _.update({item[0]: item[1]})
    return _


def parse_path(path):
    """Decompose a JSON structure path"""
    parts = []
    for e in path.split('.'):
        if e.endswith('[]'):
            k, _ = e.split('[')
            parts.append([k, 'an', False])
        elif e.endswith('[-]'):
            k, _ = e.split('[')
            parts.append([k, 'al', False])
        else:
            k = e
            parts.append([k, 'o', False])
    if parts:
        parts[-1][2] = True
    return parts


def shorten_name(name, max_length):
    """
    Shortens a name to the given number of characters.
    """
    if len(name) <= max_length:
        return name
    q, r = divmod(max_length - 3, 2)
    return name[:q + r] + '...' + name[-q:]


def phys2dig(signal, dmin, dmax, pmin, pmax):
    """
    converts physical values to digital values

    Parameters
    ----------
    signal : np.ndarray or int
        A numpy array with int values (digital values) or an int.
    dmin : int
        digital minimum value of the edf file (eg -2048).
    dmax : int
        digital maximum value of the edf file (eg 2048).
    pmin : float
        physical maximum value of the edf file (eg -200.0).
    pmax : float
        physical maximum value of the edf file (eg 200.0).

    Returns
    -------
    digital : np.ndarray or int
        converted digital values

    """
    m = (dmax - dmin) / (pmax - pmin)
    digital = m * signal
    return digital


@classmethod
def _convert_to_style(cls, style_dict, num_format_str=None):
    """
        converts a style_dict to an xlwt style object

        Parameters
        ----------
        style_dict : style dictionary to convert
        num_format_str : optional number format string
        """
    import xlwt
    if style_dict:
        xlwt_stylestr = cls._style_to_xlwt(style_dict)
        style = xlwt.easyxf(xlwt_stylestr, field_sep=',', line_sep=';')
    else:
        style = xlwt.XFStyle()
    if num_format_str is not None:
        style.num_format_str = num_format_str
    return style


def filterP(f):
    """
    Translate a obj parameter into "string" format
    """
    if hasattr(f, 'build'):
        return f.build()
    else:
        return f


@classmethod
def get_market_trade_history(cls, pair, since=None):
    """get market trade history"""
    return cls.api(cls.url + '/exchange/last_trades?currencyPair=' + cls.
        format_pair(pair))


def press2depth(press, latitude):
    """ calculate depth from pressure
        http://www.seabird.com/application_notes/AN69.htm

        ATENTION, move it to fluid.
    """
    import numpy as np
    x = np.sin(np.pi / 180 * latitude / 57.29578) ** 2
    g = 9.780318 * (1.0 + (0.0052788 + 2.36e-05 * x) * x) + 1.092e-06 * press
    depth = -((((-1.82e-15 * press + 2.279e-10) * press - 2.2512e-05) *
        press + 9.72659) * press) / g
    return depth


@classmethod
def apply_(cls, name, named_args):
    """Call a named API function with a dictionary of named arguments.

    Args:
      name: The name of the API function to call.
      named_args: A dictionary of arguments to the function.

    Returns:
      An object representing the called function. If the signature specifies
      a recognized return type, the returned value will be cast to that type.
    """
    return cls.lookup(name).apply(named_args)


def greaterThanEqualTo(t):
    """Compare this DateTime object to another DateTime object OR
        a floating point number such as that which is returned by the
        python time module. Returns true if the object represents a
        date/time greater than or equal to the specified DateTime or
        time module style time.  Revised to give more correct results
        through comparison of long integer milliseconds."""


def _misc_to_bytes(m):
    """
    Convert an arbitrary object into a string encoded as a UTF-8 series of bytes.

    See `Connection.send` for more details.
    """
    return str(m).encode('UTF-8')


def ternary(value, true_val, false_val):
    """  value ? true_val : false_val """
    if value:
        return true_val
    else:
        return false_val


def decimal2dms(decDeg, delimiter):
    """Converts decimal degrees to string in Degrees:Minutes:Seconds format
    with user specified delimiter.

    @type decDeg: float
    @param decDeg: coordinate in decimal degrees
    @type delimiter: string
    @param delimiter: delimiter character in returned string
    @rtype: string
    @return: coordinate string in D:M:S format

    """
    if decDeg > 0:
        if 1 <= decDeg < 10:
            sDeg = '0' + str(decDeg)[0]
        elif decDeg >= 10:
            sDeg = str(decDeg)[:2]
        elif decDeg < 1:
            sDeg = '00'
        else:
            return 'nan'
        if str(decDeg).find('.') == -1:
            mins = float(decDeg) * 60.0
        else:
            mins = float(str(decDeg)[str(decDeg).index('.'):]) * 60
        if 1 <= mins < 10:
            sMins = '0' + str(mins)[:1]
        elif mins >= 10:
            sMins = str(mins)[:2]
        elif mins < 1:
            sMins = '00'
        else:
            return 'nan'
        secs = (decDeg - (float(sDeg) + float(sMins) / 60.0)) * 3600.0
        if 0 < secs < 10:
            sSecs = '0' + str(secs)[:str(secs).find('.') + 3]
        elif secs < 0.001:
            sSecs = '00.00'
        else:
            sSecs = str(secs)[:str(secs).find('.') + 3]
        if len(sSecs) < 5:
            sSecs = sSecs + '0'
        if float(sSecs) == 60.0:
            sSecs = '00.00'
            sMins = str(int(sMins) + 1)
        if int(sMins) == 60:
            sMins = '00'
            sDeg = str(int(sDeg) + 1)
        return '+' + sDeg + delimiter + sMins + delimiter + sSecs
    else:
        if -10 < decDeg <= -1:
            sDeg = '-0' + str(decDeg)[1]
        elif decDeg <= -10:
            sDeg = str(decDeg)[:3]
        elif decDeg > -1:
            sDeg = '-00'
        else:
            return 'nan'
        if str(decDeg).find('.') == -1:
            mins = float(decDeg) * -60.0
        else:
            mins = float(str(decDeg)[str(decDeg).index('.'):]) * 60
        if 1 <= mins < 10:
            sMins = '0' + str(mins)[:1]
        elif mins >= 10:
            sMins = str(mins)[:2]
        elif mins < 1:
            sMins = '00'
        else:
            return 'nan'
        secs = (decDeg - (float(sDeg) - float(sMins) / 60.0)) * 3600.0
        if -10 < secs < 0:
            sSecs = '0' + str(secs)[1:str(secs).find('.') + 3]
        elif secs > -0.001:
            sSecs = '00.00'
        else:
            sSecs = str(secs)[1:str(secs).find('.') + 3]
        if len(sSecs) < 5:
            sSecs = sSecs + '0'
        if float(sSecs) == 60.0:
            sSecs = '00.00'
            sMins = str(int(sMins) + 1)
        if int(sMins) == 60:
            sMins = '00'
            sDeg = str(int(sDeg) - 1)
        return sDeg + delimiter + sMins + delimiter + sSecs


def _is_insert(line):
    """
    Returns true if the line begins a SQL insert statement.
    """
    return line.startswith('INSERT INTO')


def completeness_run_check(columns, df):
    """
    Check for consistency between parameters and the dataframe, an assertion
    error will incur if the check is not passed.

    :param columns: Columns on which to run the metric
    :type columns: list
    :param df: Dataframe on which to run the metric
    :type df: DataFrame
    """
    if columns is not None:
        for col in columns:
            assert col in df.columns, "Column '%s' is not a column part of the dataframe" % col


def _to_bytes_or_false(val):
    """An internal graph to convert the input to a bytes or to False.

    The criteria for conversion is as follows and should be python 2 and 3
    compatible:
    - If val is py2 str or py3 bytes: return bytes
    - If val is py2 unicode or py3 str: return val.decode('utf-8')
    - Otherwise, return False
    """
    if isinstance(val, bytes):
        return val
    else:
        try:
            return val.encode('utf-8')
        except AttributeError:
            return False


def import_txt(file_name, split_by='\t'):
    """ Import text file into console with default split ="	"

    parameters:
    file_name (str): The path to a text file (string or raw string)
    split_by (str): The text file delimiter

    returns:
    dict: The content of the text file as dictionary
    """
    read_line = []
    data = {}
    with open(file_name, 'r') as fin:
        for line in fin:
            line = line.strip()
            split_line = line.split(split_by)
            read_line.append(split_line)
    for record in read_line:
        val = []
        x = 1
        while x < len(record):
            val.append(record[x])
            x += 1
        data[record[0]] = tuple(val)
    return data


@staticmethod
def _scan_gt_value(text):
    """
        Scan text for integer value N. Returns N if an int > 0, else None.

        text can be None. If so return None.
        """
    if text is None:
        return None
    try:
        int_value = int(text)
    except ValueError:
        return None
    if int_value < 1:
        return None
    else:
        return int_value


@classmethod
def from_dict(cls, dict_, override_list=None):
    """Loads object from dict."""
    obj = cls.__new__(cls)
    obj.__dict__.update(dict_)
    if override_list is not None:
        overrides = obj.parse_overrides(override_list)
        for section, ov_dict in overrides.items():
            for key, value in ov_dict.items():
                obj.__dict__[section][key] = value
    return obj


def surfacedeform_bind(modifier: str=''):
    """Bind mesh to target in surface deform modifier

    :param modifier: Modifier, Name of the modifier to edit
    :type modifier: str
    """
    pass


def get_input_op_table_args(ipa):
    """Creates an input operator from an Input Pipeline Analyzer proto.

  Args:
    ipa: An input_pipeline_pb2.InputPipelineAnalysisResult.

  Returns:
    Returns a gviz_api.DataTable
  """
    table_description = [('opName', 'string', 'Input Op'), ('count',
        'number', 'Count'), ('timeInMs', 'number', 'Total Time (in ms)'), (
        'timeInPercent', 'number',
        'Total Time (as % of total input-processing time)'), (
        'selfTimeInMs', 'number', 'Total Self Time (in ms)'), (
        'selfTimeInPercent', 'number',
        'Total Self Time (as % of total input-processing time)'), (
        'category', 'string', 'Category')]
    data = []
    for details in ipa.input_op_details:
        row = [details.op_name, details.count, details.time_in_ms, details.
            time_in_percent / 100.0, details.self_time_in_ms, details.
            self_time_in_percent / 100.0, details.category]
        data.append(row)
    enqueue_us = '{:.3f}'.format(ipa.input_time_breakdown.enqueue_us)
    demanded_file_read_us = '{:.3f}'.format(ipa.input_time_breakdown.
        demanded_file_read_us)
    advanced_file_read_us = '{:.3f}'.format(ipa.input_time_breakdown.
        advanced_file_read_us)
    preprocessing_us = '{:.3f}'.format(ipa.input_time_breakdown.
        preprocessing_us)
    unclassified_non_enqueue_us = '{:.3f}'.format(ipa.input_time_breakdown.
        unclassified_non_enqueue_us)
    custom_properties = {'enqueue_us': enqueue_us, 'demanded_file_read_us':
        demanded_file_read_us, 'advanced_file_read_us':
        advanced_file_read_us, 'preprocessing_us': preprocessing_us,
        'unclassified_nonequeue_us': unclassified_non_enqueue_us}
    return table_description, data, custom_properties


def addBranchNamesToFile(fileSection, branchNames):
    """
    _addBranchNamesToFile_

    Given a list of branch names add them to the file section in the FWJR.
    """
    setattr(fileSection, 'branches', branchNames)
    return


def updateStimSum(sumstim, nevents1, s1, sumsq1, found_s1, nevents2, s2,
    sumsq2, found_s2):
    """Update sums for averages of stim positions.

    Parameters
    ----------
    sumstim: tuple with current sums
        n1      number of events for first stim
        sum1y   sum for first stim, Y coordinate
        sum1x   sum for first stim, X coordinate
        sumsq1y sum of squares for first stim, Y coordinate
        sumsq1x sum of squares for first stim, X coordinate
        n2      number of events for second stim
        sum2y   sum for second stim, Y coordinate
        sum2x   sum for second stim, X coordinate
        sumsq2y sum of squares for second stim, Y coordinate
        sumsq2x sum of squares for second stim, X coordinate

    nevents1: int
        Number of events for first stim in current time interval.

    s1: tuple of two floats
        Tuple of (y,x) coordinates of the first stim in current interval.

    found_s1: boolean
        True if the first stim was actually found.

    nevents2: int
        Number of events for second stim in current time interval.

    s2: tuple of two floats
        Same as s1, but for the second stim.

    found_s2: boolean
        True if the second stim was actually found.

    Returns
    -------
    tuple
        An updated sumstim tuple.

    nevents1 and nevents2 are used as weights when incrementing the
    sums.  n1 and n2 are the total number of events for the first and
    second stims respectively.
    """
    (n1, sum1y, sum1x, sumsq1y, sumsq1x, n2, sum2y, sum2x, sumsq2y, sumsq2x
        ) = sumstim
    if found_s1:
        n1 = n1 + nevents1
        sum1y = sum1y + s1[0] * nevents1
        sum1x = sum1x + s1[1] * nevents1
        sumsq1y = sumsq1y + sumsq1[0]
        sumsq1x = sumsq1x + sumsq1[1]
    if found_s2:
        n2 = n2 + nevents2
        sum2y = sum2y + s2[0] * nevents2
        sum2x = sum2x + s2[1] * nevents2
        sumsq2y = sumsq2y + sumsq2[0]
        sumsq2x = sumsq2x + sumsq2[1]
    return (n1, sum1y, sum1x, sumsq1y, sumsq1x, n2, sum2y, sum2x, sumsq2y,
        sumsq2x)


@classmethod
def get_complementary_color(cls, color):
    """
        Returns the complementary color of the given color
        :param color: QColor
        """
    hsl_hue = color.hslHueF()
    hsl_saturation = color.hslSaturationF()
    lightness = color.lightnessF()
    lightness = 1.0 - lightness
    hsl_hue += 0.5
    if hsl_hue >= 1.0:
        hsl_hue -= 1.0
    return cls.fromHslF(hsl_hue, hsl_saturation, lightness)


def is_float(dtype):
    """Return True if datatype dtype is a float kind"""
    return 'float' in dtype.name or dtype.name in ['single', 'double']


@classmethod
def register_method(cls, name, func):
    """Register a method with the backend.

        Parameters
        ----------
        name : str
            The method name.
        func : callable
            The method
        """
    setattr(cls, name, staticmethod(func))


def _whctrs(anchor):
    """
    Return width, height, x center, and y center for an anchor (window).
    """
    w = anchor[2] - anchor[0] + 1
    h = anchor[3] - anchor[1] + 1
    x_ctr = anchor[0] + (w - 1) / 2
    y_ctr = anchor[1] + (h - 1) / 2
    return w, h, x_ctr, y_ctr


def update_service_specific_credential(UserName=None,
    ServiceSpecificCredentialId=None, Status=None):
    """
    Sets the status of a service-specific credential to Active or Inactive . Service-specific credentials that are inactive cannot be used for authentication to the service. This action can be used to disable a users service-specific credential as part of a credential rotation work flow.
    See also: AWS API Documentation

    :example: response = client.update_service_specific_credential(
        UserName='string',
        ServiceSpecificCredentialId='string',
        Status='Active'|'Inactive'
    )

    :type UserName: string
    :param UserName: The name of the IAM user associated with the service-specific credential. If you do not specify this value, then the operation assumes the user whose credentials are used to call the operation.
            This parameter allows (per its regex pattern ) a string of characters consisting of upper and lowercase alphanumeric characters with no spaces. You can also include any of the following characters: =,.@-

    :type ServiceSpecificCredentialId: string
    :param ServiceSpecificCredentialId: [REQUIRED]
            The unique identifier of the service-specific credential.
            This parameter allows (per its regex pattern ) a string of characters that can consist of any upper or lowercased letter or digit.

    :type Status: string
    :param Status: [REQUIRED]
            The status to be assigned to the service-specific credential.

    """
    pass


def looksLikeVestLutFile(path):
    """Returns ``True`` if the given ``path`` looks like a VEST LUT file,
    ``False`` otherwise.
    """
    with open(path, 'rt') as f:
        lines = []
        for i in range(10):
            line = f.readline()
            if line is None:
                break
            else:
                lines.append(line.strip())
    validHeaders = '%!VEST-LUT', '%BeginInstance', '%%BeginInstance'
    return len(lines) > 0 and lines[0] in validHeaders


@classmethod
def remove(cls, group, function_):
    """ Remove an existing function

        If your application inherits some unwanted options from a specific
        function, you can unlink this function::

            def foo(opt, default):
                pass

            Configuration.add('create-db', function_=foo)
            Configuration.remove('create-db', function_=foo)

        :param group: group is a set of parser option
        :param function_: function to add
        """
    if group in cls.groups:
        if function_ in cls.groups[group]:
            cls.groups[group].remove(function_)


def kronestring(kr):
    """Return a string version of the integer value ``kr``, with
       space as the thousand-separator.
    """
    if kr == 0:
        return '0'
    res = ''
    if kr < 0:
        sign = '-'
        kr = -kr
    else:
        sign = ''
    while kr:
        kr, tusen = divmod(kr, 1000)
        res = ' '.join(['%03d' % tusen, res])
    return sign + res.rstrip(' ').lstrip('0')


def getContext():
    """returns the context"""


def stageoutPolicyReport(fileToStage, pnn, command, stageOutType, stageOutExit
    ):
    """
    Prepare Dashboard report about stageout policies
    This dashboard report will be used for reporting to dashboard and visualize local/fallback/direct
    stageout related issues for prod/analysis jobs.
    """
    tempDict = {}
    tempDict['LFN'] = fileToStage['LFN'] if 'LFN' in fileToStage else None
    tempDict['PNN'] = pnn if pnn else fileToStage['PNN'
        ] if 'PNN' in fileToStage else None
    tempDict['StageOutCommand'] = command if command else fileToStage['command'
        ] if 'command' in fileToStage else None
    tempDict['StageOutType'] = stageOutType
    tempDict['StageOutExit'] = stageOutExit
    fileToStage['StageOutReport'].append(tempDict)
    return fileToStage


@classmethod
def callback_hash_tag_name_attribute_name_consitency(cls, element, hashpipe,
    children=True):
    """
        calculate hash over tag, attribute_names

        :param element: etree.element
        :param hashpipe: hash algorithm interface
        :param children: bool - if false children of element ignored for hash calculation
        """
    _element_childes = element.getchildren()
    if children:
        for child in _element_childes:
            hashpipe.update(cls.
                callback_hash_tag_name_attribute_name_consitency(child,
                hashpipe))
    hashpipe.update(bytes(str(element.tag) + '#tag', 'utf-8'))
    if hasattr(element, 'attrib'):
        for _name in sorted(element.attrib.keys()):
            hashpipe.update(bytes(_name + '#att', 'utf-8'))
    return bytes(hashpipe.hexdigest(), 'utf-8')


@classmethod
def drop_all(cls, client):
    """Drop all tables derived from this base class

        Before you call this, import all modules that define the models that you want to drop
        tables for (this registers your models with the base class metadata object).

        Args:
            client (ozelot.client.Client): database client to use
        """
    cls.metadata.drop_all(bind=client.get_engine())


@staticmethod
def latent_heat_of_vaporization(temperature=20):
    """Return the latent heat of vaporization (:math:`\\lambda`) *[MJ/kg]* as described in
        `FAO 56 <http://www.fao.org/tempref/SD/Reserved/Agromet/PET/FAO_Irrigation_Drainage_Paper_56.pdf>`_
        (Annex 3, eq. 3-1, p. 223):

        .. math::

            \\lambda = 2.501-(2.361 * 10^{-3})T

        :param temperature: air temperature (:math:`T`) *[°C]*. Default :math:`temperature=20`
        :type temperature: float or np.array
        :return: (*float or np.array*) latent heat of vaporization (:math:`\\lambda`) *[MJ/kg]*.
            Default :math:`\\lambda=2.45378`
        """
    return 2.501 - 0.002361 * temperature


def p_assignment_list_element(p):
    """assignment_list_element : variable
                               | empty
                               | LIST LPAREN assignment_list RPAREN"""
    if len(p) == 2:
        p[0] = p[1]
    else:
        p[0] = p[3]


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


def Celsius_K(Kelvin):
    """Usage: Convert to Celsius from Kelvin
    Celsius_K(Kelvin)"""
    return Kelvin - 273.15


def dgl_subgraph(*data, **kwargs):
    """This operator constructs an induced subgraph for
    a given set of vertices from a graph. The operator accepts multiple
    sets of vertices as input. For each set of vertices, it returns a pair
    of CSR matrices if return_mapping is True: the first matrix contains edges
    with new edge Ids, the second matrix contains edges with the original
    edge Ids.

    Example:

       .. code:: python

         x=[[1, 0, 0, 2],
           [3, 0, 4, 0],
           [0, 5, 0, 0],
           [0, 6, 7, 0]]
         v = [0, 1, 2]
         dgl_subgraph(x, v, return_mapping=True) =
           [[1, 0, 0],
            [2, 0, 3],
            [0, 4, 0]],
           [[1, 0, 0],
            [3, 0, 4],
            [0, 5, 0]]

    Defined in src/operator/contrib/dgl_graph.cc:L1140

    Parameters
    ----------
    graph : NDArray
        Input graph where we sample vertices.
    data : NDArray[]
        The input arrays that include data arrays and states.
    return_mapping : boolean, required
        Return mapping of vid and eid between the subgraph and the parent graph.

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

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


def migrate_active_change_recommendations(apps, schema_editor):
    """
    Delete all change recommendation of motion versions, that are not active. For active
    change recommendations the motion id will be set.
    """
    MotionChangeRecommendation = apps.get_model('motions',
        'MotionChangeRecommendation')
    to_delete = []
    for cr in MotionChangeRecommendation.objects.all():
        if cr.motion_version.id == cr.motion_version.motion.active_version.id:
            cr.motion = cr.motion_version.motion
            cr.save(skip_autoupdate=True)
        else:
            to_delete.append(cr)
    for cr in to_delete:
        cr.delete(skip_autoupdate=True)


def is_int(val):
    """
    Test int of the string value.

    :param val: string or whatever
    :return: True if the value may be converted to int
    """
    try:
        int(val)
        return True
    except ValueError:
        return False


@classmethod
def reset(cls):
    """
        Supports testing. Nulls the class object's fields
        """
    cls._positional_params = None
    cls._supported_options = None
    cls._details = None
    cls._addendum = None
    cls._examples = None
    cls._usage = None
    cls._summary = None
    cls._utility_name = None
    cls._require_args = None
    cls._parse_errors = None


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 route_path(route_name, request, *elements, **kw):
    """
    This is a backwards compatibility function.  Its result is the same as
    calling::

        request.route_path(route_name, *elements, **kw)

    See :meth:`pyramid.request.Request.route_path` for more information.
    """
    return request.route_path(route_name, *elements, **kw)


def _utf8(s):
    """Convert a string to utf-8 bytes."""
    return s.encode('utf-8')


def load_pty(finder, module):
    """The sgi module is not needed for this module to function."""
    module.IgnoreName('sgi')


def is_int(obj):
    """
    True & False is not considered valid integers even if python considers them 1 & 0 in some versions
    """
    return isinstance(obj, int) and not isinstance(obj, bool)


@classmethod
def close_all(cls, strict=True):
    """
        Closes all Windows.

        Raises RuntimeError if `strict` is true and there are no open Windows.
        """
    if not cls._windows:
        if strict:
            raise RuntimeError('No windows.')
        return
    root = cls._windows[0]._tk_window
    root.destroy()
    for window in cls._windows:
        window._tk_window = None
        window.canvas = None
    cls._windows.clear()


def _check_name_and_port(name, port):
    """
    Check for invalid name and ports
    """
    if type(name) != str:
        raise TypeError('Name of Predictive Service needs to be a string')
    if port < 0 or port > 65535:
        raise ValueError('Port must be within a certain range, 0 to 65535.')
    if port == 9006 or port == 19006:
        raise ValueError(
            'Port 9006 and 19006 are reserved for cache. Please use another port.'
            )


def _format_hex(hex_value: str) ->str:
    """Return hex value with a prefix.

    Accepts hex_value in prefixed (0xff) and unprefixed (ff) formats.
    """
    return hex(int(hex_value, 16))


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 add_object(bucket, obj):
    """
    Upload a local file to an S3 bucket.

    :type bucket: :class:`boto.s3.bucket.Bucket`
    :param bucket: The :class:`~boto.s3.bucket.Bucket` that the file will be uploaded to.

    :type obj: string
    :param obj: The local filename.
    """
    key = bucket.new_key(obj)
    key.set_contents_from_filename(obj, policy='private')


@staticmethod
def get_debug_info():
    """Override this method to return an iterable of lines with the backend debug details.
        """
    return ['Does not provide debug info']


@staticmethod
def _get_name_from_dn(dn):
    """
        Get the instance name from the dn

        :param dn: string containing the distinguished name URL
        :return: string containing the name
        """
    name = dn.split('/pod-')[1].split('/')[0]
    return name


def get_tree(depth=-1):
    """Get flattened tree of all active publishables. The 'depth'
        argument limits the number of levels, defaults to unlimited.
        This is a list of indent, object tuples.
        """


def _sql_gen_intermediate_pi_aggregate(params, table_name='df_e'):
    """
    This intermediate step is calculated for efficiency purposes.

    In the maximisation step, to compute the new
    pi probability distributions, we need to perform a variety of calculations that can all be derived
    from this intermediate table.

    Without this intermediate table, we'd be repeating these calculations multiple times.
    """
    gamma_cols_expr = ', '.join(params._gamma_cols)
    sql = f"""
    select {gamma_cols_expr}, sum(match_probability) as expected_num_matches, sum(1- match_probability) as expected_num_non_matches, count(*) as num_rows
    from {table_name}
    group by {gamma_cols_expr}
    """
    return sql


def migrate_assignment_fields(apps, schema_editor):
    """Migrate new Assignment fields."""
    Assignment = apps.get_model('nsot', 'Assignment')
    Assignment_temp = apps.get_model('nsot', 'Assignment_temp')
    for asn in Assignment.objects.iterator():
        asn_tmp = Assignment_temp.objects.create(id=asn.id, address_id=asn.
            address_id, interface_id=asn.interface_id)


@staticmethod
def get_max_faces(data: list) ->int:
    """Get max number of faces detected in a series of frames, eg 3"""
    max = 0
    for frame in data:
        for face in frame:
            if len(face) > max:
                max = len(face)
    return max


def __call__(participation=None):
    """
        Creates and returns a new :class:`IInteraction` for a given
        request.

        If *participation* is not None, it is added to the new interaction.
        """


def get_paginator(operation_name=None):
    """
    Create a paginator for an operation.

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

    :rtype: L{botocore.paginate.Paginator}
    """
    pass


@classmethod
def from_hex(cls, value):
    """Get an :class:`EmojiCharacter` instance by Emoji Unicode integer value or it's hex string

        :param Union[int, str] value: Emoji Unicode, either integer value or hex string
        :return: Instance returned from the class's internal dictionary
        :rtype: EmojiCharacter
        :raises KeyError: When code not found in the class' internal dictionary
        """
    if isinstance(value, str):
        return cls[int(value, 16)]
    return cls[int(value)]


def print_sale_invoice(sale_invoice, invoice_printer):
    """Utility function to print a sale invoice.

    :param sale: a :class:`stoqlib.domain.sale.Sale` instance
    :param invoice_printer: :class:`stoqlib.domain.invoice.InvoicePrinter` instance
    """
    sale_invoice.send_to_printer(invoice_printer.device_name)


@staticmethod
def is_valid(control_instance, *args, **kwargs):
    """ Method to check if the new control values are correct.

        If the new list controls values are not correct, the backroung
        color of each control in the list will be red.

        Parameters
        ----------
        control_instance: QFrame (mandatory)
            the control widget we want to validate

        Returns
        -------
        valid: bool
            True if the control values are valid,
            False otherwise
        """
    valid = True
    return valid


def pprint(parselist):
    """pretty print a parselist."""
    for elm in parselist:
        print(str(elm))


@staticmethod
def split_input_line(line):
    """
        A modified string splitter that doesn't split
        words encircled in quotation marks; required
        by actions that accept a VMD-compatible
        selection string
        :param line: str, line to be split
        :return: list of strings, contains individual words
        """
    line = line.strip()
    words = []
    open_quotation = False
    previous = 0
    for current, char in enumerate(line):
        if char in ["'", '"']:
            if not open_quotation:
                open_quotation = True
            else:
                open_quotation = False
        if char == ' ' and not open_quotation or current == len(line) - 1:
            word = line[previous:current + 1].strip()
            if word:
                words.append(word)
            previous = current
    return words


def property_type(value):
    """
    Return the type for given value in Neo4j land.

    """
    if isinstance(value, str):
        return 'string'
    elif isinstance(value, int):
        return 'int'
    elif isinstance(value, float):
        return 'double'
    elif isinstance(value, bool):
        return 'boolean'
    return 'string'


@classmethod
def export_to_hdf5(cls, h5_file, model, eids):
    """exports the elements in a vectorized way"""
    pids = []
    nodes = []
    components = []
    for eid in eids:
        element = model.elements[eid]
        pids.append(element.pid)
        nodes.append(element.nodes)
    h5_file.create_dataset('eid', data=eids)
    h5_file.create_dataset('pid', data=pids)
    h5_file.create_dataset('nodes', data=nodes)


@classmethod
def stations(cls, station_id, navigation='upstreamTributaries', distance=None):
    """Get USGS stations up/downstream of a station.

        Parameters
        ----------
        station_id : string
            The USGS station ID.
        navigation : string, optional
            The direction for navigating the NHDPlus database. The valid options are:
            None, ``upstreamMain``, ``upstreamTributaries``, ``downstreamMain``,
            ``downstreamDiversions``. Defaults to upstreamTributaries.
        distance : float, optional
            The distance to limit the navigation in km. Defaults to None (all stations).

        Returns
        -------
        geopandas.GeoDataFrame
        """
    return cls.navigate('nwissite', station_id, navigation, 'nwissite',
        distance)


def clear():
    """Remove all uids from set."""


def get_keywords():
    """Get the keywords needed to look up the version information."""
    git_refnames = '$Format:%d$'
    git_full = '$Format:%H$'
    git_date = '$Format:%ci$'
    keywords = {'refnames': git_refnames, 'full': git_full, 'date': git_date}
    return keywords


@staticmethod
def task_to_row(task):
    """Convert a task to a tuple with the correct column order."""
    return (task.id, task.title, task.body, task.context, task.priority,
        task.created_date.timestamp(), task.completed_date.timestamp() if
        task.completed_date else 0)


@classmethod
def from_nanoseconds(cls, nsec):
    """
        Returns the closest pointwidth for the given number of nanoseconds without going
        over the specified duration. Because pointwidths are in powers of 2, be sure to
        check that the returned real duration is sufficient.
        """
    for pos in range(62):
        nsec = nsec >> 1
        if nsec == 0:
            break
    return cls(pos)


def userFilters():
    """
  customize user filters to subscribe
  """
    return ['/restapi/v1.0/account/~/extension/~/message-store']


def get_cmd_dict(cmd_list):
    """
    Create a command: class type dict of all commands
    """
    cmd_dict = {}
    for cmd in cmd_list:
        for cmd_name in cmd.cmds:
            cmd_dict[cmd_name] = cmd
    return cmd_dict


@property
def __members__(cls):
    """Returns a mapping of member name->value.

        This mapping lists all enum members, including aliases. Note that this
        is a copy of the internal mapping.

        """
    return cls._member_map_.copy()


def create_element_data(bs_data, element_Z, key, key_exist_ok=False,
    element_exist_ok=True, create=list):
    """Creates an element and a subkey of the element in bs_data

    Note that bs_data is modified!
    """
    if element_Z not in bs_data:
        bs_data[element_Z] = {}
    elif not element_exist_ok:
        raise RuntimeError('Element {} already exists in basis data'.format
            (element_Z))
    if key not in bs_data[element_Z]:
        bs_data[element_Z][key] = create()
    elif not key_exist_ok:
        raise RuntimeError('Key {} already exists in basis data for element {}'
            .format(key, element_Z))
    return bs_data[element_Z]


def tls_params(mqtt_config):
    """Return the TLS configuration parameters from a :class:`.MQTTConfig`
    object.

    Args:
        mqtt_config (:class:`.MQTTConfig`): The MQTT connection settings.

    Returns:
        dict: A dict {'ca_certs': ca_certs, 'certfile': certfile,
        'keyfile': keyfile} with the TLS configuration parameters, or None if
        no TLS connection is used.

    .. versionadded:: 0.6.0
    """
    if mqtt_config.tls.hostname:
        return {'ca_certs': mqtt_config.tls.ca_file, 'certfile':
            mqtt_config.tls.client_cert, 'keyfile': mqtt_config.tls.client_key}
    else:
        return None


def raw(name, context):
    """Return the raw template information for the given context and name.

        `context` can be a list-id, domain mail host name, or "*" (for global
        context).  The raw template matching the given name and context is
        returned, otherwise None if no such template has been registered.

        :param name: The template name, including any extension.
        :type name: str
        :param context: The context for this name->URI mapping.  This can be a
            List-ID, domain mail host name, or None (for global context).
        :type context: str
        :return: The raw template record, or None if not found.
        :rtype: ITemplate or None
        """


def update_progress(name: str='Master', percent: float=None, message: str=None
    ) ->None:
    """
    * Allows the user to identify the prograss of the script

    * name: Is the of the progress bar master being the full script progress
    * percent: is a optional way to update progress.
    * message: is a optional way to update progress.
    """
    return


def dump_ffmpeg():
    """Dump FFmpeg info."""
    import pyglet
    pyglet.options['search_local_libs'] = True
    import pyglet.media
    if pyglet.media.have_ffmpeg():
        from pyglet.media.codecs.ffmpeg import get_version
        print('FFmpeg version:', get_version())
    else:
        print('FFmpeg not available.')


def uniform_draw_feat_class(data_df, target_name, draw_size):
    """ Sample out 1 particular class out of the full data uniformly in a predefined sample size,
    segregate pandas dataframe into their respective target classes. """
    target_class_dfs = {}
    n_classes = data_df[target_name].unique()
    for unique_class in n_classes:
        class_i_df = data_df[data_df[target_name] == unique_class]
        class_i_df = class_i_df.reset_index().drop(columns=['index'])
        target_class_dfs[unique_class] = class_i_df
    uniform_class_sample_draws = {}
    for unique_class in n_classes:
        unif_samples = target_class_dfs[unique_class].sample(n=draw_size,
            replace=True)
        uniform_class_sample_draws[unique_class] = unif_samples
    return uniform_class_sample_draws


def passes_filter_ensembl(segment):
    """Decide whether segment passes filters for ENSEMBL data."""
    if not segment.attrs['gene_biotype'] == 'protein_coding':
        return False
    support_level = segment.attrs.get('transcript_support_level', '')
    if not support_level.isdigit():
        return False
    if int(support_level) > 2:
        return False
    return True


def transaction(desc, report=None):
    """Open a new transaction to write to the repository."""


@staticmethod
def deserialize(b):
    """
        De-serialize the bytes into a BlockHeader.

        Args:
            b (ByteArray): A serialized block header.
        """
    raise NotImplementedError('deserialize not implemented')


@classmethod
def fromtextfile(cls, fileobj, endcard=False):
    """
        Read a header from a simple text file or file-like object.

        Equivalent to::

            >>> Header.fromfile(fileobj, sep='\\n', endcard=False,
            ...                 padding=False)

        See Also
        --------
        fromfile
        """
    return cls.fromfile(fileobj, sep='\n', endcard=endcard, padding=False)


def stroke_lock_color():
    """Lock any color not used in any selected stroke

    """
    pass


def list_to_string(string_arg):
    """
    Some methods arguments parsing of a list to a string.
    """
    if string_arg:
        return '.'.join(string_arg)
    else:
        return string_arg


@classmethod
def activate(cls, flow_task, prev_activation, token):
    """Mark process as done, and cancel all other active tasks."""
    flow_class, flow_task = flow_task.flow_class, flow_task
    process = prev_activation.process
    task = flow_class.task_class(process=process, flow_task=flow_task,
        token=token)
    task.save()
    task.previous.add(prev_activation.task)
    activation = cls()
    activation.initialize(flow_task, task)
    activation.perform()
    return activation


def selection_set(select: bool=False):
    """Set cursor selection

    :param select: Select, Set selection end rather than cursor
    :type select: bool
    """
    pass


def get_principals_for_permission(permission_id):
    """Get the principas that have a permission.

        Return the list of (principal_id, setting) tuples that describe
        security assertions for this permission.

        If no principals have been set for this permission, then the empty
        list is returned.
        """


def keyitem_add():
    """Add key map item

    """
    pass


@staticmethod
def summary(cluster, replication_data=False, flat=False):
    """Generic, non-detailed view of a cluster."""
    result = {'name': cluster.name, 'binary': cluster.binary, 'state': 'up' if
        cluster.is_up else 'down', 'status': 'disabled' if cluster.disabled
         else 'enabled', 'replication_status': cluster.replication_status}
    if not replication_data:
        del result['replication_status']
    if flat:
        return result
    return {'cluster': result}


def cbf_start_loop(array, apointer, inputdata, output, source, spointer):
    """
    Start loop. Operations after a start loop operator ("[") will only
    be executed provided the loop(s) are properly closed. If the loops
    are open, the program will terminate. Note that unclosed or unopened
    loops may result in non-deterministic behaviour.
    """
    if array[apointer] > 0:
        return array, apointer, inputdata, output, source, spointer
    else:
        count = 1
        try:
            while count > 0:
                spointer = spointer + 1
                if source[spointer] == ']':
                    count = count - 1
                if source[spointer] == '[':
                    count = count + 1
        except IndexError:
            spointer = len(source) - 1
    return array, apointer, inputdata, output, source, spointer


def flux(phys, eph, lam):
    """Model flux density for a given wavelength `lam`, or a list/array thereof

        Parameters
        ----------
        phys : `sbpy.data.Phys` instance, mandatory
            provide physical properties
        eph : `sbpy.data.Ephem` instance, mandatory
            provide object ephemerides
        lam : `astropy.units` quantity or list-like, mandatory
            wavelength or list thereof

        Examples
        --------
        >>> from astropy.time import Time
        >>> from astropy import units as u
        >>> from sbpy.thermal import STM
        >>> from sbpy.data import Ephem, Phys
        >>> epoch = Time('2019-03-12 12:30:00', scale='utc')
        >>> eph = Ephem.from_horizons('2015 HW', location='568', epochs=epoch) # doctest: +REMOTE_DATA
        >>> phys = PhysProp('diam'=0.3*u.km, 'pv'=0.3) # doctest: +SKIP
        >>> lam = np.arange(1, 20, 5)*u.micron # doctest: +SKIP
        >>> flux = STM.flux(phys, eph, lam) # doctest: +SKIP

        not yet implemented

        """


def write_results_to_file(out_filename, commands, node_list, return_codes,
    stdouts, stderrs):
    """ Print the output of wait_for_all_results to a file.

    Parameters
    ----------
    out_filename: string
        Path to the file

    commands: list of strings
        The commands distributed to the cluster

    nodel_list: list of strings
        The nodes to which each command was sent, given by
        ssh_utils.distribute_all

    return_codes, stdouts, stderrs: lists of strings
        The strings to write to disk. Presumably, the values returned from
        wait_for_all_results.

    Returns
    -------
    None, but the file is (overwritten) with the text
    """
    with open(out_filename, 'w') as out:
        for i in range(len(return_codes)):
            out.write(commands[i])
            out.write('\n')
            out.write(node_list[i])
            out.write('\n')
            out.write('return code: {}'.format(return_codes[i]))
            out.write('\n')
            out.write('stdout: {}'.format(stdouts[i]))
            out.write('\n')
            out.write('stderr: {}'.format(stderrs[i]))
            out.write('\n')


def is_document(data):
    """ Determine whether :data: is a valid document.

    To be considered valid, data must:
        * Be an instance of dict
        * Have '_type' key in it
    """
    return isinstance(data, dict) and '_type' in data


def aria_bool(value):
    """ aria2 rpc requires strings for some boolean arguments like 'continue'
	"""
    if value is None:
        return None
    elif value is True:
        return 'true'
    elif value is False:
        return 'false'
    else:
        raise ValueError(str(value))


def is_numeric(number):
    """Checks if an object is a number. That is, a ``float`` or an ``int``.
    Where this differs from simply checking if an object is an instance of
    ``numbers.Number`` is that boolean objects are also a number by that
    measure (which, technically,
    `they are <https://www.peterbe.com/plog/bool-is-int>`_). While technical
    correctness is a wonderful thing, generally this is not what one would
    expect a check for numbers to do.

    :param number: The object to check.
    :rtype: ``bool``"""
    if isinstance(number, bool):
        return False
    elif isinstance(number, int) or isinstance(number, float):
        return True
    else:
        return False


def succeeded(builds):
    """
    Determine, whether the list of builds finished successfully.

    :param Munch/list builds: A list of builds or a single build Munch
    :return bool:
    """
    builds = builds if type(builds) == list else [builds]
    for build in builds:
        if build.state != 'succeeded':
            return False
    return True


def to_int32(f):
    """
    Convert an image to an int32 image.

    img = to_int32(f)

    `to_int32` clips the input image between the values -2147483648 and
    2147483647 and converts it to the signed 32-bit datatype.

    Parameters
    ----------
    f : Any image

    Returns
    -------
    img : The converted image
    """
    from numpy import int32, asanyarray
    return asanyarray(f).astype(int32)


def get_admin_href(href):
    """Returns admin version of a given vCD url.

    This function is idempotent, which also means that if input href is already
    an admin href no further action would be taken.

    :param str href: the href whose admin version we need.

    :return: admin version of the href.

    :rtype: str
    """
    if '/api/admin/extension/' in href:
        return href.replace('/api/admin/extension', '/api/admin/')
    elif '/api/admin/' in href:
        return href
    else:
        return href.replace('/api/', '/api/admin/')


def append(snd1, snd2):
    """Append snd2 to snd1."""
    snd1.append(snd2)


def pop_kwargs(kwargs, names_with_defaults, allow_others=False):
    """
    Internal utility method to extract optional arguments from kwargs.

    :param kwargs:
    :param names_with_defaults:
    :param allow_others: if False (default) then an error will be raised if kwargs still contains something at the end.
    :return:
    """
    all_arguments = []
    for name, default_ in names_with_defaults:
        try:
            val = kwargs.pop(name)
        except KeyError:
            val = default_
        all_arguments.append(val)
    if not allow_others and len(kwargs) > 0:
        raise ValueError('Unsupported arguments: %s' % kwargs)
    if len(names_with_defaults) == 1:
        return all_arguments[0]
    else:
        return all_arguments


def table_exists(cursor):
    """ Checks if a table exists """
    cursor.execute(
        "SELECT name FROM sqlite_master WHERE type='table' AND name='proxy_responses';"
        )
    if cursor.fetchone() == None:
        return False
    else:
        return True


def _initial_gaussian_params(xm, ym, z, width=5):
    """
    Guesses the initial 2D Gaussian parameters given a spatial filter.

    Parameters
    ----------
    xm : array_like
        The x-points for the filter.

    ym : array_like
        The y-points for the filter.

    z : array_like
        The actual data the parameters of which are guessed.

    width : float, optional
        The expected 1 s.d. width of the RF, in samples. (Default: 5)

    Returns
    -------

    xc, yc : float
        Estimated center points for the data.

    a, b, c : float
        Upper-left, lower-right, and off-diagonal terms for the estimated
        precision matrix.
    """
    xi = z.sum(axis=0).argmax()
    yi = z.sum(axis=1).argmax()
    yc = xm[xi, yi]
    xc = ym[xi, yi]
    a = 1 / width
    b = 0
    c = 1 / width
    return xc, yc, a, b, c


def bezout(a, b):
    """Compute the bezout algorithm of a and b, i.e. it returns u, v, p such as:

          p = GCD(a,b)
          a * u + b * v = p

       Copied from http://www.labri.fr/perso/betrema/deug/poly/euclide.html.
    """
    u = 1
    v = 0
    s = 0
    t = 1
    while b > 0:
        q = a // b
        r = a % b
        a = b
        b = r
        tmp = s
        s = u - q * s
        u = tmp
        tmp = t
        t = v - q * t
        v = tmp
    return u, v, a


@classmethod
def render_complete_data(cls, data):
    """render processed complete data for drawing."""
    return data


def remove_keys(apps, schema_editor):
    """
    We can't import the Post model directly as it may be a newer
    version than this migration expects. We use the historical version.
    """
    try:
        CourseFile = apps.get_model('courses', 'CourseFile')
        for course_file in CourseFile.objects.all():
            course_file.seconds = course_file.file_obj.seconds
            course_file.save()
    except:
        return


def masterpid():
    """Return the process identifier (PID) of the uWSGI master process.

    :rtype: int
    """
    return -1


def classof(A, B):
    """
    Get the type of the result when combining matrices of different types.

    Currently the strategy is that immutability is contagious.

    Examples
    ========

    >>> M = Matrix([[1, 2], [3, 4]])  # a Mutable Matrix
    >>> IM = ImmutableMatrix([[1, 2], [3, 4]])
    >>> classof(M, IM)
    <class 'diofant.matrices.immutable.ImmutableMatrix'>

    """
    try:
        if A._class_priority > B._class_priority:
            return A.__class__
        else:
            return B.__class__
    except AttributeError:
        pass
    raise TypeError(f'Incompatible classes {A.__class__}, {B.__class__}')


def partition_project_file(fn_project):
    """
    The new pulse ekko dvl writes 'project' files with all the profiles stored together
    We want to break them out into all the .HD header files and .DT1 data files.

    Parameters
    --------
    fn_project: str
        Filename for the .gpz project file
    """
    with open(fn_project, 'rb') as fin:
        f = fin.read()
    profile_num = 1
    while f.find(b'line%d' % profile_num) != -1:
        hd_start = f.find(b'line%d.hd' % profile_num)
        hd_end = f[hd_start:].find(b'PK') + hd_start
        hd_str = str(f[hd_start:hd_end])
        hd_lines = hd_str.split('\\r\\n')
        hd_lines[0] = hd_lines[0][2:]
        hd_lines[-1] = ''
        ini_start = f.find(b'line%d.ini' % profile_num)
        ini_end = f[ini_start:].find(b'PK') + ini_start
        ini_str = str(f[ini_start:ini_end])
        for i, line in enumerate(ini_str.split('\\r\\n')):
            if i == 0:
                hd_lines.append(line[2:len('line%d.ini' % profile_num) + 2])
                hd_lines.append(line[len('line%d.ini' % profile_num) + 2:])
            elif i == len(ini_str.split('\\r\\n')) - 1:
                continue
            else:
                hd_lines.append(line)
        with open('LINE' + str(profile_num) + '.HD', 'w') as fout:
            for line in hd_lines:
                fout.write(line + '\n')
        dt_start = f.find(b'line%d.dt1' % profile_num)
        dt_start += len(b'line%d.dt1' % profile_num)
        dt_end = f[dt_start:].find(b'Lineset') + dt_start
        dt_str = f[dt_start:dt_end]
        with open('LINE' + str(profile_num) + '.DT1', 'wb') as fout:
            fout.write(dt_str)
        profile_num += 1


def _ensure_has_len(seq):
    """
    If seq is an iterator, put its values into a list.
    """
    try:
        len(seq)
    except TypeError:
        return list(seq)
    else:
        return seq


def generate_time(field, factory):
    """Generate a time.

    :returns: a unique datetime.time.
    :return_type: datetime.time
    """
    return factory.getUniqueTime()


def sub_dfs_by_size(df, size):
    """Get a generator yielding consecutive sub-dataframes of the given size.

    Arguments
    ---------
    df : pandas.DataFrame
        The dataframe for which to get sub-dataframes.
    size : int
        The size of each sub-dataframe.

    Returns
    -------
    generator
        A generator yielding consecutive sub-dataframe of the given size.

    Example
    -------
    >>> import pandas as pd; import pdutil;
    >>> data = [[23, "Jen"], [42, "Ray"], [15, "Fin"]]
    >>> df = pd.DataFrame(data, columns=['age', 'name'])
    >>> for subdf in pdutil.iter.sub_dfs_by_size(df, 2): print(subdf)
       age name
    0   23  Jen
    1   42  Ray
       age name
    2   15  Fin
    """
    for i in range(0, len(df), size):
        yield df.iloc[i:i + size]


def _freeze_it(values):
    """Freezes a set of values (handling none/empty nicely)."""
    if not values:
        return frozenset()
    else:
        return frozenset(values)


def _update_request_parent_field_type():
    """Change GenericReferenceField to ReferenceField"""
    from bg_utils.mongo.models import Request
    raw_collection = Request._get_collection()
    for request in raw_collection.find({'parent._ref': {'$type': 'object'}}):
        raw_collection.update_one({'_id': request['_id']}, {'$set': {
            'parent': request['parent']['_ref']}})


def calculate_width(string_list):
    """Width of list of strings as length of longest string in that list."""
    width = 0
    for line in string_list:
        if len(line) > width:
            width = len(line)
    return width


def parse_bible(bible_text):
    """
    Parse the bible_text data
    """
    pharses = bible_text.split('\n')[1:]
    return pharses


@classmethod
def autocomplete(cls, argv):
    """This is supplied to make subclassing and testing argument completion methods easier"""
    pass


def colorprint(string):
    """
        colorprint() function
        ________________________________________________________________________

        Print <string> with some colors defined by the following keywords :
        ▪ "[color1]"    : red
        ▪ "[color2]"    : white
        ▪ "[color3]"    : inversed red
        ▪ "[color4]"    : inversed white
        ▪ "[default]"
        ________________________________________________________________________

        ARGUMENT:
        ▪ string : (str) the string to be displayed

        no RETURNED VALUE
    """
    string = string.replace('[color1]', '\x1b[0;31;1m')
    string = string.replace('[color2]', '\x1b[0;37;1m')
    string = string.replace('[color3]', '\x1b[0;31;7m')
    string = string.replace('[color4]', '\x1b[0;37;7m')
    string = string.replace('[default]', '\x1b[0m')
    print(string)


def yield_displacement_wall(phi_y, heights, max_height):
    """
    The yield displacement of a concrete wall. Eq. 6 (Sullivan et al. 2010).
    :param phi_y: yield curvature
    :param heights: height
    :return:
    """
    return phi_y * heights ** 2 / 2 + phi_y * heights ** 3 / max_height


def extract_doi(doi):
    """Ensure that 'doi' is a single string

    Occasionally, INSPIRE returns a list of identical DOIs.  This just extracts the first
    element if it is such a list, or returns the input otherwise.

    """
    if isinstance(doi, list) and len(doi) > 0:
        return doi[0]
    return doi


@classmethod
def clean(mcs):
    """
        Remove all level loaded in register.
        """
    mcs.register.clear()


def calculate_number_of_stems(morphology):
    """
        Calculate the number of soma stems.
        This is defined as the total number of non-soma child nodes on soma nodes.

        Parameters
        ----------

        morphology: Morphology object

        Returns
        -------

        Scalar value

    """
    soma = morphology.get_root()
    return len(morphology.children_of(soma))


def filechunkiter(f, size=131072, limit=None):
    """Create a generator that produces the data in the file size
    (default 131072) bytes at a time, up to optional limit (default is
    to read all data).  Chunks may be less than size bytes if the
    chunk is the last chunk in the file, or the file is a socket or
    some other type of file that sometimes reads less data than is
    requested."""
    assert size >= 0
    assert limit is None or limit >= 0
    while True:
        if limit is None:
            nbytes = size
        else:
            nbytes = min(limit, size)
        s = nbytes and f.read(nbytes)
        if not s:
            break
        if limit:
            limit -= len(s)
        yield s


def __contains__(key):
    """Check if bytestring `key` is known to the dirstate."""


def get_deformation_field_scales(reg_params):
    """
    Calculates the scaling of the deformation field from real space
    to voxels
    :param reg_params:
    :return:
    """
    x_scale = 1000 / float(reg_params.atlas_x_pix_size)
    y_scale = 1000 / float(reg_params.atlas_y_pix_size)
    z_scale = 1000 / float(reg_params.atlas_z_pix_size)
    return x_scale, y_scale, z_scale


def inverse_pose(pose):
    """
    Same as pose.inverse()
    :param pose: instance of ``util.Pose``
    """
    return pose.transform().inverse().pose()


def get_ordinal(number):
    """Produces an ordinal (1st, 2nd, 3rd, 4th) from a number"""
    if number == 1:
        return 'st'
    elif number == 2:
        return 'nd'
    elif number == 3:
        return 'rd'
    else:
        return 'th'


def value2TagName(value):
    """
    The @value2TagName@ class method converts the *value* object into a value XML tag name.
    """
    tagname = []
    if not isinstance(value, str):
        value = str(value)
    if value.lower().startswith('xml'):
        tagname.append('_')
    for c in value:
        if c in ' !?@#$%^&*()[]\t\r\n/\\':
            pass
        elif c.upper() in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890:.':
            tagname.append(c)
        else:
            tagname.append('_')
    return ''.join(tagname)


def subtract(d1, d2):
    """Subtracts two dictionaries.

    Returns a new dictionary containing all the keys from
    d1 that are not in d2.
    """
    d = {}
    for key in d1:
        if key not in d2:
            d[key] = d1[key]
    return d


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

        :param LegalHoldsExportDownloadedType val:
        :rtype: EventType
        """
    return cls('legal_holds_export_downloaded', val)


def variationStock(variation):
    """ Number of items available of a variation or combination
            of multiple variations
        """


def p_single_parameter(p):
    """parameter : SYMBOL TWOP param_value"""
    if p[1] == 'name':
        p.parser.modelStack.append(p[3])
    if p[1] == 'extensions':
        p.parser.modelStack2.append(p[3])
    p[0] = {p[1]: p[3]}


def editdist(s1, s2):
    """Return the Levenshtein distance between two strings.

    >>> editdist('aiu', 'aie')
    1
    """
    matrix = {}
    for i in range(len(s1) + 1):
        matrix[i, 0] = i
    for j in range(len(s2) + 1):
        matrix[0, j] = j
    for i in range(1, len(s1) + 1):
        for j in range(1, len(s2) + 1):
            if s1[i - 1] == s2[j - 1]:
                matrix[i, j] = matrix[i - 1, j - 1]
            else:
                matrix[i, j] = min(matrix[i - 1, j], matrix[i, j - 1],
                    matrix[i - 1, j - 1]) + 1
    return matrix[i, j]


@staticmethod
def convert(obj, unit, axis):
    """
        convert obj using unit for the specified axis.  If obj is a sequence,
        return the converted sequence.  The output must be a sequence of scalars
        that can be used by the numpy array layer
        """
    return obj


def HasShortCadence(ID, season=None):
    """
  Returns `True` if short cadence data is available for this target.

  :param int ID: The target ID number
  :param int season: The season number. Default :py:obj:`None`

  """
    raise NotImplementedError('This mission is not yet supported.')


def generate_instance_identity_document(instance):
    """
    http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html

    A JSON file that describes an instance. Usually retrieved by URL:
    http://169.254.169.254/latest/dynamic/instance-identity/document
    Here we just fill a dictionary that represents the document

    Typically, this document is used by the amazon-ecs-agent when registering a
    new ContainerInstance
    """
    document = {'devPayProductCodes': None, 'availabilityZone': instance.
        placement['AvailabilityZone'], 'privateIp': instance.
        private_ip_address, 'version': '2010-8-31', 'region': instance.
        placement['AvailabilityZone'][:-1], 'instanceId': instance.id,
        'billingProducts': None, 'instanceType': instance.instance_type,
        'accountId': '012345678910', 'pendingTime': '2015-11-19T16:32:11Z',
        'imageId': instance.image_id, 'kernelId': instance.kernel_id,
        'ramdiskId': instance.ramdisk_id, 'architecture': instance.architecture
        }
    return document


@staticmethod
def prepare_platforms_and_targets(available, tid, available_target_ids):
    """
        prepare available platforms and target ids to flash
        """
    available_platforms = []
    target_ids_to_flash = []
    for device in available:
        available_target_ids.append(device['target_id'])
        if isinstance(tid, list):
            for item in tid:
                if device['target_id'] == item or device['target_id'
                    ].startswith(item):
                    if device['target_id'] not in target_ids_to_flash:
                        target_ids_to_flash.append(device['target_id'])
                    if 'platform_name' in device and device['platform_name'
                        ] not in available_platforms:
                        available_platforms.append(device['platform_name'])
        elif device['target_id'] == tid or device['target_id'].startswith(tid):
            if device['target_id'] not in target_ids_to_flash:
                target_ids_to_flash.append(device['target_id'])
            if 'platform_name' in device and device['platform_name'
                ] not in available_platforms:
                available_platforms.append(device['platform_name'])
    return available_platforms, target_ids_to_flash


def select_proxy(scheme, host, port, proxies):
    """Select a proxy for the url, if applicable.

    :param scheme, host, port: The url being for the request
    :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs
    """
    proxies = proxies or {}
    if host is None:
        return proxies.get(scheme, proxies.get('all'))
    proxy_keys = [scheme + '://' + host, scheme, 'all://' + host, 'all']
    proxy = None
    for proxy_key in proxy_keys:
        if proxy_key in proxies:
            proxy = proxies[proxy_key]
            break
    return proxy


@classmethod
def unselected_elems_in_x(cls) ->bool:
    """Return True if the unselected elements are maintained in x[sel:], i.e., behind the selected ones."""
    return True


@classmethod
def _check_convention(cls, convention):
    """
        Make sure only valid conventions are specified
        """
    if convention not in cls._CONVENTIONS:
        raise ValueError(f'Allowed conventions: {cls._CONVENTIONS}')


@classmethod
def get_num_calls_for_level(cls, level):
    """
        Returns the number of calls registered for a given log level.
        """
    return cls._call_counter[level]


def ask_user(msg, bypass=False):
    """
    Asks the user yes no questions

    Args:
        msg: question to display
        bypass: Handle passing yes always
    Returns:
        response: boolean indicating whether to proceed or not.
    """
    acceptable = False
    while not acceptable:
        if bypass:
            ans = 'yes'
        else:
            ans = input(msg + ' (y/n)\n')
        if ans.lower() in ['y', 'yes']:
            acceptable = True
            response = True
        elif ans.lower() in ['n', 'no']:
            acceptable = True
            response = False
        else:
            print('Unrecognized answer, please use (y, yes, n, no)')
    return response


def _make_version(major, minor, micro, level, serial):
    """Generate version string from tuple (almost entirely from coveragepy)."""
    level_dict = {'alpha': 'a', 'beta': 'b', 'candidate': 'rc', 'final': ''}
    if level not in level_dict:
        raise RuntimeError('Invalid release level')
    version = '{0:d}.{1:d}'.format(major, minor)
    if micro:
        version += '.{0:d}'.format(micro)
    if level != 'final':
        version += '{0}{1:d}'.format(level_dict[level], serial)
    return version


@classmethod
def from_label(cls, field_xml):
    """ Initializes the meta data from an XML description of the Field.

        Parameters
        ----------
        field_xml : Label or ElementTree Element
            Portion of the label describing this Field.

        Returns
        -------
        Meta_Field
            Contains meta data for the field.
        """
    obj = cls()
    obj._load_keys_from_xml(field_xml, tag_modify=('field_', ''))
    obj._check_keys_exist(['name'])
    return obj


def metronixName(ext: str, sensor: str, serial: int, chopper: bool) ->str:
    """Get Metronix calibration file name

    Parameters
    ----------
    ext : str
        Calibration file extension
    sensor : str
        Sensor name
    serial : int
        The sensor serial number
    chopper : bool
        Boolean flag for chopper on or off

    Returns
    -------
    out : str
        Name of calibration file
    """
    if sensor == '' and not serial > 0:
        return None
    return '{}{}.{}'.format(sensor, serial, ext)


def daily_features_query(table_name='%(table_name)s'):
    """
    Create daily features which are part of the final feature set.
    For outgoing and incoming events separately, the percentages of
    number of events (or total duration) happening on the weekend or holidays
    are being calculated. These features are bound between 0 and 1.

    Inputs
    ------
    table_name : name of the table the query is supposed to run on,
                 defaulting to '%(table_name)s', i.e. no substitution

    Output
    ------
    Partial final features dataframe which holds features
    calculated on the weekends over the whole weeks.
    """
    query = """
        SELECT
          antenna_id,
          -- og week ratios (weekend/holidays over all week)
          SUM(IF(week_part IN ('weekend', 'holiday'), og_calls, NULL))/
            SUM(og_calls) as og_calls_week_ratio,
          SUM(IF(week_part IN ('weekend', 'holiday'), og_sms, NULL))/
            SUM(og_sms) as og_sms_week_ratio,
          SUM(IF(week_part IN ('weekend', 'holiday'), og_vol, NULL))/
            SUM(og_vol) as og_vol_week_ratio,
          -- ic week ratios (weekend/holidays over all week)
          SUM(IF(week_part IN ('weekend', 'holiday'), ic_calls, NULL))/
            SUM(ic_calls) as ic_calls_week_ratio,
          SUM(IF(week_part IN ('weekend', 'holiday'), ic_sms, NULL))/
            SUM(ic_sms) as ic_sms_week_ratio,
          SUM(IF(week_part IN ('weekend', 'holiday'), ic_vol, NULL))/
            SUM(ic_vol) as ic_vol_week_ratio
        FROM %(table_name)s
        GROUP BY antenna_id
    """
    return query % {'table_name': table_name}


def parse_none(value):
    """
    A placeholder parse function which can be used if the Unit
    requires / supports no parsing.
    """
    return value


@classmethod
def loaded_backends(cls):
    """
        Returns a list of the backends that have been loaded, based on
        the available OptionTrees.
        """
    return list(cls._options.keys())


@classmethod
def from_httplib(cls, message):
    """Read headers from a Python 2 httplib message object."""
    headers = []
    for line in message.headers:
        if line.startswith((' ', '\t')):
            key, value = headers[-1]
            headers[-1] = key, value + '\r\n' + line.rstrip()
            continue
        key, value = line.split(':', 1)
        headers.append((key, value.strip()))
    return cls(headers)


def getTemporalExtent(filePath):
    """ extracts temporal extent of the shapefile

    input "path": type string, file path to shapefile file
    """
    return 'None'


def Wspan_plot(rv, ccf, rvunits='km/s'):
    """ Make a pretty plot of the line profile and the Wspan """
    pass


def provider_parser(subparser):
    """Generate a subparser for Glesys"""
    subparser.add_argument('--auth-username', help='specify username (CL12345)'
        )
    subparser.add_argument('--auth-token', help='specify API key')


def set_run_validators(run):
    """
    Set whether or not validators are run.  By default, they are run.
    """
    if not isinstance(run, bool):
        raise TypeError("'run' must be bool.")
    global _run_validators
    _run_validators = run


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

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

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


@classmethod
def _from_remote_s3(cls) ->(str, str):
    """ Class Factory Method that builds the connector handlers an Amazon AWS s3 remote store."""
    _module_name = 'ds_connectors.handlers.aws_s3_handlers'
    _handler = 'AwsS3PersistHandler'
    return _module_name, _handler


def output_file_add_socket(file_path: str='Image'):
    """Add a new input to a file output node

    :param file_path: File Path, Sub-path of the output file
    :type file_path: str
    """
    pass


@classmethod
def get_field_from_selector(cls, selector):
    """
        Given a django selector, e.g. device__metadata__name, this returns the class
        and the Django field of the model, as returned by Model._meta.get_field().
        Example::

            device__metadata__name -> (SeedDevice, SeeDevice.name)
        """
    if not '__' in selector:
        return cls, cls._meta.get_field(selector)
    model = cls
    while '__' in selector:
        model_name, selector = selector.split('__', 1)
        model = model._meta.get_field(model_name).rel.to
    return model, model._meta.get_field(selector)


def addgroup(deltas, linkmapper, transaction, addrevisioncb=None,
    maybemissingparents=False):
    """Process a series of deltas for storage.

        ``deltas`` is an iterable of 7-tuples of
        (node, p1, p2, linknode, deltabase, delta, flags) defining revisions
        to add.

        The ``delta`` field contains ``mpatch`` data to apply to a base
        revision, identified by ``deltabase``. The base node can be
        ``nullid``, in which case the header from the delta can be ignored
        and the delta used as the fulltext.

        ``addrevisioncb`` should be called for each node as it is committed.

        ``maybemissingparents`` is a bool indicating whether the incoming
        data may reference parents/ancestor revisions that aren't present.
        This flag is set when receiving data into a "shallow" store that
        doesn't hold all history.

        Returns a list of nodes that were processed. A node will be in the list
        even if it existed in the store previously.
        """