Exemple #1
0
 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
Exemple #2
0
 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
Exemple #3
0
 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 am_migratecollection(annroot, userhome, options):
    """
    Apply migrations for a specified collection

        annalist_manager migratecollection coll

    Reads and writes every entity in a collection, thereby applying data 
    migrations and saving them in the stored data.

    annroot     is the root directory for the Annalist software installation.
    userhome    is the home directory for the host system user issuing the command.
    options     contains options parsed from the command line.

    returns     0 if all is well, or a non-zero status code.
                This value is intended to be used as an exit status code
                for the calling program.
    """
    status, settings, site = get_settings_site(annroot, userhome, options)
    if status != am_errors.AM_SUCCESS:
        return status
    coll_id = getargvalue(getarg(options.args, 0), "Collection Id: ")
    coll = Collection.load(site, coll_id)
    if not (coll and coll.get_values()):
        print("Collection not found: %s" % (coll_id), file=sys.stderr)
        return am_errors.AM_NOCOLLECTION
    status = am_errors.AM_SUCCESS
    print("Apply data migrations in collection '%s'" % (coll_id, ))
    msgs = migrate_coll_data(coll)
    if msgs:
        for msg in msgs:
            print(msg)
        status = am_errors.AM_MIGRATECOLLFAIL
    return status
def am_migratecollection(annroot, userhome, options):
    """
    Apply migrations for a specified collection

        annalist_manager migratecollection coll

    Reads and writes every entity in a collection, thereby applying data 
    migrations and saving them in the stored data.

    annroot     is the root directory for the Annalist software installation.
    userhome    is the home directory for the host system user issuing the command.
    options     contains options parsed from the command line.

    returns     0 if all is well, or a non-zero status code.
                This value is intended to be used as an exit status code
                for the calling program.
    """
    status, settings, site = get_settings_site(annroot, userhome, options)
    if status != am_errors.AM_SUCCESS:
        return status
    coll_id = getargvalue(getarg(options.args, 0), "Collection Id: ")
    coll    = Collection.load(site, coll_id)
    if not (coll and coll.get_values()):
        print("Collection not found: %s"%(coll_id), file=sys.stderr)
        return am_errors.AM_NOCOLLECTION
    status = am_errors.AM_SUCCESS
    print("Apply data migrations in collection '%s'"%(coll_id,))
    msgs   = migrate_coll_data(coll)
    if msgs:
        for msg in msgs:
            print(msg)
        status = am_errors.AM_MIGRATECOLLFAIL
    return status
Exemple #6
0
 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
Exemple #7
0
 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 am_migrateallcollections(annroot, userhome, options):
    """
    Apply migrations to all collections

        annalist_manager migrateallcollections

    Reads and writes every entity in all collections, thereby 
    applying data migrations and saving them in the stored data.

    annroot     is the root directory for the Annalist software installation.
    userhome    is the home directory for the host system user issuing the command.
    options     contains options parsed from the command line.

    returns     0 if all is well, or a non-zero status code.
                This value is intended to be used as an exit status code
                for the calling program.
    """
    status, settings, site = get_settings_site(annroot, userhome, options)
    if status != am_errors.AM_SUCCESS:
        return status
    print("Apply data migrations in all collections:")
    for coll in site.collections():
        status = am_check_site_updated(coll)
        if status != am_errors.AM_SUCCESS:
            return status
        coll_id = coll.get_id()
        if coll_id != layout.SITEDATA_ID:
            log.debug("========== Processing '%s' =========="%(coll_id,))
            print("---- Processing '%s'"%(coll_id,))
            msgs   = migrate_coll_data(coll)
            if msgs:
                for msg in msgs:
                    print(msg)
                status = am_errors.AM_MIGRATECOLLFAIL
    print("Data migrations complete.")
    return status
