Beispiel #1
0
def copy_coll_data(src_coll, tgt_coll):
    """
    Copy collection data from specified source to target collection.

    returns     list of error messages; an empty list indicates success.
    """
    # @@TESTME: Not tested by test suite
    log.info("Copying collection '%s' to '%s'"%(src_coll.get_id(), tgt_coll.get_id()))
    msgs = []
    entityfinder = EntityFinder(src_coll)
    for e in entityfinder.get_entities():
        entity_id  = e.get_id()
        typeinfo   = EntityTypeInfo(
            tgt_coll, e.get_type_id(), create_typedata=True
            )
        new_entity = typeinfo.create_entity(entity_id, e.get_values())
        if not typeinfo.entity_exists(entity_id):
            msg = (
                "Collection.copy_coll_data: Failed to create entity %s/%s"%
                    (typeinfo.type_id, entity_id)
                )
            log.warning(msg)
            msgs.append(msg)
        msgs += new_entity._copy_entity_files(e)
    return msgs
Beispiel #2
0
 def setUp(self):
     self.filepath  = "%s/README.md"%TestBaseDir
     self.fileuri   = "file://"+self.filepath
     self.imagepath = "%s/test-image.jpg"%TestBaseDir
     self.imageuri  = "file://"+self.filepath
     init_annalist_test_site()
     init_annalist_test_coll()
     self.testsite    = Site(TestBaseUri, TestBaseDir)
     self.testcoll    = Collection(self.testsite, "testcoll")
     # Populate collection with record type, view and field
     self.test_ref_type = RecordType.create(
         self.testcoll, "testreftype", test_image_ref_type_create_values
         )
     self.test_ref_view = RecordView.create(
         self.testcoll, "testrefview", test_image_ref_view_create_values
         )
     self.test_ref_field = RecordField.create(
         self.testcoll, "Test_image_ref", test_image_ref_field_create_values
         )
     # Create data records for testing image references:
     self.test_ref_type_info = EntityTypeInfo(
         self.testcoll, "testreftype", create_typedata=True
         )
     self.test_ref_type_info.create_entity("test1", test_ref_entity_create_values(self.imageuri))
     # Login and permissions
     create_test_user(self.testcoll, "testuser", "testpassword")
     self.client = Client(HTTP_HOST=TestHost)
     loggedin = self.client.login(username="******", password="******")
     self.assertTrue(loggedin)
     return
Beispiel #3
0
def migrate_coll_data(coll):
    """
    Migrate collection data for specified collection

    Returns list of error message strings, or empty list.
    """
    log.info("Migrate Annalist collection data for %s"%(coll.get_id()))
    errs = migrate_coll_config_dirs(coll)
    if errs:
        return errs
    try:
        entityfinder = EntityFinder(coll)
        for e in entityfinder.get_entities():
            log.info("migrate_coll_data: %s/%s"%(e[ANNAL.CURIE.type_id], e[ANNAL.CURIE.id]))
            typeinfo = EntityTypeInfo(coll, e[ANNAL.CURIE.type_id])
            e[ANNAL.CURIE.type] = typeinfo.get_type_uri()
            coll.update_entity_types(e)
            e._save(post_update_flags={"nocontext"})
            if e.get_errors():
                errs.extend(e.get_errors())
    except Annalist_Error as err:
        errs.append(str(err))
    if errs:
        return errs
    # Rename _group directory
    errs = migrate_collection_dir(coll, layout.GROUP_DIR, layout.GROUP_DIR+".migrated")
    if errs:
        return errs
    coll.generate_coll_jsonld_context()    
    return errs
Beispiel #4
0
 def setUp(self):
     init_annalist_test_site()
     init_annalist_test_coll()
     self.testsite = Site(TestBaseUri, TestBaseDir)
     self.testcoll = Collection(self.testsite, "testcoll")
     # Populate collection with linked record types, views and lists
     self.test_supertype_type = RecordType.create(
         self.testcoll, "test_supertype_type",
         test_supertype_type_create_values)
     self.test_subtype_type = RecordType.create(
         self.testcoll, "test_subtype_type",
         test_subtype_type_create_values)
     self.no_options = [FieldChoice('', label="(no options)")]
     # Create type and data records for testing:
     self.test_supertype_type_info = EntityTypeInfo(self.testcoll,
                                                    "test_supertype_type",
                                                    create_typedata=True)
     self.test_subtype_type_info = EntityTypeInfo(self.testcoll,
                                                  "test_subtype_type",
                                                  create_typedata=True)
     for entity_id in ("test_subtype_entity", ):
         self.test_subtype_type_info.create_entity(
             entity_id, test_subtype_entity_create_values(entity_id))
     # Login and permissions
     create_test_user(self.testcoll, "testuser", "testpassword")
     self.client = Client(HTTP_HOST=TestHost)
     loggedin = self.client.login(username="******",
                                  password="******")
     self.assertTrue(loggedin)
     return
 def setUp(self):
     init_annalist_test_site()
     init_annalist_test_coll()
     self.testsite    = Site(TestBaseUri, TestBaseDir)
     self.testcoll    = Collection(self.testsite, "testcoll")
     # Populate collection with linked record types, views and lists
     self.testsrc_type = RecordType.create(self.testcoll, "testsrc_type", testsrc_type_create_values)
     self.testtgt_type = RecordType.create(self.testcoll, "testtgt_type", testtgt_type_create_values)
     self.testsrc_view = RecordView.create(self.testcoll, "testsrc_view", testsrc_view_create_values)
     self.testtgt_view = RecordView.create(self.testcoll, "testtgt_view", testtgt_view_create_values)
     self.testsrc_list = RecordList.create(self.testcoll, "testsrc_list", testsrc_list_create_values)
     self.testtgt_list = RecordList.create(self.testcoll, "testtgt_list", testtgt_list_create_values)
     self.testtgtref_field = RecordField.create(self.testcoll, "testtgtref_field", testtgtref_field_create_values)
     self.no_options   = [ FieldChoice('', label="(no options)") ]
     self.tgt_options  = (
         [ FieldChoice("testtgt_type/"+v, 
             label="testtgt_entity %s label"%v,
             link=entity_url("testcoll", "testtgt_type", v))
           for v in ["testtgt1", "testtgt2"]
         ])
     # Create data records for testing:
     self.testtgt_type_info = EntityTypeInfo(self.testcoll, "testtgt_type", create_typedata=True)
     self.testsrc_type_info = EntityTypeInfo(self.testcoll, "testsrc_type", create_typedata=True)
     for tgt_id in ("testtgt1", "testtgt2"):
         self.testtgt_type_info.create_entity(tgt_id, testtgt_entity_create_values(tgt_id))
     for src_id, tgt_ref in (("testsrc1", "testtgt1"), ("testsrc2", "testtgt2")):
         self.testsrc_type_info.create_entity(src_id, testsrc_entity_create_values(src_id, tgt_ref))
     # Login and permissions
     create_test_user(self.testcoll, "testuser", "testpassword")
     self.client = Client(HTTP_HOST=TestHost)
     loggedin = self.client.login(username="******", password="******")
     self.assertTrue(loggedin)
     return
Beispiel #6
0
def migrate_coll_data(coll):
    """
    Migrate collection data for specified collection

    Returns list of error message strings, or empty list.
    """
    log.info("Migrate Annalist collection data for %s"%(coll.get_id()))
    errs = migrate_coll_config_dirs(coll)
    if errs:
        return errs
    try:
        entityfinder = EntityFinder(coll)
        for e in entityfinder.get_entities():
            log.info("migrate_coll_data: %s/%s"%(e[ANNAL.CURIE.type_id], e[ANNAL.CURIE.id]))
            typeinfo = EntityTypeInfo(coll, e[ANNAL.CURIE.type_id])
            typeinfo.set_type_uris(e)
            typeinfo.set_entity_uri(e[ANNAL.CURIE.id], e)
            #@@@@@
            # e[ANNAL.CURIE.type] = typeinfo.get_type_uri()
            # coll.update_entity_types(e)
            #@@@@@
            e._save(post_update_flags={"nocontext"})
            if e.get_errors():
                errs.extend(e.get_errors())
    except Annalist_Error as err:
        errs.append(str(err))
    if errs:
        return errs
    # Rename _group directory
    errs = migrate_collection_dir(coll, layout.GROUP_DIR, layout.GROUP_DIR+".migrated")
    if errs:
        return errs
    coll.generate_coll_jsonld_context()    
    return errs
Beispiel #7
0
 def get_collection_subtype_ids(self, supertype_id, altscope):
     """
     Returns a iterator of type ids for all subtypes of the supplied type 
     accessible in the indicated scope from the current collection, including 
     the identified type itself.
     """
     if not valid_id(supertype_id):
         log.warning(
             "EntityFinder.get_collection_subtype_ids: invalid type_id %s" %
             (supertype_id, ))
         return
     supertype_info = EntityTypeInfo(self._coll, supertype_id)
     supertype_uri = supertype_info.get_type_uri()
     if supertype_uri is not None:
         for try_subtype_id in self.get_collection_type_ids(altscope):
             try_subtype = self._coll.cache_get_type(try_subtype_id)
             if try_subtype:
                 try_subtype_uri = try_subtype.get_uri()
                 if ((supertype_uri == try_subtype_uri) or
                     (supertype_uri in self._coll.cache_get_supertype_uris(
                         try_subtype_uri))):
                     yield try_subtype_id
     else:
         log.warning(
             "EntityFinder.get_collection_subtype_ids: no type_uri for %s" %
             (supertype_id, ))
 def check_entity_values(self, type_id, entity_id, check_values=None):
     "Helper function checks content of entity record"
     typeinfo = EntityTypeInfo(self.testcoll, type_id)
     self.assertTrue(typeinfo.entity_exists(entity_id))
     t = typeinfo.get_entity(entity_id)
     self.assertEqual(t.get_id(), entity_id)
     self.assertEqual(t.get_type_id(), type_id)
     self.assertDictionaryMatch(t.get_values(), check_values)
     return t
Beispiel #9
0
 def check_entity_values(self, type_id, entity_id, check_values=None):
     "Helper function checks content of entity record; returns entity"
     typeinfo = EntityTypeInfo(self.testcoll, type_id)
     self.assertTrue(typeinfo.entity_exists(entity_id))
     e = typeinfo.get_entity(entity_id)
     self.assertEqual(e.get_id(), entity_id)
     self.assertEqual(e.get_type_id(), type_id)
     self.assertDictionaryMatch(e.get_values(), check_values)
     return e
Beispiel #10
0
 def get_targetvals(self):
     """
     If field description is a reference to a target type entity or field, 
     return a copy of the referenced target entity, otherwise None.
     """
     log.debug("bound_field.get_targetvals: field_description %r" %
               (self._field_description, ))
     target_type = self._field_description.get('field_ref_type', None)
     target_key = self._field_description.get('field_ref_field', None)
     log.debug("bound_field.get_targetvals: target_type %s, target_key %s" %
               (target_type, target_key))
     if self._targetvals is None:
         if target_type:
             # Extract entity_id and type_id; default to type id from field descr
             field_val = self.get_field_value()
             log.debug("field_val: %s" % (field_val, ))
             type_id, entity_id = split_type_entity_id(
                 self.get_field_value(), target_type)
             log.debug(
                 "bound_field.get_targetvals: type_id %s, entity_id %s" %
                 (type_id, entity_id))
             # Get entity type info
             coll = self._field_description._collection
             typeinfo = EntityTypeInfo(coll, type_id)
             # Check access permission, assuming user has "VIEW" permission in collection
             # This is primarily to prevent a loophole for accessing user account details
             #@@TODO: pass actual user permissions in to bound_field or field description
             #        or extra params
             user_permissions = ["VIEW"]
             req_permissions_map = typeinfo.get_entity_permissions_map(
                 entity_id)
             req_permissions = list(
                 set(req_permissions_map[a] for a in ["view", "list"]))
             if all([p in user_permissions for p in req_permissions]):
                 if entity_id is None or entity_id == "":
                     raise TargetIdNotFound_Error(
                         value=(typeinfo.type_id,
                                self._field_description["field_name"]))
                 targetentity = typeinfo.get_entity(entity_id)
                 if targetentity is None:
                     raise TargetEntityNotFound_Error(value=(target_type,
                                                             entity_id))
                 targetentity = typeinfo.get_entity_implied_values(
                     targetentity)
                 self._targetvals = get_entity_values(
                     typeinfo, targetentity)
                 log.debug("bound_field.get_targetvals: %r" %
                           (self._targetvals, ))
             else:
                 log.warning(
                     "bound_field.get_targetvals: target value type %s requires %r permissions"
                     % (target_type, req_permissions))
     log.debug("bound_field.get_targetvals: targetvals %r" %
               (self._targetvals, ))
     return self._targetvals
Beispiel #11
0
 def get_collection_subtypes(self, type_id, altscope):
     """
     Returns a iterator of `entitytypeinfo` objects for all subtypes
     of the supplied type in the current collection, including the 
     identified type itself.
     """
     supertypeinfo = EntityTypeInfo(self._coll, type_id)
     supertypeuri  = supertypeinfo.get_type_uri()
     if supertypeuri is None:
         log.warning("EntityFinder.get_collection_uri_subtypes: no type_uri for %s"%(type_id,))
     return self.get_collection_uri_subtypes(supertypeuri, altscope)
 def get_collection_subtypes(self, type_id, altscope):
     """
     Returns a iterator of `entitytypeinfo` objects for all subtypes
     of the supplied type in the current collection, including the 
     identified type itself.
     """
     supertypeinfo = EntityTypeInfo(self._coll, type_id)
     supertypeuri = supertypeinfo.get_type_uri()
     if supertypeuri is None:
         log.warning(
             "EntityFinder.get_collection_uri_subtypes: no type_uri for %s"
             % (type_id, ))
     return self.get_collection_uri_subtypes(supertypeuri, altscope)
Beispiel #13
0
    def get_type_entities(self, type_id, user_permissions, scope):
        """
        Iterate over entities from collection matching the supplied type.

        'scope' is used to determine the extend of data top be included in the listing:
        a value of 'all' means that site-wide entyioties are icnluded in the listing.
        Otherwise only collection entities are included.        
        """
        entitytypeinfo = EntityTypeInfo(self._site, self._coll, type_id)
        include_sitedata = (scope == "all")
        for e in entitytypeinfo.enum_entities(user_permissions,
                                              usealtparent=include_sitedata):
            yield e
        return
Beispiel #14
0
    def check_delete_type_values(self, listinfo, entity_id, entity_type, msg):
        """
        Checks for attempt to delete type with existing values

        Returns redirect URI to display error, or None if no error
        """
        if entity_type == "_type":
            typeinfo = EntityTypeInfo(listinfo.collection, entity_id)
            if next(typeinfo.enum_entity_ids(), None) is not None:
                return (
                    # Type has values: redisplay form with error message
                    uri_with_params(listinfo.view.get_request_path(),
                                    listinfo.view.error_params(msg),
                                    listinfo.get_continuation_url_dict()))
        return None
 def setUp(self):
     init_annalist_test_site()
     init_annalist_test_coll()
     self.testsite = Site(TestBaseUri, TestBaseDir)
     self.testcoll = Collection(self.testsite, "testcoll")
     # Populate collection with linked record types, views and lists
     self.testsrc_type = RecordType.create(self.testcoll, "testsrc_type",
                                           testsrc_type_create_values)
     self.testtgt_type = RecordType.create(self.testcoll, "testtgt_type",
                                           testtgt_type_create_values)
     self.testsrc_view = RecordView.create(self.testcoll, "testsrc_view",
                                           testsrc_view_create_values)
     self.testtgt_view = RecordView.create(self.testcoll, "testtgt_view",
                                           testtgt_view_create_values)
     self.testsrc_list = RecordList.create(self.testcoll, "testsrc_list",
                                           testsrc_list_create_values)
     self.testtgt_list = RecordList.create(self.testcoll, "testtgt_list",
                                           testtgt_list_create_values)
     self.testtgtref_field = RecordField.create(
         self.testcoll, "testtgtref_field", testtgtref_field_create_values)
     self.no_options = [FieldChoice('', label="(no options)")]
     self.tgt_options = ([
         FieldChoice("testtgt_type/" + v,
                     label="testtgt_entity %s label" % v,
                     link=entity_url("testcoll", "testtgt_type", v))
         for v in ["testtgt1", "testtgt2"]
     ])
     # Create data records for testing:
     self.testtgt_type_info = EntityTypeInfo(self.testcoll,
                                             "testtgt_type",
                                             create_typedata=True)
     self.testsrc_type_info = EntityTypeInfo(self.testcoll,
                                             "testsrc_type",
                                             create_typedata=True)
     for tgt_id in ("testtgt1", "testtgt2"):
         self.testtgt_type_info.create_entity(
             tgt_id, testtgt_entity_create_values(tgt_id))
     for src_id, tgt_ref in (("testsrc1", "testtgt1"), ("testsrc2",
                                                        "testtgt2")):
         self.testsrc_type_info.create_entity(
             src_id, testsrc_entity_create_values(src_id, tgt_ref))
     # Login and permissions
     create_test_user(self.testcoll, "testuser", "testpassword")
     self.client = Client(HTTP_HOST=TestHost)
     loggedin = self.client.login(username="******",
                                  password="******")
     self.assertTrue(loggedin)
     return
 def get_collection_uri_subtypes(self, type_uri, altscope=None):
     """
     Returns a iterator of `entitytypeinfo` objects for all subtypes
     of the supplied type in the current collection, including the 
     identified type itself.
     """
     # log.info(
     #     "@@ EntityFinder.get_collection_uri_subtypes: type_uri %s, altscope=%s"%
     #     (type_uri, altscope)
     #     )
     if type_uri is not None:
         for tid in self.get_collection_type_ids(altscope):
             tinfo = EntityTypeInfo(self._coll, tid)
             if tinfo and (type_uri in tinfo.get_all_type_uris()):
                 yield tinfo
     return
