# from __future__ import absolute_import, division, print_function, unicode_literals
# import utool as ut
# import numpy as np
# from six.moves import zip
# from dtool_ibeis import depcache_table


# def get_all_descendant_rowids(depc, tablename, root_rowids, config=None,
#                               ensure=True, eager=True, nInput=None,
#                               recompute=False, recompute_all=False,
#                               levels_up=None, _debug=False):
#     r"""
#     Connects `root_rowids` to rowids in `tablename`, and computes all
#     values needed along the way. This is the main workhorse function for
#     dependency computations.

#     Args:
#         tablename (str): table to compute dependencies to
#         root_rowids (list): rowids for ``tablename``
#         config (dict): config applicable for all tables (default = None)
#         ensure (bool): eager evaluation if True(default = True)
#         eager (bool): (default = True)
#         nInput (None): (default = None)
#         recompute (bool): (default = False)
#         recompute_all (bool): (default = False)
#         levels_up (int): only partially compute dependencies (default = 0)
#         _debug (bool): (default = False)

#     CommandLine:
#         python -m dtool_ibeis.depcache_control --exec-get_all_descendant_rowids:0
#         python -m dtool_ibeis.depcache_control --exec-get_all_descendant_rowids:1

#     Example:
#         >>> # DISABLE_DOCTEST
#         >>> from dtool_ibeis.depcache_control import *  # NOQA
#         >>> from dtool_ibeis.example_depcache import testdata_depc
#         >>> depc = testdata_depc()
#         >>> tablename = 'spam'
#         >>> root_rowids = [1, 2]
#         >>> config1 = {'dim_size': 500}
#         >>> config2 = {'dim_size': 100}
#         >>> config3 = {'dim_size': 500, 'adapt_shape': False}
#         >>> ensure, eager, nInput = True, True, None
#         >>> _debug = True
#         >>> rowid_dict1 = depc.get_all_descendant_rowids(
#         >>>     tablename, root_rowids, config1, ensure, eager, nInput, _debug=_debug)
#         >>> rowid_dict2 = depc.get_all_descendant_rowids(
#         >>>     tablename, root_rowids, config2, ensure, eager, nInput, _debug=_debug)
#         >>> rowid_dict3 = depc.get_all_descendant_rowids(
#         >>>     tablename, root_rowids, config3, ensure, eager, nInput, _debug=_debug)
#         >>> result1 = 'rowid_dict1 = ' + ut.repr3(rowid_dict1, nl=1)
#         >>> result2 = 'rowid_dict2 = ' + ut.repr3(rowid_dict2, nl=1)
#         >>> result3 = 'rowid_dict3 = ' + ut.repr3(rowid_dict3, nl=1)
#         >>> result = '\n'.join([result1, result2, result3])
#         >>> print(result)
#         rowid_dict1 = {
#             'chip': [1, 2],
#             'dummy_annot': [1, 2],
#             'fgweight': [1, 2],
#             'keypoint': [1, 2],
#             'probchip': [1, 2],
#             'spam': [1, 2],
#         }
#         rowid_dict2 = {
#             'chip': [3, 4],
#             'dummy_annot': [1, 2],
#             'fgweight': [3, 4],
#             'keypoint': [3, 4],
#             'probchip': [1, 2],
#             'spam': [3, 4],
#         }
#         rowid_dict3 = {
#             'chip': [1, 2],
#             'dummy_annot': [1, 2],
#             'fgweight': [5, 6],
#             'keypoint': [5, 6],
#             'probchip': [1, 2],
#             'spam': [5, 6],
#         }


#     Example:
#         >>> # ENABLE_DOCTEST
#         >>> from dtool_ibeis.depcache_control import *  # NOQA
#         >>> from dtool_ibeis.example_depcache import testdata_depc
#         >>> depc = testdata_depc()
#         >>> _debug = True
#         >>> tablename = 'vsmany'
#         >>> config = depc.configclass_dict['vsmany']()
#         >>> root_rowids = [1, 2, 3]
#         >>> ensure, eager, nInput = False, True, None
#         >>> # Get rowids of algo ( should be None )
#         >>> rowid_dict = depc.get_all_descendant_rowids(
#         >>>     tablename, root_rowids, config, ensure, eager, nInput,
#         >>>     _debug=_debug)
#         >>> result = ut.repr3(rowid_dict, nl=1)
#         >>> print(result)
#         {
#             'dummy_annot': [1, 2, 3],
#             'vsmany': [None, None, None],
#         }

