]> git.parisson.com Git - telemeta.git/commitdiff
add MediaCollection.get_countries() and get_ethnic_groups() ; consolidate media models
authorolivier <>
Tue, 19 Jan 2010 20:54:49 +0000 (20:54 +0000)
committerolivier <>
Tue, 19 Jan 2010 20:54:49 +0000 (20:54 +0000)
telemeta/models/crem.py
telemeta/tests/model_tests.py
telemeta/util/unaccent.py [new file with mode: 0644]

index fee057205ba32418849f0f0a64904459bb7b8b63..12a4579e7cfac98763e464cae02ae58a6001cbe7 100755 (executable)
@@ -36,6 +36,7 @@
 from django.db import models
 import cremquery as query
 from xml.dom.minidom import getDOMImplementation
+from telemeta.util.unaccent import unaccent_icmp
 
 class ModelCore(models.Model):
 
@@ -116,6 +117,17 @@ class MediaCore(ModelCore):
             return False
     is_well_formed_id = classmethod(is_well_formed_id)
 
+    def save(self, force_insert=False, force_update=False, using=None):
+        raise MissingUserError("save() method disabled, use save_by_user()")
+
+    def save_by_user(self, user, force_insert=False, force_update=False, using=None):
+        "Save a media object and add a revision"
+        super(MediaCore, self).save(force_insert, force_update, using)
+        Revision(element_type=self.element_type, element_id=self.id, user=user).touch()    
+
+    def get_revision(self):
+        return Revision.objects.filter(element_type=self.element_type, element_id=self.id).order_by('-time')[0]
+
     class Meta:
         abstract = True
 
@@ -124,6 +136,7 @@ class MetaCore:
 
 class MediaCollection(MediaCore):
     "Describe a collection of items"