Beispiel #17
0
 def get_collection_uri_subtypes(self, type_uri, altscope=None):
     """
     Returns a iterator of `entitytypeinfo` objects for all subtypes
     of the supplied type in the current collection, including the 
     identified type itself.
     """
     # log.info(
     #     "@@ EntityFinder.get_collection_uri_subtypes: type_uri %s, altscope=%s"%
     #     (type_uri, altscope)
     #     )
     if type_uri is not None:
         for tid in self.get_collection_type_ids(altscope):
             tinfo = EntityTypeInfo(self._coll, tid)
             if tinfo and (type_uri in tinfo.get_all_type_uris()):
                 yield tinfo
     return 
Beispiel #18
0
 def test_save_subproperty_field(self):
     self.create_subproperty_field_view_entity()
     # Post edit form response
     u = entitydata_edit_url("edit",
                             "testcoll",
                             "testtype",
                             entity_id="testentity",
                             view_id="testview")
     f = ({
         'entity_id': "testentity",
         'entity_type': "testtype",
         'orig_id': "testentity",
         'orig_type': "testtype",
         'Test_sup_field': "Updated subproperty value",
         'action': "edit",
         'save': "Save"
     })
     r = self.client.post(u, f)
     self.assertEqual(r.status_code, 302)
     self.assertEqual(r.reason_phrase, "FOUND")
     # Check entity exists,and compare data with expected
     typeinfo = EntityTypeInfo(self.testcoll, "testtype")
     self.assertTrue(
         typeinfo.entityclass.exists(typeinfo.entityparent, "testentity"))
     e = typeinfo.entityclass.load(typeinfo.entityparent, "testentity")
     self.assertEqual(e.get_id(), "testentity")
     # Check superproperty value remains undefined
     self.assertEqual(e.get_values().get("test:superprop_uri", "undefined"),
                      "undefined")
     # Check subproperty has been updated
     v = self.testentity_data.get_values().copy()
     v['test:subprop_uri'] = f['Test_sup_field']
     self.assertDictionaryMatch(e.get_values(), v)
     return
Beispiel #19
0
 def setUp(self):
     self.filepath  = "%s/README.md"%TestBaseDir
     self.fileuri   = "file://"+self.filepath
     self.imagepath = "%s/test-image.jpg"%TestBaseDir
     self.imageuri  = "file://"+self.filepath
     init_annalist_test_site()
     init_annalist_test_coll()
     self.testsite    = Site(TestBaseUri, TestBaseDir)
     self.testcoll    = Collection(self.testsite, "testcoll")
     # Populate collection with record type, view and field
     self.test_ref_type = RecordType.create(
         self.testcoll, "testreftype", test_image_ref_type_create_values
         )
     self.test_ref_view = RecordView.create(
         self.testcoll, "testrefview", test_image_ref_view_create_values
         )
     self.test_ref_field = RecordField.create(
         self.testcoll, "Test_image_ref", test_image_ref_field_create_values
         )
     # Create data records for testing image references:
     self.test_ref_type_info = EntityTypeInfo(
         self.testcoll, "testreftype", create_typedata=True
         )
     self.test_ref_type_info.create_entity("test1", test_ref_entity_create_values(self.imageuri))
     # Login and permissions
     create_test_user(self.testcoll, "testuser", "testpassword")
     self.client = Client(HTTP_HOST=TestHost)
     loggedin = self.client.login(username="******", password="******")
     self.assertTrue(loggedin)
     return
 def test_save_field_alias_target(self):
     # Save BibEntry from Default_view: aliased values should be included
     u = entitydata_edit_url(
         "edit", "testcoll", "BibEntry_type", 
         entity_id="bibentity1", 
         view_id="Default_view"
         )
     f = (
         { 'entity_id':          "bibentity1"
         , 'entity_type':        "BibEntry_type"
         , 'orig_id':            "bibentity1"
         , 'orig_type':          "BibEntry_type"
         , 'Entity_label':       "Updated "+self.bibentity1_data['bib:title']
         , 'Entity_comment':     "Updated "+self.bibentity1_data['bib:note']
         , 'action':             "edit"
         , 'save':               "Save"
         })
     r = self.client.post(u, f)
     self.assertEqual(r.status_code,   302)
     self.assertEqual(r.reason_phrase, "FOUND")
     # Check entity exists,and compare data with expected
     typeinfo = EntityTypeInfo(self.testsite, self.testcoll, "BibEntry_type")
     self.assertTrue(typeinfo.entityclass.exists(typeinfo.entityparent, "bibentity1"))
     e = typeinfo.entityclass.load(typeinfo.entityparent, "bibentity1")
     self.assertEqual(e.get_id(), "bibentity1")
     v = self.bibentity1_data.copy()
     v[RDFS.CURIE.label]   = f['Entity_label']
     v[RDFS.CURIE.comment] = f['Entity_comment']
     self.assertDictionaryMatch(e.get_values(), v)
     return
Beispiel #21
0
    def check_collection_entity(self, entity_id, entity_type, msg):
        """
        Test a supplied entity_id is defined in the current collection,
        returning a URI to display a supplied error message if the test fails.

        NOTE: this function works with the generic base template base_generic.html, which
        is assumed to provide an underlay for the currently viewed page.

        entity_id           entity id that is required to be defined in the current collection.
        entity_type         specified type for entity to delete.
        msg                 message to display if the test fails.

        returns a URI string for use with HttpResponseRedirect to redisplay the 
        current page with the supplied message, or None if entity id is OK.
        """
        # log.info("check_collection_entity: entity_id: %s"%(entity_id))
        # log.info("check_collection_entity: entityparent: %s"%(self.entityparent.get_id()))
        # log.info("check_collection_entity: entityclass: %s"%(self.entityclass))
        redirect_uri = None
        typeinfo = self.entitytypeinfo
        if not typeinfo or typeinfo.get_type_id() != entity_type:
            typeinfo = EntityTypeInfo(self.collection, entity_type)
        if not typeinfo.entityclass.exists(typeinfo.entityparent, entity_id):
            redirect_uri = (uri_with_params(self.view.get_request_path(),
                                            self.view.error_params(msg),
                                            self.get_continuation_url_dict()))
        return redirect_uri
Beispiel #22
0
 def setUp(self):
     self.fileuri = "file://%s/README.md"%TestBaseDir
     init_annalist_test_site()
     init_annalist_test_coll()
     self.testsite    = Site(TestBaseUri, TestBaseDir)
     self.testcoll    = Collection(self.testsite, "testcoll")
     # Populate collection with linked record types, views and lists
     self.test_imp_type = RecordType.create(
         self.testcoll, "testimptype", test_import_type_create_values
         )
     self.test_imp_view = RecordView.create(
         self.testcoll, "testimpview", test_import_view_create_values
         )
     self.test_imp_field = RecordField.create(
         self.testcoll, "Test_import", test_import_field_create_values
         )
     self.test_ref_type = RecordType.create(
         self.testcoll, "testreftype", test_reference_type_create_values
         )
     self.test_ref_view = RecordView.create(
         self.testcoll, "testrefview", test_reference_view_create_values
         )
     self.test_ref_field = RecordField.create(
         self.testcoll, "Test_reference", test_reference_field_create_values
         )
     # Create data records for testing import and references:
     self.test_imp_type_info = EntityTypeInfo(
         self.testcoll, "testimptype", create_typedata=True
         )
     for entity_id in ("test1", "test2"):
         self.test_imp_type_info.create_entity(
             entity_id, test_imp_entity_create_values(entity_id)
             )
     self.test_ref_type_info = EntityTypeInfo(
         self.testcoll, "testreftype", create_typedata=True
         )
     for entity_id in ("test1", "test2"):
         self.test_ref_type_info.create_entity(
             entity_id, test_ref_entity_create_values(entity_id)
             )
     # Login and permissions
     create_test_user(self.testcoll, "testuser", "testpassword")
     self.client = Client(HTTP_HOST=TestHost)
     loggedin = self.client.login(username="******", password="******")
     self.assertTrue(loggedin)
     return
 def setUp(self):
     self.fileuri = "file://%s/README.md"%TestBaseDir
     init_annalist_test_site()
     init_annalist_test_coll()
     self.testsite    = Site(TestBaseUri, TestBaseDir)
     self.testcoll    = Collection(self.testsite, "testcoll")
     # Populate collection with linked record types, views and lists
     self.test_imp_type = RecordType.create(
         self.testcoll, "testimptype", test_import_type_create_values
         )
     self.test_imp_view = RecordView.create(
         self.testcoll, "testimpview", test_import_view_create_values
         )
     self.test_imp_field = RecordField.create(
         self.testcoll, "Test_import", test_import_field_create_values
         )
     self.test_ref_type = RecordType.create(
         self.testcoll, "testreftype", test_reference_type_create_values
         )
     self.test_ref_view = RecordView.create(
         self.testcoll, "testrefview", test_reference_view_create_values
         )
     self.test_ref_field = RecordField.create(
         self.testcoll, "Test_reference", test_reference_field_create_values
         )
     # Create data records for testing import and references:
     self.test_imp_type_info = EntityTypeInfo(
         self.testcoll, "testimptype", create_typedata=True
         )
     for entity_id in ("test1", "test2"):
         self.test_imp_type_info.create_entity(
             entity_id, test_imp_entity_create_values(entity_id)
             )
     self.test_ref_type_info = EntityTypeInfo(
         self.testcoll, "testreftype", create_typedata=True
         )
     for entity_id in ("test1", "test2"):
         self.test_ref_type_info.create_entity(
             entity_id, test_ref_entity_create_values(entity_id)
             )
     # Login and permissions
     create_test_user(self.testcoll, "testuser", "testpassword")
     self.client = Client(HTTP_HOST=TestHost)
     loggedin = self.client.login(username="******", password="******")
     self.assertTrue(loggedin)
     return
    def get_type_entities(self, type_id, user_permissions, altscope):
        """
        Iterate over entities from collection matching the supplied type.

        'altscope' is used to determine the extent of data to be included in the listing:
        a value of 'all' means that site-wide entyities are icnluded in the listing.
        Otherwise only collection entities are included.        
        """
        #@@
        # log.info("get_type_entities: type_id %s"%type_id)
        #@@
        entitytypeinfo = EntityTypeInfo(self._coll, type_id)
        for e in entitytypeinfo.enum_entities_with_implied_values(
                user_permissions, altscope=altscope):
            if e.get_id() != "_initial_values":
                yield e
        return
Beispiel #25
0
    def get_type_entities(self, type_id, user_permissions, altscope):
        """
        Iterate over entities from collection matching the supplied type.

        'altscope' is used to determine the extent of data to be included in the listing:
        a value of 'all' means that site-wide entyities are icnluded in the listing.
        Otherwise only collection entities are included.        
        """
        #@@
        # log.info("get_type_entities: type_id %s"%type_id)
        #@@
        entitytypeinfo = EntityTypeInfo(self._coll, type_id)
        for e in entitytypeinfo.enum_entities_with_implied_values(
                user_permissions, altscope=altscope
                ):
            if e.get_id() != "_initial_values":
                yield e
        return
Beispiel #26
0
 def get_type_info(self, type_id):
     """
     Check type identifier, and get reference to type information object.
     """
     if not self.http_response:
         assert ((self.site and self.collection) is not None)
         if type_id:
             self.type_id = type_id
             self.entitytypeinfo = EntityTypeInfo(self.collection, type_id)
             if not self.entitytypeinfo.recordtype:
                 # log.warning("DisplayInfo.get_type_data: RecordType %s not found"%type_id)
                 self.http_response = self.view.error(
                     dict(self.view.error404values(),
                          message=message.RECORD_TYPE_NOT_EXISTS %
                          ({
                              'id': type_id,
                              'coll_id': self.coll_id
                          })))
     return self.http_response
Beispiel #27
0
 def get_targetvals(self):
     """
     If field description is a reference to a target type entity or field, 
     return a copy of the referenced target entity, otherwise None.
     """
     # log.debug("@@ bound_field.get_targetvals: field_description %r"%(self._field_description,))
     target_type = self._field_description.get('field_ref_type',  None)
     target_key  = self._field_description.get('field_ref_field', None)
     log.debug("bound_field.get_targetvals: target_type '%s', target_key '%s'"%(target_type, target_key))
     if self._targetvals is None:
         if target_type:
             # Extract entity_id and type_id; default to type id from field descr
             field_val = self.get_field_value()
             log.debug("field_val: %s"%(field_val,))
             type_id, entity_id = split_type_entity_id(self.get_field_value(), target_type)
             log.debug("bound_field.get_targetvals: type_id %s, entity_id %s"%(type_id, entity_id))
             # Get entity type info
             coll     = self._field_description._collection
             typeinfo = EntityTypeInfo(coll, type_id)
             # Check access permission, assuming user has "VIEW" permission in collection
             # This is primarily to prevent a loophole for accessing user account details
             #@@TODO: pass actual user permissions in to bound_field or field description 
             #        or extra params
             user_permissions    = ["VIEW"]
             req_permissions_map = typeinfo.get_entity_permissions_map(entity_id)
             req_permissions     = list(set( req_permissions_map[a] for a in ["view", "list"] ))
             if all([ p in user_permissions for p in req_permissions]):
                 if entity_id is None or entity_id == "":
                     raise TargetIdNotFound_Error(value=(typeinfo.type_id, self._field_description["field_name"]))
                 targetentity = typeinfo.get_entity(entity_id)
                 if targetentity is None:
                     raise TargetEntityNotFound_Error(value=(target_type, entity_id))
                 targetentity = typeinfo.get_entity_implied_values(targetentity)
                 self._targetvals = get_entity_values(typeinfo, targetentity)
                 log.debug("bound_field.get_targetvals: %r"%(self._targetvals,))
             else:
                 log.warning(
                     "bound_field.get_targetvals: target value type %s requires %r permissions"%
                     (target_type, req_permissions)
                     )
     log.debug("bound_field.get_targetvals: targetvals %r"%(self._targetvals,))
     return self._targetvals
Beispiel #28
0
    def check_delete_type_values(self, listinfo, entity_id, entity_type, msg):
        """
        Checks for attempt to delete type with existing values

        Returns redirect URI to display error, or None if no error
        """
        if entity_type == "_type":
            typeinfo = EntityTypeInfo(
                listinfo.collection, entity_id
                )
            if next(typeinfo.enum_entity_ids(), None) is not None:
                return (
                    # Type has values: redisplay form with error message
                    uri_with_params(
                        listinfo.view.get_request_path(),
                        listinfo.view.error_params(msg),
                        listinfo.get_continuation_url_dict()
                        )
                    )
        return None
Beispiel #29
0
 def get_collection_subtype_ids(self, supertype_id, altscope):
     """
     Returns a iterator of type ids for all subtypes of the supplied type 
     accessible in the indicated scope from the current collection, including 
     the identified type itself.
     """
     if not valid_id(supertype_id):
         log.warning("EntityFinder.get_collection_subtype_ids: invalid type_id %s"%(supertype_id,))
         return
     supertype_info = EntityTypeInfo(self._coll, supertype_id)
     supertype_uri  = supertype_info.get_type_uri()
     if supertype_uri is not None:
         for try_subtype_id in self.get_collection_type_ids(altscope):
             try_subtype = self._coll.cache_get_type(try_subtype_id)
             if try_subtype:
                 try_subtype_uri = try_subtype.get_uri()
                 if ( ( supertype_uri == try_subtype_uri ) or
                      ( supertype_uri in self._coll.cache_get_supertype_uris(try_subtype_uri) ) ):
                     yield try_subtype_id
     else:
         log.warning("EntityFinder.get_collection_subtype_ids: no type_uri for %s"%(supertype_id,))
Beispiel #30
0
    def get_subtype_entities(self, type_id, user_permissions, altscope):
        """
        Iterate over entities from collection that are of the indicated type
        or any of its subtypes.

        'altscope' is used to determine the extent of data to be included in the listing:
        a value of 'all' means that site-wide entities are included in the listing.
        Otherwise only collection entities are included.        
        """
        for subtype_id in self.get_collection_subtype_ids(type_id, "all"):
            subtype_info = EntityTypeInfo(self._coll, subtype_id)
            es = subtype_info.enum_entities_with_implied_values(
                user_permissions, altscope=altscope)
            #@@
            # es = list(es) #@@ Force strict eval
            # log.info("get_subtype_entities: %r"%([e.get_id() for e in es],))
            #@@
            for e in es:
                if e.get_id() != layout.INITIAL_VALUES_ID:
                    yield e
        return
Beispiel #31
0
    def get_subtype_entities(self, type_id, user_permissions, altscope):
        """
        Iterate over entities from collection that are of the indicated type
        or any of its subtypes.

        'altscope' is used to determine the extent of data to be included in the listing:
        a value of 'all' means that site-wide entities are included in the listing.
        Otherwise only collection entities are included.        
        """
        for subtype_id in self.get_collection_subtype_ids(type_id, "all"):
            subtype_info = EntityTypeInfo(self._coll, subtype_id)
            es = subtype_info.enum_entities_with_implied_values(
                    user_permissions, altscope=altscope
                    )
            #@@
            # es = list(es) #@@ Force strict eval
            # log.info("get_subtype_entities: %r"%([e.get_id() for e in es],))
            #@@
            for e in es:
                if e.get_id() != layout.INITIAL_VALUES_ID:
                    yield e
        return
Beispiel #32
0
def copy_coll_data(src_coll, tgt_coll):
    """
    Copy collection data from specified source to target collection.

    returns     list of error messages; an empty list indicates success.
    """
    log.info("Copying collection '%s' to '%s'" %
             (src_coll.get_id(), tgt_coll.get_id()))
    msgs = []
    entityfinder = EntityFinder(src_coll)
    for e in entityfinder.get_entities():
        entity_id = e.get_id()
        typeinfo = EntityTypeInfo(tgt_coll,
                                  e.get_type_id(),
                                  create_typedata=True)
        new_entity = typeinfo.create_entity(entity_id, e.get_values())
        if not typeinfo.entity_exists(entity_id):
            msg = ("Collection.copy_coll_data: Failed to create entity %s/%s" %
                   (typeinfo.type_id, entity_id))
            log.warning(msg)
            msgs.append(msg)
        msgs += new_entity._copy_entity_files(e)
    return msgs