#     Example:
#         >>> # ENABLE_DOCTEST
#         >>> from dtool_ibeis.depcache_control import *  # NOQA
#         >>> from dtool_ibeis.example_depcache import testdata_depc
#         >>> # Make sure algo config can correctly get properites
#         >>> depc = testdata_depc()
#         >>> tablename = 'chip'
#         >>> recompute = False
#         >>> recompute_all = False
#         >>> _debug = True
#         >>> root_rowids = [1, 2]
#         >>> configclass = depc.configclass_dict['chip']
#         >>> config_ = configclass()
#         >>> config1 = depc.configclass_dict['vsmany'](dim_size=500)
#         >>> config2 = depc.configclass_dict['vsmany'](dim_size=100)
#         >>> config = config2
#         >>> prop_dicts1 = depc.get_all_descendant_rowids(
#         >>>     tablename, root_rowids, config=config1, _debug=_debug)
#         >>> prop_dicts2 = depc.get_all_descendant_rowids(
#         >>>     tablename, root_rowids, config=config2, _debug=_debug)
#         >>> print(prop_dicts2)
#         >>> print(prop_dicts1)
#         >>> assert prop_dicts1 != prop_dicts2

#     Example:
#         >>> # ENABLE_DOCTEST
#         >>> from dtool_ibeis.depcache_control import *  # NOQA
#         >>> from dtool_ibeis.example_depcache import testdata_depc
#         >>> depc = testdata_depc()
#         >>> exec(ut.execstr_funckw(depc.get_all_descendant_rowids), globals())
#         >>> _debug = True
#         >>> qaids, daids = [1, 2, 4], [2, 3, 4]
#         >>> root_rowids = list(zip(*ut.product(qaids, daids)))
#         >>> request = depc.new_request('vsone', qaids, daids)
#         >>> results = request.execute()
#         >>> tablename = 'vsone'
#         >>> rowid_dict = depc.get_all_descendant_rowids(
#         >>>     tablename, root_rowids, config=None, _debug=_debug)
#     """
#     # TODO: Need to have a nice way of ensuring configs dont overlap
#     # via namespaces.
#     _debug = depc._debug if _debug is None else _debug
#     indenter = ut.Indenter('[Descend-to-%s]' % (tablename,), enabled=_debug)
#     if _debug:
#         indenter.start()
#         print(' * GET DESCENDANT ROWIDS %s ' % (tablename,))
#         print(' * config = %r' % (config,))
#     dependency_levels = depc.get_dependencies(tablename)
#     if levels_up is not None:
#         dependency_levels = dependency_levels[:-levels_up]

#     configclass_levels = [
#         [depc.configclass_dict.get(tablekey, None)
#          for tablekey in keys]
#         for keys in dependency_levels
#     ]
#     if _debug:
#         print('[depc] dependency_levels = %s' %
#               ut.repr3(dependency_levels, nl=1))
#         print('[depc] config_levels = %s' %
#               ut.repr3(configclass_levels, nl=1))

#     # TODO: better support for multi-edges
#     if (len(root_rowids) > 0 and ut.isiterable(root_rowids[0]) and
#          not depc[tablename].ismulti):
#         rowid_dict = {}
#         for colx, col in enumerate(root_rowids):
#             rowid_dict[depc.root + '%d' % (colx + 1,)] = col
#         rowid_dict[depc.root] = ut.unique_ordered(ut.flatten(root_rowids))
#     else:
#         rowid_dict = {depc.root: root_rowids}

#     # Ensure that each level ``tablename``'s dependencies have been computed
#     for level_keys in dependency_levels[1:]:
#         if _debug:
#             print(' * level_keys %s ' % (level_keys,))
#         # For each table in the level
#         for tablekey in level_keys:
#             try:
#                 child_rowids = depc._expand_level_rowids(
#                     tablename, tablekey, rowid_dict, ensure, eager, nInput,
#                     config, recompute, recompute_all, _debug)
#             except Exception as ex:
#                 table = depc[tablekey]  # NOQA
#                 keys = ['tablename', 'tablekey', 'rowid_dict', 'config',
#                         'table', 'dependency_levels']
#                 ut.printex(ex, 'error expanding rowids', keys=keys)
#                 raise
#             rowid_dict[tablekey] = child_rowids
#     if _debug:
#         print(' GOT DESCENDANT ROWIDS')
#         indenter.stop()
#     return rowid_dict


