Source code for concepts.authorities

from .models import Concept, Type

from conceptpower import Conceptpower
from urlparse import urlparse
from django.conf import settings

import logging
logging.basicConfig()
logger = logging.getLogger(__name__)
logger.setLevel('DEBUG')

[docs]class AuthorityManager(object): pass
[docs]class ConceptpowerAuthority(AuthorityManager, Conceptpower): __name__ = 'ConceptpowerAuthority' endpoint = settings.CONCEPTPOWER_ENDPOINT namespace = settings.CONCEPTPOWER_NAMESPACE
# # class VogonAuthority(AuthorityManager): # __name__ = "VogonAuthority" # # def search(self, query, pos='noun'): # return Concept.objects.filter(label__contains=query).filter(pos=pos) # # def get(self, uri): # return Concept.object.get(uri=uri) # # def get_type(self, uri): # return Type.objects.get(uri=uri) # # namespace = '{http://vogon.asu.edu/}' # Register AuthorityManagers here. authority_managers = ( ConceptpowerAuthority, # VogonAuthority, )
[docs]def update_instance(sender, instance, concept_data, authority): # Update description, label, (and typed). instance.description = concept_data['description'] instance.label = concept_data['label'] if 'pos' in concept_data: instance.pos = concept_data['pos'] else: instance.pos = 'unknown' # For Types, this will create a cascade of post_save # signals resulting in a crawl up the Type ontology # based on the ``supertype`` property. if sender is Concept: if 'type_uri' in concept_data: type_uri = concept_data['type_uri'] else: type_uri = None elif sender is Type: if 'supertype_uri' in concept_data: type_uri = concept_data['supertype_uri'] else: type_uri = None if type_uri is not None: type_instance = Type.objects.get_or_create(uri=type_uri, authority=authority)[0] instance.typed = type_instance logger.debug( 'Added Type {0} to Concept {1}.'.format( type_instance.uri, instance.uri)) instance.save() return instance
[docs]def resolve(sender, instance): """ Resolve :class:`.Concept`\s and :class:`.Type`\s using the registered :class:`.AuthorityManager`\s. Parameters ---------- sender : class instance : :class:`.Type` or :class:`.Concept` """ logger.debug( 'Received post_save signal for Concept {0}.'.format(instance.id)) if instance is not None: # Configure based on sender model class. try: instance_cast = instance.cast() except: return if type(instance_cast) is Concept: get_method = 'get' label_field = 'lemma' elif type(instance_cast) is Type: get_method = 'get_type' label_field = 'type' # Skip any instance that has already been resolved, or that lacks a URI. if not instance.resolved and instance.uri is not None: logger.debug('Instance {0} not yet resolved.'.format(instance.id)) # Get AuthorityManager classes by namespace. managers = get_by_namespace(get_namespace(instance.uri)) logger.debug( 'Found {0} managers for {1}'.format(len(managers),instance.uri)) # Try each AuthorityManager... for manager_class in managers: if instance.resolved: break # ...until success. manager = manager_class() method = getattr(manager, get_method) concept_data = method(instance.uri) concept_data['label'] = concept_data.get(label_field, 'No label') instance.authority = manager.__name__ logger.debug( 'Trying AuthorityManager {0}.'.format(manager.__name__)) instance.resolved = True instance.concept_state = Concept.RESOLVED update_instance(sender, instance, concept_data, manager.__name__)
[docs]def get_namespace(uri): """ Extract namespace from URI. """ o = urlparse(uri) namespace = o.scheme + "://" + o.netloc + "/" if o.scheme == '' or o.netloc == '': raise ValueError("Could not determine namespace for {0}.".format(uri)) return "{" + namespace + "}"
[docs]def get_by_namespace(namespace): """ Retrieve a registered :class:`AuthorityManager` by its namespace. """ return [ manager for manager in authority_managers if manager.namespace == namespace ]
[docs]def add(instance): """ Add the approved concept to Conceptpower Parameters ----------- instance : :class:'.Concept' Returns ------- response : dict Examples ------- .. code-block:: python >>> add(concept) { u'word': u'Askania-Nova', u'description': u'A biosphere reserve located in Kherson Oblast, Ukraine', u'conceptlist': u'VogonWeb Concepts', u'type': u'http://www.digitalhps.org/types/TYPE_dfc95f97-f128-42ae-b54c-ee40333eae8c', u'equals': [], u'pos': u'noun', u'synonymids': [], u'similar': [], u'id': u'CONf3a936bd-f9fe-415c-8e9e-e463de7d4bbf' } """ concept_list = 'VogonWeb Concepts' conceptpower = ConceptpowerAuthority() response = conceptpower.create(settings.CONCEPTPOWER_USERID, settings.CONCEPTPOWER_PASSWORD, instance.label, instance.pos, concept_list, instance.description, instance.typed.uri) # This is kind of hacky, but the current version of Conceptpower does not # return the full URI of the new Concept -- just its ID. We can remove this # when the new version of Conceptpower is released. if 'uri' not in response: response['uri'] = u'http://www.digitalhps.org/concepts/%s' % response['id'] return response