=============================================================== loops - Linked Objects for Organization and Processing Services =============================================================== ($Id$) Note: This packages depends on cybertools.organize. Letz's do some basic set up >>> from zope.app.testing.setup import placefulSetUp, placefulTearDown >>> site = placefulSetUp(True) >>> from zope import component, interface >>> from zope.app import zapi and setup a simple loops site with a concept manager and some concepts (with all the type machinery, what in real life is done via standard ZCML setup): >>> from loops import Loops >>> from loops.concept import ConceptManager, Concept >>> from loops.interfaces import IConcept, ITypeConcept >>> loopsRoot = site['loops'] = Loops() >>> from cybertools.relation.interfaces import IRelationRegistry >>> from cybertools.relation.registry import DummyRelationRegistry >>> relations = DummyRelationRegistry() >>> component.provideUtility(relations, IRelationRegistry) >>> from cybertools.typology.interfaces import IType >>> from loops.type import ConceptType, TypeConcept >>> component.provideAdapter(ConceptType, (IConcept,), IType) >>> component.provideAdapter(TypeConcept, (IConcept,), ITypeConcept) >>> loopsRoot['concepts'] = ConceptManager() >>> concepts = loopsRoot['concepts'] >>> concepts['hasType'] = Concept(u'has type') >>> concepts['type'] = Concept(u'Type') >>> type = concepts['type'] >>> type.conceptType = type >>> from loops.organize.interfaces import IPerson >>> concepts['person'] = Concept(u'Person') >>> person = concepts['person'] >>> person.conceptType = type >>> ITypeConcept(person).typeInterface = IPerson >>> johnC = Concept(u'John') >>> concepts['john'] = johnC >>> johnC.conceptType = person Organizations: Persons (and Users), Institutions, Addresses... ============================================================== The classes used in this package are just adapters to IConcept. >>> from loops.organize.party import Person >>> component.provideAdapter(Person, (IConcept,), IPerson) >>> john = IPerson(johnC) >>> john.title u'John' >>> john.firstName = u'John' >>> johnC._firstName u'John' >>> john.lastName is None True >>> john.someOtherAttribute Traceback (most recent call last): ... AttributeError: someOtherAttribute We can use the age calculations from the base Person class: >>> from datetime import date >>> john.birthDate = date(1980, 3, 26) >>> john.ageAt(date(2006, 5, 12)) 26 >>> john.age >= 26 True A person can be associated with a user of the system by setting the userId attribute; this will also register the person concept in the corresponding principal annotations so that there is a fast way to find the person(s) belonging to a user/principal. For testing, we first have to provide the needed utilities and settings (in real life this is all done during Zope startup): >>> from zope.app.security.interfaces import IAuthentication >>> from zope.app.security.principalregistry import PrincipalRegistry >>> auth = PrincipalRegistry() >>> component.provideUtility(auth, IAuthentication) >>> from zope.app.principalannotation.interfaces import IPrincipalAnnotationUtility >>> from zope.app.principalannotation import PrincipalAnnotationUtility >>> principalAnnotations = PrincipalAnnotationUtility() >>> component.provideUtility(principalAnnotations, IPrincipalAnnotationUtility) >>> principal = auth.definePrincipal('users.john', u'John', login='john') >>> john.userId = 'users.john' >>> annotations = principalAnnotations.getAnnotationsById('users.john') >>> from loops.organize.party import ANNOTATION_KEY >>> annotations.get(ANNOTATION_KEY) == johnC True Change a userId assignment: >>> principal = auth.definePrincipal('users.johnny', u'Johnny', login='johnny') >>> john.userId = 'users.johnny' >>> annotations = principalAnnotations.getAnnotationsById('users.johnny') >>> annotations.get(ANNOTATION_KEY) == johnC True >>> annotations = principalAnnotations.getAnnotationsById('users.john') >>> annotations.get(ANNOTATION_KEY) is None True >>> john.userId = None >>> annotations = principalAnnotations.getAnnotationsById('users.johnny') >>> annotations.get(ANNOTATION_KEY) is None True Deleting a person with a userId assigned removes the corresponding principal annotation: >>> from zope.app.container.interfaces import IObjectRemovedEvent >>> from zope.app.container.contained import ObjectRemovedEvent >>> from zope.event import notify >>> from zope.interface import Interface >>> from loops.organize.party import removePersonReferenceFromPrincipal >>> from zope.app.testing import ztapi >>> ztapi.subscribe([IConcept, IObjectRemovedEvent], None, ... removePersonReferenceFromPrincipal) >>> john.userId = 'users.john' >>> annotations = principalAnnotations.getAnnotationsById('users.john') >>> annotations.get(ANNOTATION_KEY) == johnC True >>> del concepts['john'] >>> annotations = principalAnnotations.getAnnotationsById('users.john') >>> annotations.get(ANNOTATION_KEY) is None True If we try to assign a userId of a principal that already has a person concept assigned we should get an error: >>> john.userId = 'users.john' >>> marthaC = Concept(u'Martha') >>> concepts['martha'] = marthaC >>> marthaC.conceptType = person >>> martha = IPerson(marthaC) >>> martha.userId = 'users.john' Traceback (most recent call last): ... ValueError: ... Fin de partie ============= >>> placefulTearDown()