# def get_rowids(depc, tablename, root_rowids, config=None, ensure=True,
#                eager=True, nInput=None, _debug=None, recompute=False,
#                recompute_all=False):
#     """
#     Returns the rowids of `tablename` that correspond to `root_rowids`
#     using `config`.

#     Ignore:
#         tablename = 'nnindexer'
#         multi_rowids = (1, 2, 3, 4, 5)
#         root_rowids = [[multi_rowids]]
#         import plottool_ibeis as pt
#         pt.ensureqt()

#         from dtool_ibeis.depcache_control import *  # NOQA
#         from dtool_ibeis.example_depcache import testdata_depc
#         depc = testdata_depc()
#         exec(ut.execstr_funckw(depc.get_rowids), globals())
#         print(ut.depth_profile(root_rowids))
#         tablename = 'neighbs'
#         table = depc[tablename]  # NOQA
#         import plottool_ibeis as pt
#         pt.ensureqt()
#         _debug = depc._debug = True
#         depc.get_rowids(tablename, root_rowids, config, _debug=_debug)

#         pt.show_nx(depc.graph)
#         for key, val in table.type_to_subgraph.items():
#             pt.show_nx(val)
#             pt.set_title(key)

#     CommandLine:
#         python -m dtool_ibeis.depcache_control --exec-get_rowids
#         python -m dtool_ibeis.depcache_control --dump-get_rowids
#         python -m dtool_ibeis.depcache_control --exec-get_rowids:0

#     GridParams:
#         >>> param_grid = dict(
#         >>>     tablename=[ 'spam', 'neighbs'] # 'spam', 'multitest_score','keypoint'],
#         >>>   #tablename=['neighbs', 'keypoint', 'spam', 'multitest_score','keypoint'],
#         >>> )
#         >>> flat_root_ids = [1, 2, 3]
#         >>> combos = ut.all_dict_combinations(param_grid)
#         >>> index = 0
#         >>> keys = 'tablename'.split(', ')
#         >>> tablename, = ut.dict_take(combos[index], keys)

#     Setup:
#         >>> # DISABLE_GRID_DOCTEST
#         >>> from dtool_ibeis.depcache_control import *  # NOQA
#         >>> from dtool_ibeis.example_depcache import testdata_depc
#         >>> depc = testdata_depc()
#         >>> exec(ut.execstr_funckw(depc.get_rowids), globals())
#         >>> import plottool_ibeis as pt
#         >>> pt.ensureqt()
#         >>> #pt.show_nx(depc.graph)

#     GridExample0:
#         >>> table = depc[tablename]  # NOQA
#         >>> flat_root_ids = [1, 2, 3]
#         >>> root_rowids = [flat_root_ids for _ in table.input_order]
#         >>> print('root_rowids = %r' % (root_rowids,))
#         >>> #root_rowids = [[flat_root_ids], [(flat_root_ids,)]]
#         >>> #root_rowids = [list(zip(flat_root_ids)), (flat_root_ids,)]
#         >>> _debug = True
#         >>> depc.get_rowids(tablename, root_rowids, config, _debug=_debug)
#         >>> for key, val in table.type_to_subgraph.items():
#         >>>     pt.show_nx(val)
#         >>>     pt.set_title(key)

#     Example1:
#         >>> # ENABLE_DOCTEST
#         >>> from dtool_ibeis.depcache_control import *  # NOQA
#         >>> from dtool_ibeis.example_depcache import testdata_depc
#         >>> depc = testdata_depc()
#         >>> exec(ut.execstr_funckw(depc.get_rowids), globals())
#         >>> root_rowids = [1, 2, 3]
#         >>> tablename = 'spam'
#         >>> table = depc[tablename]
#         >>> kp_rowids = depc.get_rowids(tablename, root_rowids)
#         >>> #result = ('prop_list = %s' % (ut.repr2(prop_list),))
#         >>> #print(result)

