OAI catalogue, started implementation + tests
authorMarcin Koziej <marcin.koziej@nowoczesnapolska.org.pl>
Thu, 2 Aug 2012 12:18:36 +0000 (14:18 +0200)
committerMarcin Koziej <marcin.koziej@nowoczesnapolska.org.pl>
Thu, 2 Aug 2012 12:18:49 +0000 (14:18 +0200)
apps/api/models.py
apps/oai/__init__.py [new file with mode: 0644]
apps/oai/handlers.py [new file with mode: 0644]
apps/oai/tests/__init__.py [new file with mode: 0644]
apps/oai/tests/files/lubie-kiedy-kobieta.xml [new file with mode: 0755]
apps/oai/tests/oaipmhapi.py [new file with mode: 0644]
requirements.txt
wolnelektury/settings/__init__.py

index 2cdc74a..20dd129 100644 (file)
@@ -5,12 +5,14 @@
 from django.contrib.contenttypes.models import ContentType
 from django.db import models
 from django.db.models.signals import pre_delete
 from django.contrib.contenttypes.models import ContentType
 from django.db import models
 from django.db.models.signals import pre_delete
+from django.utils.translation import ugettext_lazy as _
 
 from catalogue.models import Book, Tag
 
 
 class Deleted(models.Model):
     object_id = models.IntegerField()
 
 from catalogue.models import Book, Tag
 
 
 class Deleted(models.Model):
     object_id = models.IntegerField()
+    slug = models.SlugField(_('slug'), max_length=120, blank=True, db_index=True)
     content_type = models.ForeignKey(ContentType)
     category = models.CharField(max_length=64, null=True, blank=True, db_index=True)
     created_at = models.DateTimeField(editable=False, db_index=True)
     content_type = models.ForeignKey(ContentType)
     category = models.CharField(max_length=64, null=True, blank=True, db_index=True)
     created_at = models.DateTimeField(editable=False, db_index=True)
@@ -33,5 +35,5 @@ def _pre_delete_handler(sender, instance, **kwargs):
             category = None
         content_type = ContentType.objects.get_for_model(sender)
         Deleted.objects.create(content_type=content_type, object_id=instance.id, 
             category = None
         content_type = ContentType.objects.get_for_model(sender)
         Deleted.objects.create(content_type=content_type, object_id=instance.id, 
-            created_at=instance.created_at, category=category)
+            created_at=instance.created_at, category=category, slug=instance.slug)
 pre_delete.connect(_pre_delete_handler)
 pre_delete.connect(_pre_delete_handler)
