summaryrefslogtreecommitdiffstats
path: root/hyperkitty
diff options
context:
space:
mode:
authorAurélien Bompard <aurelien@bompard.org>2013-07-15 12:02:04 +0200
committerAurélien Bompard <aurelien@bompard.org>2013-07-15 12:02:04 +0200
commit1c0db6b8e3b262b9cdba6a32e71c9bbac8b5f7cc (patch)
tree54fecd587266ebac0efe2bd777d2fc2776fa092b /hyperkitty
parent1a339ac1f7dac6e63b83864b6421aed1b0fdde75 (diff)
downloadhyperkitty-1c0db6b8e3b262b9cdba6a32e71c9bbac8b5f7cc.tar.gz
hyperkitty-1c0db6b8e3b262b9cdba6a32e71c9bbac8b5f7cc.tar.xz
hyperkitty-1c0db6b8e3b262b9cdba6a32e71c9bbac8b5f7cc.zip
Cleanups in the lib/__init__.py file
Diffstat (limited to 'hyperkitty')
-rw-r--r--hyperkitty/lib/__init__.py204
-rw-r--r--hyperkitty/lib/posting.py66
-rw-r--r--hyperkitty/lib/view_helpers.py171
-rw-r--r--hyperkitty/tests/test_forms.py20
-rw-r--r--hyperkitty/tests/test_lib.py2
-rw-r--r--hyperkitty/views/accounts.py3
-rw-r--r--hyperkitty/views/list.py7
-rw-r--r--hyperkitty/views/message.py4
-rw-r--r--hyperkitty/views/search.py3
-rw-r--r--hyperkitty/views/thread.py4
10 files changed, 251 insertions, 233 deletions
diff --git a/hyperkitty/lib/__init__.py b/hyperkitty/lib/__init__.py
index 9bcded3..1970917 100644
--- a/hyperkitty/lib/__init__.py
+++ b/hyperkitty/lib/__init__.py
@@ -19,59 +19,6 @@
# Author: Aurelien Bompard <abompard@fedoraproject.org>
#
-import urllib
-from hashlib import md5
-import datetime
-
-from django.core.exceptions import SuspiciousOperation
-from django.core.mail import EmailMessage
-from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
-from django.utils.timezone import utc
-from mailmanclient import MailmanConnectionError
-
-from hyperkitty.lib import mailman
-from hyperkitty.models import ThreadCategory, LastView
-from hyperkitty.views.forms import CategoryForm
-
-
-FLASH_MESSAGES = {
- "updated-ok": ("success", "The profile was successfully updated."),
- "sent-ok": ("success", "The message has been sent successfully."),
-}
-
-
-def gravatar_url(email):
- '''Return a gravatar url for an email address'''
- size = 64
- default = "http://fedoraproject.org/static/images/" + \
- "fedora_infinity_%ix%i.png" % (size, size)
- query_string = urllib.urlencode({'s': size, 'd': default})
- identifier = md5(email).hexdigest()
- return 'http://www.gravatar.com/avatar/%s?%s' % (identifier, query_string)
-
-
-def get_months(store, list_name):
- """ Return a dictionnary of years, months for which there are
- potentially archives available for a given list (based on the
- oldest post on the list).
-
- :arg list_name, name of the mailing list in which this email
- should be searched.
- """
- date_first = store.get_start_date(list_name)
- if not date_first:
- return {}
- archives = {}
- now = datetime.datetime.now()
- year = date_first.year
- month = date_first.month
- while year < now.year:
- archives[year] = range(1, 13)[(month -1):]
- year = year + 1
- month = 1
- archives[now.year] = range(1, 13)[:now.month]
- return archives
-
def get_store(request):
return request.environ["kittystore.store"]
@@ -83,154 +30,3 @@ def stripped_subject(mlist, subject):
if subject.lower().startswith(mlist.subject_prefix.lower()):
subject = subject[len(mlist.subject_prefix) : ]
return subject
-
-
-def get_display_dates(year, month, day):
- if day is None:
- start_day = 1
- else:
- start_day = int(day)
- begin_date = datetime.datetime(int(year), int(month), start_day)
-
- if day is None:
- end_date = begin_date + datetime.timedelta(days=32)
- end_date = end_date.replace(day=1)
- else:
- end_date = begin_date + datetime.timedelta(days=1)
-
- return begin_date, end_date
-
-
-def daterange(start_date, end_date):
- for n in range(int((end_date - start_date).days)):
- yield start_date + datetime.timedelta(n)
-
-
-class PostingFailed(Exception): pass
-
-def post_to_list(request, mlist, subject, message, headers={},
- attachments=None):
- if not mlist:
- # Make sure the list exists to avoid posting to any email addess
- raise SuspiciousOperation("I don't know this mailing-list")
- # Check that the user is subscribed
- try:
- mailman.subscribe(mlist.name, request.user)
- except MailmanConnectionError:
- raise PostingFailed("Can't connect to Mailman's REST server, "
- "your message has not been sent.")
- # send the message
- headers["User-Agent"] = "HyperKitty on %s" % request.build_absolute_uri("/")
- if not request.user.first_name and not request.user.last_name:
- from_email = request.user.email
- else:
- from_email = '"%s %s" <%s>' % (request.user.first_name,
- request.user.last_name,
- request.user.email)
- msg = EmailMessage(
- subject=subject,
- body=message,
- from_email=from_email,
- to=[mlist.name],
- headers=headers,
- )
- # Attachments
- if attachments:
- if not isinstance(attachments, list):
- attachments = [attachments]
- for attach in attachments:
- msg.attach(attach.name, attach.read())
- msg.send()
-
-
-def paginate(objects, page_num, max_page_range=10, paginator=None):
- try:
- page_num = int(page_num)
- except (TypeError, ValueError):
- page_num = 1
- if paginator is None:
- paginator = Paginator(objects, 10) # else use the provided instance
- try:
- objects = paginator.page(page_num)
- except PageNotAnInteger:
- # If page is not an integer, deliver first page.
- objects = paginator.page(1)
- except EmptyPage:
- # If page is out of range (e.g. 9999), deliver last page of results.
- objects = paginator.page(paginator.num_pages)
- # Calculate the displayed page range
- if paginator.num_pages > max_page_range:
- objects.page_range = [ 1 ]
- subrange_lower = page_num - (max_page_range / 2 - 2)
- if subrange_lower > 3:
- objects.page_range.append("...")
- else:
- subrange_lower = 2
- objects.page_range.extend(range(subrange_lower, page_num))
- if page_num != 1 and page_num != 100:
- objects.page_range.append(page_num)
- subrange_upper = page_num + (max_page_range / 2 - 2)
- if subrange_upper >= paginator.num_pages - 2:
- subrange_upper = paginator.num_pages - 1
- objects.page_range.extend(range(page_num+1, subrange_upper+1))
- if subrange_upper < paginator.num_pages - 2:
- objects.page_range.append("...")
- objects.page_range.append(paginator.num_pages)
- else:
- objects.page_range = [ p+1 for p in range(paginator.num_pages) ]
- return objects
-
-
-def get_category_widget(request=None, current_category=None):
- """
- Returns the category form and the applicable category object (or None if no
- category is set for this thread).
-
- If current_category is not provided or None, try to deduce it from the POST
- request.
- if request is not provided or None, don't return the category form, return
- None instead.
- """
- categories = [ (c.name, c.name.upper())
- for c in ThreadCategory.objects.all() ] \
- + [("", "no category")]
-
- if request:
- if request.method == "POST":
- category_form = CategoryForm(request.POST)
- else:
- category_form = CategoryForm(initial={"category": current_category or ""})
- category_form["category"].field.choices = categories
- else:
- category_form = None
- if request and request.method == "POST" and category_form.is_valid():
- # is_valid() must be called after the choices have been set
- current_category = category_form.cleaned_data["category"]
-
- if not current_category:
- category = None
- else:
- try:
- category = ThreadCategory.objects.get(name=current_category)
- except ThreadCategory.DoesNotExist:
- category = None
- return category, category_form
-
-
-def is_thread_unread(request, mlist_name, thread):
- """Returns True or False if the thread is unread or not."""
- unread = False
- if request.user.is_authenticated():
- try:
- last_view_obj = LastView.objects.get(
- list_address=mlist_name,
- threadid=thread.thread_id,
- user=request.user)
- except LastView.DoesNotExist:
- unread = True
- else:
- if thread.date_active.replace(tzinfo=utc) \
- > last_view_obj.view_date:
- unread = True
- return unread
-
diff --git a/hyperkitty/lib/posting.py b/hyperkitty/lib/posting.py
new file mode 100644
index 0000000..306806e
--- /dev/null
+++ b/hyperkitty/lib/posting.py
@@ -0,0 +1,66 @@
+#-*- coding: utf-8 -*-
+# Copyright (C) 1998-2012 by the Free Software Foundation, Inc.
+#
+# This file is part of HyperKitty.
+#
+# HyperKitty is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# HyperKitty is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# HyperKitty. If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: Aurelien Bompard <abompard@fedoraproject.org>
+#
+
+
+from django.core.exceptions import SuspiciousOperation
+from django.core.mail import EmailMessage
+from mailmanclient import MailmanConnectionError
+
+from hyperkitty.lib import mailman
+
+
+class PostingFailed(Exception):
+ pass
+
+
+def post_to_list(request, mlist, subject, message, headers={},
+ attachments=None):
+ if not mlist:
+ # Make sure the list exists to avoid posting to any email addess
+ raise SuspiciousOperation("I don't know this mailing-list")
+ # Check that the user is subscribed
+ try:
+ mailman.subscribe(mlist.name, request.user)
+ except MailmanConnectionError:
+ raise PostingFailed("Can't connect to Mailman's REST server, "
+ "your message has not been sent.")
+ # send the message
+ headers["User-Agent"] = "HyperKitty on %s" % request.build_absolute_uri("/")
+ if not request.user.first_name and not request.user.last_name:
+ from_email = request.user.email
+ else:
+ from_email = '"%s %s" <%s>' % (request.user.first_name,
+ request.user.last_name,
+ request.user.email)
+ msg = EmailMessage(
+ subject=subject,
+ body=message,
+ from_email=from_email,
+ to=[mlist.name],
+ headers=headers,
+ )
+ # Attachments
+ if attachments:
+ if not isinstance(attachments, list):
+ attachments = [attachments]
+ for attach in attachments:
+ msg.attach(attach.name, attach.read())
+ msg.send()
diff --git a/hyperkitty/lib/view_helpers.py b/hyperkitty/lib/view_helpers.py
new file mode 100644
index 0000000..a27baaf
--- /dev/null
+++ b/hyperkitty/lib/view_helpers.py
@@ -0,0 +1,171 @@
+#-*- coding: utf-8 -*-
+# Copyright (C) 1998-2012 by the Free Software Foundation, Inc.
+#
+# This file is part of HyperKitty.
+#
+# HyperKitty is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# HyperKitty is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# HyperKitty. If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: Aurelien Bompard <abompard@fedoraproject.org>
+#
+
+
+import datetime
+
+from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
+from django.utils.timezone import utc
+
+from hyperkitty.models import ThreadCategory, LastView
+from hyperkitty.views.forms import CategoryForm
+
+
+FLASH_MESSAGES = {
+ "updated-ok": ("success", "The profile was successfully updated."),
+ "sent-ok": ("success", "The message has been sent successfully."),
+}
+
+
+def get_months(store, list_name):
+ """ Return a dictionnary of years, months for which there are
+ potentially archives available for a given list (based on the
+ oldest post on the list).
+
+ :arg list_name, name of the mailing list in which this email
+ should be searched.
+ """
+ date_first = store.get_start_date(list_name)
+ if not date_first:
+ return {}
+ archives = {}
+ now = datetime.datetime.now()
+ year = date_first.year
+ month = date_first.month
+ while year < now.year:
+ archives[year] = range(1, 13)[(month -1):]
+ year = year + 1
+ month = 1
+ archives[now.year] = range(1, 13)[:now.month]
+ return archives
+
+
+def get_display_dates(year, month, day):
+ if day is None:
+ start_day = 1
+ else:
+ start_day = int(day)
+ begin_date = datetime.datetime(int(year), int(month), start_day)
+
+ if day is None:
+ end_date = begin_date + datetime.timedelta(days=32)
+ end_date = end_date.replace(day=1)
+ else:
+ end_date = begin_date + datetime.timedelta(days=1)
+
+ return begin_date, end_date
+
+
+def daterange(start_date, end_date):
+ for n in range(int((end_date - start_date).days)):
+ yield start_date + datetime.timedelta(n)
+
+
+def paginate(objects, page_num, max_page_range=10, paginator=None):
+ try:
+ page_num = int(page_num)
+ except (TypeError, ValueError):
+ page_num = 1
+ if paginator is None:
+ paginator = Paginator(objects, 10) # else use the provided instance
+ try:
+ objects = paginator.page(page_num)
+ except PageNotAnInteger:
+ # If page is not an integer, deliver first page.
+ objects = paginator.page(1)
+ except EmptyPage:
+ # If page is out of range (e.g. 9999), deliver last page of results.
+ objects = paginator.page(paginator.num_pages)
+ # Calculate the displayed page range
+ if paginator.num_pages > max_page_range:
+ objects.page_range = [ 1 ]
+ subrange_lower = page_num - (max_page_range / 2 - 2)
+ if subrange_lower > 3:
+ objects.page_range.append("...")
+ else:
+ subrange_lower = 2
+ objects.page_range.extend(range(subrange_lower, page_num))
+ if page_num != 1 and page_num != 100:
+ objects.page_range.append(page_num)
+ subrange_upper = page_num + (max_page_range / 2 - 2)
+ if subrange_upper >= paginator.num_pages - 2:
+ subrange_upper = paginator.num_pages - 1
+ objects.page_range.extend(range(page_num+1, subrange_upper+1))
+ if subrange_upper < paginator.num_pages - 2:
+ objects.page_range.append("...")
+ objects.page_range.append(paginator.num_pages)
+ else:
+ objects.page_range = [ p+1 for p in range(paginator.num_pages) ]
+ return objects
+
+
+def get_category_widget(request=None, current_category=None):
+ """
+ Returns the category form and the applicable category object (or None if no
+ category is set for this thread).
+
+ If current_category is not provided or None, try to deduce it from the POST
+ request.
+ if request is not provided or None, don't return the category form, return
+ None instead.
+ """
+ categories = [ (c.name, c.name.upper())
+ for c in ThreadCategory.objects.all() ] \
+ + [("", "no category")]
+
+ if request:
+ if request.method == "POST":
+ category_form = CategoryForm(request.POST)
+ else:
+ category_form = CategoryForm(initial={"category": current_category or ""})
+ category_form["category"].field.choices = categories
+ else:
+ category_form = None
+ if request and request.method == "POST" and category_form.is_valid():
+ # is_valid() must be called after the choices have been set
+ current_category = category_form.cleaned_data["category"]
+
+ if not current_category:
+ category = None
+ else:
+ try:
+ category = ThreadCategory.objects.get(name=current_category)
+ except ThreadCategory.DoesNotExist:
+ category = None
+ return category, category_form
+
+
+def is_thread_unread(request, mlist_name, thread):
+ """Returns True or False if the thread is unread or not."""
+ unread = False
+ if request.user.is_authenticated():
+ try:
+ last_view_obj = LastView.objects.get(
+ list_address=mlist_name,
+ threadid=thread.thread_id,
+ user=request.user)
+ except LastView.DoesNotExist:
+ unread = True
+ else:
+ if thread.date_active.replace(tzinfo=utc) \
+ > last_view_obj.view_date:
+ unread = True
+ return unread
diff --git a/hyperkitty/tests/test_forms.py b/hyperkitty/tests/test_forms.py
deleted file mode 100644
index 9a056cd..0000000
--- a/hyperkitty/tests/test_forms.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (C) 1998-2012 by the Free Software Foundation, Inc.
-#
-# This file is part of HyperKitty.
-#
-# HyperKitty is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free
-# Software Foundation, either version 3 of the License, or (at your option)
-# any later version.
-#
-# HyperKitty is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-# more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# HyperKitty. If not, see <http://www.gnu.org/licenses/>.
-#
-# Author: Aamir Khan <syst3m.w0rm@gmail.com>
-#
diff --git a/hyperkitty/tests/test_lib.py b/hyperkitty/tests/test_lib.py
index b24f5c4..4b9b778 100644
--- a/hyperkitty/tests/test_lib.py
+++ b/hyperkitty/tests/test_lib.py
@@ -23,7 +23,7 @@ import datetime
from django.test import TestCase
-from hyperkitty.lib import get_display_dates, paginate
+from hyperkitty.lib.view_helpers import get_display_dates, paginate
class GetDisplayDatesTestCase(TestCase):
diff --git a/hyperkitty/views/accounts.py b/hyperkitty/views/accounts.py
index 3a91c3d..373390b 100644
--- a/hyperkitty/views/accounts.py
+++ b/hyperkitty/views/accounts.py
@@ -36,7 +36,8 @@ from social_auth.backends import SocialAuthBackend
from hyperkitty.models import UserProfile, Rating, Favorite, LastView
from hyperkitty.views.forms import RegistrationForm, UserProfileForm
-from hyperkitty.lib import get_store, FLASH_MESSAGES, paginate
+from hyperkitty.lib import get_store
+from hyperkitty.lib.view_helpers import FLASH_MESSAGES, paginate
logger = logging.getLogger(__name__)
diff --git a/hyperkitty/views/list.py b/hyperkitty/views/list.py
index 4857c27..89c113c 100644
--- a/hyperkitty/views/list.py
+++ b/hyperkitty/views/list.py
@@ -32,9 +32,10 @@ from django.utils.timezone import utc
from django.http import Http404
from hyperkitty.models import Tag, Favorite
-from hyperkitty.lib import get_months, get_store, get_display_dates, daterange
-from hyperkitty.lib import FLASH_MESSAGES, paginate, get_category_widget
-from hyperkitty.lib import is_thread_unread
+from hyperkitty.lib import get_store
+from hyperkitty.lib.view_helpers import FLASH_MESSAGES, paginate, \
+ get_category_widget, get_months, get_display_dates, daterange, \
+ is_thread_unread
from hyperkitty.lib.voting import get_votes, set_message_votes, set_thread_votes
diff --git a/hyperkitty/views/message.py b/hyperkitty/views/message.py
index 66cc314..6e3a640 100644
--- a/hyperkitty/views/message.py
+++ b/hyperkitty/views/message.py
@@ -31,7 +31,9 @@ from django.core.exceptions import SuspiciousOperation
from django.template import RequestContext, loader
from django.contrib.auth.decorators import login_required
-from hyperkitty.lib import get_store, get_months, post_to_list, PostingFailed
+from hyperkitty.lib import get_store
+from hyperkitty.lib.view_helpers import get_months
+from hyperkitty.lib.posting import post_to_list, PostingFailed
from hyperkitty.lib.voting import set_message_votes
from hyperkitty.models import Rating
from forms import ReplyForm, PostForm
diff --git a/hyperkitty/views/search.py b/hyperkitty/views/search.py
index f143876..dbef37d 100644
--- a/hyperkitty/views/search.py
+++ b/hyperkitty/views/search.py
@@ -24,7 +24,8 @@ from django.shortcuts import render
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger, Page
from hyperkitty.models import Tag
-from hyperkitty.lib import get_store, paginate
+from hyperkitty.lib import get_store
+from hyperkitty.lib.view_helpers import paginate
from hyperkitty.lib.voting import get_votes, set_message_votes
from .list import _thread_list
diff --git a/hyperkitty/views/thread.py b/hyperkitty/views/thread.py
index ecfd6eb..1098302 100644
--- a/hyperkitty/views/thread.py
+++ b/hyperkitty/views/thread.py
@@ -35,8 +35,8 @@ import robot_detection
from hyperkitty.models import Tag, Favorite, LastView, ThreadCategory
from hyperkitty.views.forms import AddTagForm, ReplyForm, CategoryForm
-from hyperkitty.lib import get_months, get_store, stripped_subject
-from hyperkitty.lib import get_category_widget
+from hyperkitty.lib import get_store, stripped_subject
+from hyperkitty.lib.view_helpers import get_months, get_category_widget
from hyperkitty.lib.voting import set_message_votes