Beispiel #33
0
 def test_save_subproperty_list(self):
     self.create_subproperty_field_view_entity()
     self.create_subproperty_list_field_view_entity()
     # Post edit form response
     u = entitydata_edit_url("edit",
                             "testcoll",
                             "testtype",
                             entity_id="testlistentity",
                             view_id="testlistview")
     f = ({
         'entity_id': "testlistentity",
         'entity_type': "testtype",
         'orig_id': "testlistentity",
         'orig_type': "testtype",
         'Test_sup_list__0__Test_sup_field': "Updated subprop 1",
         'Test_sup_list__1__Test_sup_field': "Updated subprop 2",
         'action': "edit",
         'save': "Save"
     })
     r = self.client.post(u, f)
     self.assertEqual(r.status_code, 302)
     self.assertEqual(r.reason_phrase, "FOUND")
     # Check entity exists,and compare data with expected
     typeinfo = EntityTypeInfo(self.testcoll, "testtype")
     self.assertTrue(
         typeinfo.entityclass.exists(typeinfo.entityparent,
                                     "testlistentity"))
     e = typeinfo.entityclass.load(typeinfo.entityparent, "testlistentity")
     # print("@@@@ e: "+repr(e.get_values()))
     self.assertEqual(e.get_id(), "testlistentity")
     # Check superproperty value remains undefined
     self.assertEqual(e.get_values().get("test:superprop_uri", "undefined"),
                      "undefined")
     # Check subproperty has been updated
     v = self.testlistentity_data.get_values().copy()
     #@@NOTE:
     #   With reference to 'test:superprop_uri' below:
     #   It is a known restriction that subproperties used within repeating field
     #   groups are not propagated.  See RepeatValuesMap.map_form_to_entity.
     #@@
     v['test:subprop_list_uri'] = ([{
         "test:superprop_uri":
         "Updated subprop 1"
     }, {
         "test:superprop_uri":
         "Updated subprop 2"
     }])
     self.assertDictionaryMatch(e.get_values(), v)
     return
 def _check_entity_data_values(self, 
     entity_id, type_id="testtype", update="Entity", 
     comment2="Comment field 2",
     comment3="Comment field 3"
     ):
     "Helper function checks content of form-updated record type entry with supplied entity_id"
     # log.info("_check_entity_data_values: type_id %s, entity_id %s"%(type_id, entity_id))
     typeinfo = EntityTypeInfo(self.testcoll, type_id)
     self.assertTrue(typeinfo.entityclass.exists(typeinfo.entityparent, entity_id))
     e = typeinfo.entityclass.load(typeinfo.entityparent, entity_id)
     self.assertEqual(e.get_id(), entity_id)
     v = entitydata_values(entity_id, type_id=type_id, update=update)
     v = entitydata_values_add_field(v, "rdfs:comment", 2, comment2)
     v = entitydata_values_add_field(v, "rdfs:comment_alt", 3, comment3)
     self.assertDictionaryMatch(e.get_values(), v)
     return e
Beispiel #35
0
 def _check_entity_data_values(self, entity_id, type_id="testtype", update="Entity", update_dict=None):
     "Helper function checks content of form-updated record type entry with supplied entity_id"
     # log.info("_check_entity_data_values: type_id %s, entity_id %s"%(type_id, entity_id))
     typeinfo = EntityTypeInfo(self.testsite, self.testcoll, type_id)
     self.assertTrue(typeinfo.entityclass.exists(typeinfo.entityparent, entity_id))
     e = typeinfo.entityclass.load(typeinfo.entityparent, entity_id)
     self.assertEqual(e.get_id(), entity_id)
     self.assertEqual(e.get_view_url(""), TestHostUri + entity_url("testcoll", type_id, entity_id))
     v = entitydata_values(entity_id, type_id=type_id, update=update)
     if update_dict:
         v.update(update_dict)
         for k in update_dict:
             if update_dict[k] is None:
                 v.pop(k, None)
     # log.info(e.get_values())
     self.assertDictionaryMatch(e.get_values(), v)
     return e
Beispiel #36
0
 def get_type_info(self, type_id):
     """
     Check type identifier, and get reference to type information object.
     """
     if not self.http_response:
         assert ((self.site and self.collection) is not None)
         if type_id:
             self.type_id        = type_id
             self.entitytypeinfo = EntityTypeInfo(self.collection, type_id)
             if not self.entitytypeinfo.recordtype:
                 # log.warning("DisplayInfo.get_type_data: RecordType %s not found"%type_id)
                 self.http_response = self.view.error(
                     dict(self.view.error404values(),
                         message=message.RECORD_TYPE_NOT_EXISTS%(
                             {'id': type_id, 'coll_id': self.coll_id})
                         )
                     )
     return self.http_response
Beispiel #37
0
def get_entity_values(displayinfo, entity, entity_id=None):
    """
    Returns an entity values dictionary for a supplied entity, suitable for
    use with a bound_field object.
    """
    if not entity_id:
        entity_id = entity.get_id()
    type_id = entity.get_type_id()
    entityvals = entity.get_values().copy()
    entityvals['entity_id'] = entity_id
    entityvals['entity_link'] = entity.get_view_url_path()
    # log.info("type_id %s"%(type_id))
    entityvals['entity_type_id'] = type_id
    typeinfo = EntityTypeInfo(displayinfo.site, displayinfo.collection,
                              type_id)
    if typeinfo.recordtype:
        entityvals['entity_type_link'] = typeinfo.recordtype.get_view_url_path(
        )
        # @@other type-related info; e.g., aliases - populate
    return entityvals
 def test_save_field_alias_source(self):
     # Save BibEntry from BibEntry_view: aliases should not be included
     u = entitydata_edit_url("edit",
                             "testcoll",
                             "BibEntry_type",
                             entity_id="bibentity1",
                             view_id="BibEntry_view")
     f = ({
         'entity_id': "bibentity1",
         'entity_type': "BibEntry_type",
         'orig_id': "bibentity1",
         'orig_type': "BibEntry_type",
         'Bib_type': "article",
         'Bib_title': "Updated " + self.bibentity1_data['bib:title'],
         'Bib_year': "2014",
         'Bib_month': "09",
         'Bib_note': "Updated " + self.bibentity1_data['bib:note'],
         'action': "edit",
         'save': "Save"
     })
     r = self.client.post(u, f)
     self.assertEqual(r.status_code, 302)
     self.assertEqual(r.reason_phrase, "FOUND")
     # Check entity exists,and compare data with expected
     typeinfo = EntityTypeInfo(self.testcoll, "BibEntry_type")
     self.assertTrue(
         typeinfo.entityclass.exists(typeinfo.entityparent, "bibentity1"))
     e = typeinfo.entityclass.load(typeinfo.entityparent, "bibentity1")
     self.assertEqual(e.get_id(), "bibentity1")
     v = self.bibentity1_data.copy()
     v['bib:title'] = f['Bib_title']
     v['bib:note'] = f['Bib_note']
     del v['bib:author']
     self.assertDictionaryMatch(e.get_values(), v)
     self.assertEqual(e.get_values().get(RDFS.CURIE.label, None), None)
     # Comment defaults from aliased label value
     self.assertEqual(e.get_values().get(RDFS.CURIE.comment, None),
                      f['Bib_title'])
     return
Beispiel #39
0
class ImageReferenceTest(AnnalistTestCase):
    """
    Tests image URI reference
    """

    def setUp(self):
        self.filepath  = "%s/README.md"%TestBaseDir
        self.fileuri   = "file://"+self.filepath
        self.imagepath = "%s/test-image.jpg"%TestBaseDir
        self.imageuri  = "file://"+self.filepath
        init_annalist_test_site()
        init_annalist_test_coll()
        self.testsite    = Site(TestBaseUri, TestBaseDir)
        self.testcoll    = Collection(self.testsite, "testcoll")
        # Populate collection with record type, view and field
        self.test_ref_type = RecordType.create(
            self.testcoll, "testreftype", test_image_ref_type_create_values
            )
        self.test_ref_view = RecordView.create(
            self.testcoll, "testrefview", test_image_ref_view_create_values
            )
        self.test_ref_field = RecordField.create(
            self.testcoll, "Test_image_ref", test_image_ref_field_create_values
            )
        # Create data records for testing image references:
        self.test_ref_type_info = EntityTypeInfo(
            self.testcoll, "testreftype", create_typedata=True
            )
        self.test_ref_type_info.create_entity("test1", test_ref_entity_create_values(self.imageuri))
        # Login and permissions
        create_test_user(self.testcoll, "testuser", "testpassword")
        self.client = Client(HTTP_HOST=TestHost)
        loggedin = self.client.login(username="******", password="******")
        self.assertTrue(loggedin)
        return

    def tearDown(self):
        # resetSitedata(scope="collections")
        return

    @classmethod
    def setUpClass(cls):
        super(ImageReferenceTest, cls).setUpClass()
        return

    @classmethod
    def tearDownClass(cls):
        super(ImageReferenceTest, cls).tearDownClass()
        resetSitedata(scope="collections")
        return

    # Utility functions

    # Tests

    def test_reference_image(self):

        # Display resource with image reference
        u = entitydata_edit_url("view", "testcoll", "testreftype", entity_id="test1", view_id="testrefview")
        r = self.client.get(u)
        self.assertEqual(r.status_code,   200)
        self.assertEqual(r.reason_phrase, "OK")
        # Check display context
        self.assertEqual(len(r.context['fields']), 4)
        f0 = context_view_field(r.context, 0, 0)
        self.assertEqual(f0.field_id,           "Entity_id")
        self.assertEqual(f0.field_value,        "test1")
        f1 = context_view_field(r.context, 1, 0)
        self.assertEqual(f1.field_id,           "Entity_label")
        self.assertEqual(f1.field_value,        "test_ref_image label")
        f2 = context_view_field(r.context, 2, 0)
        self.assertEqual(f2.field_id,           "Entity_comment")
        self.assertEqual(f2.field_value,        "test_ref_image comment")
        f3 = context_view_field(r.context, 3, 0)
        basepath = TestBasePath + "/c/testcoll/d/testreftype/"
        # print "\n*****\n"+repr(f3)+"\n*****\n"
        self.assertEqual(f3.field_id,           "Test_image_ref")
        self.assertEqual(f3.field_value,        self.imageuri)
        self.assertEqual(f3.field_value_link,   None)
        self.assertEqual(f3.target_value,       self.imageuri)
        self.assertEqual(f3.target_value_link,  self.imageuri)
        # Check for rendered image link
        # log.info(r.content)
        field_details = (
            { "basepath":   TestBasePath
            , "coll_id":    "testcoll"
            , "type_id":    "testupltype"
            , "entity_id":  "test1"
            , "image_uri":  self.imageuri
            , "field_id":   "ref_image"
            , "tooltip":    "" # 'title="%s"'%r.context['fields'][i].field_help
            })
        img_element = """
            <div class="small-12 columns" %(tooltip)s>
              <div class="row view-value-row">
                <div class="view-label small-12 medium-2 columns">
                  <span>test_image_ref_field label</span>
                </div>
                <div class="view-value small-12 medium-10 columns">
                  <a href="%(image_uri)s" target="_blank">
                    <img src="%(image_uri)s"
                         alt="Image at '%(image_uri)s'" />
                  </a>
                </div>
              </div>
            </div>
            """%field_details
        self.assertContains(r, img_element, html=True)
        return
Beispiel #40
0
class DataMigrationTest(AnnalistTestCase):
    """
    Tests for entity data migration
    """
    def setUp(self):
        init_annalist_test_site()
        init_annalist_test_coll()
        self.testsite = Site(TestBaseUri, TestBaseDir)
        self.testcoll = Collection(self.testsite, "testcoll")
        # Populate collection with linked record types, views and lists
        self.test_supertype_type = RecordType.create(
            self.testcoll, "test_supertype_type",
            test_supertype_type_create_values)
        self.test_subtype_type = RecordType.create(
            self.testcoll, "test_subtype_type",
            test_subtype_type_create_values)
        self.no_options = [FieldChoice('', label="(no options)")]
        # Create type and data records for testing:
        self.test_supertype_type_info = EntityTypeInfo(self.testcoll,
                                                       "test_supertype_type",
                                                       create_typedata=True)
        self.test_subtype_type_info = EntityTypeInfo(self.testcoll,
                                                     "test_subtype_type",
                                                     create_typedata=True)
        for entity_id in ("test_subtype_entity", ):
            self.test_subtype_type_info.create_entity(
                entity_id, test_subtype_entity_create_values(entity_id))
        # Login and permissions
        create_test_user(self.testcoll, "testuser", "testpassword")
        self.client = Client(HTTP_HOST=TestHost)
        loggedin = self.client.login(username="******",
                                     password="******")
        self.assertTrue(loggedin)
        return

    def tearDown(self):
        resetSitedata(scope="collections")
        return

    @classmethod
    def tearDownClass(cls):
        resetSitedata(scope="all")
        return

    # Utility functions

    def check_subtype_data(self, coll_id, type_id, entity_id, entity_vals):
        expected_types = ["annal:EntityData", "test:%s" % type_id]
        expected_vals = ({
            "@id":
            "%s/%s" % (type_id, entity_id),
            "@type":
            expected_types,
            "rdfs:label":
            "test_subtype_entity %s label" % (entity_id, ),
            "rdfs:comment":
            "test_subtype_entity %s comment" % (entity_id, )
        })
        expected_vals.update(entity_vals)
        self.check_entity_values(type_id,
                                 entity_id,
                                 check_values=expected_vals)
        return

    # Tests

    def test_subtype_supertype_references(self):
        coll_id = "testcoll"
        type_id = "test_subtype_type"
        entity_id = "test_subtype_entity"
        self.check_subtype_data(
            coll_id, type_id, entity_id,
            {'@type': ["test:test_subtype_type", "annal:EntityData"]})
        # Update subtype definition to include supertype reference
        test_subtype_meta = self.test_subtype_type.get_values()
        test_subtype_meta[ANNAL.CURIE.supertype_uri] = [{
            "@id":
            "test:test_supertype_type"
        }]
        self.testcoll.add_type(type_id, test_subtype_meta)
        # Test migration of updated type information to data
        migrate_coll_data(self.testcoll)
        self.check_subtype_data(
            coll_id, type_id, entity_id, {
                '@type': [
                    'test:test_subtype_type', 'test:test_supertype_type',
                    'annal:EntityData'
                ]
            })
        return

    def test_wrong_type_uri_references(self):
        coll_id = "testcoll"
        type_id = "test_subtype_type"
        entity_id = "test_subtype_entity"
        # Create subtype record with wrong type URI
        subtype_entity_values = test_subtype_entity_create_values(entity_id)
        entity = self.test_subtype_type_info.create_entity(
            entity_id, subtype_entity_values)
        entity[ANNAL.CURIE.type] = "test:wrong_type_uri"
        entity._save()
        # Test subtype entity created
        self.check_subtype_data(
            coll_id, type_id, entity_id, {
                '@type': ['test:test_subtype_type', 'annal:EntityData'],
                'annal:type': "test:wrong_type_uri"
            })
        # Update subtype definition to include supertype reference
        test_subtype_meta = self.test_subtype_type.get_values()
        test_subtype_meta[ANNAL.CURIE.supertype_uri] = [{
            "@id":
            "test:test_supertype_type"
        }]
        self.testcoll.add_type(type_id, test_subtype_meta)
        # Test migration of updated type information to data
        migrate_coll_data(self.testcoll)
        self.check_subtype_data(
            coll_id, type_id, entity_id, {
                '@type': [
                    'test:test_subtype_type', 'test:test_supertype_type',
                    'annal:EntityData'
                ],
                'annal:type':
                "test:test_subtype_type"
            })
        return

    def test_field_fieldgroup_references(self):
        """
        Test migration of field group references in field definitions 
        """
        # Create field group
        self.test_group = RecordGroup_migration.create(
            self.testcoll, test_group_id, test_group_create_values)
        # Create field definition referencing field group
        self.test_field = RecordField.create(self.testcoll, test_field_id,
                                             test_field_group_create_values)
        # Apply migration to collection
        migrate_coll_data(self.testcoll)
        # Read field definition and check for inline field list
        field_data = self.check_entity_values(
            "_field",
            test_field_id,
            check_values=test_field_group_migrated_values)
        self.assertNotIn("annal:group_ref", field_data)
        self.check_entity_does_not_exist("_group", test_group_id)
        return

    def test_field_comment_tooltip(self):
        """
        Test migration of field without tooltip
        """
        # Create field definition
        self.test_field = RecordField.create(self.testcoll, test_field_id,
                                             test_field_tooltip_create_values)
        # Apply migration to collection
        migrate_coll_data(self.testcoll)
        # Read field definition and check for inline field list
        field_data = self.check_entity_values(
            "_field",
            test_field_id,
            check_values=test_field_tooltip_migrated_values)
        return

    def test_migrate_view_fields(self):
        """
        Test migration of view fields
        """
        self.test_view = RecordView.create(self.testcoll, test_view_id,
                                           test_view_create_values)
        migrate_coll_data(self.testcoll)
        # Read field definition and check for inline field list
        view_data = self.check_entity_values(
            "_view", test_view_id, check_values=test_view_migrated_values)
        return

    def test_migrate_list_fields(self):
        """
        Test migration of list fields
        """
        self.test_list = RecordList.create(self.testcoll, test_list_id,
                                           test_list_create_values)
        migrate_coll_data(self.testcoll)
        # Read field definition and check for inline field list
        view_data = self.check_entity_values(
            "_list", test_list_id, check_values=test_list_migrated_values)
        return
