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, _)]
Esempio n. 2
0
    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.
    """

    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)
Esempio n. 7
0
    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, _)]
Esempio n. 8
0
    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, _)]
Esempio n. 9
0
    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, _)]