diff --git a/apps/oai/__init__.py b/apps/oai/__init__.py
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/apps/oai/handlers.py b/apps/oai/handlers.py
new file mode 100644 (file)
index 0000000..db43657
--- /dev/null
@@ -0,0 +1,58 @@
+
+from oaipmh import server, common
+from catalogue.models import Book, Tag
+from api.models import Deleted
+from librarian.dcparser import BookInfo
+from django.contrib.contenttypes.models import ContentType
+
+
+class Catalogue(common.ResumptionOAIPMH):
+    def __init__(self):
+        super(Catalogue, self).__init__()
+
+    def metadata(self, book):
+        bi = BookInfo.from_file(book.xml_file)
+        meta = {}
+        for field in bi.FIELDS:
+            dc_field = field.uri.split('}')[1]
+            value = getattr(bi, dc_field.name)
+            if isinstance(value,list):
+                value = ';'.join(map(unicode, value))
+            else:
+                value = unicode(value)
+            meta["dc:"+dc_field] = value
+        return meta
+
+    def record_for_book(self, book):
+        header = common.Header(book.slug, book.changed_at, [], False)
+        meta = common.Metadata(self.metadata(book))
+        about = None
+        return header, meta, about
+
+    def getRecord(self, record, **kw):
+        """
+Returns (header, metadata, about) for given record.
+        """
+        slug = kw['record']
+        try:
+            book = Book.objects.get(slug=slug)
+            return self.record_for_book(book)
+        except Book.DoesNotExist, e:
+            book_type = ContentType.objects.get_for_model(Book)
+            deleted_book = Deleted.objects.filter(content_type=book_type,
+                                                  slug=slug)
+            header = common.Header(deleted_book.slug,
+                                   deleted_book.deleted_at,
+                                   [], True)
+            meta = common.Metadata({})
+            return header, meta, None # None for about.
+                                   
+
+        
+    def listRecords(self, **kw):
+        """
+can get a resumptionToken kw.
+returns result, token
+        """
+        return [self.record_for_book(book) for book in Book.objects.all()]
+            
diff --git a/apps/oai/tests/__init__.py b/apps/oai/tests/__init__.py
new file mode 100644 (file)
index 0000000..08a39d7
--- /dev/null
@@ -0,0 +1 @@
+from oai.tests.oaipmhapi import *
diff --git a/apps/oai/tests/files/lubie-kiedy-kobieta.xml b/apps/oai/tests/files/lubie-kiedy-kobieta.xml
new file mode 100755 (executable)
index 0000000..7ea6f44
--- /dev/null
@@ -0,0 +1,63 @@
+<utwor>
+<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<rdf:Description rdf:about="http://redakcja.wolnelektury.pl/documents/book/przerwa_tetmajer__lubie_kiedy_kobieta/">
+<dc:creator xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">Przerwa-Tetmajer, Kazimierz</dc:creator>
+<dc:title xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">Lubię, kiedy kobieta...</dc:title>
+<dc:contributor.editor xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">Kozioł, Paweł</dc:contributor.editor>
+<dc:contributor.technical_editor xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">Niedziałkowska, Marta</dc:contributor.technical_editor>
+<dc:publisher xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">Fundacja Nowoczesna Polska</dc:publisher>
+<dc:subject.period xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">Modernizm</dc:subject.period>
+<dc:subject.type xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">Liryka</dc:subject.type>
+<dc:subject.genre xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">Wiersz</dc:subject.genre>
+<dc:description xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Reprodukcja cyfrowa wykonana przez Bibliotekę Śląską z egzemplarza pochodzącego ze zbiorów BŚ.</dc:description>
+<dc:identifier.url xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">http://wolnelektury.pl/katalog/lektura/lubie-kiedy-kobieta</dc:identifier.url>
+<dc:source xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">Kazimierz Przerwa-Tetmajer, Wybór poezji, nakł. Gebethnera i Wolffa, Warszawa-Kraków 1897</dc:source>
+<dc:rights xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">Domena publiczna - Kazimierz Przerwa-Tetmajer zm. 1940</dc:rights>
+<dc:date.pd xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">1940</dc:date.pd>
+<dc:format xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">xml</dc:format>
+<dc:type xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">text</dc:type>
+<dc:type xml:lang="en" xmlns:dc="http://purl.org/dc/elements/1.1/">text</dc:type>
+<dc:date xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">2010-10-12</dc:date>
+<dc:audience xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">L</dc:audience>
+<dc:language xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">pol</dc:language></rdf:Description>
+</rdf:RDF>
+
+
+<liryka_l>
+<autor_utworu>Kazimierz Przerwa-Tetmajer</autor_utworu>
+
+<nazwa_utworu>Lubię, kiedy kobieta...</nazwa_utworu>
+
+<strofa>Lubię, kiedy kobieta omdlewa w objęciu,/
+Kiedy w lubieżnym zwisa przez ramię przegięciu,/
+<begin id="b1288014720458-1717646767"/><motyw id="m1288014720458-1717646767">Pożądanie</motyw>Gdy jej oczy zachodzą mgłą, twarz cała blednie,/
+I wargi się wilgotne rozchylą bezwiednie.</strofa>
+
+
+<strofa>
+Lubię, kiedy ją rozkosz i żądza oniemi,/
+Gdy wpija się w ramiona palcami drżącemi,/
+Gdy krótkim, urywanym oddycha oddechem,/
+I oddaje się cała z mdlejącym uśmiechem.
+<end id="e1288014720458-1717646767"/></strofa>
+
+
+<strofa><begin id="b1288014780333-48828945"/><motyw id="m1288014780333-48828945">Wstyd</motyw>I lubię ten wstyd, co się kobiecie zabrania/
+Przyznać, że czuje rozkosz, że moc pożądania/
+Zwalcza ją, a sycenie żądzy oszalenia<pe><slowo_obce>oszaleniać</slowo_obce> (neol.) --- czynić szalonym.</pe>,/
+Gdy szuka ust, a lęka się słów i spojrzenia.
+<end id="e1288014780333-48828945"/></strofa>
+
+
+<strofa><begin id="b1288014533484-249140150"/><motyw id="m1288014533484-249140150">Poeta, Mizoginia</motyw>Lubię to --- i tę chwilę lubię, gdy koło mnie/
+Wyczerpana, zmęczona leży nieprzytomnie,/
+A myśl moja już od niej wybiega skrzydlata/
+W nieskończone przestrzenie nieziemskiego świata.
+<end id="e1288014533484-249140150"/></strofa>
+
+
+</liryka_l>
+
+
+
+</utwor>
\ No newline at end of file
diff --git a/apps/oai/tests/oaipmhapi.py b/apps/oai/tests/oaipmhapi.py
new file mode 100644 (file)
index 0000000..ae5e543
--- /dev/null
@@ -0,0 +1,20 @@
+
+import sys
+print sys.path
+
+from catalogue.test_utils import WLTestCase
+from catalogue import models
+from nose.tools import raises
+from os import path
+from oai.handlers import Catalogue
+
+class BookMetadataTest(WLTestCase):
+    def setUp(self):
+        super(BookMetadata, self).setUp()
+        xml = path.join(path.dirname(__file__), 'files/lubie-kiedy-kobieta.xml')
+        self.book = models.Book.from_xml_file(xml)
+        self.catalogue = Catalogue()
+
+    def test_get_record(self):
+        r = self.catalogue.getRecord(record='lubie-kiedy-kobieta')
+        print r
index 037fa76..70cf8b9 100644 (file)
@@ -6,11 +6,11 @@ South>=0.7 # migrations for django
 django-pipeline>=1.2
 django-pagination>=1.0
 django-maintenancemode>=0.10
 django-pipeline>=1.2
 django-pagination>=1.0
 django-maintenancemode>=0.10
