Commits

Anonymous committed 651d2ed

don't use a module here.

Comments (0)

Files changed (3)

friendpaste/utils.py

+# -*- coding: utf-8 -
+# Copyright 2008 by Benoît Chesneau <benoitc@e-engura.com>
+# 
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from calendar import timegm
+from datetime import datetime, timedelta, time, tzinfo
+from time import strptime, localtime, struct_time
+from gettext import gettext, ngettext
+import thread, threading
+
+from werkzeug import Local, LocalManager
+
+
+local = Local()
+local_manager = LocalManager([local])
+
+
+def ungettext(singular, plural, number):
+    """ stupid wrapper yet waiting internationalisation """
+    return ngettext(singular, plural, number)
+
+def ugettext(message):
+    """ 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
+    as a nicely formatted string, e.g. "10 minutes".  If d occurs after now,
+    then "0 minutes" is returned.
+
+    Units used are years, months, weeks, days, hours, and minutes.
+    Seconds and microseconds are ignored.  Up to two adjacent units will be
+    displayed.  For example, "2 weeks, 3 days" and "1 year, 3 months" are
+    possible outputs, but "2 weeks, 3 hours" and "1 year, 5 days" are not.
+
+    Adapted from http://blog.natbat.co.uk/archive/2003/Jun/14/time_since
+    """
+    chunks = (
+      (60 * 60 * 24 * 365, lambda n: ungettext('year', 'years', n)),
+      (60 * 60 * 24 * 30, lambda n: ungettext('month', 'months', n)),
+      (60 * 60 * 24 * 7, lambda n : ungettext('week', 'weeks', n)),
+      (60 * 60 * 24, lambda n : ungettext('day', 'days', n)),
+      (60 * 60, lambda n: ungettext('hour', 'hours', n)),
+      (60, lambda n: ungettext('minute', 'minutes', n))
+    )
+    
+    # Convert datetime.date to datetime.datetime for comparison
+    if d.__class__ is not datetime:
+        type= d.__class__
+        d = datetime(d.year, d.month, d.day)
+    if now:
+        t = now.timetuple()
+    else:
+        t = localtime()
+    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).utcnow()
+
+    # ignore microsecond part of 'd' since we removed it from 'now'
+    delta = now - (d - timedelta(0, 0, d.microsecond))
+    since = delta.days * 24 * 60 * 60 + delta.seconds
+    if since <= 0:
+        # d is in the future compared to now, stop processing.
+        return u'0 ' + ugettext('minutes')
+    for i, (seconds, name) in enumerate(chunks):
+        count = since // seconds
+        if count != 0:
+            break
+    s = ugettext('%(number)d %(type)s') % {'number': count, 'type': name(count)}
+    if i + 1 < len(chunks):
+        # Now get the second item
+        seconds2, name2 = chunks[i + 1]
+        count2 = (since - (seconds * count)) // seconds2
+        if count2 != 0:
+            s += ugettext(', %(number)d %(type)s') % {'number': count2, 'type': name2(count2)}
+    return s
+
+def utf8(text):
+    """Encodes text in utf-8.
+        
+        >> utf8(u'\u1234') # doctest doesn't seem to like utf-8
+        '\xe1\x88\xb4'
+
+        >>> utf8('hello')
+        'hello'
+        >>> utf8(42)
+        '42'
+    """
+    if isinstance(text, unicode):
+        return text.encode('utf-8')
+    elif isinstance(text, str):
+        return text
+    else:
+        return str(text)
+
+def to_str(s):
+    """
+    return a bytestring version of s, encoded in utf8
+    """
+
+    if not isinstance(s, basestring):
+        try:
+            return str(s)
+        except UnicodeEncodeError:
+            return unicode(s).encode('utf-8', 'strict')
+    elif isinstance(s, unicode):
+        return s.encode('utf-8', 'strict')
+    else:
+        return s
+
+
+def iri_to_uri(iri):
+    """
+    Convert an Internationalized Resource Identifier (IRI) portion to a URI
+    portion that is suitable for inclusion in a URL.
+
+    Returns an ASCII string containing the encoded result.
+    code from djangoprohect.
+    """
+    # The list of safe characters here is constructed from the printable ASCII
+    # characters that are not explicitly excluded by the list at the end of
+    # section 3.1 of RFC 3987.
+    if iri is None:
+        return iri
+
+    return urllib.quote(to_str(iri), safe='/#%[]=:;$&()+,!?*')
+
+def datetimestr_topython(value):
+    if isinstance(value, basestring):
+        try:
+            value = value.split('.', 1)[0] # strip out microseconds
+            value = value.rstrip('Z') # remove timezone separator
+            timestamp = timegm(strptime(value, '%Y-%m-%dT%H:%M:%S'))
+            value = datetime.utcfromtimestamp(timestamp)
+        except ValueError, e:
+            raise ValueError('Invalid ISO date/time %r' % value)
+    return value
+
+
+def datetime_tojson(value):
+    if isinstance(value, struct_time):
+        value = datetime.utcfromtimestamp(timegm(value))
+    elif not isinstance(value, datetime):
+        value = datetime.combine(value, time(0))
+    return value.replace(microsecond=0).isoformat() + 'Z'

