Removing print statements from convert_gps_media_data migration
[mediagoblin.git] / mediagoblin / db / mongo / models.py
index e085840e7ce3ab9e25deddbb72bc62edec11c13b..2e35a2b8f00c24265cb57c0689cd2bb8b427d20c 100644 (file)
@@ -1,5 +1,5 @@
 # GNU MediaGoblin -- federated, autonomous media hosting
-# Copyright (C) 2011 MediaGoblin contributors.  See AUTHORS.
+# Copyright (C) 2011, 2012 MediaGoblin contributors.  See AUTHORS.
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as published by
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-import datetime, uuid
+import datetime
 
 from mongokit import Document
 
-from mediagoblin.auth import lib as auth_lib
-from mediagoblin import mg_globals
-from mediagoblin.db import migrations
-from mediagoblin.db.util import ASCENDING, DESCENDING, ObjectId
+from mediagoblin.db.mongo import migrations
+from mediagoblin.db.mongo.util import ASCENDING, DESCENDING, ObjectId
 from mediagoblin.tools.pagination import Pagination
-from mediagoblin.tools import url, common
-from mediagoblin.tools import licenses
+from mediagoblin.db.mixin import UserMixin, MediaEntryMixin, MediaCommentMixin
+
+
+class MongoPK(object):
+    """An alias for the _id primary key"""
+    def __get__(self, instance, cls):
+       return instance['_id']   
+    def __set__(self, instance, val):
+       instance['_id'] = val  
+    def __delete__(self, instance):
+       del instance['_id']
+
 
 ###################
 # Custom validators
@@ -35,7 +43,7 @@ from mediagoblin.tools import licenses
 ########
 
 
-class User(Document):
+class User(Document, UserMixin):
     """
     A user of MediaGoblin.
 
@@ -60,25 +68,24 @@ class User(Document):
      - is_admin: Whether or not this user is an administrator or not.
      - url: this user's personal webpage/website, if appropriate.
      - bio: biography of this user (plaintext, in markdown)
-     - bio_html: biography of the user converted to proper HTML.
     """
     __collection__ = 'users'
+    use_dot_notation = True
 
     structure = {
         'username': unicode,
         'email': unicode,
         'created': datetime.datetime,
-        'plugin_data': dict, # plugins can dump stuff here.
+        'plugin_data': dict,  # plugins can dump stuff here.
         'pw_hash': unicode,
         'email_verified': bool,
         'status': unicode,
         'verification_key': unicode,
         'is_admin': bool,
-        'url' : unicode,
-        'bio' : unicode,     # May contain markdown
-        'bio_html': unicode, # May contain plaintext, or HTML
-        'fp_verification_key': unicode, # forgotten password verification key
-        'fp_token_expire': datetime.datetime
+        'url': unicode,
+        'bio': unicode,      # May contain markdown
+        'fp_verification_key': unicode,  # forgotten password verification key
+        'fp_token_expire': datetime.datetime,
         }
 
     required_fields = ['username', 'created', 'pw_hash', 'email']
@@ -87,18 +94,12 @@ class User(Document):
         'created': datetime.datetime.utcnow,
         'email_verified': False,
         'status': u'needs_email_verification',
-        'verification_key': lambda: unicode(uuid.uuid4()),
         'is_admin': False}
 
-    def check_login(self, password):
-        """
-        See if a user can login with this password
-        """
-        return auth_lib.bcrypt_check_password(
-            password, self['pw_hash'])
+    id = MongoPK()
 
 
-class MediaEntry(Document):
+class MediaEntry(Document, MediaEntryMixin):
     """
     Record of a piece of media.
 
@@ -120,9 +121,6 @@ class MediaEntry(Document):
        up with MarkDown for slight fanciness (links, boldness, italics,
        paragraphs...)
 
-     - description_html: Rendered version of the description, run through
-       Markdown and cleaned with our cleaning tool.
-
      - media_type: What type of media is this?  Currently we only support
        'image' ;)
 
@@ -130,7 +128,7 @@ class MediaEntry(Document):
        For example, images might contain some EXIF data that's not appropriate
        to other formats.  You might store it like:
 
-         mediaentry['media_data']['exif'] = {
+         mediaentry.media_data['exif'] = {
              'manufacturer': 'CASIO',
              'model': 'QV-4000',
              'exposure_time': .659}
@@ -138,7 +136,7 @@ class MediaEntry(Document):
        Alternately for video you might store:
 
          # play length in seconds
-         mediaentry['media_data']['play_length'] = 340
+         mediaentry.media_data['play_length'] = 340
 
        ... so what's appropriate here really depends on the media type.
 
@@ -159,7 +157,7 @@ class MediaEntry(Document):
         "unprocessed": uploaded but needs to go through processing for display
         "processed": processed and able to be displayed
 
-     - license: URI for entry's license
+     - license: URI for media's license.
 
      - queued_media_file: storage interface style filepath describing a file
        queued for processing.  This is stored in the mg_globals.queue_store
@@ -175,25 +173,24 @@ class MediaEntry(Document):
        critical to this piece of media but may be usefully relevant to people
        viewing the work.  (currently unused.)
 
-     - fail_error: path to the exception raised 
-     - fail_metadata: 
-
+     - fail_error: path to the exception raised
+     - fail_metadata:
     """
     __collection__ = 'media_entries'