Beispiel #41
0
class DisplayInfo(object):
    """
    This class collects and organizes common information needed to process various
    kinds of view requests.

    A number of methods are provided that collect different kinds of information,
    allowing the calling method flexibility over what information is actually 
    gathered.  All methods follow a common pattern loosely modeled on an error
    monad, which uses a Django HttpResponse object to record the first problem
    found in the information gathering chain.  Once an error has been detected, 
    subsequent methods do not update the display information, but simply return
    the error response object.

    The information gathering methods do have some dependencies and must be
    invoked in a sequence that ensures the dependencies are satisfied.

    view                is the view object that is being rendered.  This is an instance
                        of a class derived from `AnnalistGenericView`, which in turn is 
                        derived from `django.views.generic.View`.
    action              is the user action for which the form has ben invoked
                        (e.g. "new", "copy", "edit", etc.)
    request_dict        is a dictionary of request parameters
                        For GET requests, this derives from the URI query parameters; 
                        for POST requests it is derived from the submitted form data.
    default_continue    is a default continuation URI to be used when returning from the 
                        current view without an explciitly specified continuation in
                        the request.
    """

    def __init__(self, view, action, request_dict, default_continue):
        self.view               = view
        self.action             = action
        self.is_saved           = False
        self.request_dict       = request_dict
        self.continuation_url   = request_dict.get('continuation_url', None)
        self.default_continue   = default_continue
        # Type/Entity ids from form
        self.orig_type_id       = None
        self.orig_entity_id     = None
        self.curr_type_id       = None
        self.curr_entity_id     = None
        # Type-specific messages
        self.type_messages      = None
        # Default no permissions:
        self.authorizations     = dict([(k, False) for k in authorization_map])
        self.reqhost            = None
        self.site               = None
        self.sitedata           = None
        self.coll_id            = None
        self.collection         = None
        self.coll_perms         = None  # Collection used for permissions checking
        self.type_id            = None
        self.entitytypeinfo     = None
        self.list_id            = None
        self.recordlist         = None
        self.view_id            = None
        self.recordview         = None
        self.entitydata         = None
        self.http_response      = None
        return

    def set_type_entity_id(self,
        orig_type_id=None, orig_entity_id=None,
        curr_type_id=None, curr_entity_id=None
        ):
        """
        Save type and entity ids from form
        """
        self.orig_type_id       = EntityIdValueMapper.decode(orig_type_id)
        self.orig_entity_id     = EntityIdValueMapper.decode(orig_entity_id)
        self.curr_type_id       = EntityIdValueMapper.decode(curr_type_id)
        self.curr_entity_id     = EntityIdValueMapper.decode(curr_entity_id)
        return self.http_response

    def set_messages(self, messages):
        """
        Save type-specific messages for later reporting
        """
        self.type_messages      = messages
        return self.http_response

    def get_site_info(self, reqhost):
        """
        Get site information: site entity object and a copy of the site description data.
        Also saves a copy of the host name to which the current request was directed.
        """
        if not self.http_response:
            self.reqhost        = reqhost
            self.site           = self.view.site(host=reqhost)
            self.sitedata       = self.view.site_data()
        return self.http_response

    def get_coll_info(self, coll_id):
        """
        Check collection identifier, and get reference to collection object.
        """
        assert (self.site is not None)
        if not self.http_response:
            if not Collection.exists(self.site, coll_id):
                self.http_response = self.view.error(
                    dict(self.view.error404values(),
                        message=message.COLLECTION_NOT_EXISTS%{'id': coll_id}
                        )
                    )
            else:
                self.coll_id    = coll_id
                #@@TODO: try with altscope="site"?
                self.collection = Collection.load(self.site, coll_id, altscope="all")
                self.coll_perms = self.collection
                ver = self.collection.get(ANNAL.CURIE.software_version, None) or "0.0.0"
                if LooseVersion(ver) > LooseVersion(annalist.__version__):
                    self.http_response = self.view.error(
                        dict(self.view.error500values(),
                            message=message.COLLECTION_NEWER_VERSION%{'id': coll_id, 'ver': ver}
                            )
                        )
        return self.http_response

    def update_coll_version(self):
        """
        Called when an entity has been updatred to also update the data version 
        associated with the collection if it was previously created by an older 
        version of Annalist.
        """
        assert (self.collection is not None)
        if not self.http_response:
            ver = self.collection.get(ANNAL.CURIE.software_version, None) or "0.0.0"
            if LooseVersion(ver) < LooseVersion(annalist.__version_data__):
                self.collection[ANNAL.CURIE.software_version] = annalist.__version_data__
                self.collection._save()
        return

    def saved(self, is_saved=None):
        """
        Make note that current entity has been saved, and/or return saved status
        """
        if is_saved is not None:
            self.is_saved = is_saved
        return self.is_saved

    def get_type_info(self, type_id):
        """
        Check type identifier, and get reference to type information object.
        """
        if not self.http_response:
            assert ((self.site and self.collection) is not None)
            if type_id:
                self.type_id        = type_id
                self.entitytypeinfo = EntityTypeInfo(self.collection, type_id)
                if not self.entitytypeinfo.recordtype:
                    # log.warning("DisplayInfo.get_type_data: RecordType %s not found"%type_id)
                    self.http_response = self.view.error(
                        dict(self.view.error404values(),
                            message=message.RECORD_TYPE_NOT_EXISTS%(
                                {'id': type_id, 'coll_id': self.coll_id})
                            )
                        )
        return self.http_response

    def get_list_info(self, list_id):
        """
        Retrieve list definition to use for display
        """
        if not self.http_response:
            assert ((self.site and self.collection) is not None)
            assert list_id
            # log.debug(
            #     "DisplayInfo.get_list_info: collection.get_alt_entities %r"%
            #     [ c.get_id() for c in  self.collection.get_alt_entities(altscope="all") ]
            #     )
            if not RecordList.exists(self.collection, list_id, altscope="all"):
                log.warning("DisplayInfo.get_list_info: RecordList %s not found"%list_id)
                self.http_response = self.view.error(
                    dict(self.view.error404values(),
                        message=message.RECORD_LIST_NOT_EXISTS%(
                            {'id': list_id, 'coll_id': self.coll_id})
                        )
                    )
            else:
                self.list_id    = list_id
                self.recordlist = RecordList.load(self.collection, list_id, altscope="all")
                if "@error" in self.recordlist:
                    self.http_response = self.view.error(
                        dict(self.view.error500values(),
                            message=message.RECORD_LIST_LOAD_ERROR%(
                                { 'id':       list_id
                                , 'file':     self.recordlist["@error"]
                                , 'message':  self.recordlist["@message"]
                                })
                            )
                        )
                elif self.type_id is None and self.entitytypeinfo is None:
                    self.get_type_info(
                        extract_entity_id(self.recordlist[ANNAL.CURIE.default_type])
                        )
                # log.debug("DisplayInfo.get_list_info: %r"%(self.recordlist.get_values()))
        return self.http_response

    def get_view_info(self, view_id):
        """
        Retrieve view definition to use for display
        """
        if not self.http_response:
            assert ((self.site and self.collection) is not None)
            if not RecordView.exists(self.collection, view_id, altscope="all"):
                log.warning("DisplayInfo.get_view_info: RecordView %s not found"%view_id)
                log.warning("Collection: %r"%(self.collection))
                log.warning("Collection._altparent: %r"%(self.collection._altparent))
                # log.warning("\n".join(traceback.format_stack()))
                self.http_response = self.view.error(
                    dict(self.view.error404values(),
                        message=message.RECORD_VIEW_NOT_EXISTS%(
                            {'id': view_id, 'coll_id': self.coll_id})
                        )
                    )
            else:
                self.view_id    = view_id
                self.recordview = RecordView.load(self.collection, view_id, altscope="all")
                if "@error" in self.recordview:
                    self.http_response = self.view.error(
                        dict(self.view.error500values(),
                            message=message.RECORD_VIEW_LOAD_ERROR%(
                                { 'id':       list_id
                                , 'file':     self.recordview["@error"]
                                , 'message':  self.recordview["@message"]
                                })
                            )
                        )
                # log.debug("DisplayInfo.get_view_info: %r"%(self.recordview.get_values()))
        return self.http_response

    def get_entity_info(self, action, entity_id):
        """
        Set up entity id and info to use for display

        Also handles some special case permissions settings if the entity is a Collection.
        """
        if not self.http_response:
            assert self.entitytypeinfo is not None
            self.src_entity_id  = entity_id
            if action in ["new", "copy"]:
                self.use_entity_id = self.entitytypeinfo.entityclass.allocate_new_id(
                    self.entitytypeinfo.entityparent, base_id=entity_id
                    )
            else:
                self.use_entity_id  = entity_id
            # Special case permissions...
            if self.type_id == "_coll":
                # log.info("DisplayInfo.get_entity_info: access collection data for %s"%entity_id)
                c = Collection.load(self.site, entity_id, altscope="all")
                if c:
                    self.coll_perms = c
        return self.http_response

    def check_authorization(self, action):
        """
        Check authorization.  Return None if all is OK, or HttpResonse object.

        Also, save copy of key authorizations for later rendering.
        """
        if not self.http_response:
            # Save key authorizations for later rendering
            for k in authorization_map:
                for p in authorization_map[k]:
                    self.authorizations[k] = (
                        self.authorizations[k] or 
                        self.view.authorize(p, self.coll_perms) is None
                        )
            # Check requested action
            action = action or "view"
            if self.entitytypeinfo:
                # print "@@ type permissions map, action %s"%action
                permissions_map = self.entitytypeinfo.permissions_map
            else:
                # Use Collection permissions map
                # print "@@ site permissions map, action %s"%action
                permissions_map = SITE_PERMISSIONS
                # raise ValueError("displayinfo.check_authorization without entitytypeinfo")
                # # permissions_map = {}

            # Previously, default permission map was applied in view.form_action_auth if no 
            # type-based map was provided.
            self.http_response = (
                self.http_response or 
                self.view.form_action_auth(action, self.collection, permissions_map)
                )
        return self.http_response

    def report_error(self, message):
        log.error(message)
        if not self.http_response:
            self.http_response = self.view.error(
                dict(self.view.error400values(),
                    message=message
                    )
                )
        return self.http_response

    # Additional support functions for collection view

    def get_default_view(self):
        """
        Return default view_id, type_id and entity_id to display for collection,
        or None for any values not defined.
        """
        return self.collection.get_default_view()

    # Additonal support functions for list views

    def get_type_list_id(self, type_id):
        """
        Return default list_id for listing defined type, or None
        """
        list_id = None
        # print "@@ get_type_list_id type_id %s, list_id %s"%(type_id, list_id)
        if type_id:
            if self.entitytypeinfo.recordtype:
                list_id = extract_entity_id(
                    self.entitytypeinfo.recordtype.get(ANNAL.CURIE.type_list, None)
                    )
            else:
                log.warning("DisplayInfo.get_type_list_id no type data for %s"%(type_id))
        # print "@@ get_type_list_id %s"%list_id
        return list_id

    def get_list_id(self, type_id, list_id):
        """
        Return supplied list_id if defined, otherwise find default list_id for
        entity type or collection (unless an error has been detected).
        """
        # print "@@ get_list_id 1 %s"%list_id
        if not self.http_response:
            list_id = (
                list_id or 
                self.get_type_list_id(type_id) or
                self.collection.get_default_list() or
                ("Default_list" if type_id else "Default_list_all")
                )
            # print "@@ get_list_id 2 %s"%list_id
            if not list_id:
                log.warning("get_list_id: %s, type_id %s"%(list_id, type_id))
            # print "@@ get_list_id 3 %s"%list_id
        return list_id

    def get_list_view_id(self):
        return extract_entity_id(
            self.recordlist.get(ANNAL.CURIE.default_view, None) or "Default_view"
            )

    def get_list_type_id(self):
        return extract_entity_id(
            self.recordlist.get(ANNAL.CURIE.default_type, None) or "Default_type"
            )

    def check_collection_entity(self, entity_id, entity_type, msg):
        """
        Test a supplied entity_id is defined in the current collection,
        returning a URI to display a supplied error message if the test fails.

        NOTE: this function works with the generic base template base_generic.html, which
        is assumed to provide an underlay for the currently viewed page.

        entity_id           entity id that is required to be defined in the current collection.
        entity_type         specified type for entity to delete.
        msg                 message to display if the test fails.

        returns a URI string for use with HttpResponseRedirect to redisplay the 
        current page with the supplied message, or None if entity id is OK.
        """
        # log.info("check_collection_entity: entity_id: %s"%(entity_id))
        # log.info("check_collection_entity: entityparent: %s"%(self.entityparent.get_id()))
        # log.info("check_collection_entity: entityclass: %s"%(self.entityclass))
        redirect_uri = None
        typeinfo     = self.entitytypeinfo
        if not typeinfo or typeinfo.get_type_id() != entity_type:
            typeinfo = EntityTypeInfo(self.collection, entity_type)
        if not typeinfo.entityclass.exists(typeinfo.entityparent, entity_id):
            redirect_uri = (
                uri_with_params(
                    self.view.get_request_path(),
                    self.view.error_params(msg),
                    self.get_continuation_url_dict()
                    )
                )
        return redirect_uri

    def get_new_view_uri(self, coll_id, type_id):
        """
        Get URI for entity new view from list display
        """
        return self.view.view_uri(
            "AnnalistEntityNewView", 
            coll_id=coll_id, 
            view_id=self.get_list_view_id(), 
            type_id=type_id,
            action="new"
            )

    def get_edit_view_uri(self, coll_id, type_id, entity_id, action):
        """
        Get URI for entity edit or copy view from list display
        """
        return self.view.view_uri(
                "AnnalistEntityEditView", 
                coll_id=coll_id, 
                view_id=self.get_list_view_id(), 
                type_id=type_id,
                entity_id=entity_id,
                action=action
                )

    # Additonal support functions

    def get_view_id(self, type_id, view_id):
        """
        Get view id or suitable default using type if defined.
        """
        if not self.http_response:
            view_id = (
                view_id or 
                self.entitytypeinfo.get_default_view_id()
                )
            if not view_id:
                log.warning("get_view_id: %s, type_id %s"%(view_id, self.type_id))
        return view_id

    def get_continuation_param(self):
        """
        Return continuation URL specified for the current request, or None.
        """
        cont_here = self.view.continuation_here(self.request_dict, self.default_continue)
        return uri_params({"continuation_url": cont_here})

    def get_continuation_url(self):
        """
        Return continuation URL specified for the current request, or None.
        """
        return self.continuation_url

    def get_continuation_url_dict(self):
        """
        Return dictionary with continuation URL specified for the current request.
        """
        c = self.get_continuation_url()
        return {'continuation_url': c} if c else {}

    def get_continuation_next(self):
        """
        Return continuation URL to be used when returning from the current view.

        Uses the default continuation if no value supplied in request dictionary.
        """
        log.debug(
            "get_continuation_next '%s', default '%s'"%
              (self.continuation_url, self.default_continue)
            )
        return self.continuation_url or self.default_continue

    def get_continuation_here(self, base_here=None):
        """
        Return continuation URL back to the current view.
        """
        # @@TODO: consider merging logic from generic.py, and eliminating method there
        return self.view.continuation_here(
            request_dict=self.request_dict,
            default_cont=self.get_continuation_url(),
            base_here=base_here
            )

    def update_continuation_url(self, 
        old_type_id=None, new_type_id=None, 
        old_entity_id=None, new_entity_id=None
        ):
        """
        Update continuation URI to reflect renamed type or entity.
        """
        # def update_hop(chop):
        #     return url_update_type_entity_id(chop, 
        #         old_type_id=old_type_id, new_type_id=new_type_id, 
        #         old_entity_id=old_entity_id, new_entity_id=new_entity_id
        #         )
        curi = self.continuation_url
        if curi:
            hops = continuation_url_chain(curi)
            for i in range(len(hops)):
                uribase, params = hops[i]
                uribase = url_update_type_entity_id(uribase, 
                    old_type_id=old_type_id, new_type_id=new_type_id, 
                    old_entity_id=old_entity_id, new_entity_id=new_entity_id
                    )
                hops[i] = (uribase, params)
            curi = continuation_chain_url(hops)
            self.continuation_url = curi
        return curi

    def get_entity_data_ref(self, return_type=None):
        """
        Returns a string that can be used as a reference to the entity metadata resource
        relative to an entity URL, optionally with a specified type parameter added.
        """
        assert self.entitytypeinfo is not None
        return make_data_ref(
            self.view.get_request_path(), 
            self.entitytypeinfo.entityclass._entityfile, 
            return_type
            )

    def get_entity_list_ref(self, return_type=None):
        """
        Returns a string that can be used as a reference to the entity list data
        relative to the current list URL.
        """
        return make_data_ref(
            self.view.get_request_path(), 
            layout.ENTITY_LIST_FILE, 
            return_type
            )

    def context_data(self, entity_label=None):
        """
        Return dictionary of rendering context data available from the 
        elements assembled.

        Values that are added here to the view context are used for view rendering, 
        and are not passed to the entity value mapping process.

        NOTE: values that are needed to be accessible as part of bound_field values 
        must be provided earlier in the form generation process, as elements of the 
        "context_extra_values" dictionary.

        Context values set here do not need to be named in the valuye maop used to
        create the view context.
        """
        context = (
            { 'site_label':         self.sitedata["title"]
            , 'title':              self.sitedata["title"]
            , 'heading':            self.sitedata["title"]
            , 'action':             self.action
            , 'coll_id':            self.coll_id
            , 'type_id':            self.type_id
            , 'view_id':            self.view_id
            , 'list_id':            self.list_id
            , "SITE":               self.site._entityurl
            , "HOST":               self.reqhost
            })
        context.update(self.authorizations)
        if self.collection:
            coll_url_parts = urlparse.urlsplit(self.collection._entityurl)
            context.update(
                { 'heading':    self.collection[RDFS.CURIE.label]
                , 'coll_label': self.collection[RDFS.CURIE.label]
                , "COLL":       self.collection._entityurl
                , "BASE":       coll_url_parts.path + layout.COLL_ENTITYDATA_PATH
                })
            context['title'] = "%(coll_label)s"%context
        if self.recordview:
            context.update(
                { 'heading':            self.recordview[RDFS.CURIE.label]
                , 'view_label':         self.recordview[RDFS.CURIE.label]
                , 'edit_view_button':   self.recordview.get(ANNAL.CURIE.open_view, "yes")
                })
            context['title'] = "%(view_label)s - %(coll_label)s"%context
            edit_task_buttons = self.recordview.get(ANNAL.CURIE.edit_task_buttons, None)
            view_task_buttons = self.recordview.get(ANNAL.CURIE.view_task_buttons, None)
            self.add_task_button_context('edit_task_buttons', edit_task_buttons, context)
            self.add_task_button_context('view_task_buttons', view_task_buttons, context)
        if self.recordlist:
            context.update(
                { 'heading':                self.recordlist[RDFS.CURIE.label]
                , 'list_label':             self.recordlist[RDFS.CURIE.label]
                , 'entity_list_ref':        self.get_entity_list_ref()
                , 'entity_list_ref_json':   self.get_entity_list_ref("application/json")
                })
            context['title'] = "%(list_label)s - %(coll_label)s"%context
        if self.entitytypeinfo:
            context.update(
                { 'entity_data_ref':        self.get_entity_data_ref()
                , 'entity_data_ref_json':   self.get_entity_data_ref("application/json")
                })
        if entity_label:
            context.update(
                { 'entity_label':       entity_label
                })
            # context['heading'] = "%(entity_label)s - %(view_label)s"%context
            context['title']   = "%(entity_label)s - %(view_label)s - %(coll_label)s"%context
        if hasattr(self.view, 'help') and self.view.help:
            context.update(
                { 'help_filename':  self.view.help
                })
        if hasattr(self.view, 'help_markdown') and self.view.help_markdown:
            substituted_text = apply_substitutions(context, self.view.help_markdown)
            context.update(
                { 'help_markdown':  substituted_text
                })
        return context

    def add_task_button_context(self, task_buttons_name, task_buttons, context):
        """
        Adds context values to a supplied context dictionary corresponding 
        to the supplied task_buttons value(s) from a view description.

        @NOTE: subsequent versions of this function may extract values from
        an identified task description record.
        """
        if isinstance(task_buttons, list):
            context.update(
                { task_buttons_name:
                    [ { 'button_id':    b[ANNAL.CURIE.button_id]
                      , 'button_name':  extract_entity_id(b[ANNAL.CURIE.button_id])
                      , 'button_label': b.get(ANNAL.CURIE.button_label, "@@annal:button_label@@")
                      , 'button_help':  b.get(ANNAL.CURIE.button_help,  "@@annal:button_help@@")
                      } for b in task_buttons
                    ]
                })
        elif task_buttons is not None:
            log.error(
                "DisplayInfo.context_data: Unexpected value for task_buttons: %r"%
                (task_buttons)
                )
        return

    def __str__(self):
        attrs = (
            [ "view"
            , "action"
            , "authorizations"
            , "reqhost"
            , "site"
            , "sitedata"
            , "coll_id"
            , "collection"
            , "type_id"
            , "entitytypeinfo"
            , "list_id"
            , "recordlist"
            , "view_id"
            , "recordview"
            , "entity_id"
            ])
        fields = ["DisplayInfo("]
        for attr in attrs:
            val = getattr(self, attr, None)
            if val is not None:
                fields.append("%s: %r"%(attr, val))
        fields.append(")")
        return ("\n  ".join(fields))

    def __repr__(self):
        return str(self)
