""" cclicense.py Wraps Creative Commons licenses in Python objects; allows creation of new licenses, parsing of RDF licenses and extraction of license components. (c) 2003, Nathan R. Yergler Licensed under the GNU GPL2 """ __version__ = 'ccLicense 0.02' __copyright__ = '(c) 2003, Nathan R. Yergler' __license__ = 'licensed under the GNU GPL2' # import some basic support structure import sys import xml.sax.xmlreader import cStringIO # import RDF-related facilities; # rdflib available at http://www.rdflib.net # aaronrdf available at http://www.aaronsw.com/2002/tramp.py from rdflib.TripleStore import TripleStore from aaronrdf import cc # check the version of Python we're running on and # set Boolean constants if necessary if (sys.version_info < (2,3)): True = 1 False = 0 # define some values which are useful for defining licenses permits = cc.permits prohibits = cc.prohibits requires = cc.requires class StringInputSource(xml.sax.xmlreader.InputSource): """ StringInputSource: helper source to allow SAX parsing of a string; wraps string in appropriate superclass and emulates file-like interface. """ def __init__(self, sourceString): # call the superclass constructor xml.sax.xmlreader.InputSource.__init__(self) # store the input string self.__source = cStringIO.StringIO(sourceString) self.setByteStream(self.__source) class ListDict: """ Dictionary wrapper class which auto-magically coerces elements to Lists """ def __init__(self): self.__items = {} def __setitem__(self, key, value): if key in self.__items: self.__items[key].append(value) else: self.__items[key] = [value,] def __getattr__(self, attr): return getattr(self.__items, attr) def __getitem__(self, key): return self.__items[key] def __str__(self): return str(self.__items) def humanKeys(self): """ Returns a list of tuples containing (key, humankey) where humankey is obtained by extracting the last element of the URI contained in key. """ return [(n, n.split('/')[-1]) for n in self.__items.keys() if '#' not in n] def dict(self): return self.__items class ccLicense: """ ccLicense: wraps a Creative Commons license with Python-ic API; allows parsing of licenses, creation of new licenses and emits RDF suitable for embedding. """ def __init__(self, url=None): self.__store = TripleStore() self.url = url self.work = ListDict() def parseRdf(self, rdf, clearStore=False): """ Load a license from rdf where rdf is a String. If clearStore is True, remove existing elements from the current license instance. """ if clearStore: # reset the current triple store self.__store = TripleStore() # load/parse the string into triples self.__store.load( StringInputSource (rdf) ) # parse the Work information, if any try: self.work['about'] = self.__store.subjects(object=cc.Work).next() except: pass if self.work.has_key('about'): self.__parsePredicateObjects(self.__store, self.work, self.work['about'][0] ) def __parsePredicateObjects(self, store, listDict, subject): """ Recursively parses objects with a particular subject, storing them as predicate-object pairs in the given listDict. """ for item in store.predicate_objects(subject=subject): if ( (len(item[1]) > 1) and (item[1][:2] == '_:') ): # this is a sub-object; parse as such listDict[item[0]] = ListDict() self.__parsePredicateObjects(store, listDict[item[0]][-1], item[1]) else: # add it to the listDict listDict[item[0]] = item[1] def getWorkAttr(self, predicate): """ Returns a particular attribute of the license's Work information. """ return self.__store.objects(subject = self.work['about'][0], predicate = predicate).next() def hasWorkMetadata(self): """ Returns True if the license contains work metadata. """ return self.work.has_key('about') def licenses(self): """ Returns a list of license URLs. """ licenses = [] for license in self.__store.objects(subject=None, predicate=cc.license): licenses.append(license) return licenses def requiresURIs(self, license=None): """ Returns a list of URIs which represent requirements of the license. """ required = [] for item in self.__store.objects(subject=license, predicate=cc.requires): required.append(item) return required def requires(self, license=None): """ Returns a list of human-readable requirements for the license. """ return [n.split('/')[-1] for n in self.requiresURIs(license)] def permitsURIs(self, license=None): """ Returns a list of URIs which represent permissions granted. """ permitted = [] for item in self.__store.objects(subject=license, predicate=cc.permits): permitted.append(item) return permitted def permits(self, license=None): """ Returns a list of human-readable permissions for the license. """ return [n.split('/')[-1] for n in self.permitsURIs(license)] def prohibitsURIs(self, license=None): """ Returns a list of URIs which represent prohibitions imposed by the license. """ prohibited = [] for item in self.__store.objects(subject=license, predicate=cc.prohibits): prohibited.append(item) return prohibited def prohibits(self, license=None): """ Returns a list of human-readable prohibitions imposed by the license. """ return [n.split('/')[-1] for n in self.prohibitsURIs(license)] def addLicenseTerm(self, term_type, term, license=None): """ Adds a licensing term, where the term_type is a valid RDF URI (predicate) and term is a valid RDF URI (object). The pre-defined values of permits, prohibits and requires are valid, standard CC term_types. URI's for term can be generated as cc.Reproduction, cc.Distribution, etc. """ self.__store.add( (license, term_type, term) ) def delLicenseTerm(self, term_type, term, license=None): """ Removes a licensing term from the current license, where the term_type is a valid RDF URI (predicate) and term is a valid RDF URI (object). The pre-defined values of permits, prohibits and requires are valid, standard CC term_types. URI's for term can be generated as cc.Reproduction, cc.Distribution, etc. """ self.__store.remove( (license, term_type, term) ) def emitRdf(self): """ Return a string containing the RDF representation of this license. """ if self.__store is not None: rdf = cStringIO.StringIO() self.__store.output(rdf) return rdf.getvalue() else: return "" __str__ = emitRdf