friendpaste/utils/__init__.py

 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import binascii
 from calendar import timegm
-from datetime import datetime, timedelta, time, tzinfo
+from datetime import datetime, timedelta, time, tzinfo, date
 from time import strptime, localtime, struct_time
 from gettext import gettext, ngettext
-import thread, threading
+# compatibility with python 2.4
+try:
+    from hashlib import sha1 as _sha
+except ImportError:
+    import sha
+    _sha = sha.new
 
 from werkzeug import Local, LocalManager
 
-
+_hex = binascii.hexlify
 local = Local()
 local_manager = LocalManager([local])
 
-
 def ungettext(singular, plural, number):
     """ stupid wrapper yet waiting internationalisation """
     return ngettext(singular, plural, number)
         tt = time.localtime(stamp)
         return tt.tm_isdst > 0
 
+def prettytime(d):
+    if d.__class__ is not datetime:
+        type= d.__class__
+        d = datetime(d.year, d.month, d.day)
+    t = localtime()
+    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).utcnow()
+    
+    if d.year == now.year and d.month == now.month and d.day == now.day:
+            return d.strftime("%H:%M")
+    return d.strftime("%d %b %y")
+    
 def timesince(d, now=None):
     """
     Takes two datetime objects and returns the time between d and now
     if since <= 0:
         # d is in the future compared to now, stop processing.
         return u'0 ' + ugettext('minutes')
+    if since > 86400:
+        return d.strftime("%d %b %y")
     for i, (seconds, name) in enumerate(chunks):
         count = since // seconds
         if count != 0:
     elif not isinstance(value, datetime):
         value = datetime.combine(value, time(0))
     return value.replace(microsecond=0).isoformat() + 'Z'
+
+def make_hash(*args):
+    if len(args) <= 0:
+        return None
+    s = _sha()
+    for arg in args:
+        s.update(to_str(arg))
+
+    return _hex(s.digest())
+    
+def short(node):
+    return _hex(node[:6])

static/js/friendpaste.js

         $(".show-history").click(this.do_history);
 
 
-          /* init default */
-            is_wrap = $.cookie("nowrap-lines")
-            if (is_wrap == "yes") {
-                $("table.sourcetable tbody").addClass("wrap");
-                $("#wrap-lines").attr("checked", "")
-            }
+        /* init default */
+        is_wrap = $.cookie("nowrap-lines")
+        if (is_wrap == "yes") {
+            $("table.sourcetable tbody").addClass("wrap");
+            $("#wrap-lines").attr("checked", "")
+        }
 
-            is_hide = $.cookie("hide-linenos");
-            if (is_hide == "yes") {
-                $("table.sourcetable tbody").addClass("hidenos");
-                $("#show-linenos").attr("checked", "");
-            }
-        
+        is_hide = $.cookie("hide-linenos");
+        if (is_hide == "yes") {
+            $("table.sourcetable tbody").addClass("hidenos");
+            $("#show-linenos").attr("checked", "");
+        }
+
         $("#snippet-edit").each(function() {
-            $("#paste_snippet").makeResizable({vertical: true});
+            $("#paste_snippet").makeResizable({
+                vertical: true
+            });
         })
-        
+
     },
+    
     do_edit: function(e) {
         $("#snippet").addClass("hidden");
         $("#snippet-edit").removeClass("hidden");
-        
+
         return false;
     },
 
         $("#snippet").removeClass("hidden");
         return false;
     },
-    
+
     toggleLineNumber: function(event) {
         if ($(this).attr("checked")) {
             $.cookie("hide-linenos", null);
         }
         $("table.sourcetable tbody").toggleClass("hidenos");
     },
-    
+
     wrapLines: function(event) {
         if (this.checked) {
             $.cookie("nowrap-lines", null);
         }
         $("table.sourcetable tbody").toggleClass("wrap");
     },
-    
+
     setTheme: function(event) {
         setCookie("theme", this.value, 60);
         document.location.reload();
     },
 
     do_history: function(event) {
-        $.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>");
-                });
+        $.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").addClass("hidden");
-                $("#revisions").removeClass("hidden");
-            });
-        
+            $("#snippet").addClass("hidden");
+            $("#revisions").removeClass("hidden");
+        });
+
 
         return false;
     }
-    
 
-    
+
+
 }