+    use_dot_notation = True
 
     structure = {
         'uploader': ObjectId,
         'title': unicode,
         'slug': unicode,
         'created': datetime.datetime,
-        'description': unicode, # May contain markdown/up
-        'description_html': unicode, # May contain plaintext, or HTML
+        'description': unicode,  # May contain markdown/up
         'media_type': unicode,
-        'media_data': dict, # extra data relevant to this media_type
-        'plugin_data': dict, # plugins can dump stuff here.
+        'media_data': dict,  # extra data relevant to this media_type
+        'plugin_data': dict,  # plugins can dump stuff here.
         'tags': [dict],
         'state': unicode,
-        'license': unicode, # License URI
+        'license': unicode,
 
         # For now let's assume there can only be one main file queued
         # at a time
@@ -219,102 +216,49 @@ class MediaEntry(Document):
         'created': datetime.datetime.utcnow,
         'state': u'unprocessed'}
 
-    def get_comments(self):
-        return self.db.MediaComment.find({
-                'media_entry': self['_id']}).sort('created', DESCENDING)
-
-    def get_display_media(self, media_map, fetch_order=common.DISPLAY_IMAGE_FETCHING_ORDER):
-        """
-        Find the best media for display.
-
-        Args:
-        - media_map: a dict like
-          {u'image_size': [u'dir1', u'dir2', u'image.jpg']}
-        - fetch_order: the order we should try fetching images in
-
-        Returns:
-        (media_size, media_path)
-        """
-        media_sizes = media_map.keys()
-
-        for media_size in common.DISPLAY_IMAGE_FETCHING_ORDER:
-            if media_size in media_sizes:
-                return media_map[media_size]
+    id = MongoPK()
 
-    def main_mediafile(self):
-        pass
+    def media_data_init(self, **kwargs):
+        self.media_data.update(kwargs)
 
-    def generate_slug(self):
-        self['slug'] = url.slugify(self['title'])
-
-        duplicate = mg_globals.database.media_entries.find_one(
-            {'slug': self['slug']})
-
-        if duplicate:
-            self['slug'] = "%s-%s" % (self['_id'], self['slug'])
-
-    def url_for_self(self, urlgen):
-        """
-        Generate an appropriate url for ourselves
-
-        Use a slug if we have one, else use our '_id'.
-        """
-        uploader = self.uploader()
-
-        if self.get('slug'):
-            return urlgen(
-                'mediagoblin.user_pages.media_home',
-                user=uploader['username'],
-                media=self['slug'])
+    def get_comments(self, ascending=False):
+        if ascending:
+            order = ASCENDING
         else:
-            return urlgen(
-                'mediagoblin.user_pages.media_home',
-                user=uploader['username'],
-                media=unicode(self['_id']))
+            order = DESCENDING
+            
+        return self.db.MediaComment.find({
+                'media_entry': self._id}).sort('created', order)
 
     def url_to_prev(self, urlgen):
         """
         Provide a url to the previous entry from this user, if there is one
         """
-        cursor = self.db.MediaEntry.find({'_id' : {"$gt": self['_id']},
-                                          'uploader': self['uploader'],
+        cursor = self.db.MediaEntry.find({'_id': {"$gt": self._id},
+                                          'uploader': self.uploader,
                                           'state': 'processed'}).sort(
                                                     '_id', ASCENDING).limit(1)
-        if cursor.count():
-            return urlgen('mediagoblin.user_pages.media_home',
-                          user=self.uploader()['username'],
-                          media=unicode(cursor[0]['slug']))
+        for media in cursor:
+            return media.url_for_self(urlgen)
 
     def url_to_next(self, urlgen):
         """
         Provide a url to the next entry from this user, if there is one
         """
-        cursor = self.db.MediaEntry.find({'_id' : {"$lt": self['_id']},
-                                          'uploader': self['uploader'],
+        cursor = self.db.MediaEntry.find({'_id': {"$lt": self._id},
+                                          'uploader': self.uploader,
                                           'state': 'processed'}).sort(
                                                     '_id', DESCENDING).limit(1)
 
-        if cursor.count():
-            return urlgen('mediagoblin.user_pages.media_home',
-                          user=self.uploader()['username'],
-                          media=unicode(cursor[0]['slug']))
-
-    def uploader(self):
-        return self.db.User.find_one({'_id': self['uploader']})
+        for media in cursor:
+            return media.url_for_self(urlgen)
 
-    def get_fail_exception(self):
-        """
-        Get the exception that's appropriate for this error
-        """
-        if self['fail_error']:
-            return common.import_component(self['fail_error'])
+    @property
+    def get_uploader(self):
+        return self.db.User.find_one({'_id': self.uploader})
 
-    def get_license_data(self):
-        """Return license dict for requested license"""
-        return licenses.SUPPORTED_LICENSES[self['license']]
 
-
-class MediaComment(Document):
+class MediaComment(Document, MediaCommentMixin):
     """
     A comment on a MediaEntry.
 
@@ -323,18 +267,17 @@ class MediaComment(Document):
      - author: user who posted this comment
      - created: when the comment was created
      - content: plaintext (but markdown'able) version of the comment's content.
-     - content_html: the actual html-rendered version of the comment displayed.
-       Run through Markdown and the HTML cleaner.
     """
 
     __collection__ = 'media_comments'
+    use_dot_notation = True
 
     structure = {
         'media_entry': ObjectId,
         'author': ObjectId,
         'created': datetime.datetime,
         'content': unicode,
-        'content_html': unicode}
+        }
 
     required_fields = [
         'media_entry', 'author', 'created', 'content']
@@ -345,7 +288,8 @@ class MediaComment(Document):
     def media_entry(self):
         return self.db.MediaEntry.find_one({'_id': self['media_entry']})
 
-    def author(self):
+    @property
+    def get_author(self):
         return self.db.User.find_one({'_id': self['author']})
 
 
@@ -360,4 +304,3 @@ def register_models(connection):
     Register all models in REGISTER_MODELS with this connection.
     """
     connection.register(REGISTER_MODELS)
-