#     Example:
#         >>> # ENABLE_DOCTEST
#         >>> from dtool_ibeis.depcache_control import *  # NOQA
#         >>> from dtool_ibeis.example_depcache import testdata_depc
#         >>> depc = testdata_depc()
#         >>> exec(ut.execstr_funckw(depc.get_rowids), globals())
#         >>> flat_root_ids = [1, 2, 3]
#         >>> kp_rowids = depc.get_rowids('keypoint', flat_root_ids)
#         >>> root_rowids = [flat_root_ids] * 8
#         >>> _debug = True
#         >>> tablename = 'nnindexer'
#         >>> tablename = 'multitest_score'
#         >>> table = depc[tablename]  # NOQA
#         >>> #result = ('prop_list = %s' % (ut.repr2(prop_list),))
#         >>> # print(result)
#     """
#     _debug = depc._debug if _debug is None else _debug
#     if _debug:
#         print(' * root_rowids=%s' % (ut.trunc_repr(root_rowids),))
#         print(' * config = %r' % (config,))
#     table = depc[tablename]  # NOQA
#     INDEXER_VERSION = False

#     if tablename == 'neighbor_index':
#         """
#         python -m ibeis.core_annots --exec-compute_neighbor_index --show
#         """

#         import utool
#         utool.embed()

#     if INDEXER_VERSION or tablename == 'neighbs':
#         compute_order = table.compute_order
#         depend_order = compute_order['depend_compute_ids']
#         input_order = compute_order['input_compute_ids']

#         if _debug:
#             print(' * input_order = %s' % (ut.repr3(input_order, nl=1),))
#             print(' * depend_order = %s' % (ut.repr3(depend_order, nl=1),))
#         if len(input_order) > 1:
#             assert ut.depth_atleast(root_rowids, 2), (
#                 'input_order = %r' % (input_order,))

#         with ut.Indenter('[GetRowID-%s]' % (tablename,),
#                          enabled=_debug):
#             # New way to get rowids
#             input_level = depend_order[0]
#             mid_levels = depend_order[1:-1]
#             output_level = depend_order[-1]

#             # List that holds a mapping from input order to input "name"
#             input_order_lookup = ut.make_index_lookup(input_order)
#             # Dictionary that holds the rowids computed for each table
#             # while tracing the dependencies.
#             rowid_lookup = ut.odict([(key, ut.odict()) for key in input_order])

#             # Need to split each path into parts.
#             # Each part represents another level of unflattening
#             # (because root indicies are all flat)

#             # Handle input level
#             assert input_level[0] == depc.root
#             for compute_id in input_order:
#                 # for name in input_names:
#                 argx = input_order_lookup[compute_id]
#                 rowid_lookup[compute_id] = root_rowids[argx]
#                 # HACK: Flatten to scalars
#                 # The inputs should just be given in the "correct" nesting.
#                 # TODO: determine what correct nesting is.
#                 for i in range(5):
#                     try:
#                         current = rowid_lookup[compute_id]
#                         rowid_lookup[compute_id] = ut.flatten(current)
#                     except Exception:
#                         pass

#             level = 0
#             if _debug:
#                 print('input_order_lookup = %r' % (input_order_lookup,))
#                 ut.printdict(rowid_lookup, 'rowid_lookup')

#             def handle_level(compute_id, rowid_lookup, _recompute, level):
#                 print('+--- HANDLE LEVEL %d -------' % (level,))
#                 tablekey = compute_id[0]
#                 input_suff = compute_id[1]
#                 config_ = depc._ensure_config(tablekey, config)
#                 table = depc[tablekey]
#                 lookupkeys = [(n, input_suff) for n in table.parent_id_tablenames]
#                 # ordering = ut.dict_take(input_order_lookup, input_names)
#                 # sortx = ut.argsort(ordering)
#                 # FIXME: get inputs for each table.
#                 # input_names = ut.take(input_names, sortx)
#                 # lookupkeys = list(ut.iprod(table.parent_id_tablenames, input_names))
#                 # lookupkeys = list(zip(table.parent_id_tablenames, input_types))
#                 if _debug:
#                     print('---- LOCALS ------')
#                     ut.print_locals(compute_id, tablekey, lookupkeys, table)
#                     print('L----------')
#                 # FIXME generalize
#                 _parent_ids = [rowid_lookup[tblkey] for tblkey in lookupkeys]
#                 if table.ismulti:
#                     parent_rowidsT = [[tuple(x)] for x in _parent_ids]
#                 else:
#                     parent_rowidsT = _parent_ids
#                 parent_rowidsT = np.broadcast_arrays(*parent_rowidsT)
#                 parent_rowids = list(zip(*parent_rowidsT))
#                 # Probably not right for general multi-input
#                 import utool
#                 with utool.embed_on_exception_context:
#                     next_rowids = table.get_rowid(
#                         parent_rowids, config=config_, eager=eager, nInput=nInput,
#                         ensure=ensure, recompute=_recompute)
#                 rowid_lookup[compute_id] = next_rowids
#                 if _debug:
#                     ut.printdict(rowid_lookup, 'rowid_lookup')
#                 if _debug:
#                     print('L___ HANDLE LEVEL %d -------' % (level,))
#                 return next_rowids

