Пример #1
0
def _locate_all_auto_traits():
    """Extract all automatically assigned traits from cereconf.

    cereconf.AFFILIATE_TRAITS contains a mapping for translating role ids in
    source data to trait descriptions for all automatically awarded
    traits. This function processes this mapping and returns a sequence of all
    auto traits.

    @rtype: sequence
    @return:
      A sequence of trait codes for all automatically awarded traits. The
      actual trait assignment (from role ids) happens in
      L{import_HR_person.py}. This script takes the traits and assigns group
      membersships based on them.
    """

    # IVR 2008-01-17 FIXME: This is a copy of a similar function from
    # import_HR_person.py. Duplication is bad.
    # Collect all known auto traits.
    if not hasattr(cereconf, "AFFILIATE_TRAITS"):
        return set()

    auto_traits = set()
    for trait_code_str in cereconf.AFFILIATE_TRAITS.itervalues():
        try:
            trait = constants.EntityTrait(trait_code_str)
            int(trait)
        except Errors.NotFoundError:
            logger.error("Trait <%s> is defined in cereconf.AFFILIATE_TRAITS, "
                         "but it is unknown i Cerebrum (code)", trait_code_str)
            continue

        # Check that the trait is actually associated with a person (and not
        # something else. AFFILIATE_TRAITS is supposed to "cover" person
        # objects ONLY!)
        if trait.entity_type != constants.entity_person:
            logger.error("Trait <%s> from AFFILIATE_TRAITS is associated with "
                         "<%s>, but we allow person traits only",
                         trait, trait.entity_type)
            continue

        auto_traits.add(int(trait))

    return auto_traits
Пример #2
0
 def get_target_by_external_id(ext_id):
     # This does not have to be person, but cereconf.CLASS_ENTITY is
     # insufficient. We need EntityExternalId here.
     en = Factory.get("Person")(self.db)
     # first, locate the entity_id
     candidates = en.list_external_ids(external_id=ext_id)
     only_ids = set([int(x["entity_id"]) for x in candidates])
     if len(only_ids) < 1:
         raise CerebrumError("No entity with external id=%s" % ext_id)
     if len(only_ids) > 1:
         raise CerebrumError("Too many targets with external id=%s" "[entity_ids=%s]" % (ext_id, only_ids))
     return get_target_entity(only_ids.pop())
Пример #3
0
 def get_target_by_external_id(ext_id):
     # This does not have to be person, but cereconf.CLASS_ENTITY is
     # insufficient. We need EntityExternalId here.
     en = Factory.get("Person")(self.db)
     # first, locate the entity_id
     candidates = en.list_external_ids(external_id=ext_id)
     only_ids = set([int(x["entity_id"]) for x in candidates])
     if len(only_ids) < 1:
         raise CerebrumError("No entity with external id=%s" % ext_id)
     if len(only_ids) > 1:
         raise CerebrumError("Too many targets with external id=%s"
                             "[entity_ids=%s]" % (ext_id, only_ids))
     return get_target_entity(only_ids.pop())
Пример #4
0
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Cerebrum; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.


from Cerebrum.Entity import Entity
from Cerebrum.Constants import _ChangeTypeCode, _get_code
from Cerebrum import Errors
from Cerebrum.Utils import NotSet
from EntityTraitConstants import _EntityTraitCode

try:
    set()
except:
    from Cerebrum.extlib.sets import Set as set

__version__ = "1.1"


@_ChangeTypeCode.formatter('trait')
def format_cl_trait(co, val):
    return _get_code(co.EntityTrait, val, '<unknown>')


class EntityTrait(Entity):
    """Mixin class which adds generic traits to an entity."""

    def clear(self):
Пример #5
0
#
# You should have received a copy of the GNU General Public License
# along with Cerebrum; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.

import time
import cerebrum_path
import cereconf
from Cerebrum import Constants
from Cerebrum.Utils import Factory
from Cerebrum.modules.bofhd.errors import CerebrumError
from Cerebrum import Errors
import xmlrpclib
from mx import DateTime
try:
    set()
except NameError:
    from Cerebrum.extlib.sets import Set as set


class _BofhdRequestOpCode(Constants._CerebrumCode):
    "Mappings stored in the auth_role_op_code table"
    _lookup_table = '[:table schema=cerebrum name=bofhd_request_code]'


class _AuthRoleOpCode(Constants._CerebrumCode):
    "Mappings stored in the auth_role_op_code table"
    _lookup_table = '[:table schema=cerebrum name=auth_op_code]'