Beispiel #42
0
    def test_inherited_image_edit(self):
        # This tests that editing an inherited image creartes a new copy in the
        # inheriting collection.

        # Upload image
        self.test_image_edit_field()

        # Create collection inheriting uploaded image
        testsubcoll = create_test_coll_inheriting(
            base_coll_id="testcoll", coll_id="testsubcoll", type_id="testtype"
            )
        # create_test_user(testsubcoll, "testuser", "testpassword")
        user_permissions = ["VIEW", "CREATE", "UPDATE", "DELETE", "CONFIG"]
        user_id          = "testuser"
        user_perms = testsubcoll.create_user_permissions(
            user_id, "mailto:%s@%s"%(user_id, TestHost),
            "Test User",
            "User %s: permissions for %s in collection %s"%(user_id, "Test User", testsubcoll.get_id()),
            user_permissions)

        # Get editing form
        u = entitydata_edit_url(
            "edit", "testsubcoll", "testimgtype", entity_id="test1", view_id="testimgview"
            )
        r = self.client.get(u)
        self.assertEqual(r.status_code,   200)
        self.assertEqual(r.reason_phrase, "OK")
        # log.info(r.content)     #@@
        hi1 = """<input type="hidden" name="orig_id"          value="test1" />"""
        hi2 = """<input type="hidden" name="orig_type"        value="testimgtype" />"""
        hi3 = """<input type="hidden" name="orig_coll"        value="testcoll" />"""
        hi4 = """<input type="hidden" name="action"           value="edit" />"""
        hi5 = """<input type="hidden" name="view_id"          value="testimgview" />"""
        self.assertContains(r, hi1, html=True)
        self.assertContains(r, hi2, html=True)
        self.assertContains(r, hi3, html=True)
        self.assertContains(r, hi4, html=True)
        self.assertContains(r, hi5, html=True)

        # Edit entity
        f = default_view_form_data(
            coll_id="testsubcoll", type_id="testimgtype", entity_id="test1", 
            orig_coll="testcoll", action="edit", 
            update="Updated"
            )
        u = entitydata_edit_url(
            "edit", "testsubcoll", "testimgtype", entity_id="test1", view_id="testimgview"
            )
        r = self.client.post(u, f)
        self.assertEqual(r.status_code,   302)
        self.assertEqual(r.reason_phrase, "Found")

        # Retrieve updated form
        r = self.client.get(u)
        # Test context
        self.assertEqual(len(r.context['fields']), 4)
        f0 = context_view_field(r.context, 0, 0)
        self.assertEqual(f0.field_id,     "Entity_id")
        self.assertEqual(f0.field_value,  "test1")
        f1 = context_view_field(r.context, 1, 0)
        self.assertEqual(f1.field_id,     "Entity_label")
        self.assertEqual(f1.field_value,  "Updated testsubcoll/testimgtype/test1")
        f2 = context_view_field(r.context, 2, 0)
        self.assertEqual(f2.field_id,     "Entity_comment")
        f3 = context_view_field(r.context, 3, 0)
        self.assertEqual(f3.field_id,     "Test_image")
        self.assertDictionaryMatch(f3.field_value, test_image_field_value())

        # Read back and compare entity resource
        inherited_test_img_type_info = EntityTypeInfo(
            testsubcoll, "testimgtype", create_typedata=True
            )
        siteobj = open(self.imagepath, "rb")
        testobj = inherited_test_img_type_info.get_fileobj(
            "test1", "img_field", "annal:Image", "image/jpeg", "rb"
            )
        self.assertTrue(siteobj.read() == testobj.read(), "Edited entity image != original")
Beispiel #43
0
    def setUp(self):
        self.filepath  = "%s/testdatafile.md"%TestBaseDir
        self.fileuri   = "file://"+self.filepath
        self.imagepath = "%s/test-image.jpg"%TestBaseDir
        self.imageuri  = "file://"+self.imagepath
        init_annalist_test_site()
        init_annalist_test_coll()
        self.testsite  = Site(TestBaseUri, TestBaseDir)
        self.testcoll  = Collection(self.testsite, "testcoll")
        # Populate collection with linked record types, views and lists

        # Types
        self.test_upl_type = RecordType.create(
            self.testcoll, "testupltype", test_upload_type_create_values
            )
        self.test_ref_type = RecordType.create(
            self.testcoll, "testreftype", test_reference_type_create_values
            )
        self.test_image_type = RecordType.create(
            self.testcoll, "testimgtype", test_image_type_create_values
            )

        # Views
        self.test_upl_file_view = RecordView.create(
            self.testcoll, "testuplfileview", test_upload_file_view_create_values
            )
        self.test_upl_image_view = RecordView.create(
            self.testcoll, "testuplimageview", test_upload_image_view_create_values
            )
        self.test_ref_file_view = RecordView.create(
            self.testcoll, "testrefview", test_reference_view_create_values
            )
        self.test_ref_image_view = RecordView.create(
            self.testcoll, "testimgrefview", test_image_ref_view_create_values
            )
        self.test_image_view = RecordView.create(
            self.testcoll, "testimgview", test_image_view_create_values
            )

        # Fields
        self.test_upl_file_field = RecordField.create(
            self.testcoll, "Test_upload_file", test_upload_file_field_create_values
            )
        self.test_upl_image_field = RecordField.create(
            self.testcoll, "Test_upload_image", test_upload_image_field_create_values
            )
        self.test_ref_file_field = RecordField.create(
            self.testcoll, "Test_reference", test_reference_field_create_values
            )
        self.test_ref_image_field = RecordField.create(
            self.testcoll, "Test_image_ref", test_image_ref_field_create_values
            )
        self.test_image_field = RecordField.create(
            self.testcoll, "Test_image", test_image_field_create_values
            )

        # Create data records for testing import and references:
        test_entity_ids = ("test1", "test2")
        test_entity_ids = ("test1",)
        self.test_upl_type_info = EntityTypeInfo(
            self.testcoll, "testupltype", create_typedata=True
            )
        for entity_id in test_entity_ids:
            self.test_upl_type_info.create_entity(
                entity_id, test_imp_entity_create_values(entity_id)
                )
        self.test_ref_type_info = EntityTypeInfo(
            self.testcoll, "testreftype", create_typedata=True
            )
        for entity_id in test_entity_ids:
            self.test_ref_type_info.create_entity(
                entity_id, test_ref_entity_create_values(entity_id)
                )
        self.test_img_type_info = EntityTypeInfo(
            self.testcoll, "testimgtype", create_typedata=True
            )
        for entity_id in test_entity_ids:
            self.test_img_type_info.create_entity(
                entity_id, test_img_entity_create_values(entity_id)
                )
        # Login and permissions
        create_test_user(self.testcoll, "testuser", "testpassword")
        self.client = Client(HTTP_HOST=TestHost)
        loggedin = self.client.login(username="******", password="******")
        self.assertTrue(loggedin)
        return
class LinkedRecordTest(AnnalistTestCase):
    """
    Tests for linked records
    """
    def setUp(self):
        init_annalist_test_site()
        init_annalist_test_coll()
        self.testsite = Site(TestBaseUri, TestBaseDir)
        self.testcoll = Collection(self.testsite, "testcoll")
        # Populate collection with linked record types, views and lists
        self.testsrc_type = RecordType.create(self.testcoll, "testsrc_type",
                                              testsrc_type_create_values)
        self.testtgt_type = RecordType.create(self.testcoll, "testtgt_type",
                                              testtgt_type_create_values)
        self.testsrc_view = RecordView.create(self.testcoll, "testsrc_view",
                                              testsrc_view_create_values)
        self.testtgt_view = RecordView.create(self.testcoll, "testtgt_view",
                                              testtgt_view_create_values)
        self.testsrc_list = RecordList.create(self.testcoll, "testsrc_list",
                                              testsrc_list_create_values)
        self.testtgt_list = RecordList.create(self.testcoll, "testtgt_list",
                                              testtgt_list_create_values)
        self.testtgtref_field = RecordField.create(
            self.testcoll, "testtgtref_field", testtgtref_field_create_values)
        self.no_options = [FieldChoice('', label="(no options)")]
        self.tgt_options = ([
            FieldChoice("testtgt_type/" + v,
                        label="testtgt_entity %s label" % v,
                        link=entity_url("testcoll", "testtgt_type", v))
            for v in ["testtgt1", "testtgt2"]
        ])
        # Create data records for testing:
        self.testtgt_type_info = EntityTypeInfo(self.testcoll,
                                                "testtgt_type",
                                                create_typedata=True)
        self.testsrc_type_info = EntityTypeInfo(self.testcoll,
                                                "testsrc_type",
                                                create_typedata=True)
        for tgt_id in ("testtgt1", "testtgt2"):
            self.testtgt_type_info.create_entity(
                tgt_id, testtgt_entity_create_values(tgt_id))
        for src_id, tgt_ref in (("testsrc1", "testtgt1"), ("testsrc2",
                                                           "testtgt2")):
            self.testsrc_type_info.create_entity(
                src_id, testsrc_entity_create_values(src_id, tgt_ref))
        # Login and permissions
        create_test_user(self.testcoll, "testuser", "testpassword")
        self.client = Client(HTTP_HOST=TestHost)
        loggedin = self.client.login(username="******",
                                     password="******")
        self.assertTrue(loggedin)
        return

    def tearDown(self):
        # resetSitedata(scope="collections")
        return

    @classmethod
    def tearDownClass(cls):
        resetSitedata()
        return

    # Utility functions

    # Tests

    def test_view_entity_references(self):
        u = entity_url(coll_id="testcoll",
                       type_id="testsrc_type",
                       entity_id="testsrc1")
        r = self.client.get(u)
        self.assertEqual(r.status_code, 200)
        self.assertEqual(r.reason_phrase, "OK")
        # Test context
        self.assertEqual(len(r.context['fields']), 3)
        f0 = context_view_field(r.context, 0, 0)
        self.assertEqual(f0.field_id, "Entity_id")
        self.assertEqual(f0.field_value, "testsrc1")
        self.assertEqual(f0.field_value_link, None)
        self.assertEqual(f0.options, self.no_options)
        f1 = context_view_field(r.context, 0, 1)
        self.assertEqual(f1.field_id, "testtgtref_field")
        self.assertEqual(f1.field_value, "testtgt_type/testtgt1")
        self.assertEqual(f1.field_value_link,
                         "/testsite/c/testcoll/d/testtgt_type/testtgt1/")
        self.assertEqual(f1.options, self.tgt_options)
        f2 = context_view_field(r.context, 1, 0)
        self.assertEqual(f2.field_id, "Entity_label")
        self.assertEqual(f2.field_value, "testsrc_entity testsrc1 label")
        self.assertEqual(f2.field_value_link, None)
        self.assertEqual(f2.options, self.no_options)
        f3 = context_view_field(r.context, 2, 0)
        self.assertEqual(f3.field_id, "Entity_comment")
        self.assertEqual(f3.field_value, "testsrc_entity testsrc1 comment")
        self.assertEqual(f3.field_value_link, None)
        self.assertEqual(f3.options, self.no_options)
        return

    def test_list_entity_references(self):
        # List linked records - check values in listing
        u = entitydata_list_type_url("testcoll",
                                     "testsrc_type",
                                     list_id="testsrc_list")
        r = self.client.get(u)
        self.assertEqual(r.status_code, 200)
        self.assertEqual(r.reason_phrase, "OK")
        # Test context
        entities = context_list_entities(r.context)
        head_fields = context_list_head_fields(r.context)
        # print "@@ context: "+repr(r.context['List_rows'])
        # print "@@ head_fields: "+repr(head_fields)
        self.assertEqual(len(entities), 2)
        self.assertEqual(len(head_fields), 1)  # One row of 3 cols..
        self.assertEqual(len(head_fields[0]['row_field_descs']), 3)
        entity_values = ((entities[0], "testsrc1", "testtgt1"),
                         (entities[1], "testsrc2", "testtgt2"))
        for entc, esrc, etgt in entity_values:
            item_fields = context_list_item_fields(r.context, entc)
            self.assertEqual(len(item_fields), 3)
            self.assertEqual(entc['entity_id'], esrc)
            self.assertEqual(entc['entity_type_id'], "testsrc_type")
            self.assertEqual(item_fields[0].field_id, "Entity_id")
            self.assertEqual(item_fields[0].field_value, esrc)
            self.assertEqual(item_fields[0].field_value_link, None)
            self.assertEqual(item_fields[1].field_id, "testtgtref_field")
            self.assertEqual(item_fields[1].field_value,
                             "testtgt_type/" + etgt)
            self.assertEqual(item_fields[1].field_value_link,
                             "/testsite/c/testcoll/d/testtgt_type/%s/" % etgt)
            self.assertEqual(item_fields[2].field_id, "Entity_label")
            self.assertEqual(item_fields[2].field_value,
                             "testsrc_entity %s label" % esrc)
            self.assertEqual(item_fields[2].field_value_link, None)
        return