#             # Handle mid levels
#             _recompute = recompute_all
#             for level, compute_id in enumerate(mid_levels, start=1):
#                 handle_level(compute_id, rowid_lookup, _recompute, level)
#             level += 1

#             # Handel final (requested) level
#             compute_id = output_level
#             _recompute = recompute
#             rowid_list =  handle_level(compute_id, rowid_lookup,
#                                        _recompute, level)
#     else:
#         with ut.Indenter('[GetRowID-%s]' % (tablename,),
#                          enabled=_debug):
#             # TODO: Get nonself rowids first
#             # THen get self rowids for debugging ease
#             try:
#                 if False:
#                     recompute_ = recompute or recompute_all
#                     parent_rowids = depc._get_parent_input(
#                         tablename, root_rowids, config, ensure=True, _debug=None,
#                         recompute=False, recompute_all=False, eager=True,
#                         nInput=None)
#                     config_ = depc._ensure_config(tablename, config)
#                     #if onthefly:
#                     #    pass
#                     table = depc[tablename]
#                     rowid_list = table.get_rowid(
#                         parent_rowids, config=config_, eager=eager, nInput=nInput,
#                         ensure=ensure, recompute=recompute_)
#                 else:
#                     # Compute everything from the root to the requested table
#                     rowid_dict = depc.get_all_descendant_rowids(
#                         tablename, root_rowids, config=config, ensure=ensure,
#                         eager=eager, nInput=nInput, recompute=recompute,
#                         recompute_all=recompute_all, _debug=ut.countdown_flag(_debug))
#                     rowid_list = rowid_dict[tablename]
#             except depcache_table.ExternalStorageException:
#                 print('EXTERNAL EXCEPTION One retry in get_rowids')
#                 rowid_dict = depc.get_all_descendant_rowids(
#                     tablename, root_rowids, config=config, ensure=ensure,
#                     eager=eager, nInput=nInput, recompute=recompute,
#                     recompute_all=recompute_all, _debug=ut.countdown_flag(_debug))
#                 rowid_list = rowid_dict[tablename]
#     if _debug:
#         print(' * return rowid_list = %s' % (ut.trunc_repr(rowid_list),))
#     return rowid_list


# def _get_parent_input(depc, tablename, root_rowids, config, ensure=True,
#                       _debug=None, recompute=False, recompute_all=False,
#                       eager=True, nInput=None):
#     # Get ancestor rowids that are descendants of root
#     table = depc[tablename]
#     rowid_dict = depc.get_all_descendant_rowids(
#         tablename, root_rowids, config=config, ensure=ensure,
#         eager=eager, nInput=nInput, recompute=recompute,
#         recompute_all=recompute_all, _debug=ut.countdown_flag(_debug),
#         levels_up=1)
#     parent_rowids = depc._get_parent_rowids(table, rowid_dict)
#     return parent_rowids

# #def get_relevant_subconfigs(depc, tablename, config):
# #    depc._ensure_config(tablename, config)
# #    pass


# def _get_parent_rowids(depc, table, rowid_dict):
#     # FIXME to handle multiedges correctly
#     parent_rowidsT = ut.dict_take(rowid_dict,
#                                   table.parent_id_tablenames)
#     if table.ismulti:
#         parent_rowids = parent_rowidsT
#     else:
#         parent_rowids = ut.list_transpose(parent_rowidsT)
#     return parent_rowids


