Commits

Anonymous committed 6c46e10

don't hit the database when you don't need it.

Comments (0)

Files changed (6)

friendpaste/application.py

 def init_views(db):
     paste_view={
             'by_id': 'function(doc) { if (doc.type == "snippet") { map([doc._id, 0], doc); } else if (doc.type == "revision") { map([doc.parent, 1, doc.updated], doc); }}',
-            'by_revision': 'function(doc) { if (doc.type == "revision") { map([doc.parent,doc.revid], doc); }}'
+            'revisions': 'function(doc) { if (doc.type == "revision") { map([doc.parent,doc.updated], doc); } if (doc.type == "snippet") { map([doc._id,doc.updated], doc); }}'
 
     }
     try:

friendpaste/paste/models.py

         """
         override store procedure to generate small id
         """
-        self.updated = datetime.now()
+        self.updated = datetime.utcnow()
         if getattr(self._data, 'id', None) is None:
-            self.created = datetime.now()
+            self.created = datetime.utcnow()
             node = hash(self.snippet+self.title+self.language,'')
             self.revid = short(node)
             stored=False
             self._data = db.get(docid)
         else:
             old_data = db.get(self._data.id)
-            self.created = datetime.now()
+            self.created = datetime.utcnow()
             old_hash = hash(old_data['snippet']+old_data['title']+old_data['language'], '')
             new_hash = hash(self.snippet+self.title+self.language, '')
             if old_hash != new_hash:

friendpaste/paste/views.py

     snippet= Snippet.wrap(data)
     return snippet, revisions
 
+def get_revision(snippetid, revid):
+    revision = couchdb_proxy.view('_view/paste/by_id', key=[str(snippetid), str(revid)])
+    data = revision.value
+    data['_id'] = r.value['parent']
+    return Snippet.wrap(data)
+
+
 def view_snippet(request, id):
     mimetypes = request.accept_mimetypes
     
         })
 
     rev = request.values.get('rev', None)
-    #s, revisions = get_snippet(id, rev)
     if rev is None:
         s = couchdb_proxy.load(Snippet, id)
+    else:
+        s, revisions = get_snippet(id, rev) 
 
     if 'application/json' in mimetypes:
         if request.method == 'GET':
     return feed.get_response()
 
 def view_revisions(request, id):
-    res = _get_snippet_revisions(id)
-    if not res:
-        raise NotFound 
-    # set revisions
-    revisions = res[1:]
-    revisions.reverse()
+    revs = couchdb_proxy.view('_view/paste/revisions', startkey=[str(id), "0"], endkey=[str(id), "9"])
+    revisions = []
+    s = None
+    if len(revs) > 0:
+        for rev in revs:
+            if rev.value['_id'] == id:
+                s = Snippet.wrap(rev.value)
+                rev.value['parent']=rev.value['_id']
+            revisions.append(rev.value)
+            revisions.sort(lambda a,b: cmp(a['updated'], b['updated']), reverse=True)
+     
+    if 'application/json' in request.accept_mimetypes:
+        if len(revisions) <= 0:
+            return send_json([])
+        return send_json([r for r in revisions])
 
-    # set snippet
-    data = res[0].value
-    data['_id'] = res[0].id
-    s = Snippet.wrap(data)
-
+    if s is None:
+        raise NotFound
     return render_response('paste/revisions.html', snippet=s, revisions=revisions)
 
 def view_rawsnippet(request, id, rev):

friendpaste/utils/__init__.py

 # limitations under the License.
 
 from calendar import timegm
-from datetime import datetime, timedelta, time
+from datetime import datetime, timedelta, time, tzinfo
 from time import strptime, localtime
 from gettext import gettext, ngettext
 import thread, threading
     """ stupid wrapper yet waiting internationalisation """
     return gettext(message)
 