+    element_type = 'collection'
     PUBLIC_ACCESS_CHOICES = (('none', 'none'), ('metadata', 'metadata'), ('metadata', 'full'))
 
     reference             = models.CharField(unique=True, max_length=250,
@@ -180,14 +193,6 @@ class MediaCollection(MediaCore):
     def __unicode__(self):
         return self.code
 
-    def save(self, force_insert=False, force_update=False, using=None):
-        raise MissingUserError("save() method disabled, use save_by_user()")
-
-    def save_by_user(self, user, force_insert=False, force_update=False, using=None):
-        "Save a collection and add a revision"
-        super(MediaCollection, self).save(force_insert, force_update, using)
-        Revision(element_type='collection', element_id=self.id, user=user).touch()    
-
     def has_mediafile(self):
         "Tell wether this collection has any media files attached to its items"
         items = self.items.all()
@@ -196,11 +201,41 @@ class MediaCollection(MediaCore):
                 return True
         return False
 
+    def __name_cmp(self, obj1, obj2):
+        return unaccent_icmp(obj1.name, obj2.name)
+
+    def get_countries(self):
+        "Return the countries of the items"
+        countries = []
+        items = self.items.all()
+        for item in items:
+            if item.location:
+                country = item.location.country()
+                if country and not country in countries:
+                    countries.append(country)
+
+        countries.sort(self.__name_cmp)                
+
+        return countries
+
+    def get_ethnic_groups(self):
+        "Return the ethnic groups of the items"
+        groups = []
+        items = self.items.all()
+        for item in items:
+            if item.ethnic_group and not item.ethnic_group in groups:
+                groups.append(item.ethnic_group)
+
+        groups.sort(self.__name_cmp)                
+
+        return groups
+
     class Meta(MetaCore):
         db_table = 'media_collections'
 
 class MediaItem(MediaCore):
     "Describe an item"
+    element_type = 'item'
     PUBLIC_ACCESS_CHOICES = (('none', 'none'), ('metadata', 'metadata'), ('full', 'full'))
 
     collection            = models.ForeignKey('MediaCollection', related_name="items")
@@ -246,16 +281,9 @@ class MediaItem(MediaCore):
             return self.code
         return self.old_code
 
-    def save(self, force_insert=False, force_update=False):
-        raise MissingUserError("save() method disabled, use save_by_user()")
-
-    def save_by_user(self, user, force_insert=False, force_update=False):
-        "Save an item and add a revision"
-        super(MediaItem, self).save(force_insert, force_update)
-        Revision(element_type='item', element_id=self.id, user=user).touch()    
-
 class MediaPart(MediaCore):
     "Describe an item part"
+    element_type = 'part'
     item  = models.ForeignKey('MediaItem', related_name="parts")
     title = models.CharField(max_length=250)
     start = models.FloatField()
index cc1f540cab4483eb30c8403a9fba7e56925d8ee9..fdd7f00f0a9770dcf77f49ff3176ab85df8e7f30 100644 (file)
@@ -250,6 +250,7 @@ class CollectionItemTestCase(unittest.TestCase):
         self.assertEquals(self.items.without_collection().count(), 0)
 
     def testCodeRequired(self):
+        "Test that a proper failure occur when a collection code isn't provided"
         c = MediaCollection()
         try:
             c.save_by_user(self.olivier)
@@ -259,11 +260,18 @@ class CollectionItemTestCase(unittest.TestCase):
             self.fail("No exception raised")
        
     def testDomForeignKey(self):
+        "Test DOM foreign key embedding"
         doc = self.item_4.to_dom()
         self.assertEquals(doc.getElementsByTagName('collection')[0].getAttribute('key'), str(self.persepolis.id))
 
     def testLocationRelation(self):
+        "Test location country and continent resolving"
         self.assertEquals(self.france, self.item_1.location.country())
         self.assertEquals(self.europe, self.item_1.location.continent())
         self.assertEquals(self.france, self.item_2.location.country())
         self.assertEquals(self.europe, self.item_2.location.continent())
+
+    def testCollectionCountries(self):
+        "Test the MediaCollection.get_countries() method"
+        self.assertEquals(self.volonte.get_countries(), [self.belgique, self.france])
+
diff --git a/telemeta/util/unaccent.py b/telemeta/util/unaccent.py
new file mode 100644 (file)
index 0000000..7c5757d
--- /dev/null
@@ -0,0 +1,71 @@
+# This file by Fredrik Lundh from:
+# http://effbot.org/zone/unicode-convert.htm
+# http://effbot.python-hosting.com/file/stuff/sandbox/text/unaccent.py
+
+# use a dynamically populated translation dictionary to remove accents
+# from a string
+
+import unicodedata, sys
+
+CHAR_REPLACEMENT = {
+    # latin-1 characters that don't have a unicode decomposition
+    0xc6: u"AE", # LATIN CAPITAL LETTER AE
+    0xd0: u"D",  # LATIN CAPITAL LETTER ETH
+    0xd8: u"OE", # LATIN CAPITAL LETTER O WITH STROKE
+    0xde: u"Th", # LATIN CAPITAL LETTER THORN
+    0xdf: u"ss", # LATIN SMALL LETTER SHARP S
+    0xe6: u"ae", # LATIN SMALL LETTER AE
+    0xf0: u"d",  # LATIN SMALL LETTER ETH
+    0xf8: u"oe", # LATIN SMALL LETTER O WITH STROKE
+    0xfe: u"th", # LATIN SMALL LETTER THORN
+    }
+
+##
+# Translation dictionary.  Translation entries are added to this
+# dictionary as needed.
+
+class UnaccentedMap(dict):
+
+    ##
+    # Maps a unicode character code (the key) to a replacement code
+    # (either a character code or a unicode string).
+
+    def mapchar(self, key):
+        ch = self.get(key)
+        if ch is not None:
+            return ch
+        de = unicodedata.decomposition(unichr(key))
+        if de:
+            try:
+                ch = int(de.split(None, 1)[0], 16)
+            except (IndexError, ValueError):
+                ch = key
+        else:
+            ch = CHAR_REPLACEMENT.get(key, key)
+        self[key] = ch
+        return ch
+
+    if sys.version >= "2.5":
+        # use __missing__ where available
+        __missing__ = mapchar
+    else:
+        # otherwise, use standard __getitem__ hook (this is slower,
+        # since it's called for each character)
+        __getitem__ = mapchar
+
+
+_map = UnaccentedMap()
+
+def unaccent(str):
+    return str.translate(_map)
+
+def unaccent_icmp(str1, str2):
+    str1 = unaccent(str1).lower()
+    str2 = unaccent(str2).lower()
+    if str1 > str2:
+        return 1
+
+    if str1 < str2:
+        return -1
+
+    return 0