Beispiel #45
0
class ImportResourceTest(AnnalistTestCase):
    """
    Tests for resource import
    """

    def setUp(self):
        self.fileuri = "file://%s/README.md"%TestBaseDir
        init_annalist_test_site()
        init_annalist_test_coll()
        self.testsite    = Site(TestBaseUri, TestBaseDir)
        self.testcoll    = Collection(self.testsite, "testcoll")
        # Populate collection with linked record types, views and lists
        self.test_imp_type = RecordType.create(
            self.testcoll, "testimptype", test_import_type_create_values
            )
        self.test_imp_view = RecordView.create(
            self.testcoll, "testimpview", test_import_view_create_values
            )
        self.test_imp_field = RecordField.create(
            self.testcoll, "Test_import", test_import_field_create_values
            )
        self.test_ref_type = RecordType.create(
            self.testcoll, "testreftype", test_reference_type_create_values
            )
        self.test_ref_view = RecordView.create(
            self.testcoll, "testrefview", test_reference_view_create_values
            )
        self.test_ref_field = RecordField.create(
            self.testcoll, "Test_reference", test_reference_field_create_values
            )
        # Create data records for testing import and references:
        self.test_imp_type_info = EntityTypeInfo(
            self.testcoll, "testimptype", create_typedata=True
            )
        for entity_id in ("test1", "test2"):
            self.test_imp_type_info.create_entity(
                entity_id, test_imp_entity_create_values(entity_id)
                )
        self.test_ref_type_info = EntityTypeInfo(
            self.testcoll, "testreftype", create_typedata=True
            )
        for entity_id in ("test1", "test2"):
            self.test_ref_type_info.create_entity(
                entity_id, test_ref_entity_create_values(entity_id)
                )
        # Login and permissions
        create_test_user(self.testcoll, "testuser", "testpassword")
        self.client = Client(HTTP_HOST=TestHost)
        loggedin = self.client.login(username="******", password="******")
        self.assertTrue(loggedin)
        return

    def tearDown(self):
        # resetSitedata(scope="collections")
        return

    @classmethod
    def tearDownClass(cls):
        resetSitedata(scope="collections")
        return

    # Utility functions

    # Tests

    def test_entity_fileobj(self):
        test1    = self.test_imp_type_info.get_entity("test1")
        test1dir, test1file = test1._dir_path()
        testobj1 = self.test_imp_type_info.get_fileobj(
            "test1", "test1res", "annal:Text", "text/plain", "wb"
            )
        testobj1.write("Test data test1res.txt")
        self.assertEqual(testobj1.name, test1dir+"/test1res.txt")
        testobj1.close()
        testobj2 = self.test_imp_type_info.get_fileobj(
            "test1", "test1res", "annal:Text", "text/plain", "rb"
            )
        self.assertEqual(testobj2.read(), "Test data test1res.txt")
        testobj2.close()
        return

    def test_util_fileobj(self):
        resource_fileobj, resource_url, resource_type = util.open_url(self.fileuri)
        self.assertEqual(resource_url,  self.fileuri)
        self.assertEqual(resource_type, "text/markdown")
        testobj1 = self.test_imp_type_info.get_fileobj(
            "test1", "test1res", "annal:Richtext", resource_type, "wb"
            )
        util.copy_resource_to_fileobj(resource_fileobj, testobj1)
        resource_fileobj.close()
        testobj1.close()
        # Read back both and compare
        siteobj = open(TestBaseDir+"/README.md", "rb")
        testobj = self.test_imp_type_info.get_fileobj(
            "test1", "test1res", "annal:Richtext", resource_type, "rb"
            )
        self.assertEqual(siteobj.read(), testobj.read())
        return

    def test_import_resource(self):
        f = default_view_form_data(
            entity_id="test1", type_id="testimptype", action="edit", 
            do_import="imp_field__import"
            )
        f['imp_field'] = self.fileuri
        u = entitydata_edit_url(
            "edit", "testcoll", "testimptype", entity_id="test1", view_id="testimpview"
            )
        r = self.client.post(u, f)
        self.assertEqual(r.status_code,   302)
        self.assertEqual(r.reason_phrase, "FOUND")
        self.assertMatch(r['location'], TestHostUri+u)
        # Read back form following redirect
        r = self.client.get(u)
        self.assertEqual(r.status_code,   200)
        self.assertEqual(r.reason_phrase, "OK")
        # Test context
        self.assertEqual(len(r.context['fields']), 4)
        f0 = context_view_field(r.context, 0, 0)
        self.assertEqual(f0.field_id,     "Entity_id")
        self.assertEqual(f0.field_value,  "test1")
        f1 = context_view_field(r.context, 1, 0)
        self.assertEqual(f1.field_id,     "Entity_label")
        f2 = context_view_field(r.context, 2, 0)
        self.assertEqual(f2.field_id,     "Entity_comment")
        f3 = context_view_field(r.context, 3, 0)
        self.assertEqual(f3.field_id,     "Test_import")
        self.assertDictionaryMatch(f3.field_value, test_import_field_value())
        # Read back and compare entity resource just created
        siteobj = open(TestBaseDir+"/README.md", "rb")
        testobj = self.test_imp_type_info.get_fileobj(
            "test1", "imp_field", "annal:Richtext", "text/markdown", "rb"
            )
        self.assertEqual(siteobj.read(), testobj.read())
        return

    def test_reference_imported_resource(self):
        # Create imported resource (see previous test)
        f = default_view_form_data(
            entity_id="test1", type_id="testimptype", action="edit", 
            do_import="imp_field__import"
            )
        f['imp_field'] = self.fileuri
        u = entitydata_edit_url(
            "edit", "testcoll", "testimptype", entity_id="test1", view_id="testimpview"
            )
        r = self.client.post(u, f)
        self.assertEqual(r.status_code,   302)
        self.assertEqual(r.reason_phrase, "FOUND")
        # Display resource with reference
        u = entitydata_edit_url(
            "view", "testcoll", "testreftype", entity_id="test1", view_id="testrefview"
            )
        r = self.client.get(u)
        self.assertEqual(r.status_code,   200)
        self.assertEqual(r.reason_phrase, "OK")
        # Check display context
        self.assertEqual(len(r.context['fields']), 4)
        f0 = context_view_field(r.context, 0, 0)
        self.assertEqual(f0.field_id,     "Entity_id")
        self.assertEqual(f0.field_value,  "test1")
        f1 = context_view_field(r.context, 1, 0)
        self.assertEqual(f1.field_id,     "Entity_label")
        self.assertEqual(f1.field_value,  "test_ref_entity test1 label")
        f2 = context_view_field(r.context, 2, 0)
        self.assertEqual(f2.field_id,     "Entity_comment")
        self.assertEqual(f2.field_value,  "test_ref_entity test1 comment")
        f3 = context_view_field(r.context, 3, 0)
        basepath = TestBasePath + "/c/testcoll/d/testimptype/"
        self.assertEqual(f3.field_id,           "Test_reference")
        self.assertEqual(f3.field_value,        "testimptype/test1")
        self.assertEqual(f3.field_value_link,   basepath+"test1/")
        self.assertEqual(f3.target_value['import_name'],   "imp_field")
        self.assertEqual(f3.target_value['resource_name'], "imp_field.md")
        self.assertEqual(f3.target_value['resource_type'], "text/markdown")
        self.assertEqual(f3.target_value_link,  basepath+"test1/imp_field.md")
        return
Beispiel #46
0
class UploadResourceTest(AnnalistTestCase):
    """
    Tests for resource import
    """

    def setUp(self):
        self.filepath  = "%s/testdatafile.md"%TestBaseDir
        self.fileuri   = "file://"+self.filepath
        self.imagepath = "%s/test-image.jpg"%TestBaseDir
        self.imageuri  = "file://"+self.imagepath
        init_annalist_test_site()
        init_annalist_test_coll()
        self.testsite  = Site(TestBaseUri, TestBaseDir)
        self.testcoll  = Collection(self.testsite, "testcoll")
        # Populate collection with linked record types, views and lists

        # Types
        self.test_upl_type = RecordType.create(
            self.testcoll, "testupltype", test_upload_type_create_values
            )
        self.test_ref_type = RecordType.create(
            self.testcoll, "testreftype", test_reference_type_create_values
            )
        self.test_image_type = RecordType.create(
            self.testcoll, "testimgtype", test_image_type_create_values
            )

        # Views
        self.test_upl_file_view = RecordView.create(
            self.testcoll, "testuplfileview", test_upload_file_view_create_values
            )
        self.test_upl_image_view = RecordView.create(
            self.testcoll, "testuplimageview", test_upload_image_view_create_values
            )
        self.test_ref_file_view = RecordView.create(
            self.testcoll, "testrefview", test_reference_view_create_values
            )
        self.test_ref_image_view = RecordView.create(
            self.testcoll, "testimgrefview", test_image_ref_view_create_values
            )
        self.test_image_view = RecordView.create(
            self.testcoll, "testimgview", test_image_view_create_values
            )

        # Fields
        self.test_upl_file_field = RecordField.create(
            self.testcoll, "Test_upload_file", test_upload_file_field_create_values
            )
        self.test_upl_image_field = RecordField.create(
            self.testcoll, "Test_upload_image", test_upload_image_field_create_values
            )
        self.test_ref_file_field = RecordField.create(
            self.testcoll, "Test_reference", test_reference_field_create_values
            )
        self.test_ref_image_field = RecordField.create(
            self.testcoll, "Test_image_ref", test_image_ref_field_create_values
            )
        self.test_image_field = RecordField.create(
            self.testcoll, "Test_image", test_image_field_create_values
            )

        # Create data records for testing import and references:
        test_entity_ids = ("test1", "test2")
        test_entity_ids = ("test1",)
        self.test_upl_type_info = EntityTypeInfo(
            self.testcoll, "testupltype", create_typedata=True
            )
        for entity_id in test_entity_ids:
            self.test_upl_type_info.create_entity(
                entity_id, test_imp_entity_create_values(entity_id)
                )
        self.test_ref_type_info = EntityTypeInfo(
            self.testcoll, "testreftype", create_typedata=True
            )
        for entity_id in test_entity_ids:
            self.test_ref_type_info.create_entity(
                entity_id, test_ref_entity_create_values(entity_id)
                )
        self.test_img_type_info = EntityTypeInfo(
            self.testcoll, "testimgtype", create_typedata=True
            )
        for entity_id in test_entity_ids:
            self.test_img_type_info.create_entity(
                entity_id, test_img_entity_create_values(entity_id)
                )
        # Login and permissions
        create_test_user(self.testcoll, "testuser", "testpassword")
        self.client = Client(HTTP_HOST=TestHost)
        loggedin = self.client.login(username="******", password="******")
        self.assertTrue(loggedin)
        return

    def tearDown(self):
        # resetSitedata(scope="collections")
        return

    @classmethod
    def setUpClass(cls):
        super(UploadResourceTest, cls).setUpClass()
        return

    @classmethod
    def tearDownClass(cls):
        super(UploadResourceTest, cls).tearDownClass()
        resetSitedata(scope="collections")      # @@checkme@@
        return

    # Utility functions

    # Tests

    def test_entity_fileobj(self):
        test1    = self.test_upl_type_info.get_entity("test1")
        test1dir, test1file = test1._dir_path()
        testobj1 = self.test_upl_type_info.get_fileobj(
            "test1", "test1res", "annal:Text", "text/plain", "wb"
            )
        testobj1.write(b"Test data test1res.txt")
        self.assertEqual(testobj1.name, test1dir+"/test1res.txt")
        testobj1.close()
        testobj2 = self.test_upl_type_info.get_fileobj(
            "test1", "test1res", "annal:Text", "text/plain", "rb"
            )
        self.assertEqual(testobj2.read(), b"Test data test1res.txt")
        testobj2.close()
        return

    def test_util_fileobj(self):
        resource_fileobj, resource_url, resource_type = util.open_url(self.fileuri)
        self.assertEqual(resource_url,  self.fileuri)
        self.assertEqual(resource_type, "text/markdown")
        testobj1 = self.test_upl_type_info.get_fileobj(
            "test1", "test1res", "annal:Richtext", resource_type, "wb"
            )
        util.copy_resource_to_fileobj(resource_fileobj, testobj1)
        resource_fileobj.close()
        testobj1.close()
        # Read back both and compare
        siteobj = open(TestBaseDir+"/testdatafile.md", "rb")
        testobj = self.test_upl_type_info.get_fileobj(
            "test1", "test1res", "annal:Richtext", resource_type, "rb"
            )
        self.assertEqual(siteobj.read(), testobj.read())
        return

    def test_upload_file_resource(self):
        # See https://docs.djangoproject.com/en/1.7/topics/testing/tools/#django.test.Client.post
        with open(self.filepath) as fp:
            f = default_view_form_data(
                type_id="testupltype", entity_id="test1", action="edit"
                )
            f['upl_field'] = fp     # Upload file with submission
            u = entitydata_edit_url("edit", "testcoll", "testupltype", entity_id="test1", view_id="testuplfileview")
            r = self.client.post(u, f)
        self.assertEqual(r.status_code,   302)
        self.assertEqual(r.reason_phrase, "Found")
        # Retrieve updated form
        r = self.client.get(u)
        # Test context
        self.assertEqual(len(r.context['fields']), 4)
        f0 = context_view_field(r.context, 0, 0)
        self.assertEqual(f0.field_id,     "Entity_id")
        self.assertEqual(f0.field_value,  "test1")
        f1 = context_view_field(r.context, 1, 0)
        self.assertEqual(f1.field_id,     "Entity_label")
        f2 = context_view_field(r.context, 2, 0)
        self.assertEqual(f2.field_id,     "Entity_comment")
        f3 = context_view_field(r.context, 3, 0)
        self.assertEqual(f3.field_id,     "Test_upload_file")
        self.assertDictionaryMatch(f3.field_value, test_upload_file_field_value())
        # Read back and compare entity resource just created
        siteobj = open(self.filepath, "rb")
        testobj = self.test_upl_type_info.get_fileobj(
            "test1", "upl_field", "annal:Richtext", "text/markdown", "rb"
            )
        self.assertEqual(siteobj.read(), testobj.read())
        return

    def test_reference_uploaded_resource(self):
        # Create uploaded resource (see previous test)
        with open(self.filepath) as fp:
            f = default_view_form_data(
                type_id="testupltype", entity_id="test1", action="edit"
                )
            f['upl_field'] = fp     # Upload file with submission
            u = entitydata_edit_url(
                "view", "testcoll", "testupltype", entity_id="test1", view_id="testuplfileview"
                )
            r = self.client.post(u, f)
        self.assertEqual(r.status_code,   302)
        self.assertEqual(r.reason_phrase, "Found")
        # Display resource with reference
        u = entitydata_edit_url(
            "view", "testcoll", "testreftype", entity_id="test1", view_id="testrefview"
            )
        r = self.client.get(u)
        self.assertEqual(r.status_code,   200)
        self.assertEqual(r.reason_phrase, "OK")
        # Check display context
        self.assertEqual(len(r.context['fields']), 4)
        f0 = context_view_field(r.context, 0, 0)
        self.assertEqual(f0.field_id,     "Entity_id")
        self.assertEqual(f0.field_value,  "test1")
        f1 = context_view_field(r.context, 1, 0)
        self.assertEqual(f1.field_id,     "Entity_label")
        self.assertEqual(f1.field_value,  "test_ref_entity test1 label")
        f2 = context_view_field(r.context, 2, 0)
        self.assertEqual(f2.field_id,     "Entity_comment")
        self.assertEqual(f2.field_value,  "test_ref_entity test1 comment")
        f3 = context_view_field(r.context, 3, 0)
        basepath = TestBasePath + "/c/testcoll/d/testupltype/"
        # print "\n*****\n"+repr(context_view_field(r.context, i, 0).target_value)+"\n*****\n"
        self.assertEqual(f3.field_id,     "Test_reference")
        self.assertEqual(f3.field_value,        "testupltype/test1")
        self.assertEqual(f3.field_value_link,   basepath+"test1/")
        self.assertEqual(f3.target_value['upload_name'],   "upl_field")
        self.assertEqual(f3.target_value['resource_name'], "upl_field.md")
        self.assertEqual(f3.target_value['resource_type'], "text/markdown")
        self.assertEqual(f3.target_value['uploaded_file'], "testdatafile.md")
        self.assertEqual(f3.target_value['uploaded_size'], 137)
        self.assertEqual(f3.target_value_link,  basepath+"test1/upl_field.md")
        return

    def test_upload_image_resource(self):
        # See https://docs.djangoproject.com/en/1.7/topics/testing/tools/#django.test.Client.post
        with open(self.imagepath, "rb") as fp:
            f = default_view_form_data(
                type_id="testupltype", entity_id="test1", action="edit"
                )
            f['upl_field'] = fp     # Upload file with submission
            u = entitydata_edit_url("edit", "testcoll", "testupltype", entity_id="test1", view_id="testuplimageview")
            r = self.client.post(u, f)
        self.assertEqual(r.status_code,   302)
        self.assertEqual(r.reason_phrase, "Found")
        # Retrieve updated form
        r = self.client.get(u)
        # Test context
        self.assertEqual(len(r.context['fields']), 4)
        f0 = context_view_field(r.context, 0, 0)
        self.assertEqual(f0.field_id,     "Entity_id")
        self.assertEqual(f0.field_value,  "test1")
        f1 = context_view_field(r.context, 1, 0)
        self.assertEqual(f1.field_id,     "Entity_label")
        f2 = context_view_field(r.context, 2, 0)
        self.assertEqual(f2.field_id,     "Entity_comment")
        f3 = context_view_field(r.context, 3, 0)
        self.assertEqual(f3.field_id,     "Test_upload_image")
        self.assertDictionaryMatch(f3.field_value, test_upload_image_field_value())
        # Read back and compare entity resource just created
        siteobj = open(self.imagepath, "rb")
        testobj = self.test_upl_type_info.get_fileobj(
            "test1", "upl_field", "annal:Image", "image/jpeg", "rb"
            )
        self.assertTrue(siteobj.read() == testobj.read(), "Uploaded image != original")
        # self.assertEqual(siteobj.read(), testobj.read())
        return

    def test_reference_uploaded_image(self):
        self.test_upload_image_resource()

        # Display resource with image reference
        u = entitydata_edit_url("view", "testcoll", "testreftype", entity_id="test1", view_id="testimgrefview")
        r = self.client.get(u)
        self.assertEqual(r.status_code,   200)
        self.assertEqual(r.reason_phrase, "OK")
        # Check display context
        self.assertEqual(len(r.context['fields']), 4)
        f0 = context_view_field(r.context, 0, 0)
        self.assertEqual(f0.field_id,     "Entity_id")
        self.assertEqual(f0.field_value,  "test1")
        f1 = context_view_field(r.context, 1, 0)
        self.assertEqual(f1.field_id,     "Entity_label")
        self.assertEqual(f1.field_value,  "test_ref_entity test1 label")
        f2 = context_view_field(r.context, 2, 0)
        self.assertEqual(f2.field_id,     "Entity_comment")
        self.assertEqual(f2.field_value,  "test_ref_entity test1 comment")
        f3 = context_view_field(r.context, 3, 0)
        basepath = TestBasePath + "/c/testcoll/d/testupltype/"
        # print "\n*****\n"+repr(context_view_field(r.context, i, 0).target_value)+"\n*****\n"
        self.assertEqual(f3.field_id,     "Test_image_ref")
        self.assertEqual(f3.field_value,        "testupltype/test1")
        self.assertEqual(f3.field_value_link,   basepath+"test1/")
        self.assertEqual(f3.target_value['upload_name'],   "upl_field")
        self.assertEqual(f3.target_value['resource_name'], "upl_field.jpg")
        self.assertEqual(f3.target_value['resource_type'], "image/jpeg")
        self.assertEqual(f3.target_value['uploaded_file'], "test-image.jpg")
        self.assertEqual(f3.target_value['uploaded_size'], 1547926)
        self.assertEqual(f3.target_value_link,  basepath+"test1/upl_field.jpg")
        # Check for rendered image link
        # log.info(r.content)
        field_details = (
            { "basepath":   TestBasePath
            , "coll_id":    "testcoll"
            , "type_id":    "testupltype"
            , "entity_id":  "test1"
            , "field_id":   "upl_field"
            , "tooltip":    ""
            })
        img_element = """
            <div class="small-12 columns" %(tooltip)s>
              <div class="row view-value-row">
                <div class="view-label small-12 medium-2 columns">
                  <span>test_image_ref_field label</span>
                </div>
                <div class="view-value small-12 medium-10 columns">
                  <a href="%(basepath)s/c/%(coll_id)s/d/%(type_id)s/%(entity_id)s/%(field_id)s.jpg" target="_blank">
                    <img src="%(basepath)s/c/%(coll_id)s/d/%(type_id)s/%(entity_id)s/%(field_id)s.jpg"
                         alt="Image at '%(basepath)s/c/%(coll_id)s/d/%(type_id)s/%(entity_id)s/%(field_id)s.jpg'" />
                  </a>
                </div>
              </div>
            </div>
            """%field_details
        self.assertContains(r, img_element, html=True)
        return

    def test_image_edit_field(self):
        # Upload to an image view field
        with open(self.imagepath, "rb") as fp:
            f = default_view_form_data(
                type_id="testimgtype", entity_id="test1", action="edit"
                )
            f['img_field'] = fp     # Upload file with submission
            u = entitydata_edit_url("edit", "testcoll", "testimgtype", entity_id="test1", view_id="testimgview")
            r = self.client.post(u, f)
        self.assertEqual(r.status_code,   302)
        self.assertEqual(r.reason_phrase, "Found")

        # Read back and compare entity resource just created
        siteobj = open(self.imagepath, "rb")
        testobj = self.test_img_type_info.get_fileobj(
            "test1", "img_field", "annal:Image", "image/jpeg", "rb"
            )
        self.assertTrue(siteobj.read() == testobj.read(), "Referenced image != original")

        # Retrieve updated form
        r = self.client.get(u)
        # Test context
        # print "@@ "+context_field_map(r.context)
        self.assertEqual(len(r.context['fields']), 4)
        f0 = context_view_field(r.context, 0, 0)
        self.assertEqual(f0.field_id,     "Entity_id")
        self.assertEqual(f0.field_value,  "test1")
        f1 = context_view_field(r.context, 1, 0)
        self.assertEqual(f1.field_id,     "Entity_label")
        f2 = context_view_field(r.context, 2, 0)
        self.assertEqual(f2.field_id,     "Entity_comment")
        f3 = context_view_field(r.context, 3, 0)
        self.assertEqual(f3.field_id,     "Test_image")
        self.assertDictionaryMatch(f3.field_value, test_image_field_value())
        return

    def test_image_view_field(self):
        # This test is for an image field that supports file upload in the same entity

        # Upload image
        self.test_image_edit_field()

        # Display resource in view mode
        u = entitydata_edit_url("view", "testcoll", "testimgtype", entity_id="test1", view_id="testimgview")
        r = self.client.get(u)
        self.assertEqual(r.status_code,   200)
        self.assertEqual(r.reason_phrase, "OK")
        # Check display context
        self.assertEqual(len(r.context['fields']), 4)
        f0 = context_view_field(r.context, 0, 0)
        self.assertEqual(f0.field_id,     "Entity_id")
        self.assertEqual(f0.field_value,  "test1")
        f1 = context_view_field(r.context, 1, 0)
        self.assertEqual(f1.field_id,     "Entity_label")
        f2 = context_view_field(r.context, 2, 0)
        self.assertEqual(f2.field_id,     "Entity_comment")
        f3 = context_view_field(r.context, 3, 0)
        basepath = TestBasePath + "/c/testcoll/d/testimgtype/"
        # print "\n*****\n"+repr(context_view_field(r.context, i, 0).target_value)+"\n*****\n"
        self.assertEqual(f3.field_id,           "Test_image")
        self.assertEqual(f3.field_value,        test_image_field_value())
        self.assertEqual(f3.target_value_link,  basepath+"test1/img_field.jpg")
        # Check for rendered image link
        # log.info(r.content)
        field_details = (
            { "basepath":   TestBasePath
            , "coll_id":    "testcoll"
            , "type_id":    "testimgtype"
            , "entity_id":  "test1"
            , "field_id":   "img_field"
            , "tooltip":    ""
            })
        img_element = """
            <div class="small-12 columns" %(tooltip)s>
              <div class="row view-value-row">
                <div class="view-label small-12 medium-2 columns">
                  <span>test_image_field label</span>
                </div>
                <div class="view-value small-12 medium-10 columns">
                  <a href="%(basepath)s/c/%(coll_id)s/d/%(type_id)s/%(entity_id)s/%(field_id)s.jpg" target="_blank">
                    <img src="%(basepath)s/c/%(coll_id)s/d/%(type_id)s/%(entity_id)s/%(field_id)s.jpg"
                         alt="Image at '%(basepath)s/c/%(coll_id)s/d/%(type_id)s/%(entity_id)s/%(field_id)s.jpg'" />
                  </a>
                </div>
              </div>
            </div>
            """%field_details
        self.assertContains(r, img_element, html=True)
        return

    def test_image_edit(self):
        # This test that entity editing leaves attachment intact

        # Upload image
        self.test_image_edit_field()

        # Edit entity
        f = default_view_form_data(
            type_id="testimgtype", entity_id="test1", action="edit", update="Updated"
            )
        u = entitydata_edit_url("edit", "testcoll", "testimgtype", entity_id="test1", view_id="testimgview")
        r = self.client.post(u, f)
        self.assertEqual(r.status_code,   302)
        self.assertEqual(r.reason_phrase, "Found")

        # Retrieve updated form
        r = self.client.get(u)
        # Test context
        self.assertEqual(len(r.context['fields']), 4)
        f0 = context_view_field(r.context, 0, 0)
        self.assertEqual(f0.field_id,     "Entity_id")
        self.assertEqual(f0.field_value,  "test1")
        f1 = context_view_field(r.context, 1, 0)
        self.assertEqual(f1.field_id,     "Entity_label")
        self.assertEqual(f1.field_value,  "Updated testcoll/testimgtype/test1")
        f2 = context_view_field(r.context, 2, 0)
        self.assertEqual(f2.field_id,     "Entity_comment")
        f3 = context_view_field(r.context, 3, 0)
        self.assertEqual(f3.field_id,     "Test_image")
        self.assertDictionaryMatch(f3.field_value, test_image_field_value())

        # Read back and compare entity resource
        siteobj = open(self.imagepath, "rb")
        testobj = self.test_img_type_info.get_fileobj(
            "test1", "img_field", "annal:Image", "image/jpeg", "rb"
            )
        self.assertTrue(siteobj.read() == testobj.read(), "Edited entity image != original")
        return

    def test_image_rename(self):
        # This test that entity renaming also copies over an attachment

        # Upload image
        self.test_image_edit_field()

        # Rename entity
        f = default_view_form_data(
            type_id="testimgtype", orig_id="test1", entity_id="test_new", action="edit"
            )
        u = entitydata_edit_url("edit", "testcoll", "testimgtype", entity_id="test1", view_id="testimgview")
        r = self.client.post(u, f)
        self.assertEqual(r.status_code,   302)
        self.assertEqual(r.reason_phrase, "Found")

        # Read back and compare renamed entity resource
        siteobj = open(self.imagepath, "rb")
        testobj = self.test_img_type_info.get_fileobj(
            "test_new", "img_field", "annal:Image", "image/jpeg", "rb"
            )
        self.assertTrue(siteobj.read() == testobj.read(), "Renamed entity image != original")
        return

    def test_inherited_image_edit(self):
        # This tests that editing an inherited image creartes a new copy in the
        # inheriting collection.

        # Upload image
        self.test_image_edit_field()

        # Create collection inheriting uploaded image
        testsubcoll = create_test_coll_inheriting(
            base_coll_id="testcoll", coll_id="testsubcoll", type_id="testtype"
            )
        # create_test_user(testsubcoll, "testuser", "testpassword")
        user_permissions = ["VIEW", "CREATE", "UPDATE", "DELETE", "CONFIG"]
        user_id          = "testuser"
        user_perms = testsubcoll.create_user_permissions(
            user_id, "mailto:%s@%s"%(user_id, TestHost),
            "Test User",
            "User %s: permissions for %s in collection %s"%(user_id, "Test User", testsubcoll.get_id()),
            user_permissions)

        # Get editing form
        u = entitydata_edit_url(
            "edit", "testsubcoll", "testimgtype", entity_id="test1", view_id="testimgview"
            )
        r = self.client.get(u)
        self.assertEqual(r.status_code,   200)
        self.assertEqual(r.reason_phrase, "OK")
        # log.info(r.content)     #@@
        hi1 = """<input type="hidden" name="orig_id"          value="test1" />"""
        hi2 = """<input type="hidden" name="orig_type"        value="testimgtype" />"""
        hi3 = """<input type="hidden" name="orig_coll"        value="testcoll" />"""
        hi4 = """<input type="hidden" name="action"           value="edit" />"""
        hi5 = """<input type="hidden" name="view_id"          value="testimgview" />"""
        self.assertContains(r, hi1, html=True)
        self.assertContains(r, hi2, html=True)
        self.assertContains(r, hi3, html=True)
        self.assertContains(r, hi4, html=True)
        self.assertContains(r, hi5, html=True)

        # Edit entity
        f = default_view_form_data(
            coll_id="testsubcoll", type_id="testimgtype", entity_id="test1", 
            orig_coll="testcoll", action="edit", 
            update="Updated"
            )
        u = entitydata_edit_url(
            "edit", "testsubcoll", "testimgtype", entity_id="test1", view_id="testimgview"
            )
        r = self.client.post(u, f)
        self.assertEqual(r.status_code,   302)
        self.assertEqual(r.reason_phrase, "Found")

        # Retrieve updated form
        r = self.client.get(u)
        # Test context
        self.assertEqual(len(r.context['fields']), 4)
        f0 = context_view_field(r.context, 0, 0)
        self.assertEqual(f0.field_id,     "Entity_id")
        self.assertEqual(f0.field_value,  "test1")
        f1 = context_view_field(r.context, 1, 0)
        self.assertEqual(f1.field_id,     "Entity_label")
        self.assertEqual(f1.field_value,  "Updated testsubcoll/testimgtype/test1")
        f2 = context_view_field(r.context, 2, 0)
        self.assertEqual(f2.field_id,     "Entity_comment")
        f3 = context_view_field(r.context, 3, 0)
        self.assertEqual(f3.field_id,     "Test_image")
        self.assertDictionaryMatch(f3.field_value, test_image_field_value())

        # Read back and compare entity resource
        inherited_test_img_type_info = EntityTypeInfo(
            testsubcoll, "testimgtype", create_typedata=True
            )
        siteobj = open(self.imagepath, "rb")
        testobj = inherited_test_img_type_info.get_fileobj(
            "test1", "img_field", "annal:Image", "image/jpeg", "rb"
            )
        self.assertTrue(siteobj.read() == testobj.read(), "Edited entity image != original")