# def _expand_level_rowids(depc, tablename, tablekey, rowid_dict, ensure,
#                          eager, nInput, config, recompute, recompute_all,
#                          _debug):
#     table = depc[tablekey]
#     config_ = depc._ensure_config(tablekey, config)
#     parent_rowids = depc._get_parent_rowids(table, rowid_dict)
#     if _debug:
#         print('   * tablekey = %r' % (tablekey,))
#         print('   * (ensured) config_ = %r' % (config_,))
#         print('   * config_rowid = %r' % (table.get_config_rowid(config_),))
#         print('   * parent_rowids = %s' % (ut.trunc_repr(parent_rowids),))
#     _recompute = recompute_all or (tablekey == tablename and recompute)
#     level_rowids = table.get_rowid(
#         parent_rowids, config=config_, eager=eager, nInput=nInput,
#         ensure=ensure, recompute=_recompute)
#     if _debug:
#         print('   * level_rowids = %s' % (ut.trunc_repr(level_rowids),))
#     r


# def test_getprop_with_configs():
#     r"""
#     CommandLine:
#         python -m dtool_ibeis.example_depcache2 test_getprop_with_configs --show

#     Example:
#         >>> # DISABLE_DOCTEST
#         >>> from dtool_ibeis.example_depcache2 import *  # NOQA
#         >>> test_getprop_with_configs()
#     """
#     config1 = {'manual_extract': True}
#     config2 = {'manual_extract': False}
#     depc = testdata_depc2()

#     aid = 2
#     _debug = False

#     cropchip1 = depc.get('cropchip', aid, 'img', config=config1)
#     cropchip2 = depc.get('cropchip', aid, 'img', config=config2)
#     print('cropchip1.shape = %r' % (cropchip1.shape,))
#     print('cropchip2.shape = %r' % (cropchip2.shape,))
#     cropchip1 = depc.get('cropchip', aid, 'img', config=config1)
#     cropchip2 = depc.get('cropchip', aid, 'img', config=config2)

#     print('cropchip1.shape = %r' % (cropchip1.shape,))
#     print('cropchip2.shape = %r' % (cropchip2.shape,))

#     chip = depc.get('chip', aid, 'img')
#     print('chip.shape = %r' % (chip.shape,))

#     tip1 = depc.get('tip', aid, config=config1, _debug=_debug)
#     tip2 = depc.get('tip', aid, config=config2, _debug=_debug)

#     print('tip1 = %r' % (tip1,))
#     print('tip2 = %r' % (tip2,))

#     depc.print_all_tables()
#     depc.print_config_tables()
#     #import utool
#     #utool.embed()


# def testdata_depc2():
#     """
#     Example of local registration
#     sudo pip install freetype-py

#     CommandLine:
#         python -m dtool_ibeis.example_depcache2 testdata_depc2 --show

#     Example:
#         >>> # DISABLE_DOCTEST
#         >>> from dtool_ibeis.example_depcache2 import *  # NOQA
#         >>> depc = testdata_depc2()
#         >>> ut.quit_if_noshow()
#         >>> import plottool_ibeis as pt
#         >>> depc.show_graph()
#         >>> ut.show_if_requested()
#     """
#     import dtool_ibeis
#     import vtool_ibeis as vt
#     from vtool_ibeis import fontdemo

#     # put the test cache in the dtool_ibeis repo
#     dtool_repo = dirname(ut.get_module_dir(dtool_ibeis))
#     cache_dpath = join(dtool_repo, 'DEPCACHE2')

#     root = 'annot'

#     depc = dtool_ibeis.DependencyCache(
#         root_tablename=root, cache_dpath=cache_dpath, use_globals=False)

#     # ----------

#     class ChipConfig(dtool_ibeis.Config):
#         _param_info_list = [
#             ut.ParamInfo('dim_size', 500),
#             ut.ParamInfo('ext', '.png'),
#         ]

#     @depc.register_preproc(
#         tablename='chip', parents=[root], colnames=['size', 'img'],
#         coltypes=[(int, int), ('extern', vt.imread, vt.imwrite)],
#         configclass=ChipConfig)
#     def compute_chip(depc, aids, config=None):
#         for aid in aids:
#             chip = fontdemo.get_text_test_img(str(aid))
#             size = vt.get_size(chip)
#             yield size, chip

