def list_units_in_subject_recursive(db_conn, main_subject): """ Get the list of units contained within the subject. Recursive. Connecting. TODO-2 what about required units outside the subject? """ def _(): # *** First, we need to break down # the subject into a list of known units. *** unit_ids = set() subjects = [main_subject] while subjects: subject_ids = set() for subject in subjects: unit_ids.update({ member['id'] for member in subject.get('members') if member['kind'] == 'unit' }) subject_ids.update({ member['id'] for member in subject.get('members') if member['kind'] == 'subject' }) subjects = list_latest_accepted_subjects(db_conn, subject_ids) # *** Second, we need to find all # the required connecting units. *** units = list_latest_accepted_units(db_conn, unit_ids) return units # If we already have it stored, use that key = 'subject_{id}'.format(id=main_subject['entity_id']) return [data for data in memoize_redis(key, _)]
def list_by_unit_id(cls, unit_id): """ Get a list of sets which contain the given member ID. Recursive. # TODO-2 is there a way to simplify this method? """ def _(): # *** First, find the list of sets # directly containing the member ID. *** query = (cls.start_accepted_query().filter( r.row['members'].contains( lambda member: member['id'] == unit_id))) sets = query.run(database.db_conn) # *** Second, find all the sets containing # those sets... recursively. *** found_sets, all_sets = sets, [] while found_sets: set_ids = {set_['entity_id'] for set_ in found_sets} all_sets += found_sets query = (cls.start_accepted_query().filter( r.row['members'].contains(lambda member: r.expr(set_ids). contains(member['id'])))) found_sets = query.run(database.db_conn) return all_sets key = 'list_sets_by_unit_id_{id}'.format(id=unit_id) return [Set(data) for data in memoize_redis(key, _)]
def list_subjects_by_unit_recursive(db_conn, unit_id): """ Get a list of subjects which contain the given member ID. Recursive. TODO-2 is there a way to simplify this method? """ def _(): # *** First, find the list of subjects # directly containing the member ID. *** subjects = list_subjects_by_unit_flat(db_conn, unit_id) # *** Second, find all the subjects containing # those subjects... recursively. *** found_subjects, all_subjects = subjects, [] while found_subjects: all_subjects += found_subjects subject_ids = { subject['entity_id'] for subject in found_subjects } found_subjects = [] for subject_id in subject_ids: found_subjects += list_subject_parents(db_conn, subject_id) return all_subjects key = 'list_subjects_by_unit_{id}'.format(id=unit_id) return [data for data in memoize_redis(key, _)]
def test_memoize_redis(): """ Expect to memoize the result of a function into Redis. """ def a(): return {'a': 1, 'z': 1} key = 'test_memoize_redis' redis.delete(key) assert memoize_redis(key, a) == {'a': 1, 'z': 1} redis.delete(key)
def test_memoize_redis(): """ Expect to memoize the result of a function into Redis. """ value = {'a': 1, 'z': 1} def a(): return value key = 'test_memoize_redis' red.delete(key) # try memoization assert memoize_redis(key, a) == value assert memoize_redis(key, a) == value # a second time, memoized # try a bad value red.setex(key, 24 * 60 * 60, b'\x80abc') assert memoize_redis(key, a) == b'\x80abc' # clean up red.delete(key)
def list_by_unit_id(cls, unit_id): """ Get a list of sets which contain the given member ID. Recursive. # TODO-2 is there a way to simplify this method? """ def _(): # *** First, find the list of sets # directly containing the member ID. *** query = (cls.start_accepted_query() .filter(r.row['members'].contains( lambda member: member['id'] == unit_id ))) sets = query.run(database.db_conn) # *** Second, find all the sets containing # those sets... recursively. *** found_sets, all_sets = sets, [] while found_sets: set_ids = {set_['entity_id'] for set_ in found_sets} all_sets += found_sets query = (cls.start_accepted_query() .filter(r.row['members'].contains( lambda member: r.expr(set_ids).contains(member['id']) ))) found_sets = query.run(database.db_conn) return all_sets key = 'list_sets_by_unit_id_{id}'.format(id=unit_id) return [Set(data) for data in memoize_redis(key, _)]
def list_units(self): """ Get the list of units contained within the set. Recursive. Connecting. TODO-2 OMG break into smaller functions TODO-2 Should this method be part of the Unit class/module, as it returns units? """ def _(): # *** First, we need to break down # the set into a list of known units. *** unit_ids = set() sets = [self] while sets: set_ids = set() for set_ in sets: unit_ids.update({ member['id'] for member in set_.data.get('members') if member['kind'] == 'unit' }) set_ids.update({ member['id'] for member in set_.data.get('members') if member['kind'] == 'set' }) sets = Set.list_by_entity_ids(set_ids) # *** Second, we need to find all # the required connecting units. *** next_grab, units, unit_requires = unit_ids, [], {} while next_grab: tier_units = Unit.list_by_entity_ids(next_grab) units += tier_units next_grab = set() for unit in tier_units: if 'require_ids' not in unit: continue unit_id = unit['entity_id'] require_ids = unit_requires[unit_id] = \ set(unit['require_ids']) for require_id in require_ids: if require_id in unit_ids: ids = {unit_id} while ids: unit_ids.update(ids) ids = { unit_id for unit_id, require_ids in unit_requires.items() if unit_id not in unit_ids and require_ids & ids } elif require_id not in unit_requires: next_grab.add(require_id) units = [ unit.data for unit in units if unit['entity_id'] in unit_ids ] return units # If we already have it stored, use that key = 'set_units_{id}'.format(id=self['entity_id']) return [Unit(data) for data in memoize_redis(key, _)]
def list_units(self): """ Get the list of units contained within the set. Recursive. Connecting. TODO-2 OMG break into smaller functions TODO-2 Should this method be part of the Unit class/module, as it returns units? """ def _(): # *** First, we need to break down # the set into a list of known units. *** unit_ids = set() sets = [self] while sets: set_ids = set() for set_ in sets: unit_ids.update({member['id'] for member in set_.data.get('members') if member['kind'] == 'unit'}) set_ids.update({member['id'] for member in set_.data.get('members') if member['kind'] == 'set'}) sets = Set.list_by_entity_ids(set_ids) # *** Second, we need to find all # the required connecting units. *** next_grab, units, unit_requires = unit_ids, [], {} while next_grab: tier_units = Unit.list_by_entity_ids(next_grab) units += tier_units next_grab = set() for unit in tier_units: if 'require_ids' not in unit: continue unit_id = unit['entity_id'] require_ids = unit_requires[unit_id] = \ set(unit['require_ids']) for require_id in require_ids: if require_id in unit_ids: ids = {unit_id} while ids: unit_ids.update(ids) ids = {unit_id for unit_id, require_ids in unit_requires.items() if unit_id not in unit_ids and require_ids & ids} elif require_id not in unit_requires: next_grab.add(require_id) units = [unit.data for unit in units if unit['entity_id'] in unit_ids] return units # If we already have it stored, use that key = 'set_units_{id}'.format(id=self['entity_id']) return [Unit(data) for data in memoize_redis(key, _)]