-django-piston
+django-piston<=0.2.3
 #django-jsonfield
 -e git+git://github.com/bradjasper/django-jsonfield.git@2f427368ad70bf8d9a0580df58ec0eb0654d62ae#egg=django-jsonfield
 django-picklefield
 #django-jsonfield
 -e git+git://github.com/bradjasper/django-jsonfield.git@2f427368ad70bf8d9a0580df58ec0eb0654d62ae#egg=django-jsonfield
 django-picklefield
-django-allauth
+django-allauth<=0.4.0
 django-honeypot
 django-uni-form
 
 django-honeypot
 django-uni-form
 
@@ -38,3 +38,8 @@ django-kombu
 
 # spell checking
 pyenchant
 
 # spell checking
 pyenchant
+
+# OAI-PMH
+pyoai
+
+
index 15126b9..de1b442 100644 (file)
@@ -64,6 +64,7 @@ INSTALLED_APPS_OUR = [
     'social',
     'waiter',
     'search',
     'social',
     'waiter',
     'search',
+    'oai',
     ]
 
 INSTALLED_APPS_CONTRIB = [
     ]
 
 INSTALLED_APPS_CONTRIB = [
@@ -85,7 +86,7 @@ INSTALLED_APPS_CONTRIB = [
     'djcelery',
     'djkombu',
     'honeypot',
     'djcelery',
     'djkombu',
     'honeypot',
-    #    'django_nose',
+    'django_nose',
 
     #allauth stuff
     'emailconfirmation',
 
     #allauth stuff
     'emailconfirmation',