#     # ----------

#     class TipConfig(dtool_ibeis.Config):
#         _param_info_list = [
#             ut.ParamInfo('manual_extract', False, hideif=False),
#         ]

#     @depc.register_preproc(
#         tablename='tip', parents=['chip'],
#         colnames=['notch', 'left', 'right'],
#         coltypes=[np.ndarray, np.ndarray, np.ndarray],
#         configclass=TipConfig,
#     )
#     def compute_tips(depc, chip_rowids, config=None):
#         manual_extract = config['manual_extract']
#         chips = depc.get_native('chip', chip_rowids, 'img')
#         for chip in chips:
#             seed = (chip).sum()
#             perb = ((seed % 1000) / 1000) * .25
#             w, h = vt.get_size(chip)
#             if manual_extract:
#                 # Make noticable difference between config outputs
#                 lpb =  np.ceil(w * perb)
#                 npb =  np.ceil(h * perb)
#                 rpb = -np.ceil(w * perb)
#             else:
#                 lpb =  np.ceil(w * perb / 2)
#                 npb = -np.ceil(h * perb)
#                 rpb = -np.ceil(w * perb)
#             wh = np.array([w, h], dtype=np.int32)[None, :]
#             rel_base = np.array([[.0, .5], [.5, .5], [1., .5]])
#             offset   = np.array([[lpb, 0], [0, npb], [rpb, 0]])
#             tip = np.round((wh * rel_base)) + offset
#             left, notch, right = tip
#             yield left, notch, right

#     # ----------

#     class CropChipConfig(dtool_ibeis.Config):
#         _param_info_list = [
#             ut.ParamInfo('dim_size', 500),
#         ]

#     @depc.register_preproc(
#         tablename='cropchip', parents=['chip', 'tip'],
#         colnames=['img'],
#         coltypes=[np.ndarray],
#         configclass=CropChipConfig,
#     )
#     def compute_cropchip(depc, cids, tids, config=None):
#         print("COMPUTE CROPCHIP")
#         print('config = %r' % (config,))
#         chips = depc.get_native('chip', cids, 'img')
#         tips = depc.get_native('tip', tids)
#         print('tips = %r' % (tips,))
#         for chip, tip in zip(chips, tips):
#             notch, left, right = tip
#             lx = left[0]
#             rx = right[0]
#             cropped_chip = chip[lx:(rx - 1), ...]
#             yield (cropped_chip,)

#     # ----------

#     class TrailingEdgeConfig(dtool_ibeis.Config):
#         _param_info_list = []

#     @depc.register_preproc(
#         tablename='trailingedge', parents=['cropchip'],
#         colnames=['te'],
#         coltypes=[np.ndarray],
#         configclass=TrailingEdgeConfig,
#     )
#     def compute_trailing_edge(depc, cropped_chips, config=None):
#         for cc in cropped_chips:
#             #depc.get_native('chip', cids)
#             size = 1
#             te = np.arange(size)
#             yield (te,)

#     depc.initialize()
#     return depc


# def testdata_depc_image():
#     """
#     Example of local registration
#     sudo pip install freetype-py

#     CommandLine:
#         python -m dtool_ibeis.example_depcache2 testdata_depc_image --show

#     Example:
#         >>> # DISABLE_DOCTEST
#         >>> from dtool_ibeis.example_depcache2 import *  # NOQA
#         >>> depc = testdata_depc_image()
#         >>> ut.quit_if_noshow()
#         >>> import plottool_ibeis as pt
#         >>> depc.show_graph()
#         >>> depc['detection'].show_input_graph()
#         >>> print(depc['detection'].compute_order)
#         >>> ut.show_if_requested()
#     """
#     import dtool_ibeis

#     # put the test cache in the dtool_ibeis repo
#     dtool_repo = dirname(ut.get_module_dir(dtool_ibeis))
#     cache_dpath = join(dtool_repo, 'DEPCACHE2')

#     root = 'image'

#     depc = dtool_ibeis.DependencyCache(
#         root_tablename=root, cache_dpath=cache_dpath, use_globals=False)

#     # ----------
#     dummy_cols = dict(colnames=['data'], coltypes=[np.ndarray])
#     def dummy_func(depc, *args, **kwargs):
#         for row_arg in zip(*args):
#             yield (np.array([42]),)