Beispiel #47
0
class ImageReferenceTest(AnnalistTestCase):
    """
    Tests image URI reference
    """

    def setUp(self):
        self.filepath  = "%s/README.md"%TestBaseDir
        self.fileuri   = "file://"+self.filepath
        self.imagepath = "%s/test-image.jpg"%TestBaseDir
        self.imageuri  = "file://"+self.filepath
        init_annalist_test_site()
        init_annalist_test_coll()
        self.testsite    = Site(TestBaseUri, TestBaseDir)
        self.testcoll    = Collection(self.testsite, "testcoll")
        # Populate collection with record type, view and field
        self.test_ref_type = RecordType.create(
            self.testcoll, "testreftype", test_image_ref_type_create_values
            )
        self.test_ref_view = RecordView.create(
            self.testcoll, "testrefview", test_image_ref_view_create_values
            )
        self.test_ref_field = RecordField.create(
            self.testcoll, "Test_image_ref", test_image_ref_field_create_values
            )
        # Create data records for testing image references:
        self.test_ref_type_info = EntityTypeInfo(
            self.testcoll, "testreftype", create_typedata=True
            )
        self.test_ref_type_info.create_entity("test1", test_ref_entity_create_values(self.imageuri))
        # Login and permissions
        create_test_user(self.testcoll, "testuser", "testpassword")
        self.client = Client(HTTP_HOST=TestHost)
        loggedin = self.client.login(username="******", password="******")
        self.assertTrue(loggedin)
        return

    def tearDown(self):
        # resetSitedata(scope="collections")
        return

    @classmethod
    def tearDownClass(cls):
        resetSitedata(scope="collections")
        return

    # Utility functions

    # Tests

    def test_reference_image(self):

        # Display resource with image reference
        u = entitydata_edit_url("view", "testcoll", "testreftype", entity_id="test1", view_id="testrefview")
        r = self.client.get(u)
        self.assertEqual(r.status_code,   200)
        self.assertEqual(r.reason_phrase, "OK")
        # Check display context
        self.assertEqual(len(r.context['fields']), 4)
        f0 = context_view_field(r.context, 0, 0)
        self.assertEqual(f0.field_id,           "Entity_id")
        self.assertEqual(f0.field_value,        "test1")
        f1 = context_view_field(r.context, 1, 0)
        self.assertEqual(f1.field_id,           "Entity_label")
        self.assertEqual(f1.field_value,        "test_ref_image label")
        f2 = context_view_field(r.context, 2, 0)
        self.assertEqual(f2.field_id,           "Entity_comment")
        self.assertEqual(f2.field_value,        "test_ref_image comment")
        f3 = context_view_field(r.context, 3, 0)
        basepath = TestBasePath + "/c/testcoll/d/testreftype/"
        # print "\n*****\n"+repr(f3)+"\n*****\n"
        self.assertEqual(f3.field_id,           "Test_image_ref")
        self.assertEqual(f3.field_value,        self.imageuri)
        self.assertEqual(f3.field_value_link,   None)
        self.assertEqual(f3.target_value,       self.imageuri)
        self.assertEqual(f3.target_value_link,  self.imageuri)
        # Check for rendered image link
        # log.info(r.content)
        field_details = (
            { "basepath":   TestBasePath
            , "coll_id":    "testcoll"
            , "type_id":    "testupltype"
            , "entity_id":  "test1"
            , "image_uri":  self.imageuri
            , "field_id":   "ref_image"
            , "tooltip":    "" # 'title="%s"'%r.context['fields'][i].field_help
            })
        img_element = """
            <div class="small-12 columns" %(tooltip)s>
              <div class="row view-value-row">
                <div class="view-label small-12 medium-2 columns">
                  <span>test_image_ref_field label</span>
                </div>
                <div class="view-value small-12 medium-10 columns">
                  <a href="%(image_uri)s" target="_blank">
                    <img src="%(image_uri)s"
                         alt="Image at '%(image_uri)s'" />
                  </a>
                </div>
              </div>
            </div>
            """%field_details
        self.assertContains(r, img_element, html=True)
        return