Exemple #9
0
 def post(self, request, coll_id):
     """
     Update some aspect of the current collection
     """
     # Note: in many cases, this function redirects to a URI that displays a form
     #       to gather further details of values to update.  Values returned by
     #       POST to this view are then passed as URI segments in the GET request
     #       that renders the form.  Maybe there's an easier way than all this
     #       URI-wrangling?
     redirect_uri = None
     http_response = None
     viewinfo = self.collection_edit_setup(coll_id, "config",
                                           request.POST.dict())
     if viewinfo.http_response:
         return viewinfo.http_response
     if "close" in request.POST:
         redirect_uri = viewinfo.get_continuation_next()
     if "migrate" in request.POST:
         msgs = migrate_coll_data(viewinfo.collection)
         msg_vals = {'id': coll_id}
         if msgs:
             for msg in msgs:
                 log.warning(msg)
             err = message.MIGRATE_COLLECTION_ERROR % msg_vals
             msg = "\n".join([err] + msgs)
             log.error(msg)
             http_response = self.error(
                 dict(self.error500values(), message=msg))
         else:
             # Redisplay current page with completion message
             viewuri = self.get_request_path()
             http_response = self.redirect_info(
                 self.get_request_path(),
                 view_params=continuation_params(uri_param_dict(viewuri)),
                 info_message=message.MIGRATED_COLLECTION_DATA % msg_vals)
         return http_response
     # Edit collection metadata
     if "metadata" in request.POST:
         redirect_uri = self.item_edit_uri(layout.SITEDATA_ID, "_coll",
                                           "Collection_view", coll_id,
                                           message.NO_COLLECTION_METADATA,
                                           viewinfo.get_continuation_here(),
                                           viewinfo.get_continuation_url())
     # Record types
     type_id = request.POST.get('typelist', None)
     if "type_new" in request.POST:
         redirect_uri = self.item_new_uri(coll_id, "_type", "Type_view",
                                          viewinfo.get_continuation_here())
     if "type_copy" in request.POST:
         redirect_uri = self.item_copy_uri(coll_id, "_type", "Type_view",
                                           type_id,
                                           message.NO_TYPE_FOR_COPY,
                                           viewinfo.get_continuation_here(),
                                           viewinfo.get_continuation_url())
     if "type_edit" in request.POST:
         redirect_uri = self.item_edit_uri(coll_id, "_type", "Type_view",
                                           type_id,
                                           message.NO_TYPE_FOR_COPY,
                                           viewinfo.get_continuation_here(),
                                           viewinfo.get_continuation_url())
     if "type_delete" in request.POST:
         http_response = viewinfo.confirm_delete_entity_response(
             layout.TYPE_TYPEID,
             type_id,
             self.view_uri("AnnalistRecordTypeDeleteView", coll_id=coll_id),
             form_action_field="type_delete",
             form_value_field="typelist",
             response_messages={
                 "no_entity": message.NO_TYPE_FOR_DELETE,
                 "confirm_completion": message.REMOVE_RECORD_TYPE
             })
     # List views
     list_id = request.POST.get('listlist', None)
     if "list_new" in request.POST:
         redirect_uri = self.item_new_uri(coll_id, "_list", "List_view",
                                          viewinfo.get_continuation_here())
     if "list_copy" in request.POST:
         redirect_uri = self.item_copy_uri(coll_id, "_list", "List_view",
                                           list_id,
                                           message.NO_LIST_FOR_COPY,
                                           viewinfo.get_continuation_here(),
                                           viewinfo.get_continuation_url())
     if "list_edit" in request.POST:
         redirect_uri = self.item_edit_uri(coll_id, "_list", "List_view",
                                           list_id,
                                           message.NO_LIST_FOR_COPY,
                                           viewinfo.get_continuation_here(),
                                           viewinfo.get_continuation_url())
     if "list_delete" in request.POST:
         http_response = viewinfo.confirm_delete_entity_response(
             layout.LIST_TYPEID,
             list_id,
             self.view_uri("AnnalistRecordListDeleteView", coll_id=coll_id),
             form_action_field="list_delete",
             form_value_field="listlist",
             response_messages={
                 "no_entity": message.NO_LIST_FOR_DELETE,
                 "confirm_completion": message.REMOVE_RECORD_LIST
             })
     # Record views
     view_id = request.POST.get('viewlist', None)
     if "view_new" in request.POST:
         redirect_uri = self.item_new_uri(coll_id, "_view", "View_view",
                                          viewinfo.get_continuation_here())
     if "view_copy" in request.POST:
         redirect_uri = self.item_copy_uri(coll_id, "_view", "View_view",
                                           view_id,
                                           message.NO_VIEW_FOR_COPY,
                                           viewinfo.get_continuation_here(),
                                           viewinfo.get_continuation_url())
     if "view_edit" in request.POST:
         redirect_uri = self.item_edit_uri(coll_id, "_view", "View_view",
                                           view_id,
                                           message.NO_VIEW_FOR_COPY,
                                           viewinfo.get_continuation_here(),
                                           viewinfo.get_continuation_url())
     if "view_delete" in request.POST:
         http_response = viewinfo.confirm_delete_entity_response(
             layout.VIEW_TYPEID,
             view_id,
             self.view_uri("AnnalistRecordViewDeleteView", coll_id=coll_id),
             form_action_field="view_delete",
             form_value_field="viewlist",
             response_messages={
                 "no_entity": message.NO_VIEW_FOR_DELETE,
                 "confirm_completion": message.REMOVE_RECORD_VIEW
             })
     # Invoke selected view and/or render status response
     if redirect_uri:
         http_response = http_response or HttpResponseRedirect(redirect_uri)
     if http_response:
         return http_response
     e = Annalist_Error(
         request.POST,
         "Unexpected values in POST to " + self.get_request_path())
     log.exception(str(e))
     return self.error(
         dict(self.error500values(),
              message=str(e) + " - see server log for details"))
