def get_next_pid(self, namespace=None, count=None): """ Request next available pid or pids from Fedora, optionally in a specified namespace. Calls :meth:`ApiFacade.getNextPID`. .. deprecated :: 0.14 Mint pids for new objects with :func:`eulfedora.models.DigitalObject.get_default_pid` instead, or call :meth:`ApiFacade.getNextPID` directly. :param namespace: (optional) get the next pid in the specified pid namespace; otherwise, Fedora will return the next pid in the configured default namespace. :param count: (optional) get the specified number of pids; by default, returns 1 pid :rtype: string or list of strings """ # this method should no longer be needed - default pid logic moved to DigitalObject warnings.warn( """get_next_pid() method is deprecated; you should mint new pids via DigitalObject or ApiFacade.getNextPID() instead.""", DeprecationWarning) kwargs = {} if namespace: kwargs['namespace'] = namespace elif self.default_pidspace: kwargs['namespace'] = self.default_pidspace if count: kwargs['numPIDs'] = count r = self.api.getNextPID(**kwargs) nextpids = parse_xml_object(NewPids, r.content, r.url) if count is None: return nextpids.pids[0] else: return nextpids.pids
def get_next_pid(self, namespace=None, count=None): """ Request next available pid or pids from Fedora, optionally in a specified namespace. Calls :meth:`ApiFacade.getNextPID`. .. deprecated :: 0.14 Mint pids for new objects with :func:`eulfedora.models.DigitalObject.get_default_pid` instead, or call :meth:`ApiFacade.getNextPID` directly. :param namespace: (optional) get the next pid in the specified pid namespace; otherwise, Fedora will return the next pid in the configured default namespace. :param count: (optional) get the specified number of pids; by default, returns 1 pid :rtype: string or list of strings """ # this method should no longer be needed - default pid logic moved to DigitalObject warnings.warn("""get_next_pid() method is deprecated; you should mint new pids via DigitalObject or ApiFacade.getNextPID() instead.""", DeprecationWarning) kwargs = {} if namespace: kwargs['namespace'] = namespace elif self.default_pidspace: kwargs['namespace'] = self.default_pidspace if count: kwargs['numPIDs'] = count r = self.api.getNextPID(**kwargs) nextpids = parse_xml_object(NewPids, r.content, r.url) if count is None: return nextpids.pids[0] else: return nextpids.pids
def datastream_lastmodified(request, pid, dsid, repo=None, as_of_date=None, *args, **kwargs): '''Method suitable for use as a a last-modified function with :class:`django.views.decorators.http.condition`. Takes basically the same arguments as :meth:`~eulfedora.views.raw_datastream`. ''' try: if repo is None: repo = Repository() resp = repo.api.getDatastream(pid, dsid, asOfDateTime=as_of_date) dsprofile = parse_xml_object(DatastreamProfile, resp.content, resp.url) if dsprofile: return dsprofile.created except RequestFailed: pass
def datastream_etag(request, pid, dsid, repo=None, as_of_date=None, **kwargs): '''Method suitable for use as an etag function with :class:`django.views.decorators.http.condition`. Takes the same arguments as :meth:`~eulfedora.views.raw_datastream`. ''' # if a range is requested and it is not for the entire file, # do *NOT* return an etag # NOTE: using api directly here instead of object/ds models # to avoid making unneeded api calls try: if repo is None: repo = Repository() resp = repo.api.getDatastream(pid, dsid, asOfDateTime=as_of_date) dsprofile = parse_xml_object(DatastreamProfile, resp.content, resp.url) if dsprofile and dsprofile.checksum_type != 'DISABLED': return dsprofile.checksum except RequestFailed: pass return None
def find_objects(self, terms=None, type=None, chunksize=None, **kwargs): """ Find objects in Fedora. Find query should be generated via keyword args, based on the fields in Fedora documentation. By default, the query uses a contains (~) search for all search terms. Calls :meth:`ApiFacade.findObjects`. Results seem to return consistently in ascending PID order. Example usage - search for all objects where the owner contains 'jdoe':: repository.find_objects(ownerId='jdoe') Supports all search operators provided by Fedora findObjects query (exact, gt, gte, lt, lte, and contains). To specify the type of query for a particular search term, call find_objects like this:: repository.find_objects(ownerId__exact='lskywalker') repository.find_objects(date__gt='20010302') :param type: type of objects to return; defaults to :class:`DigitalObject` :param chunksize: number of objects to return at a time :rtype: generator for list of objects """ type = type or self.default_object_type find_opts = {'chunksize': chunksize} search_operators = { 'exact': '=', 'gt': '>', 'gte': '>=', 'lt': '<', 'lte': '<=', 'contains': '~' } if terms is not None: find_opts['terms'] = terms else: conditions = [] for field, value in six.iteritems(kwargs): if '__' in field: field, filtr = field.split('__') if filtr not in search_operators: raise Exception("Unsupported search filter '%s'" % filtr) op = search_operators[filtr] else: op = search_operators['contains'] # default search mode if field in self.search_fields_aliases: field = self.search_fields_aliases[field] if field not in self.search_fields: raise Exception("Error generating Fedora findObjects query: unknown search field '%s'" \ % field) if ' ' in value: # if value contains whitespace, it must be delimited with single quotes value = "'%s'" % value conditions.append("%s%s%s" % (field, op, value)) query = ' '.join(conditions) find_opts['query'] = query r = self.api.findObjects(**find_opts) chunk = parse_xml_object(SearchResults, r.content, r.url) while True: for result in chunk.results: yield type(self.api, result.pid) if chunk.session_token: r = self.api.findObjects(session_token=chunk.session_token, **find_opts) chunk = parse_xml_object(SearchResults, r.content, r.url) else: break
def find_objects(self, terms=None, type=None, chunksize=None, **kwargs): """ Find objects in Fedora. Find query should be generated via keyword args, based on the fields in Fedora documentation. By default, the query uses a contains (~) search for all search terms. Calls :meth:`ApiFacade.findObjects`. Results seem to return consistently in ascending PID order. Example usage - search for all objects where the owner contains 'jdoe':: repository.find_objects(ownerId='jdoe') Supports all search operators provided by Fedora findObjects query (exact, gt, gte, lt, lte, and contains). To specify the type of query for a particular search term, call find_objects like this:: repository.find_objects(ownerId__exact='lskywalker') repository.find_objects(date__gt='20010302') :param type: type of objects to return; defaults to :class:`DigitalObject` :param chunksize: number of objects to return at a time :rtype: generator for list of objects """ type = type or self.default_object_type find_opts = {'chunksize' : chunksize} search_operators = { 'exact': '=', 'gt': '>', 'gte': '>=', 'lt': '<', 'lte': '<=', 'contains': '~' } if terms is not None: find_opts['terms'] = terms else: conditions = [] for field, value in six.iteritems(kwargs): if '__' in field: field, filter = field.split('__') if filter not in search_operators: raise Exception("Unsupported search filter '%s'" % filter) op = search_operators[filter] else: op = search_operators['contains'] # default search mode if field in self.search_fields_aliases: field = self.search_fields_aliases[field] if field not in self.search_fields: raise Exception("Error generating Fedora findObjects query: unknown search field '%s'" \ % field) if ' ' in value: # if value contains whitespace, it must be delimited with single quotes value = "'%s'" % value conditions.append("%s%s%s" % (field, op, value)) query = ' '.join(conditions) find_opts['query'] = query r = self.api.findObjects(**find_opts) chunk = parse_xml_object(SearchResults, r.content, r.url) while True: for result in chunk.results: yield type(self.api, result.pid) if chunk.session_token: r = self.api.findObjects(session_token=chunk.session_token, **find_opts) chunk = parse_xml_object(SearchResults, r.content, r.url) else: break
def fs_members(self, *els, **kwargs): """Get all the members of a "container" element (i.e. an object treated as a directory by fuse). :param els: list of path elements :params writable_only: if True, only return members that are capable of being written :rtype: list """ if "writable_only" in kwargs: writable_only = kwargs["writable_only"] else: writable_only = False members = [] if len(els) == 0: # top level # no elements - top-level view of the object itself # find all members of this object that should be listed in the directory # - should be strings, not unicode if not writable_only: members.append(".info") if len(self.history): members.append(".versions") # add all datastreams - using datastream id for directory listing members.extend([str(dsid) for dsid in self.ds_list.keys()]) # relations to other objects - use short-hand rel names for directory names members.extend(self.rel_shortnames) if not writable_only: # add methods - using method name for directory listing # NOTE: it's possible to have duplicate method names defined # on different service objects... current implementation does # *not* take this into account self.method_names = {} for sdef, method_list in self.methods.iteritems(): # FIXME: any way to exclude methods that require parameters? for m in method_list: self.method_names[m] = sdef members.extend(self.method_names) elif els[0] == ".versions": # list revisions of this object # (not completely implemented...) if len(els) == 1: members = [str(dt) for dt in self.history] else: # TODO: get a *versioned* list of datastreams # (don't list ones that didn't exist at the specified time!) data, url = self.api.listDatastreams(self.pid) dsobj = parse_xml_object(ObjectDatastreams, data, url) return [str(ds.dsid) for ds in dsobj.datastreams] # related objects elif els[0] in self.rel_shortnames: # top level: directory with objects related by the specified short-name relation if len(els) == 1: rel_uri = self.rel_shortnames[els[0]] members = self.related_objects[rel_uri] return members