+class LocalTimezone(tzinfo):
+    "Proxy timezone information from time module."
+    def __init__(self, dt):
+        tzinfo.__init__(self, dt)
+        self._tzname = self.tzname(dt)
+
+    def __repr__(self):
+        return self._tzname
+
+    def utcoffset(self, dt):
+        if self._isdst(dt):
+            return timedelta(seconds=-time.altzone)
+        else:
+            return timedelta(seconds=-time.timezone)
+
+    def dst(self, dt):
+        if self._isdst(dt):
+            return timedelta(seconds=-time.altzone) - timedelta(seconds=-time.timezone)
+        else:
+            return timedelta(0)
+
+    def tzname(self, dt):
+        try:
+            return smart_unicode(time.tzname[self._isdst(dt)], DEFAULT_ENCODING)
+        except UnicodeDecodeError:
+            return None
+
+    def _isdst(self, dt):
+        tt = (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.weekday(), 0, -1)
+        try:
+            stamp = time.mktime(tt)
+        except OverflowError:
+            # 32 bit systems can't handle dates after Jan 2038, so we fake it
+            # in that case (since we only care about the DST flag here).
+            tt = (2037,) + tt[1:]
+            stamp = time.mktime(tt)
+        tt = time.localtime(stamp)
+        return tt.tm_isdst > 0
+
+
 def timesince(d, now=None):
     """
     Takes two datetime objects and returns the time between d and now
         t = now.timetuple()
     else:
         t = localtime()
-    #if d.tzinfo:
-    #    tz = LocalTimezone(d)
-    #else:
-    #    tz = None
+    if d.tzinfo:
+        tz = LocalTimezone(d)
+    else:
+        tz = None
     tz = None
-    now = datetime(t[0], t[1], t[2], t[3], t[4], t[5], tzinfo=tz)
+    now = datetime(t[0], t[1], t[2], t[3], t[4], t[5], tzinfo=tz).utcnow()
 
     # ignore microsecond part of 'd' since we removed it from 'now'
     delta = now - (d - timedelta(0, 0, d.microsecond))

static/js/friendpaste.js

  *
  */
 
+
 function getCookie(name) {
     var nameEq = name + "=";
     var ca = document.cookie.split(";");
     },
 
     do_history: function(event) {
-        $("#snippet").hide();
-        $("#revisions").show();
+        $.getJSON("/"+snippet_id+"/revisions",
+            function(data) {
+                $(".revisionstable tbody.content").html("");
+                $.each(data, function (i, item) {
+                    d= new Date()
+                    d.setISODate(item['updated']);
+                    $("#revisions tbody.content").append("<tr>" +
+                        "<td class=\"since\">"+d.toTimeSinceString(1)+"</td>"+
+                        "<td class=\"rev\">rev. <a href='/"+  item['parent'] + '?rev='+item['revid'] + "'>"+item['revid']+"</a></td>"+
+                        "<td class=\"changeset\"><a href='/"+ item['parent'] + '/changeset?rev='+item['revid'] + "'>Diff</a></td>"+
+                        "<td class=\"view-rev\"><a href='/"+ item['parent'] + '?rev='+item['revid'] + "'>View</a></td></tr>");
+                });
+
+                $("#snippet").hide();
+                $("#revisions").show();
+            });
+        
 
         return false;
     }

templates/paste/view.html

 <link rel="alternate" href="/{{ snippet.id }}/rss" type="application/rss+xml" class="rss" title="RSS Feed" />
 
 <link rel="stylesheet" href="/static/css/{{theme }}.css" type="text/css" />
+
+<script type="text/javascript">
+    snippet_id = "{{ snippet.id }}";
+</script>
+<script type="text/javascript" src="/static/js/date.js"></script>
 <script type="text/javascript" src="/static/js/friendpaste.js"></script>
 {% endblock %}
 
 
 <div id="revisions">
     <h2><a href="/{{ snippet.id }}" class="root">{{ snippet.id }}</a>&nbsp;/&nbsp;{% if snippet.title %}{{ snippet.title }}{% else %}No title{% endif %}</h2>
-    <p>last change {{ snippet.updated|datetimeformat }}</p>
+    <p>last change {{ snippet.updated|datetimeformat }} (UTC)</p>
     <h3>Older revisions</h3>
     <table class="revisionstable">
-        <tr>
-            <td class="since">{{ snippet.updated|timesince }}</td>
-            <td class="rev">rev. <a href="/{{ snippet.id }}">{{ snippet.revid }}</a></td>
-            <td class="changeset"><a href="/{{ snippet.id }}/changeset?rev={{ snippet.revid }}">Diff</a></td>
-            <td class="view-rev"><a href="{{ snippet.id }}">View</a></td>
-        </tr>
-    
-
-    {% for rev in revisions %}
-        <tr>
-            <td class="since">{{ rev.value['updated']|timesince }}</td>
-            <td class="rev">rev. <a href="/{{ snippet.id }}?rev={{ rev.value['revid'] }}">{{ rev.value['revid'] }}</a></td>
-            <td class="changeset"><a href="/{{ snippet.id }}/changeset?rev={{ rev.value['revid'] }}">Diff</a></td>
-            <td class="view-rev"><a href="/{{ snippet.id }}?rev={{ rev.value['revid'] }}">View</a></td>
-        </tr>
-    {% endfor %}
+        <thead></thead>
+            <tbody class="content">
+            </tbody>
+            
     </table>
     <form action="/{{ snippet.id }}" method="get"><input type="submit" class="cancel" value="Back to the paste..." /></form>
 </div>