class LinkedRecordTest(AnnalistTestCase):
    """
    Tests for linked records
    """

    def setUp(self):
        init_annalist_test_site()
        init_annalist_test_coll()
        self.testsite    = Site(TestBaseUri, TestBaseDir)
        self.testcoll    = Collection(self.testsite, "testcoll")
        # Populate collection with linked record types, views and lists
        self.testsrc_type = RecordType.create(self.testcoll, "testsrc_type", testsrc_type_create_values)
        self.testtgt_type = RecordType.create(self.testcoll, "testtgt_type", testtgt_type_create_values)
        self.testsrc_view = RecordView.create(self.testcoll, "testsrc_view", testsrc_view_create_values)
        self.testtgt_view = RecordView.create(self.testcoll, "testtgt_view", testtgt_view_create_values)
        self.testsrc_list = RecordList.create(self.testcoll, "testsrc_list", testsrc_list_create_values)
        self.testtgt_list = RecordList.create(self.testcoll, "testtgt_list", testtgt_list_create_values)
        self.testtgtref_field = RecordField.create(self.testcoll, "testtgtref_field", testtgtref_field_create_values)
        self.no_options   = [ FieldChoice('', label="(no options)") ]
        self.tgt_options  = (
            [ FieldChoice("testtgt_type/"+v, 
                label="testtgt_entity %s label"%v,
                link=entity_url("testcoll", "testtgt_type", v))
              for v in ["testtgt1", "testtgt2"]
            ])
        # Create data records for testing:
        self.testtgt_type_info = EntityTypeInfo(self.testcoll, "testtgt_type", create_typedata=True)
        self.testsrc_type_info = EntityTypeInfo(self.testcoll, "testsrc_type", create_typedata=True)
        for tgt_id in ("testtgt1", "testtgt2"):
            self.testtgt_type_info.create_entity(tgt_id, testtgt_entity_create_values(tgt_id))
        for src_id, tgt_ref in (("testsrc1", "testtgt1"), ("testsrc2", "testtgt2")):
            self.testsrc_type_info.create_entity(src_id, testsrc_entity_create_values(src_id, tgt_ref))
        # Login and permissions
        create_test_user(self.testcoll, "testuser", "testpassword")
        self.client = Client(HTTP_HOST=TestHost)
        loggedin = self.client.login(username="******", password="******")
        self.assertTrue(loggedin)
        return

    def tearDown(self):
        # resetSitedata(scope="collections")
        return

    @classmethod
    def tearDownClass(cls):
        resetSitedata()
        return

    # Utility functions

    # Tests

    def test_view_entity_references(self):
        u = entity_url(coll_id="testcoll", type_id="testsrc_type", entity_id="testsrc1")
        r = self.client.get(u)
        self.assertEqual(r.status_code,   200)
        self.assertEqual(r.reason_phrase, "OK")
        # Test context
        self.assertEqual(len(r.context['fields']), 3)
        f0 = context_view_field(r.context, 0, 0)
        self.assertEqual(f0.field_id,         "Entity_id")
        self.assertEqual(f0.field_value,      "testsrc1")
        self.assertEqual(f0.field_value_link, None)
        self.assertEqual(f0.options,          self.no_options)
        f1 = context_view_field(r.context, 0, 1)
        self.assertEqual(f1.field_id,         "testtgtref_field")
        self.assertEqual(f1.field_value,      "testtgt_type/testtgt1")
        self.assertEqual(f1.field_value_link, "/testsite/c/testcoll/d/testtgt_type/testtgt1/")
        self.assertEqual(f1.options,          self.tgt_options)
        f2 = context_view_field(r.context, 1, 0)
        self.assertEqual(f2.field_id,         "Entity_label")
        self.assertEqual(f2.field_value,      "testsrc_entity testsrc1 label")
        self.assertEqual(f2.field_value_link, None)
        self.assertEqual(f2.options,          self.no_options)
        f3 = context_view_field(r.context, 2, 0)
        self.assertEqual(f3.field_id,         "Entity_comment")
        self.assertEqual(f3.field_value,      "testsrc_entity testsrc1 comment")
        self.assertEqual(f3.field_value_link, None)
        self.assertEqual(f3.options,          self.no_options)
        return

    def test_list_entity_references(self):
        # List linked records - check values in listing
        u = entitydata_list_type_url("testcoll", "testsrc_type", list_id="testsrc_list")
        r = self.client.get(u)
        self.assertEqual(r.status_code,   200)
        self.assertEqual(r.reason_phrase, "OK")
        # Test context
        entities    = context_list_entities(r.context)
        head_fields = context_list_head_fields(r.context)
        # print "@@ context: "+repr(r.context['List_rows'])
        # print "@@ head_fields: "+repr(head_fields)
        self.assertEqual(len(entities),    2)
        self.assertEqual(len(head_fields), 1)       # One row of 3 cols..
        self.assertEqual(len(head_fields[0]['row_field_descs']), 3)
        entity_values = (
            (entities[0], "testsrc1", "testtgt1"), 
            (entities[1], "testsrc2", "testtgt2")
            )
        for entc, esrc, etgt in entity_values:
            item_fields = context_list_item_fields(r.context, entc)
            self.assertEqual(len(item_fields), 3)
            self.assertEqual(entc['entity_id'],               esrc)
            self.assertEqual(entc['entity_type_id'],          "testsrc_type")
            self.assertEqual(item_fields[0].field_id,         "Entity_id")
            self.assertEqual(item_fields[0].field_value,      esrc)
            self.assertEqual(item_fields[0].field_value_link, None)
            self.assertEqual(item_fields[1].field_id,         "testtgtref_field")
            self.assertEqual(item_fields[1].field_value,      "testtgt_type/"+etgt)
            self.assertEqual(item_fields[1].field_value_link, "/testsite/c/testcoll/d/testtgt_type/%s/"%etgt)
            self.assertEqual(item_fields[2].field_id,         "Entity_label")
            self.assertEqual(item_fields[2].field_value,      "testsrc_entity %s label"%esrc)
            self.assertEqual(item_fields[2].field_value_link, None)
        return
Beispiel #49
0
 def get_uri_type_info(self, type_uri):
     """
     Return typeinfo corresponding to the supplied type URI
     """
     t = self._coll.get_uri_type(type_uri)
     return t and EntityTypeInfo(self._coll, t.get_id())
class ImportResourceTest(AnnalistTestCase):
    """
    Tests for resource import
    """

    def setUp(self):
        self.fileuri = "file://%s/README.md"%TestBaseDir
        init_annalist_test_site()
        init_annalist_test_coll()
        self.testsite    = Site(TestBaseUri, TestBaseDir)
        self.testcoll    = Collection(self.testsite, "testcoll")
        # Populate collection with linked record types, views and lists
        self.test_imp_type = RecordType.create(
            self.testcoll, "testimptype", test_import_type_create_values
            )
        self.test_imp_view = RecordView.create(
            self.testcoll, "testimpview", test_import_view_create_values
            )
        self.test_imp_field = RecordField.create(
            self.testcoll, "Test_import", test_import_field_create_values
            )
        self.test_ref_type = RecordType.create(
            self.testcoll, "testreftype", test_reference_type_create_values
            )
        self.test_ref_view = RecordView.create(
            self.testcoll, "testrefview", test_reference_view_create_values
            )
        self.test_ref_field = RecordField.create(
            self.testcoll, "Test_reference", test_reference_field_create_values
            )
        # Create data records for testing import and references:
        self.test_imp_type_info = EntityTypeInfo(
            self.testcoll, "testimptype", create_typedata=True
            )
        for entity_id in ("test1", "test2"):
            self.test_imp_type_info.create_entity(
                entity_id, test_imp_entity_create_values(entity_id)
                )
        self.test_ref_type_info = EntityTypeInfo(
            self.testcoll, "testreftype", create_typedata=True
            )
        for entity_id in ("test1", "test2"):
            self.test_ref_type_info.create_entity(
                entity_id, test_ref_entity_create_values(entity_id)
                )
        # Login and permissions
        create_test_user(self.testcoll, "testuser", "testpassword")
        self.client = Client(HTTP_HOST=TestHost)
        loggedin = self.client.login(username="******", password="******")
        self.assertTrue(loggedin)
        return

    def tearDown(self):
        # resetSitedata(scope="collections")
        return

    @classmethod
    def tearDownClass(cls):
        resetSitedata()
        return

    # Utility functions

    # Tests

    def test_entity_fileobj(self):
        test1    = self.test_imp_type_info.get_entity("test1")
        test1dir, test1file = test1._dir_path()
        testobj1 = self.test_imp_type_info.get_fileobj(
            "test1", "test1res", "annal:Text", "text/plain", "wb"
            )
        testobj1.write("Test data test1res.txt")
        self.assertEqual(testobj1.name, test1dir+"/test1res.txt")
        testobj1.close()
        testobj2 = self.test_imp_type_info.get_fileobj(
            "test1", "test1res", "annal:Text", "text/plain", "rb"
            )
        self.assertEqual(testobj2.read(), "Test data test1res.txt")
        testobj2.close()
        return

    def test_util_fileobj(self):
        resource_fileobj, resource_url, resource_type = util.open_url(self.fileuri)
        self.assertEqual(resource_url,  self.fileuri)
        self.assertEqual(resource_type, "text/markdown")
        testobj1 = self.test_imp_type_info.get_fileobj(
            "test1", "test1res", "annal:Richtext", resource_type, "wb"
            )
        util.copy_resource_to_fileobj(resource_fileobj, testobj1)
        resource_fileobj.close()
        testobj1.close()
        # Read back both and compare
        siteobj = open(TestBaseDir+"/README.md", "rb")
        testobj = self.test_imp_type_info.get_fileobj(
            "test1", "test1res", "annal:Richtext", resource_type, "rb"
            )
        self.assertEqual(siteobj.read(), testobj.read())
        return

    def test_import_resource(self):
        f = entitydata_default_view_form_data(
            entity_id="test1", type_id="testimptype", action="edit", 
            do_import="imp_field__import"
            )
        f['imp_field'] = self.fileuri
        u = entitydata_edit_url(
            "edit", "testcoll", "testimptype", entity_id="test1", view_id="testimpview"
            )
        r = self.client.post(u, f)
        self.assertEqual(r.status_code,   302)
        self.assertEqual(r.reason_phrase, "FOUND")
        self.assertMatch(r['location'], TestHostUri+u)
        # Read back form following redirect
        r = self.client.get(u)
        self.assertEqual(r.status_code,   200)
        self.assertEqual(r.reason_phrase, "OK")
        # Test context
        self.assertEqual(len(r.context['fields']), 4)
        f0 = context_view_field(r.context, 0, 0)
        self.assertEqual(f0.field_id,     "Entity_id")
        self.assertEqual(f0.field_value,  "test1")
        f1 = context_view_field(r.context, 1, 0)
        self.assertEqual(f1.field_id,     "Entity_label")
        f2 = context_view_field(r.context, 2, 0)
        self.assertEqual(f2.field_id,     "Entity_comment")
        f3 = context_view_field(r.context, 3, 0)
        self.assertEqual(f3.field_id,     "Test_import")
        self.assertDictionaryMatch(f3.field_value, test_import_field_value())
        # Read back and compare entity resource just created
        siteobj = open(TestBaseDir+"/README.md", "rb")
        testobj = self.test_imp_type_info.get_fileobj(
            "test1", "imp_field", "annal:Richtext", "text/markdown", "rb"
            )
        self.assertEqual(siteobj.read(), testobj.read())
        return

    def test_reference_imported_resource(self):
        # Create imported resource (see previous test)
        f = entitydata_default_view_form_data(
            entity_id="test1", type_id="testimptype", action="edit", 
            do_import="imp_field__import"
            )
        f['imp_field'] = self.fileuri
        u = entitydata_edit_url(
            "edit", "testcoll", "testimptype", entity_id="test1", view_id="testimpview"
            )
        r = self.client.post(u, f)
        self.assertEqual(r.status_code,   302)
        self.assertEqual(r.reason_phrase, "FOUND")
        # Display resource with reference
        u = entitydata_edit_url(
            "view", "testcoll", "testreftype", entity_id="test1", view_id="testrefview"
            )
        r = self.client.get(u)
        self.assertEqual(r.status_code,   200)
        self.assertEqual(r.reason_phrase, "OK")
        # Check display context
        self.assertEqual(len(r.context['fields']), 4)
        f0 = context_view_field(r.context, 0, 0)
        self.assertEqual(f0.field_id,     "Entity_id")
        self.assertEqual(f0.field_value,  "test1")
        f1 = context_view_field(r.context, 1, 0)
        self.assertEqual(f1.field_id,     "Entity_label")
        self.assertEqual(f1.field_value,  "test_ref_entity test1 label")
        f2 = context_view_field(r.context, 2, 0)
        self.assertEqual(f2.field_id,     "Entity_comment")
        self.assertEqual(f2.field_value,  "test_ref_entity test1 comment")
        f3 = context_view_field(r.context, 3, 0)
        basepath = TestBasePath + "/c/testcoll/d/testimptype/"
        self.assertEqual(f3.field_id,           "Test_reference")
        self.assertEqual(f3.field_value,        "testimptype/test1")
        self.assertEqual(f3.field_value_link,   basepath+"test1/")
        self.assertEqual(f3.target_value['import_name'],   "imp_field")
        self.assertEqual(f3.target_value['resource_name'], "imp_field.md")
        self.assertEqual(f3.target_value['resource_type'], "text/markdown")
        self.assertEqual(f3.target_value_link,  basepath+"test1/imp_field.md")
        return
Beispiel #51
0
    def post(self,
             request,
             coll_id=None,
             type_id=None,
             list_id=None,
             scope=None):
        """
        Handle response from dynamically generated list display form.
        """
        log.info("views.entitylist.post: coll_id %s, type_id %s, list_id %s" %
                 (coll_id, type_id, list_id))
        # log.info("  %s"%(self.get_request_path()))
        # log.info("  form data %r"%(request.POST))
        continuation_next, continuation_here = self.continuation_urls(
            request.POST, None
            # self.view_uri("AnnalistSiteView")
            # self.view_uri("AnnalistCollectionEditView", coll_id=coll_id)
        )
        if 'close' in request.POST:
            return HttpResponseRedirect(
                continuation_next.get('continuation_url',
                                      self.view_uri("AnnalistSiteView")))

        # Not "Close": set up list parameters
        listinfo = self.list_setup(coll_id, type_id, list_id)
        if listinfo.http_response:
            return listinfo.http_response

        # Process requested action
        redirect_uri = None
        entity_ids = request.POST.getlist('entity_select')
        log.debug("entity_ids %r" % (entity_ids))
        if len(entity_ids) > 1:
            action = ""
            redirect_uri = self.check_value_supplied(
                None, message.TOO_MANY_ENTITIES_SEL)
        else:
            (entity_type, entity_id) = (entity_ids[0].split("/") if
                                        len(entity_ids) == 1 else (None, None))
            entity_type = entity_type or type_id or listinfo.get_list_type_id()
            if "new" in request.POST:
                action = "new"
                redirect_uri = uri_with_params(
                    listinfo.get_new_view_uri(coll_id, entity_type),
                    continuation_here)
            if "copy" in request.POST:
                action = "copy"
                redirect_uri = (self.check_value_supplied(
                    entity_id,
                    message.NO_ENTITY_FOR_COPY,
                    continuation_url=continuation_next) or uri_with_params(
                        listinfo.get_edit_view_uri(coll_id, entity_type,
                                                   entity_id, action),
                        continuation_here))
            if "edit" in request.POST:
                action = "edit"
                redirect_uri = (self.check_value_supplied(
                    entity_id,
                    message.NO_ENTITY_FOR_EDIT,
                    continuation_url=continuation_next) or uri_with_params(
                        listinfo.get_edit_view_uri(coll_id, entity_type,
                                                   entity_id, action),
                        continuation_here))
            if "delete" in request.POST:
                action = "delete"
                redirect_uri = (self.check_value_supplied(
                    entity_id,
                    message.NO_ENTITY_FOR_DELETE,
                    continuation_url=continuation_next)
                                or listinfo.check_collection_entity(
                                    entity_id,
                                    entity_type,
                                    message.SITE_ENTITY_FOR_DELETE %
                                    {'id': entity_id},
                                    continuation_url=continuation_next)
                                or self.check_delete_type_values(
                                    listinfo,
                                    entity_id,
                                    entity_type,
                                    message.TYPE_VALUES_FOR_DELETE %
                                    {'type_id': entity_id},
                                    continuation_url=continuation_next))
                if not redirect_uri:
                    # Get user to confirm action before actually doing it
                    confirmed_action_uri = self.view_uri(
                        "AnnalistEntityDataDeleteView",
                        coll_id=coll_id,
                        type_id=entity_type)
                    # log.info("coll_id %s, type_id %s, confirmed_action_uri %s"%(coll_id, entity_type, confirmed_action_uri))
                    delete_params = dict_querydict({
                        "entity_delete": ["Delete"],
                        "entity_id": [entity_id],
                        "completion_url":
                        [continuation_here['continuation_url']],
                        "continuation_url":
                        [continuation_next.get('continuation_url')],
                        "search_for": [request.POST['search_for']]
                    })
                    message_vals = {
                        'id': entity_id,
                        'type_id': entity_type,
                        'coll_id': coll_id
                    }
                    typeinfo = listinfo.entitytypeinfo
                    if typeinfo is None:
                        typeinfo = EntityTypeInfo(listinfo.site,
                                                  listinfo.collection,
                                                  entity_type)
                    return (self.form_action_auth(
                        "delete", listinfo.collection,
                        typeinfo.permissions_map) or ConfirmView.render_form(
                            request,
                            action_description=message.REMOVE_ENTITY_DATA %
                            message_vals,
                            confirmed_action_uri=confirmed_action_uri,
                            action_params=delete_params,
                            cancel_action_uri=self.get_request_path(),
                            title=self.site_data()["title"]))
            if "default_view" in request.POST:
                if listinfo.entitytypeinfo:
                    permissions_map = listinfo.entitytypeinfo.permissions_map
                else:
                    permissions_map = CONFIG_PERMISSIONS
                auth_check = self.form_action_auth("config",
                                                   listinfo.collection,
                                                   permissions_map)
                if auth_check:
                    return auth_check
                listinfo.collection.set_default_list(list_id)
                action = "list"
                msg = message.DEFAULT_VIEW_UPDATED % {
                    'coll_id': coll_id,
                    'list_id': list_id
                }
                redirect_uri = (uri_with_params(self.get_request_path(),
                                                self.info_params(msg),
                                                continuation_next))
            if ("view" in request.POST) or ("view_all" in request.POST):
                action = "list"
                search = request.POST['search_for']
                params = continuation_next
                if search:
                    params = dict(params, search=search)
                list_uri_params = ({
                    'coll_id': coll_id,
                    'list_id': request.POST['list_choice']
                })
                if "view_all" in request.POST:
                    list_uri_params['scope'] = "all"
                #@@
                # if type_id:
                #     list_uri_params.update({'type_id': type_id})
                #@@
                redirect_uri = (uri_with_params(
                    self.view_uri("AnnalistEntityGenericList",
                                  **list_uri_params), params))
            if "customize" in request.POST:
                action = "config"
                redirect_uri = (uri_with_params(
                    self.view_uri("AnnalistCollectionEditView",
                                  coll_id=coll_id), continuation_here))
        if redirect_uri:
            return (listinfo.check_authorization(action)
                    or HttpResponseRedirect(redirect_uri))
        # Report unexpected form data
        # This shouldn't happen, but just in case...
        # Redirect to continuation with error
        log.error("Unexpected form data posted to %s: %r" %
                  (request.get_full_path(), request.POST))
        err_values = self.error_params(
            message.UNEXPECTED_FORM_DATA % (request.POST),
            message.SYSTEM_ERROR)
        redirect_uri = uri_with_params(continuation_next['continuation_url'],
                                       err_values)
        return HttpResponseRedirect(redirect_uri)
Beispiel #52
0
 def check_entity_does_not_exist(self, type_id, entity_id):
     "Helper function checks non-existence of entity record"
     typeinfo = EntityTypeInfo(self.testcoll, type_id)
     self.assertFalse(typeinfo.entity_exists(entity_id))
     return