class Constants(Constants.Constants):
Пример #6
0
def synchronise_groups(groups_from_cerebrum, groups_from_data):
    """Synchronise current in-memory representation of groups with the db.

    The groups (through the rules) are built in-memory. This function
    synchronises the in-memory data structure with Cerebrum. For each group,
    read the membership info, compare it with groups_from_data, adjust the
    information, write_db() on the group.

    NB! L{groups_from_cerebrum} is modified by this function.

    @type groups_from_cerebrum: dict
    @param: Cf. L{find_all_auto_groups}.

    @type groups_from_data: dict
    @param: Cf. L{populate_groups_from_rule}.

    @rtype: type(groups_from_cerebrum)
    @return:
      Modified L{groups_from_cerebrum}.
    """

    group = Factory.get("Group")(database)

    for group_id, membership_info in groups_from_data.iteritems():
        try:
            group.clear()
            group.find(group_id)
            gname = group.group_name
        except Errors.NotFoundError:
            logger.warn("group_id=%s disappeared from Cerebrum.", group_id)
            continue

        # select just the entity_ids (we don't care about entity_type)
        group_members = set(int(x["member_id"]) for x in
                            group.search_members(group_id=group.entity_id))
        # now, synch the union members. sync'ing means making sure that the
        # members of group are exactly the ones in memberset.

        # those that are not in 'group_members', should be added
        add_count = 0
        to_add = list()
        for member_type, members in membership_info.iteritems():
            to_add = members.difference(group_members)
            add_count += len(to_add)
            add_members(group, to_add)

        # those that are in 'group_members', but not in membership_info,
        # should be removed.
        to_remove = group_members.copy()
        for member_type, members in membership_info.iteritems():
            to_remove = to_remove.difference(members)
        remove_members(group, to_remove)

        if gname not in groups_from_cerebrum:
            logger.debug("New group id=%s, name=%s", group_id, gname)
        else:
            del groups_from_cerebrum[gname]
            logger.debug("Existing group id=%s, name=%s", group_id, gname)

        if to_remove or to_add:
            logger.debug("Updated group id=%s, name=%s; added=%d, removed=%d",
                         group_id, gname, add_count, len(to_remove))
        else:
            logger.debug("No changes to group id=%s, name=%s", group_id, gname)

        # It's harmless when no changes are made, and placing it here makes
        # the code simpler.
        group.write_db()

    return groups_from_cerebrum
Пример #7
0
def populate_groups_from_rule(person_generator, row2groups, current_groups,
                              new_groups):
    """Sweep all the people from generator and assign group memberships.

    There may be several rules for building all of the groups. For each rule,
    this functions assigns proper memberships to new_groups. Once we have
    finished processing the rules, we can synchronize the in-memory data
    structure with the database.

    @type person_generator:
      Generator (or a function returning a sequence) of db_rows. 
    @param person_generator:
      Next db-row 'source' to process. Calling this yields something we can
      iterate across. The items in the sequence should be db_rows (or
      something which emulates them, like a dict)

    @type row2groups: callable
    @param row2groups:
      Function that converts a row returned by L{person_generator} to a list
      of memberships. Calling row2groups on any row D returned by
      L{person_generator} returns a list of triples (x, y, z) (cf.
      L{employee2groups} for the precise description of their meanings).

    @type current_groups: dict
    @param current_groups:
      Cf. L{find_all_auto_groups}.

    @type new_groups: dict
    @param new_groups:
      A dictionary mapping group_ids to membership info. Each membership info
      is a dictionary, mapping entity types to member ids. All group_ids
      referenced refer to groups existing in Cerebrum (i.e. we are guaranteed
      (at least at some isolation level) that all group_ids in this dict exist
      in Cerebrum.

      An example of this dictionary would be::

          {1: {<entity person>: set([10, 11, 12, 13]),
               <entity group>: set([20, 21, 22])}}

      ... meaning that group with id=1 has two types of members: people (with
    ids 10-13) and other groups (ids 20, 21, 22). Note that it is unlikely
    that a group would have *both* people and groups as members. It is either
    one or the other, but not both.
    """

    count = 0
    for person in person_generator():
        memberships = row2groups(person, current_groups)

        for member_id, member_type, group_id in memberships:
            # all known memberships for group_id
            d = new_groups.setdefault(group_id, dict())
            member_type = int(member_type)

            # Add the member to the membership set of the right type.
            # Typically, any given group would have either all members as
            # people or as groups.
            d.setdefault(member_type, set()).add(member_id)
            count += 1

    logger.debug("After processing rule, we have %d groups", len(new_groups))
    logger.debug("... and <= %d members", count)