def testConfig(self): """ $ ro config \ -r http://calatola.man.poznan.pl/robox/dropbox_accounts/1/ro_containers/2 \ -p d41d8cd98f00b204e9800998ecf8427e \ -b /usr/workspace/Dropbox/myROs \ -n "Graham Klyne" \ -e [email protected] """ ro_utils.resetconfig(ro_test_config.CONFIGDIR) config = ro_utils.readconfig(ro_test_config.CONFIGDIR) self.assertEqual(config["robase"], None) self.assertEqual(config["roboxuri"], None) self.assertEqual(config["roboxpass"], None) self.assertEqual(config["username"], None) self.assertEqual(config["useremail"], None) args = [ "ro", "config", "-b", ro_test_config.ROBASEDIR, "-r", ro_test_config.ROBOXURI, "-n", ro_test_config.ROBOXUSERNAME, "-p", ro_test_config.ROBOXPASSWORD, "-e", ro_test_config.ROBOXEMAIL ] with SwitchStdout(self.outstr): status = ro.runCommand(ro_test_config.CONFIGDIR, ro_test_config.ROBASEDIR, args) assert status == 0 self.assertEqual(self.outstr.getvalue().count("ro config"), 0) config = ro_utils.readconfig(ro_test_config.CONFIGDIR) self.assertEqual(config["robase"], os.path.abspath(ro_test_config.ROBASEDIR)) self.assertEqual(config["roboxuri"], ro_test_config.ROBOXURI) self.assertEqual(config["roboxpass"], ro_test_config.ROBOXPASSWORD) self.assertEqual(config["username"], ro_test_config.ROBOXUSERNAME) self.assertEqual(config["useremail"], ro_test_config.ROBOXEMAIL) return
def checkout(progname, configbase, options, args): """ Checkout a RO from ROSRS ro checkout <RO-identifier> [-d <dir> ] [ -r <rosrs_uri> ] [ -t <access_token> ] """ ro_config = ro_utils.readconfig(configbase) ro_options = { "roident": args[2], "rodir": options.rodir or "", "rosrs_uri": options.rosrs_uri or getoptionvalue(ro_config['rosrs_uri'], "URI for ROSRS service: "), "rosrs_access_token": options.rosrs_access_token or getoptionvalue(ro_config['rosrs_access_token'], "Access token for ROSRS service: "), } log.debug("ro_options: " + repr(ro_options)) if options.verbose: print "ro checkout %(roident)s %(rodir)s %(rosrs_uri)s %(rosrs_access_token)s" % ro_options ro_dir = os.path.join(ro_options['rodir'], ro_options["roident"]) if not ro_dir: return 1 rouri = urlparse.urljoin(ro_options["rosrs_uri"], ro_options["roident"]) try: zipdata = ro_remote_metadata.getAsZip(rouri) __unpackZip(zipdata, ro_dir, options.verbose) except urllib2.URLError as e: print "Could not checkout %s: %s" % (rouri, e) return 0
def push_zip(progname, configbase, options, args): """ push RO in zip format ro push <zip> | -d <dir> [ -f ] [ -r <rosrs_uri> ] [ -t <access_token> ] """ if options.verbose: print "ro push %(zip)s -r %(rosrs_uri)s -t %(rosrs_access_token)s" % dict(vars(options).items() + {'zip':args[2]}.items()) ro_config = ro_utils.readconfig(configbase) ro_options = { "zip": args[2], "rosrs_uri": options.rosrs_uri or getoptionvalue(ro_config['rosrs_uri'], "URI for ROSRS service: "), "rosrs_access_token": options.rosrs_access_token or getoptionvalue(ro_config['rosrs_access_token'], "Access token for ROSRS service: "), "force": options.force, "roId": args[2].replace(".zip", "").split("/")[-1] } rosrs = ROSRS_Session(ro_options["rosrs_uri"], ro_options["rosrs_access_token"]) (status, reason, headers, data) = ro_remote_metadata.sendZipRO(rosrs, ro_options["rosrs_uri"], ro_options["roId"], open(args[2], 'rb').read()) if options.verbose: print "Status: %s" % status print "Reason: %s" % reason print "Headers: %s" % headers print "Data: %s" % data log.debug("Status: %s" % status) log.debug("Reason: %s" % reason) log.debug("Headers: %s" % headers) log.debug("Data: %s" % data) return 0
def annotations(progname, configbase, options, args): """ Display annotations ro annotations [ file | -d dir ] """ log.debug("annotations: progname %s, configbase %s, args %s" % (progname, configbase, repr(args))) ro_config = ro_utils.readconfig(configbase) ro_file = (args[2] if len(args) >= 3 else "") ro_options = { "rofile": ro_file, "rodir": options.rodir or os.path.dirname(ro_file) } log.debug("ro_options: " + repr(ro_options)) if options.verbose: print "ro annotations -d \"%(rodir)s\" %(rofile)s " % ro_options ro_dir = ro_root_directory(progname + " annotations", ro_config, ro_options['rodir']) if not ro_dir: return 1 # Enumerate and display annotations rometa = ro_metadata(ro_config, ro_dir) if ro_options['rofile']: rofile = ro_uriutils.resolveFileAsUri(ro_options['rofile']) # Relative to CWD log.debug("Annotations for %s" % str(rofile)) annotations = rometa.getFileAnnotations(rofile) else: annotations = rometa.getAllAnnotations() if options.debug: log.debug("---- Annotations:") for a in annotations: log.debug(" %s" % repr(a)) log.debug("----") rometa.showAnnotations(annotations, sys.stdout) return 0
def add(progname, configbase, options, args): """ Add files to a research object manifest ro add [ -d dir ] file ro add [ -d dir ] [-a] [directory] Use -a/--all to add subdirectories recursively If no file or directory specified, defaults to current directory. """ ro_config = ro_utils.readconfig(configbase) ro_options = { "rodir": options.rodir or "", "rofile": args[2] if len(args) == 3 else ".", "recurse": options.all, "recurseopt": "-a" if options.all else "" } log.debug("ro_options: " + repr(ro_options)) # Find RO root directory ro_dir = ro_root_directory(progname + " add", ro_config, ro_options['rodir']) if not ro_dir: return 1 # Read and update manifest if options.verbose: print "ro add -d %(rodir)s %(recurseopt)s %(rofile)s" % ro_options rometa = ro_metadata(ro_config, ro_dir) rometa.addAggregatedResources(ro_options['rofile'], recurse=ro_options['recurse'], includeDirs=not ro_options['recurse']) return 0
def status(progname, configbase, options, args): """ Display status of a designated research object ro status [ -d dir ] """ # Check command arguments ro_config = ro_utils.readconfig(configbase) ro_options = { "rodir": options.rodir or "", } log.debug("ro_options: " + repr(ro_options)) # Find RO root directory ro_dir = ro_root_directory(progname + " status", ro_config, ro_options['rodir']) if not ro_dir: return 1 # Read manifest and display status if options.verbose: print "ro status -d \"%(rodir)s\"" % ro_options rometa = ro_metadata(ro_config, ro_dir) rodict = rometa.getRoMetadataDict() print "Research Object status" print " identifier: %(roident)s, title: %(rotitle)s" % rodict print " creator: %(rocreator)s, created: %(rocreated)s" % rodict print " path: %(ropath)s" % rodict if rodict['rouri']: print " uri: %(rouri)s" % rodict print " description: %(rodescription)s" % rodict # @@TODO: add ROEVO information return 0
def getroconfig(configbase, options, rouri=None): ro_config = ro_utils.readconfig(configbase) if options.rosrs_uri: ro_config['rosrs_uri'] = options.rosrs_uri if options.rosrs_access_token: ro_config['rosrs_access_token'] = options.rosrs_access_token if rouri: ro_config['rosrs_uri'] = rouri return ro_config
def evaluate(progname, configbase, options, args): """ Evaluate RO ro evaluate checklist [ -d <dir> ] <minim> <purpose> [ <target> ]" """ log.debug("evaluate: progname %s, configbase %s, args %s" % (progname, configbase, repr(args))) ro_config = ro_utils.readconfig(configbase) ro_options = ( { "rodir": options.rodir or "" , "function": args[2] }) log.debug("ro_options: " + repr(ro_options)) ro_dir = ro_root_directory(progname + " annotations", ro_config, ro_options['rodir']) if not ro_dir: return 1 # Evaluate... if ro_options["function"] == "checklist": if len(args) not in [5, 6]: print ("%s evaluate checklist: wrong number of arguments provided" % (progname)) print ("Usage: %s evaluate checklist [ -d <dir> ] [ -a | -l <level> ] <minim> <purpose> [ <target> ]" % (progname)) return 1 levels = ["summary", "must", "should", "may", "full"] if options.level not in ["summary", "must", "should", "may", "full"]: print ("%s evaluate checklist: invalid reporting level %s, must be one of %s" % (progname, options.level, repr(levels))) return 1 ro_options["minim"] = ((len(args) > 3) and args[3]) or "minim.rdf" ro_options["purpose"] = ((len(args) > 4) and args[4]) or "create" ro_options["target"] = ((len(args) > 5) and args[5]) or "." if options.verbose: print "ro evaluate %(function)s -d \"%(rodir)s\" %(minim)s %(purpose)s %(target)s" % ro_options rometa = ro_metadata(ro_config, ro_dir) (minimgraph, evalresult) = ro_eval_minim.evaluate(rometa, ro_options["minim"], ro_options["target"], ro_options["purpose"]) if options.verbose: print "== Evaluation result ==" print json.dumps(evalresult, indent=2) ro_eval_minim.format(evalresult, { "detail" : "full" if options.all else options.level }, sys.stdout) # elif ... other functions here else: print ("%s evaluate: unrecognized function provided (%s)" % (progname, ro_options["function"])) print ("Usage:") print (" %s evaluate checklist [ -d <dir> ] [ -a | -l <level> ] <minim> <purpose> [ <target> ]" % (progname)) return 1 return 0
def list(progname, configbase, options, args): """ List contents of a designated research object -a displays files present as well as aggregated resources -h includes hidden files in display ro list [ -a ] [ -h ] [ -d dir ] ro ls [ -a ] [ -h ] [ -d dir ] """ # Check command arguments ro_config = ro_utils.readconfig(configbase) ro_options = { "rodir": options.rodir or "", "all": " -a" if options.all else "", "hidden": " -h" if options.hidden else "", } log.debug("ro_options: " + repr(ro_options)) # Find RO root directory ro_dir = ro_root_directory(progname + " list", ro_config, ro_options['rodir']) if not ro_dir: return 1 # Scan directory tree and collect filenames if options.verbose: print "ro list%(all)s%(hidden)s -d \"%(rodir)s\"" % ro_options prep_f = "" prep_a = "" rofiles = [] if options.all: prep_f = "f: " prep_a = "a: " rofiles = MiscLib.ScanDirectories.CollectDirectoryContents( ro_dir, baseDir=os.path.abspath(ro_dir), listDirs=False, listFiles=True, recursive=True, appendSep=False) if not options.hidden: def notHidden(f): return re.match("\.|.*/\.", f) == None rofiles = filter(notHidden, rofiles) # Scan RO and collect aggregated resources rometa = ro_metadata(ro_config, ro_dir) roaggs = [ str(rometa.getComponentUriRel(a)) for a in rometa.getAggregatedResources() ] # Assemble and output listing print "\n".join(mapmerge(prepend_f(prep_a), roaggs, prepend_f(prep_f), rofiles)) return 0
def remove(progname, configbase, options, args): """ Remove a specified research object component or components remove [ -d <dir> ] <file-or-uri> remove -d <dir> -w <pattern> """ ro_config = ro_utils.readconfig(configbase) rodir = options.rodir or (not options.wildcard and os.path.dirname(args[2])) ro_options = { # Usding graph annotation form "rofile": args[2], "rodir": rodir, "wildcard": options.wildcard, "wild": "-w " if options.wildcard else "", "rocmd": progname, } log.debug("remove: ro_options: " + repr(ro_options)) # Find RO root directory ro_dir = ro_root_directory("%s %s" % (progname, args[1]), ro_config, ro_options['rodir']) if not ro_dir: return 1 if options.verbose: print "%(rocmd)s remove -d %(rodir)s %(wild)s%(rofile)s" % (ro_options) # Read and update manifest and annotations rometa = ro_metadata(ro_config, ro_dir) if options.wildcard: try: rofilepattern = re.compile(ro_options['rofile']) except re.error as e: ro_options["err"] = str(e) print '''%(rocmd)s remove -w "%(rofile)s" <...> : %(err)s''' % ro_options return 1 for rofile in [ r for r in rometa.getAggregatedResources() if rofilepattern.search(str(r)) ]: rometa.removeAggregatedResource(rofile) else: rofile = rometa.getComponentUri(ro_options['rofile']) rometa.removeAggregatedResource(rofile) return 0
def annotations(progname, configbase, options, args): """ Dusplay annotations ro annotations [ file | -d dir ] """ # Check command arguments if len(args) not in [2,3]: print ("%s annotations: wrong number of arguments provided"% (progname)) print ("Usage: %s annotations [ file | -d dir ]"% (progname)) return 1 ro_config = ro_utils.readconfig(configbase) ro_file = (args[2] if len(args) >= 3 else "") ro_options = { "rofile": ro_file, "rodir": options.rodir or os.path.dirname(ro_file) } log.debug("ro_options: "+repr(ro_options)) if options.verbose: print "ro annotations -d \"%(rodir)s\" %(rofile)s "%ro_options ro_dir= ro_root_directory(progname+" annotations", ro_config, ro_options['rodir']) if not ro_dir: return 1 ro_graph = ro_manifest.readManifestGraph(ro_dir) if ro_options['rofile']: ro_file = ro_manifest.getComponentUri(ro_dir, os.path.abspath(ro_options['rofile'])) annotations = ro_graph.predicate_objects(subject=ro_file) print str(ro_file) # @@TODO figure relativization log.debug("annotations for %s"%str(ro_file)) for (atyp,aval) in annotations: aname = getAnnotationNameByUri(ro_config, atyp) log.debug("Annotations atyp %s, aname %s, aval %s"%(repr(atyp), aname, repr(aval))) print " %s: %s"%(aname,str(aval)) else: # list all annotations assert False, "@@TODO - show annotations for all RO components" return 0
def annotate(progname, configbase, options, args): """ Annotate a specified research object component ro annotate file attribute-name [ attribute-value ] """ # Check command arguments if len(args) not in [4,5]: print ("%s annotate: wrong number of arguments provided"% (progname)) print ("Usage: %s annotate file attribute-name [ attribute-value ]"% (progname)) return 1 ro_config = ro_utils.readconfig(configbase) ro_options = { "rofile": args[2], "rodir": os.path.dirname(args[2]), "roattribute": args[3], "rovalue": args[4] or None } log.debug("ro_options: "+repr(ro_options)) # Find RO root directory ro_dir = ro_root_directory(progname+" attribute", ro_config, ro_options['rodir']) if not ro_dir: return 1 # Read and update manifest if options.verbose: print "ro annotate %(rofile)s %(roattribute)s \"%(rovalue)s\""%ro_options ro_graph = ro_manifest.readManifestGraph(ro_dir) (predicate,valtype) = getAnnotationByName(ro_config, ro_options['roattribute']) log.debug("Adding annotation predicate: %s, value %s"%(repr(predicate),repr(ro_options['rovalue']))) ro_graph.add( ( ro_manifest.getComponentUri(ro_dir, os.path.abspath(ro_options['rofile'])), predicate, rdflib.Literal(ro_options['rovalue']) ) ) ro_manifest.writeManifestGraph(ro_dir, ro_graph) return 0
def list(progname, configbase, options, args): """ List contents of a designated research object ro list [ -d dir ] ro ls [ -d dir ] """ # Check command arguments ro_config = ro_utils.readconfig(configbase) ro_options = { "rodir": options.rodir or "", } log.debug("ro_options: "+repr(ro_options)) # Find RO root directory ro_dir = ro_root_directory(progname+" list", ro_config, ro_options['rodir']) if not ro_dir: return 1 # Scan directory tree and display files if options.verbose: print "ro list -d \"%(rodir)s\""%ro_options rofiles = MiscLib.ScanDirectories.CollectDirectoryContents( ro_dir, baseDir=os.path.abspath(ro_dir), listDirs=False, listFiles=True, recursive=True, appendSep=False) print "\n".join(rofiles) return 0
def push(progname, configbase, options, args): """ Push all or selected ROs and their resources to ROSRS ro push <zip> | -d <dir> [ -f ] [ -r <rosrs_uri> ] [ -t <access_token> ] """ ro_config = ro_utils.readconfig(configbase) ro_options = { "rodir": options.rodir, "rosrs_uri": options.rosrs_uri or getoptionvalue(ro_config['rosrs_uri'], "URI for ROSRS service: "), "rosrs_access_token": options.rosrs_access_token or getoptionvalue(ro_config['rosrs_access_token'], "Access token for ROSRS service: "), "force": options.force } log.debug("ro_options: " + repr(ro_options)) if len(args) == 3: return push_zip(progname, configbase, options, args) if options.verbose: print "ro push -d %(rodir)s -r %(rosrs_uri)s -t %(rosrs_access_token)s" % ro_options ro_dir = ro_root_directory(progname + " push", ro_config, ro_options['rodir']) if not ro_dir: return 1 localRo = ro_metadata(ro_config, ro_dir) roId = ro_dir.replace(ro_config["robase"], "", 1) if roId.startswith("/"): roId = roId.replace("/", "", 1) rosrs = ROSRS_Session(ro_options["rosrs_uri"], ro_options["rosrs_access_token"]) (status, _, rouri, _) = ro_remote_metadata.createRO(rosrs, roId) if status == 201: print "Created RO: %s" % (rouri) elif status == 409: rouri = urlparse.urljoin(ro_options["rosrs_uri"], roId + "/") print "RO already exists: %s" % (rouri) remoteRo = ro_remote_metadata.ro_remote_metadata(ro_config, rosrs, rouri) pushedResCnt = 0 pushedAnnCnt = 0 deletedResCnt = 0 deletedAnnCnt = 0 for (action, resuri) in ro_rosrs_sync.pushResearchObject(localRo, remoteRo): if action == ro_rosrs_sync.ACTION_AGGREGATE_INTERNAL: print "Resource uploaded: %s" % (resuri) log.debug("Resource uploaded: %s" % (resuri)) pushedResCnt += 1 elif action == ro_rosrs_sync.ACTION_AGGREGATE_EXTERNAL: print "External resource pushed: %s" % (resuri) log.debug("External resource pushed: %s" % (resuri)) pushedResCnt += 1 elif action == ro_rosrs_sync.ACTION_AGGREGATE_ANNOTATION: if options.verbose: print "Annotation pushed: %s" % (resuri) log.debug("Annotation pushed: %s" % (resuri)) pushedAnnCnt += 1 elif action == ro_rosrs_sync.ACTION_UPDATE_OVERWRITE: # TODO ask user for confirmation print "Resource uploaded (WARNING: it has overwritten changes in RODL): %s" % (resuri) log.debug("Resource uploaded (WARNING: it has overwritten changes in RODL): %s" % (resuri)) pushedResCnt += 1 elif action == ro_rosrs_sync.ACTION_UPDATE: print "Resource uploaded: %s" % (resuri) log.debug("Resource uploaded: %s" % (resuri)) pushedResCnt += 1 elif action == ro_rosrs_sync.ACTION_UPDATE_ANNOTATION: if options.verbose: print "Annotation updated: %s" % (resuri) log.debug("Annotation updated: %s" % (resuri)) pushedAnnCnt += 1 elif action == ro_rosrs_sync.ACTION_SKIP: print "Resource skipped: %s" % (resuri) log.debug("Resource skipped: %s" % (resuri)) elif action == ro_rosrs_sync.ACTION_DELETE: # TODO ask user for confirmation print "Resource deleted in ROSRS: %s" % (resuri) log.debug("Resource deleted in ROSRS: %s" % (resuri)) deletedResCnt += 1 elif action == ro_rosrs_sync.ACTION_DELETE_ANNOTATION: if options.verbose: print "Annotation deleted in ROSRS: %s" % (resuri) log.debug("Annotation deleted in ROSRS: %s" % (resuri)) deletedAnnCnt += 1 elif action == ro_rosrs_sync.ACTION_ERROR: print resuri print "%d resources pushed, %d annotations pushed, %d resources deleted, %d annotations deleted" \ % (pushedResCnt, pushedAnnCnt, deletedResCnt, deletedAnnCnt) return 0
def annotate(progname, configbase, options, args): """ Annotate a specified research object component ro annotate file attribute-name [ attribute-value ] ro link file attribute-name [ attribute-value ] """ ro_config = ro_utils.readconfig(configbase) rodir = options.rodir or (not options.wildcard and os.path.dirname(args[2])) if len(args) == 3: # Using graph form ro_options = { # Usding graph annotation form "rofile": args[2], "rodir": rodir, "wildcard": options.wildcard, "wild": "-w " if options.wildcard else "", "graph": options.graph or None, "defaultType": "resource" if args[1] == "link" else "string", "rocmd": progname, "anncmd": args[1] } else: ro_options = { # Usding explicit annotation form "rofile": args[2], "rodir": rodir, "wildcard": options.wildcard, "wild": "-w " if options.wildcard else "", "roattribute": args[3], "rovalue": args[4] if len(args) == 5 else None, "defaultType": "resource" if args[1] == "link" else "string", "rocmd": progname, "anncmd": args[1] } log.debug("ro_options: " + repr(ro_options)) # Find RO root directory ro_dir = ro_root_directory("%s %s" % (progname, args[1]), ro_config, ro_options['rodir']) if not ro_dir: return 1 if options.verbose: if len(args) == 3: print "%(rocmd)s %(anncmd)s -d %(rodir)s %(wild)s%(rofile)s -g %(graph)s " % (ro_options) else: print "%(rocmd)s %(anncmd)s -d %(rodir)s %(wild)s%(rofile)s %(roattribute)s \"%(rovalue)s\"" % ro_options # Read and update manifest and annotations # ---- local function to annotate a single entry ---- def annotate_single(rofile): if len(args) == 3: # Add existing graph as annotation rometa.addGraphAnnotation(rofile, ro_options['graph']) else: # Create new annotation graph rometa.addSimpleAnnotation(rofile, ro_options['roattribute'], ro_options['rovalue'], ro_options['defaultType']) # ---- rometa = ro_metadata(ro_config, ro_dir) if options.wildcard: try: rofilepattern = re.compile(ro_options['rofile']) except re.error as e: ro_options["err"] = str(e) print '''%(rocmd)s %(anncmd)s -w "%(rofile)s" <...> : %(err)s''' % ro_options return 1 for rofile in [ str(r) for r in rometa.getAggregatedResources() if rofilepattern.search(str(r)) ]: annotate_single(rofile) else: rofile = ro_uriutils.resolveFileAsUri(ro_options['rofile']) # Relative to CWD annotate_single(rofile) return 0
def create(progname, configbase, options, args): """ Create a new Research Object. ro create RO-name [ -d dir ] [ -i RO-ident ] """ ro_options = { "roname": getoptionvalue(args[2], "Name of new research object: "), "rodir": options.rodir or "", "roident": options.roident or "" } log.debug("cwd: " + os.getcwd()) log.debug("ro_options: " + repr(ro_options)) ro_options['roident'] = ro_options['roident'] or ro_utils.ronametoident(ro_options['roname']) # Read local ro configuration and extract creator ro_config = ro_utils.readconfig(configbase) timestamp = datetime.datetime.now().replace(microsecond=0) ro_options['rocreator'] = ro_config['username'] ro_options['rocreated'] = timestamp.isoformat() ro_dir = ro_utils.ropath(ro_config, ro_options['rodir']) if not ro_dir: print ("%s: research object not in configured research object directory tree: %s" % (ro_utils.progname(args), ro_options['rodir'])) return 1 # Create directory for manifest if options.verbose: print "ro create \"%(roname)s\" -d \"%(rodir)s\" -i \"%(roident)s\"" % ro_options manifestdir = os.path.join(ro_dir, ro_settings.MANIFEST_DIR) log.debug("manifestdir: " + manifestdir) try: os.makedirs(manifestdir) except OSError: if os.path.isdir(manifestdir): # Someone else created it... # See http://stackoverflow.com/questions/273192/ # python-best-way-to-create-directory-if-it-doesnt-exist-for-file-write pass else: # There was an error on creation, so make sure we know about it raise # Create manifest file # @@TODO: create in-memory graph and serialize that manifestfilename = os.path.join(manifestdir, ro_settings.MANIFEST_FILE) log.debug("manifestfilename: " + manifestfilename) manifest = ( """<?xml version="1.0" encoding="utf-8"?> <rdf:RDF xml:base=".." xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:ro="http://purl.org/wf4ever/ro#" xmlns:ore="http://www.openarchives.org/ore/terms/" xmlns:ao="http://purl.org/ao/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:foaf="http://xmlns.com/foaf/0.1/" > <ro:ResearchObject rdf:about=""> <dcterms:identifier>%(roident)s</dcterms:identifier> <dcterms:title>%(roname)s</dcterms:title> <dcterms:description>%(roname)s</dcterms:description> <dcterms:creator>%(rocreator)s</dcterms:creator> <dcterms:created>%(rocreated)s</dcterms:created> <!-- self-reference to include above details as annotation --> <ore:aggregates> <ro:AggregatedAnnotation> <ro:annotatesAggregatedResource rdf:resource="" /> <ao:body rdf:resource=".ro/manifest.rdf" /> </ro:AggregatedAnnotation> </ore:aggregates> </ro:ResearchObject> </rdf:RDF> """ % ro_options) log.debug("manifest: " + manifest) manifestfile = open(manifestfilename, 'w') manifestfile.write(manifest) manifestfile.close() return 0