'Return a key that is between key_start and key_end inclusive.
This method compares components of the ancestor paths of key_start
and key_end.  The first place in the path that differs is
approximately split in half.  If the kind components differ, a new
non-existent kind halfway between the two is used to split the
space. If the id_or_name components differ, then a new id_or_name
that is halfway between the two is selected.  If the lower
id_or_name is numeric and the upper id_or_name is a string, then
the minumum string key u\'\' is used as the split id_or_name.  The
key that is returned is the shared portion of the ancestor path
followed by the generated split component.
Args:
key_start: A db.Key or ndb.Key instance for the lower end of a range.
key_end: A db.Key or ndb.Key instance for the upper end of a range.
batch_size: The maximum size of a range that should not be split.
Returns:
A db.Key instance, k, such that key_start <= k <= key_end.
NOTE: Even though ndb.Key instances are accepted as arguments,
the return value is always a db.Key instance.'

@staticmethod
def split_keys(key_start, key_end, batch_size):

    if (ndb is not None):
        if isinstance(key_start, ndb.Key):
            key_start = key_start.to_old_key()
        if isinstance(key_end, ndb.Key):
            key_end = key_end.to_old_key()
    assert (key_start.app() == key_end.app())
    assert (key_start.namespace() == key_end.namespace())
    path1 = key_start.to_path()
    path2 = key_end.to_path()
    len1 = len(path1)
    len2 = len(path2)
    assert ((len1 % 2) == 0)
    assert ((len2 % 2) == 0)
    out_path = []
    min_path_len = (min(len1, len2) / 2)
    for i in xrange(min_path_len):
        kind1 = path1[(2 * i)]
        kind2 = path2[(2 * i)]
        if (kind1 != kind2):
            split_kind = KeyRange.bisect_string_range(kind1, kind2)
            out_path.append(split_kind)
            out_path.append(unichr(0))
            break
        last = (len1 == len2 == (2 * (i + 1)))
        id_or_name1 = path1[((2 * i) + 1)]
        id_or_name2 = path2[((2 * i) + 1)]
        id_or_name_split = KeyRange._split_id_or_name(id_or_name1, id_or_name2, batch_size, last)
        if (id_or_name1 == id_or_name_split):
            out_path.append(kind1)
            out_path.append(id_or_name1)
        else:
            out_path.append(kind1)
            out_path.append(id_or_name_split)
            break
    return db.Key.from_path(*out_path, **{'_app': key_start.app(), 'namespace': key_start.namespace()})