#     depc.register_preproc(tablename='detector', parents=['image*'], **dummy_cols)(dummy_func)
#     depc.register_preproc(tablename='detection', parents=['image', 'detector'], **dummy_cols)(dummy_func)

#     depc.initialize()
#     return depc


# def testdata_depc_annot():
#     """
#     CommandLine:
#         python -m dtool_ibeis.example_depcache2 testdata_depc_annot --show

#     Example:
#         >>> # DISABLE_DOCTEST
#         >>> from dtool_ibeis.example_depcache2 import *  # NOQA
#         >>> depc = testdata_depc_annot()
#         >>> ut.quit_if_noshow()
#         >>> import plottool_ibeis as pt
#         >>> depc.show_graph()
#         >>> tablename = 'featweight'
#         >>> table = depc[tablename]
#         >>> table.show_input_graph()
#         >>> print(table.compute_order)
#         >>> ut.show_if_requested()
#     """
#     import dtool_ibeis
#     # put the test cache in the dtool_ibeis repo
#     dtool_repo = dirname(ut.get_module_dir(dtool_ibeis))
#     cache_dpath = join(dtool_repo, 'DEPCACHE2')
#     dummy_cols = dict(colnames=['data'], coltypes=[np.ndarray])
#     def dummy_func(depc, *args, **kwargs):
#         for row_arg in zip(*args):
#             yield (np.array([42]),)

#     # NOTE: Consider the smk_match.
#     # It would be really cool if we could say that the vocab
#     # for the input to the parent smk_vec must be the same vocab
#     # that was used to compute the inverted index. How do we encode that?

#     root = 'annot'
#     #vocab_parent = 'annot'
#     #vocab_parent = 'chip'
#     #vocab_parent = 'feat'
#     vocab_parent = 'featweight'
#     depc = dtool_ibeis.DependencyCache(
#         root_tablename=root, cache_dpath=cache_dpath, use_globals=False)
#     depc.register_preproc(tablename='chip', parents=['annot'], **dummy_cols)(dummy_func)
#     depc.register_preproc(tablename='fgmodel', parents=['chip*'], **dummy_cols)(dummy_func)
#     depc.register_preproc(tablename='probchip', parents=['annot', 'fgmodel'], **dummy_cols)(dummy_func)
#     #depc.register_preproc(tablename='probchip', parents=['annot'], **dummy_cols)(dummy_func)
#     depc.register_preproc(tablename='feat', parents=['chip'], **dummy_cols)(dummy_func)
#     #depc.register_preproc(tablename='feat', parents=['annot'], **dummy_cols)(dummy_func)
#     depc.register_preproc(tablename='featweight', parents=['feat', 'probchip'], **dummy_cols)(dummy_func)

#     depc.register_preproc(tablename='indexer', parents=[vocab_parent + '*'], **dummy_cols)(dummy_func)
#     depc.register_preproc(tablename='neighbs', parents=[vocab_parent, 'indexer'], **dummy_cols)(dummy_func)
#     depc.register_preproc(tablename='vocab', parents=[vocab_parent + '*'], **dummy_cols)(dummy_func)
#     depc.register_preproc(tablename='smk_vec', parents=[vocab_parent, 'vocab'], **dummy_cols)(dummy_func)
#     depc.register_preproc(tablename='inv_index', parents=['smk_vec*'], **dummy_cols)(dummy_func)
#     depc.register_preproc(tablename='smk_match', parents=['smk_vec', 'inv_index'], **dummy_cols)(dummy_func)
#     depc.register_preproc(tablename='vsone', parents=[vocab_parent, vocab_parent], **dummy_cols)(dummy_func)

#     depc.register_preproc(tablename='viewpoint_model', parents=['annot*'], **dummy_cols)(dummy_func)
#     depc.register_preproc(tablename='viewpoint', parents=['annot', 'viewpoint_model'], **dummy_cols)(dummy_func)

#     depc.register_preproc(tablename='quality_model', parents=['annot*'], **dummy_cols)(dummy_func)
#     depc.register_preproc(tablename='quality', parents=['annot', 'quality_model'], **dummy_cols)(dummy_func)

#     depc.initialize()
#     return depc

# return level_rowids
