Another Step in the Quest to clean up the code base.

This commit is contained in:
2017-09-08 07:19:50 +02:00
parent 8f4bdec701
commit 6e2240ed5f
229 changed files with 1915 additions and 15175 deletions

View File

@@ -20,7 +20,6 @@ STATUS_CHOICES = (
)
class OverwriteStorage(FileSystemStorage):
"""
Returns same name for existing file and deletes existing file on save.
@@ -31,5 +30,5 @@ class OverwriteStorage(FileSystemStorage):
self.delete(name)
return super(OverwriteStorage, self)._save(name, content)
def get_available_name(self, name):
def get_available_name(self, name, max_length=None):
return name

View File

@@ -1,3 +1,4 @@
"""A list of all approved countries on planet earth, i18n enabled."""
from django.utils.translation import ugettext as _
COUNTRIES = (

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: kasu.utils\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-05-10 23:16+0200\n"
"POT-Creation-Date: 2017-06-19 22:46+0200\n"
"PO-Revision-Date: 2016-09-28 00:24+0200\n"
"Last-Translator: Christian Berg <xeniac@posteo.at>\n"
"Language-Team: Kasu <verein@kasu.at>\n"
@@ -18,15 +18,15 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.8.9\n"
#: utils/__init__.py:16
#: utils/__init__.py:17
msgid "Rejected"
msgstr "Zurückgewiesen"
#: utils/__init__.py:17
#: utils/__init__.py:18
msgid "Waiting..."
msgstr "Wartend..."
#: utils/__init__.py:18
#: utils/__init__.py:19
msgid "Published"
msgstr "Veröffentlicht"
@@ -1014,53 +1014,44 @@ msgstr "Sambia"
msgid "Zimbabwe"
msgstr "Zimbabwe"
#: utils/html5/forms.py:48
msgid ""
"Select a valid choice. That choice is not one of the available "
"choices."
msgstr ""
"Bitte eine gültige Auswahl treffen. Diese Option steht nicht zur Verfügung."
#~ msgid ""
#~ "Select a valid choice. That choice is not one of the available "
#~ "choices."
#~ msgstr ""
#~ "Bitte eine gültige Auswahl treffen. Diese Option steht nicht zur "
#~ "Verfügung."
#: utils/html5/forms.py:94
msgid ""
"Select a valid choice. That choice is not one of the available "
"choices."
msgstr ""
"Bitte eine gültige Auswahl treffen. Diese Option steht nicht zur Verfügung."
#~ msgid ""
#~ "Select a valid choice. That choice is not one of the available "
#~ "choices."
#~ msgstr ""
#~ "Bitte eine gültige Auswahl treffen. Diese Option steht nicht zur "
#~ "Verfügung."
#: utils/html5/forms.py:132
msgid "yyyy-mm-dd"
msgstr "tt.mm.jjjj"
#~ msgid "yyyy-mm-dd"
#~ msgstr "tt.mm.jjjj"
#: utils/html5/forms.py:238
msgid "Only humans are allowed to submit this form."
msgstr "Nur Menschen dürfen dieses Formular übermitteln."
#~ msgid "Only humans are allowed to submit this form."
#~ msgstr "Nur Menschen dürfen dieses Formular übermitteln."
#: utils/management/commands/compresscss.py:22
#: utils/management/commands/compressjs.py:21
msgid "Reads raw CSS from stdin, and writes compressed CSS to stdout."
msgstr "Lese das CSS von stdin, und gebe es in komprimierter Form wieder aus."
#~ msgid "Reads raw CSS from stdin, and writes compressed CSS to stdout."
#~ msgstr ""
#~ "Lese das CSS von stdin, und gebe es in komprimierter Form wieder aus."
#: utils/management/commands/scss-compiler.py:20
msgid "Compile SCSS rules."
msgstr "kompiliere SCSS Regeln."
#~ msgid "Compile SCSS rules."
#~ msgstr "kompiliere SCSS Regeln."
#: utils/management/commands/scss-compiler.py:29
#, python-format
msgid "Compressing CSS for %s"
msgstr "Komprimiere CSS für %s"
#~ msgid "Compressing CSS for %s"
#~ msgstr "Komprimiere CSS für %s"
#: utils/mixins.py:28
msgid "You need to be logged in"
msgstr "Eine Anmeldung ist erforderlich"
#~ msgid "You need to be logged in"
#~ msgstr "Eine Anmeldung ist erforderlich"
#: utils/mixins.py:60
msgid "You don't have the permission to do this"
msgstr "Du hast nicht genügend Rechte dafür."
#~ msgid "You don't have the permission to do this"
#~ msgstr "Du hast nicht genügend Rechte dafür."
#: utils/mixins.py:100
msgid "You don't have the permissions for this"
msgstr "Du hast nicht genügend Rechte dafür."
#~ msgid "You don't have the permissions for this"
#~ msgstr "Du hast nicht genügend Rechte dafür."
#~ msgid "Compressing JavaScript for %s"
#~ msgstr "Komprimiere JavaScript für %s"

View File

@@ -1,9 +1,18 @@
import logging
"""
MassMailer can send E-Mails via an SMTP Connection to multiple recipients.
from django.core import mail
Each E-Mail will be send individually and can be personalized. It will be send
as HTML and Plain-Text Message.
"""
import logging
import smtplib
import django.core.mail
from django.contrib.auth import get_user_model
from django.contrib.sites.models import Site
from django.template import loader
from django.contrib.auth import get_user_model
LOGGER = logging.getLogger('maillog')
class MassMailer(object):
@@ -12,64 +21,39 @@ class MassMailer(object):
Each E-Mail will be send individually and can be personalized.
It will be send as HTML and Plain-Text Message.
"""
context = {}
headers = {}
subject = None
txt_template = None
html_template = None
def __init__(self, subject=None, template=None, context=None):
self.USER_MODEL = get_user_model()
self.mail_queue = set()
self.recipients = set()
self.subject = subject
self.template = 'email'
def __init__(self, subject=None, context=None, txt_template=None,
html_template=None):
"""set the subject and context for further processing."""
self.context = context
self.log = logging.getLogger('maillog')
def open_smtp_connection(self):
try:
self.smtp_connection = mail.get_connection(fail_silently=False)
self.smtp_connection.open()
self.mail_counter = 0
except:
self.log.error('Connection to SMTP server failed. Giving up!')
raise False
self.context['site'] = Site.objects.get_current()
self.headers = {}
self.subject = subject
self.txt_template = loader.get_template(txt_template)
if html_template:
self.html_template = loader.get_template(html_template)
else:
self.log.debug('Connected to SMTP server.')
return True
self.html_template = None
def close_smtp_connection(self):
self.smtp_connection.close()
self.log.debug("closed the SMTP connection. I'm done")
def process_mails(self, recipients):
""" Generate personalised e-mails for each user in the recipients list.
def add_recipient(self, recipient):
if isinstance(recipient, self.USER_MODEL):
self.recipients.add(recipient)
else:
self.log.warning('%s is not a User Object!', recipient)
def add_recipients(self, user_list):
for user in user_list:
if isinstance(user, self.USER_MODEL):
self.log.debug('Adding %s as Recipient' % user)
self.recipients.add(user)
else:
self.log.warning('%s is not a User Object!', user)
def process_mails(self):
:param recipients: A iterateable of User objects that shoud get the mail
:return: a iteratable of Mail Objects that should read for sending.
"""
mail_context = self.context
mail_context['site'] = Site.objects.get_current()
self.txt_template = loader.get_template(self.txt_template)
if self.html_template:
self.html_template = loader.get_template(self.html_template)
for recipient in self.recipients:
mail_queue = set()
for recipient in recipients:
if isinstance(recipient, get_user_model()):
LOGGER.debug('Adding %s as Recipient' % recipient)
else:
LOGGER.warning('%s is not a User Object!', recipient)
continue
mail_context['recipient'] = recipient
mail_to = "%s %s <%s>" % (recipient.first_name,
recipient.last_name, recipient.email)
message = mail.EmailMultiAlternatives(
print(recipient.__dict__)
mail_to = "{first_name!s} {last_name!s} <{email!s}>".format(
**recipient.__dict__)
message = django.core.mail.EmailMultiAlternatives(
subject=self.subject,
body=self.txt_template.render(mail_context),
to=(mail_to,),
@@ -79,30 +63,38 @@ class MassMailer(object):
message.attach_alternative(
self.html_template.render(mail_context), "text/html"
)
self.mail_queue.add(message)
mail_queue.add(message)
return mail_queue
def set_header(self, name, value):
"""Add or modify an E-Mail Header to the Messages
:param name: The Header Name that should be added
:param value: THe Header Value that shoud be added or set
"""
self.headers[name] = value
def send(self):
def send(self, recipients=set()):
"""
Process the E-Mails and send them
:param recipients: list of Users that should receive this Mail
:return:
"""
self.process_mails()
if len(self.mail_queue) == 0:
self.log.info('No recipients for eMail "%s", bye!', self.subject)
mail_queue = self.process_mails(recipients)
if len(mail_queue) == 0:
LOGGER.info('No recipients for eMail "%s", bye!', self.subject)
return True
else:
self.log.info('Sending eMail "%s" to %d people', self.subject,
len(self.mail_queue))
self.log.debug(self.recipients)
LOGGER.info('Sending eMail "%s" to %d people', self.subject,
len(mail_queue))
LOGGER.debug(recipients)
self.open_smtp_connection()
for mail in self.mail_queue:
try:
mail.send()
except:
self.log.warning("Mail failed for: %s", mail.to)
else:
self.log.info("Mail sent successful to: %s" % mail.to)
self.close_smtp_connection()
with django.core.mail.get_connection(fail_silently=False) as connection:
for mail in mail_queue:
try:
mail.connection = connection
mail.send()
except smtplib.SMTPException:
LOGGER.warning("Mail failed for: %s", mail.to)
else:
LOGGER.info("Mail sent successful to: %s" % mail.to)

View File

@@ -1,20 +1,33 @@
# -*- coding: utf-8 -*-
"""
Created on 23.05.2011
@author: christian
"""
"""This Middleware compresses the HTML Output at the End. It strips the Spaces
between Tags, an at the beginning and the end of the content."""
from django.utils.html import strip_spaces_between_tags
class CompressHtmlMiddleware(object):
"""
This Middleware compresses the HTML Output at the End. It strips the Spaces
between Tags, an at the beginning and the end of the content.
"""
"""This Middleware compresses strips the spaces between tags, and at the
beginning and the end of the content."""
# TODO: Port to django 1.10 and upward
def process_response(self, request, response):
def __init__(self, get_response):
"""
:param get_response:
"""
self.get_response = get_response
regex = ">[\s]*<"
def __call__(self, request):
"""
:param request:
:return:
"""
# Code to be executed for each request before
# the view (and later middleware) are called.
response = self.get_response(request)
if 'text/html' in response['Content-Type']:
response.content = strip_spaces_between_tags(response.content)
response.content = response.content.strip()
response.content = strip_spaces_between_tags(
response.content).strip()
return response

View File

@@ -1,103 +0,0 @@
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.core.exceptions import ImproperlyConfigured
from django import http
from django.utils.translation import ugettext as _
from django.utils.http import urlquote
class LoginRequiredMixin(object):
"""
View mixin which verifies that the user has authenticated.
NOTE:
This should be the left-most mixin of a view.
"""
login_url = settings.LOGIN_URL
raise_exception = False
redirect_field_name = REDIRECT_FIELD_NAME
def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated():
return super(LoginRequiredMixin, self).dispatch(request, *args,
**kwargs)
elif self.raise_exception: # if an exception was desired
return http.HttpResponseForbidden() # return a forbidden response.
else:
messages.error(request, _("You need to be logged in"))
path = urlquote(request.get_full_path())
return http.HttpResponseRedirect(
"%s?%s=%s" % (self.login_url, self.redirect_field_name, path))
class PermissionRequiredMixin(object):
"""
View mixin which verifies that the loggedin user has the specified
permission.
Class Settings
`permission_required` - the permission to check for.
`login_url` - the login url of site
`redirect_field_name` - defaults to "next"
`raise_exception` - defaults to False - raise 403 if set to True
Example Usage
class SomeView(PermissionRequiredMixin, ListView):
...
# required
permission_required = "app.permission"
# optional
login_url = "/signup/"
redirect_field_name = "hollaback"
raise_exception = True
...
"""
login_url = settings.LOGIN_URL
permission_required = None
permission_failed_message = _("You don't have the permission to do this")
raise_exception = False
redirect_field_name = REDIRECT_FIELD_NAME
def dispatch(self, request, *args, **kwargs):
# Verify class settings
if self.permission_required is None or len(
self.permission_required.split(".")) != 2:
raise ImproperlyConfigured(
"'PermissionRequiredMixin' requires 'permission_required' attribute to be set.")
has_permission = request.user.has_perm(self.permission_required)
if has_permission:
return super(PermissionRequiredMixin, self).dispatch(request, *args,
**kwargs)
elif self.raise_exception:
return http.HttpResponseForbidden()
else:
messages.warning(request, self.permission_failed_message)
path = urlquote(request.get_full_path())
return http.HttpResponseRedirect(
"%s?%s=%s" % (self.login_url, self.redirect_field_name, path))
class SuperuserRequiredMixin(object):
"""
Mixin allows you to require a user with `is_superuser` set to True.
"""
login_url = settings.LOGIN_URL # LOGIN_URL from project settings
raise_exception = False # Default whether to raise an exception to none
redirect_field_name = REDIRECT_FIELD_NAME # Set by django.contrib.auth
def dispatch(self, request, *args, **kwargs):
if request.user.is_superuser: # If the user is a standard user,
return super(SuperuserRequiredMixin, self).dispatch(request, *args,
**kwargs)
elif self.raise_exception: # *and* if an exception was desired
return http.HttpResponseForbidden() # return a forbidden response.
else:
messages.error(request,
_("You don't have the permissions for this"))
path = urlquote(request.get_full_path())
return http.HttpResponseRedirect(
"%s?%s=%s" % (self.login_url, self.redirect_field_name, path))

View File

@@ -1,8 +1,18 @@
""" This should be the place to test the functinality of the random
stuff that has been collected in the utils package. Idealy we shuld get rid
of this random addons. """
import unittest
import html_cleaner
from utils import html_cleaner
class HtmlTestCase(unittest.TestCase):
""" Unit testcase to verify the HTML cleanup class.
It should removed unwanted syling tags an more get rid of dangerous
JavaScript elements.
"""
known_html = (
('<STRONG>Fett!</STRONG>', '<strong>Fett!</strong>'),
('<a href="link.html" onclick="do_evil()">Bad Link</a>',
@@ -34,7 +44,7 @@ class HtmlTestCase(unittest.TestCase):
xxx-xxxx</FONT></DIV></BODY></HTML>
''',
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">'
)
)
)
def test_html_cleaner(self):