Exemple #10
0
 def post(self, request, coll_id):
     """
     Update some aspect of the current collection
     """
     # Note: in many cases, this function redirects to a URI that displays a form
     #       to gather further details of values to update.  Values returned by
     #       POST to this view are then passed as URI segments in the GET request
     #       that renders the form.  Maybe there's an easier way than all this 
     #       URI-wrangling?
     redirect_uri  = None
     http_response = None
     viewinfo = self.collection_edit_setup(coll_id, "config", request.POST.dict())
     if viewinfo.http_response:
         return viewinfo.http_response
     if "close" in request.POST:
         redirect_uri = viewinfo.get_continuation_next()
     if "migrate" in request.POST:
         msgs = migrate_coll_data(viewinfo.collection)
         msg_vals = {'id': coll_id}
         if msgs:
             for msg in msgs:
                 log.warning(msg)
             err = message.MIGRATE_COLLECTION_ERROR%msg_vals
             msg = "\n".join([err]+msgs)
             log.error(msg)
             http_response = self.error(dict(self.error500values(),message=msg))
         else:
             # Redisplay current page with completion message
             viewuri = self.get_request_path()
             http_response = self.redirect_info(
                 self.get_request_path(),
                 view_params=continuation_params(uri_param_dict(viewuri)),
                 info_message=message.MIGRATED_COLLECTION_DATA%msg_vals
                 )
         return http_response
     # Edit collection metadata
     if "metadata" in request.POST:
         redirect_uri = self.item_edit_uri(
             layout.SITEDATA_ID, "_coll", "Collection_view", coll_id, 
             message.NO_COLLECTION_METADATA, 
             viewinfo.get_continuation_here(),
             viewinfo.get_continuation_url()
             )
     # Record types
     type_id = request.POST.get('typelist', None)
     if "type_new" in request.POST:
         redirect_uri = self.item_new_uri(
             coll_id, "_type", "Type_view", 
             viewinfo.get_continuation_here()
             )
     if "type_copy" in request.POST:
         redirect_uri = self.item_copy_uri(
             coll_id, "_type", "Type_view", type_id, 
             message.NO_TYPE_FOR_COPY, 
             viewinfo.get_continuation_here(),
             viewinfo.get_continuation_url()
             )
     if "type_edit" in request.POST:
         redirect_uri = self.item_edit_uri(
             coll_id, "_type", "Type_view", type_id, 
             message.NO_TYPE_FOR_COPY, 
             viewinfo.get_continuation_here(),
             viewinfo.get_continuation_url()
             )
     if "type_delete" in request.POST:
         http_response = viewinfo.confirm_delete_entity_response(
             layout.TYPE_TYPEID, type_id, 
             self.view_uri("AnnalistRecordTypeDeleteView", coll_id=coll_id),
             form_action_field="type_delete",
             form_value_field="typelist",
             response_messages=
                 { "no_entity":          message.NO_TYPE_FOR_DELETE
                 , "confirm_completion": message.REMOVE_RECORD_TYPE
                 }
             )
     # List views
     list_id = request.POST.get('listlist', None)
     if "list_new" in request.POST:
         redirect_uri = self.item_new_uri(
             coll_id, "_list", "List_view", 
             viewinfo.get_continuation_here()
             )
     if "list_copy" in request.POST:
         redirect_uri = self.item_copy_uri(
             coll_id, "_list", "List_view", list_id, 
             message.NO_LIST_FOR_COPY, 
             viewinfo.get_continuation_here(),
             viewinfo.get_continuation_url()
             )
     if "list_edit" in request.POST:
         redirect_uri = self.item_edit_uri(
             coll_id, "_list", "List_view", list_id, 
             message.NO_LIST_FOR_COPY, 
             viewinfo.get_continuation_here(),
             viewinfo.get_continuation_url()
             )
     if "list_delete" in request.POST:
         http_response = viewinfo.confirm_delete_entity_response(
             layout.LIST_TYPEID, list_id, 
             self.view_uri("AnnalistRecordListDeleteView", coll_id=coll_id),
             form_action_field="list_delete",
             form_value_field="listlist",
             response_messages=
                 { "no_entity":          message.NO_LIST_FOR_DELETE
                 , "confirm_completion": message.REMOVE_RECORD_LIST
                 }
             )
     # Record views
     view_id = request.POST.get('viewlist', None)
     if "view_new" in request.POST:
         redirect_uri = self.item_new_uri(
             coll_id, "_view", "View_view", 
             viewinfo.get_continuation_here()
             )
     if "view_copy" in request.POST:
         redirect_uri = self.item_copy_uri(
             coll_id, "_view", "View_view", view_id, 
             message.NO_VIEW_FOR_COPY, 
             viewinfo.get_continuation_here(),
             viewinfo.get_continuation_url()
             )
     if "view_edit" in request.POST:
         redirect_uri = self.item_edit_uri(
             coll_id, "_view", "View_view", view_id, 
             message.NO_VIEW_FOR_COPY, 
             viewinfo.get_continuation_here(),
             viewinfo.get_continuation_url()
             )
     if "view_delete" in request.POST:
         http_response = viewinfo.confirm_delete_entity_response(
             layout.VIEW_TYPEID, view_id, 
             self.view_uri("AnnalistRecordViewDeleteView", coll_id=coll_id),
             form_action_field="view_delete",
             form_value_field="viewlist",
             response_messages=
                 { "no_entity":          message.NO_VIEW_FOR_DELETE
                 , "confirm_completion": message.REMOVE_RECORD_VIEW
                 }
             )
     # Invoke selected view and/or render status response
     if redirect_uri:
         http_response = http_response or HttpResponseRedirect(redirect_uri)
     if http_response:
         return http_response
     e = Annalist_Error(request.POST, "Unexpected values in POST to "+self.get_request_path())
     log.exception(str(e))
     return self.error(
         dict(self.error500values(),
             message=str(e)+" - see server log for details"
             )
         )